]> git.sesse.net Git - vlc/blobdiff - modules/gui/skins2/controls/ctrl_slider.cpp
skins2: improve refresh of layouts
[vlc] / modules / gui / skins2 / controls / ctrl_slider.cpp
index 5159caebde40434c36970bbb83f2677947251a42..8eca2b03752f536c38ea890b10adf34a67d959ac 100644 (file)
@@ -143,24 +143,65 @@ bool CtrlSliderCursor::mouseOver( int x, int y ) const
 }
 
 
-void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
     if( m_pImg )
     {
-        // Compute the position of the cursor
-        int xPos, yPos;
-        m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
+        // Draw the current image
+        rect inter;
+        rect clip( xDest, yDest, w, h);
+
+        if( rect::intersect( m_currentCursorRect, clip, &inter ) )
+            rImage.drawGraphics( *m_pImg,
+                             inter.x - m_currentCursorRect.x,
+                             inter.y - m_currentCursorRect.y,
+                             inter.x, inter.y, inter.width, inter.height );
+    }
+}
 
-        // Compute the resize factors
-        float factorX, factorY;
-        getResizeFactors( factorX, factorY );
-        xPos = (int)(xPos * factorX);
-        yPos = (int)(yPos * factorY);
 
-        // Draw the current image
-        rImage.drawGraphics( *m_pImg, 0, 0,
-                             xDest + xPos - m_pImg->getWidth() / 2,
-                             yDest + yPos - m_pImg->getHeight() / 2 );
+void CtrlSliderCursor::onPositionChange()
+{
+    // Compute the position of the cursor
+    int xPos, yPos;
+    m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
+
+    // Compute the resize factors
+    float factorX, factorY;
+    getResizeFactors( factorX, factorY );
+    xPos = (int)(xPos * factorX);
+    yPos = (int)(yPos * factorY);
+
+    const Position *pPos = getPosition();
+
+    int x = pPos->getLeft() + xPos - m_pImg->getWidth() / 2;
+    int y = pPos->getTop() + yPos - m_pImg->getHeight() / 2;
+
+    m_currentCursorRect = rect( x, y, m_pImg->getWidth(), m_pImg->getHeight() );
+}
+
+
+void CtrlSliderCursor::onResize()
+{
+    onPositionChange();
+}
+
+
+void CtrlSliderCursor::notifyLayout( int width, int height, int xOffSet, int yOffSet )
+{
+    if( width > 0 && height > 0 )
+    {
+        CtrlGeneric::notifyLayout( width, height, xOffSet, yOffSet );
+    }
+    else
+    {
+        onPositionChange();
+
+        const Position *pPos = getPosition();
+        CtrlGeneric::notifyLayout( m_currentCursorRect.width,
+                                   m_currentCursorRect.height,
+                                   m_currentCursorRect.x - pPos->getLeft(),
+                                   m_currentCursorRect.y - pPos->getTop() );
     }
 }
 
@@ -169,7 +210,7 @@ void CtrlSliderCursor::onUpdate( Subject<VarPercent> &rVariable,
                                  void *arg  )
 {
     // The position has changed
-    refreshLayout();
+    refreshLayout( false );
 }
 
 
@@ -280,20 +321,42 @@ void CtrlSliderCursor::getResizeFactors( float &rFactorX,
 }
 
 
-void CtrlSliderCursor::refreshLayout()
+void CtrlSliderCursor::refreshLayout( bool force )
 {
-    if( !m_pImg )
-        notifyLayout();
-    else
+    // Compute the position of the cursor
+    int xPos, yPos;
+    m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
+
+    // Compute the resize factors
+    float factorX, factorY;
+    getResizeFactors( factorX, factorY );
+    xPos = (int)(xPos * factorX);
+    yPos = (int)(yPos * factorY);
+
+    const Position *pPos = getPosition();
+
+    int x = pPos->getLeft() + xPos - m_pImg->getWidth() / 2;
+    int y = pPos->getTop() + yPos - m_pImg->getHeight() / 2;
+
+    rect region( x, y, m_pImg->getWidth(), m_pImg->getHeight() );
+
+
+    if( !force &&
+        region.x == m_currentCursorRect.x &&
+        region.y == m_currentCursorRect.y &&
+        region.width == m_currentCursorRect.width &&
+        region.height == m_currentCursorRect.height )
     {
-        // Compute the resize factors
-        float factorX, factorY;
-        getResizeFactors( factorX, factorY );
+        return;
+    }
 
-        notifyLayout( (int)(m_rCurve.getWidth() * factorX) + m_pImg->getWidth(),
-                      (int)(m_rCurve.getHeight() * factorY) + m_pImg->getHeight(),
-                      - m_pImg->getWidth() / 2,
-                      - m_pImg->getHeight() / 2 );
+    rect join;
+    if( rect::join( m_currentCursorRect, region, &join ) )
+    {
+        m_currentCursorRect = region;
+        notifyLayout( join.width, join.height,
+                      join.x - pPos->getLeft(),
+                      join.y - pPos->getTop() );
     }
 }
 
@@ -308,9 +371,9 @@ CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
     m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
     m_pImgSeq( pBackground ), m_nbHoriz( nbHoriz ), m_nbVert( nbVert ),
     m_padHoriz( padHoriz ), m_padVert( padVert ), m_bgWidth( 0 ),
-    m_bgHeight( 0 ), m_position( 0 )
+    m_bgHeight( 0 ), m_position( 0 ), m_pScaledBmp( NULL )
 {
-    if( pBackground )
+    if( m_pImgSeq )
     {
         // Build the background image sequence
         // Note: we suppose that the last padding is not included in the
@@ -332,7 +395,10 @@ CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
 
 CtrlSliderBg::~CtrlSliderBg()
 {
-    m_rVariable.delObserver( this );
+    if( m_pImgSeq )
+        m_rVariable.delObserver( this );
+
+    delete m_pScaledBmp;
 }
 
 
@@ -347,7 +413,7 @@ bool CtrlSliderBg::mouseOver( int x, int y ) const
 }
 
 
-void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
     if( !m_pImgSeq || m_bgWidth <=0 || m_bgHeight <= 0 )
         return;
@@ -356,18 +422,35 @@ void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest )
     float factorX, factorY;
     getResizeFactors( factorX, factorY );
 
-    // Rescale the image with the actual size of the control
-    ScaledBitmap bmp( getIntf(), *m_pImgSeq,
-         m_bgWidth * m_nbHoriz - (int)(m_padHoriz * factorX),
-         m_bgHeight * m_nbVert - (int)(m_padVert * factorY) );
+    int width = m_bgWidth * m_nbHoriz - (int)(m_padHoriz * factorX);
+    int height = m_bgHeight * m_nbVert - (int)(m_padVert * factorY);
+
+    // Rescale the image with the actual size of the control if needed
+    if( !m_pScaledBmp ||
+        m_pScaledBmp->getWidth() != width ||
+        m_pScaledBmp->getHeight() != height )
+    {
+        delete m_pScaledBmp;
+        m_pScaledBmp = new ScaledBitmap( getIntf(), *m_pImgSeq, width, height );
+    }
 
     // Locate the right image in the background bitmap
     int x = m_bgWidth * ( m_position % m_nbHoriz );
     int y = m_bgHeight * ( m_position / m_nbHoriz );
+
     // Draw the background image
-    rImage.drawBitmap( bmp, x, y, xDest, yDest,
-                       m_bgWidth - (int)(m_padHoriz * factorX),
-                       m_bgHeight - (int)(m_padVert * factorY) );
+    const Position *pPos = getPosition();
+    rect region( pPos->getLeft(), pPos->getTop(),
+                 m_bgWidth - (int)(m_padHoriz * factorX),
+                 m_bgHeight - (int)(m_padVert * factorY) );
+    rect clip( xDest, yDest, w, h );
+    rect inter;
+    if( rect::intersect( region, clip, &inter ) )
+        rImage.drawBitmap( *m_pScaledBmp,
+                           x + inter.x - region.x,
+                           y + inter.y - region.y,
+                           inter.x, inter.y,
+                           inter.width, inter.height );
 }