]> git.sesse.net Git - vlc/commitdiff
skins2: improve refresh of layouts
authorErwan Tulou <erwan10@videolan.org>
Thu, 29 Jul 2010 22:13:02 +0000 (00:13 +0200)
committerErwan Tulou <erwan10@videolan.org>
Sat, 31 Jul 2010 20:48:33 +0000 (22:48 +0200)
Up to now, notification of invalidated subareas was available for controls
but yet, the layout always ended up being totally rebuilt. For instance,
 a small animated image meant a total rebuild of everything. For simple skins,
 this could go unnoticed, but old computers had much difficulty with more
 complex skins (e.g wmp11), that were mostly busy rebuilding layouts
 over and over.

This patch ensures that only what needs to be rebuilt is rebuilt. Some skins
 like wmp11 on Linux do show dramatic improvement with this one patch.

28 files changed:
modules/gui/skins2/controls/ctrl_button.cpp
modules/gui/skins2/controls/ctrl_button.hpp
modules/gui/skins2/controls/ctrl_checkbox.cpp
modules/gui/skins2/controls/ctrl_checkbox.hpp
modules/gui/skins2/controls/ctrl_generic.cpp
modules/gui/skins2/controls/ctrl_generic.hpp
modules/gui/skins2/controls/ctrl_image.cpp
modules/gui/skins2/controls/ctrl_image.hpp
modules/gui/skins2/controls/ctrl_list.cpp
modules/gui/skins2/controls/ctrl_list.hpp
modules/gui/skins2/controls/ctrl_move.cpp
modules/gui/skins2/controls/ctrl_move.hpp
modules/gui/skins2/controls/ctrl_radialslider.cpp
modules/gui/skins2/controls/ctrl_radialslider.hpp
modules/gui/skins2/controls/ctrl_resize.cpp
modules/gui/skins2/controls/ctrl_resize.hpp
modules/gui/skins2/controls/ctrl_slider.cpp
modules/gui/skins2/controls/ctrl_slider.hpp
modules/gui/skins2/controls/ctrl_text.cpp
modules/gui/skins2/controls/ctrl_text.hpp
modules/gui/skins2/controls/ctrl_tree.cpp
modules/gui/skins2/controls/ctrl_tree.hpp
modules/gui/skins2/controls/ctrl_video.cpp
modules/gui/skins2/controls/ctrl_video.hpp
modules/gui/skins2/src/anim_bitmap.cpp
modules/gui/skins2/src/anim_bitmap.hpp
modules/gui/skins2/src/generic_layout.cpp
modules/gui/skins2/utils/pointer.hpp

index a1eb12559a6f0f576e57cebc775b68c91e100f43..1c19bc3bdadf16da9df30a1b920fe7d7c1a9545a 100644 (file)
@@ -114,16 +114,22 @@ bool CtrlButton::mouseOver( int x, int y ) const
 }
 
 
-void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest )
-{
-    if( m_pImg )
+void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
+{
+    const Position *pPos = getPosition();
+    rect region( pPos->getLeft(), pPos->getTop(),
+                 pPos->getWidth(), pPos->getHeight() );
+    rect clip( xDest, yDest, w, h );
+    rect inter;
+    if( rect::intersect( region, clip, &inter ) && m_pImg )
     {
         // Draw the current image
-        m_pImg->draw( rImage, xDest, yDest );
+        m_pImg->draw( rImage, inter.x, inter.y, inter.width, inter.height,
+                      inter.x - pPos->getLeft(),
+                      inter.y - pPos->getTop() );
     }
 }
 
-
 void CtrlButton::setImage( AnimBitmap *pImg )
 {
     AnimBitmap *pOldImg = m_pImg;
@@ -147,7 +153,7 @@ void CtrlButton::setImage( AnimBitmap *pImg )
 
 void CtrlButton::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg )
 {
-    notifyLayout();
+    notifyLayout( m_pImg->getWidth(), m_pImg->getHeight() );
 }
 
 
index 6e4581a8c983fbd47a8f0006a2e61df822f7ef8b..b6a8652da797d1738eba9a3a8089d5d39afc1af1 100644 (file)
@@ -57,7 +57,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Get the text of the tooltip
     virtual UString getTooltipText() const { return m_tooltip; }
index 0f0116faf31ce721ade15e50a5c179e84cf1824b..82991a831162f2b6e2e9064ddbc28810d8ca317a 100644 (file)
@@ -134,12 +134,25 @@ bool CtrlCheckbox::mouseOver( int x, int y ) const
 }
 
 
-void CtrlCheckbox::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlCheckbox::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
-    if( m_pImgCurrent )
+    if( !m_pImgCurrent )
+        return;
+
+    const Position *pPos = getPosition();
+    // rect region( pPos->getLeft(), pPos->getTop(),
+    //              pPos->getWidth(), pPos->getHeight() );
+    rect region( pPos->getLeft(), pPos->getTop(),
+                 m_pImgCurrent->getWidth(), m_pImgCurrent->getHeight() );
+    rect clip( xDest, yDest, w, h );
+    rect inter;
+    if( rect::intersect( region, clip, &inter ) )
     {
         // Draw the current image
-        m_pImgCurrent->draw( rImage, xDest, yDest );
+        m_pImgCurrent->draw( rImage,
+                      inter.x, inter.y, inter.width, inter.height,
+                      inter.x - pPos->getLeft(),
+                      inter.y - pPos->getTop() );
     }
 }
 
@@ -248,7 +261,7 @@ void CtrlCheckbox::onVarBoolUpdate( VarBool &rVariable )
 
 void CtrlCheckbox::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg )
 {
-    notifyLayout();
+    notifyLayout( m_pImgCurrent->getWidth(), m_pImgCurrent->getHeight() );
 }
 
 
index 7342bf0ae0e9b9ae8ad4ecb72ff36c19873ba75b..78fff7c41e49559d8d5e79e7dcf00d1005664165 100644 (file)
@@ -61,7 +61,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Get the text of the tooltip XXX
     virtual UString getTooltipText() const { return *m_pTooltip; }
index 81465feebf03da90ec843597fd3d80d61c02f0dc..1e9f7a3a5bb8d31c3ecede334ed27bdf930ea247 100644 (file)
@@ -74,8 +74,11 @@ void CtrlGeneric::unsetLayout()
 }
 
 void CtrlGeneric::notifyLayout( int width, int height,
-                                int xOffSet, int yOffSet ) const
+                                int xOffSet, int yOffSet )
 {
+    width = ( width > 0 ) ? width : m_pPosition->getWidth();
+    height = ( height > 0 ) ? height : m_pPosition->getHeight();
+
     // Notify the layout
     if( m_pLayout )
     {
index d1decf734f1bfb83110929063107a72c219567ca..cc33f4620a1b3e1f8cd8d659cde4b5a9c8f464b8 100644 (file)
@@ -53,7 +53,7 @@ public:
     virtual bool mouseOver( int x, int y ) const { return false; }
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest ) { }
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h ) { }
 
     /// Set the position and the associated layout of the control
     virtual void setLayout( GenericLayout *pLayout,
@@ -96,7 +96,7 @@ protected:
      * Use the default values to repaint the whole window
      */
     virtual void notifyLayout( int witdh = -1, int height = -1,
-                               int xOffSet = 0, int yOffSet = 0 ) const;
+                               int xOffSet = 0, int yOffSet = 0 );
 
     /**
      * Same as notifyLayout(), but takes optional images as parameters.
index c9c35ca6883203baeaede832471950eea7e4c4e3..9709de7e9ff9284d7fcecba4db9885d01abd3c06 100644 (file)
@@ -118,7 +118,7 @@ bool CtrlImage::mouseOver( int x, int y ) const
 }
 
 
-void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
     const Position *pPos = getPosition();
     if( !pPos )
@@ -129,6 +129,13 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
     if( width <= 0 || height <= 0 )
         return;
 
+    rect region( pPos->getLeft(), pPos->getTop(),
+                 pPos->getWidth(), pPos->getHeight() );
+    rect clip( xDest, yDest, w, h );
+    rect inter;
+    if( !rect::intersect( region, clip, &inter ) )
+        return;
+
     if( m_resizeMethod == kScale )
     {
         // Use scaling method
@@ -142,25 +149,40 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
             m_pImage = pOsFactory->createOSGraphics( width, height );
             m_pImage->drawBitmap( bmp, 0, 0 );
         }
-        rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
+        rImage.drawGraphics( *m_pImage,
+                             inter.x - pPos->getLeft(),
+                             inter.y - pPos->getTop(),
+                             inter.x, inter.y,
+                             inter.width, inter.height );
     }
     else if( m_resizeMethod == kMosaic )
     {
+        int xDest0 = pPos->getLeft();
+        int yDest0 = pPos->getTop();
+
         // Use mosaic method
         while( width > 0 )
         {
             int curWidth = __MIN( width, m_pImage->getWidth() );
             height = pPos->getHeight();
-            int curYDest = yDest;
+            int curYDest = yDest0;
             while( height > 0 )
             {
                 int curHeight = __MIN( height, m_pImage->getHeight() );
-                rImage.drawGraphics( *m_pImage, 0, 0, xDest, curYDest,
-                                     curWidth, curHeight );
+                rect region1( xDest0, curYDest, curWidth, curHeight );
+                rect inter1;
+                if( rect::intersect( region1, clip, &inter1 ) )
+                {
+                    rImage.drawGraphics( *m_pImage,
+                                   inter1.x - region1.x,
+                                   inter1.y - region1.y,
+                                   inter1.x, inter1.y,
+                                   inter1.width, inter1.height );
+                }
                 curYDest += curHeight;
                 height -= m_pImage->getHeight();
             }
-            xDest += curWidth;
+            xDest0 += curWidth;
             width -= m_pImage->getWidth();
         }
     }
@@ -202,7 +224,16 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
         }
 
         // draw the scaled image at offset (m_x, m_y) from control origin
-        rImage.drawGraphics( *m_pImage, 0, 0, xDest + m_x, yDest + m_y );
+        rect region1( pPos->getLeft() + m_x, pPos->getTop() + m_y, w, h );
+        rect inter1;
+        if( rect::intersect( region1, inter, &inter1 ) )
+        {
+            rImage.drawGraphics( *m_pImage,
+                                 inter1.x - pPos->getLeft() - m_x,
+                                 inter1.y - pPos->getTop() - m_y,
+                                 inter1.x, inter1.y,
+                                 inter1.width, inter1.height );
+        }
     }
 }
 
index 470ab9f73ab09e1b1a8b340ee803ba2c3ef3bab5..f1d18f17ae10070fa41cc717048ea565a896f22c 100644 (file)
@@ -60,7 +60,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Get the type of control (custom RTTI)
     virtual string getType() const { return "image"; }
index 4bf7d1e757115cd5a8df703bfbc933c48e7b2751..4c01bec711a80a9a7b1fc96a4c239cea95b1ff01 100644 (file)
@@ -349,11 +349,19 @@ bool CtrlList::mouseOver( int x, int y ) const
 }
 
 
-void CtrlList::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlList::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
-    if( m_pImage )
+    const Position *pPos = getPosition();
+    rect region( pPos->getLeft(), pPos->getTop(),
+                 pPos->getWidth(), pPos->getHeight() );
+    rect clip( xDest, yDest, w, h );
+    rect inter;
+    if( rect::intersect( region, clip, &inter ) && m_pImage )
     {
-        rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
+        rImage.drawGraphics( *m_pImage,
+                      inter.x - pPos->getLeft(),
+                      inter.y - pPos->getTop(),
+                      inter.x, inter.y, inter.width, inter.height );
     }
 }
 
index 5fd6f7a8db845588573488970e9b8d4b29479191..fcfb33e3f33e5b62de1a0483b901f0a1ac4c87de 100644 (file)
@@ -53,7 +53,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Called when the layout is resized
     virtual void onResize();
index f4cf8880fdb7b3c07d27183357d41fe728ac133a..39700c839b270c110318596b40ff117d07fd9d07 100644 (file)
@@ -66,9 +66,9 @@ bool CtrlMove::mouseOver( int x, int y ) const
 }
 
 
-void CtrlMove::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlMove::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
-    m_rCtrl.draw( rImage, xDest, yDest );
+    m_rCtrl.draw( rImage, xDest, yDest, w, h );
 }
 
 
index 67e813fe2bd9103c783721bfdb57985045daf471..13fbcfaf7c4a3cf412d0690bc5d31eeebab4eca5 100644 (file)
@@ -49,7 +49,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Set the position and the associated layout of the decorated control
     virtual void setLayout( GenericLayout *pLayout,
index a1bbec3c00e02dc8d6632327e31c4b064548c718..3ca78acccd596af3e493c8a1b73a4cbbddc824bc 100644 (file)
@@ -90,18 +90,33 @@ bool CtrlRadialSlider::mouseOver( int x, int y ) const
 }
 
 
-void CtrlRadialSlider::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlRadialSlider::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
-    rImage.drawGraphics( *m_pImgSeq, 0, m_position * m_height, xDest, yDest,
-                         m_width, m_height );
+    const Position *pPos = getPosition();
+    rect region( pPos->getLeft(), pPos->getTop(), m_width, m_height );
+    rect clip( xDest, yDest, w ,h );
+    rect inter;
+    if( rect::intersect( region, clip, &inter ) )
+        rImage.drawGraphics( *m_pImgSeq,
+                              inter.x - region.x,
+                              inter.y - region.y + m_position * m_height,
+                              inter.x, inter.y,
+                              inter.width, inter.height );
 }
 
 
 void CtrlRadialSlider::onUpdate( Subject<VarPercent> &rVariable,
                                  void *arg  )
 {
-    m_position = (int)( m_rVariable.get() * ( m_numImg - 1 ) );
-    notifyLayout( m_width, m_height );
+    if( &rVariable == &m_rVariable )
+    {
+        int position = (int)( m_rVariable.get() * ( m_numImg - 1 ) );
+        if( position == m_position )
+            return;
+
+        m_position = position;
+        notifyLayout( m_width, m_height );
+    }
 }
 
 
index a528c2cab5261db80a0d7c99779d9b0955918076..e17852b0a23aa82bbb689a41c8b985622fe334f0 100644 (file)
@@ -55,7 +55,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Get the type of control (custom RTTI)
     virtual string getType() const { return "radial_slider"; }
index 1fb37b72bf9ffe6c7aaccbf067c7f52686d59418..7992d4b0fef4b983f731c09962b182da87fe4d14 100644 (file)
@@ -75,9 +75,9 @@ bool CtrlResize::mouseOver( int x, int y ) const
 }
 
 
-void CtrlResize::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlResize::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
-    m_rCtrl.draw( rImage, xDest, yDest );
+    m_rCtrl.draw( rImage, xDest, yDest, w, h );
 }
 
 
index 7d2d718b1819b059e9371fb7663c2d7a8e44aacb..8f2912cfb96bd631f9ba5af9ac448d7967412c43 100644 (file)
@@ -50,7 +50,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Set the position and the associated layout of the decorated control
     virtual void setLayout( GenericLayout *pLayout,
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 );
 }
 
 
index ac31b9944fb3a225b1b80f5df34827be1587788b..df010a5e6951e9c15d180015876402ae263ebaec 100644 (file)
@@ -32,6 +32,7 @@
 
 
 class GenericBitmap;
+class ScaledBitmap;
 class OSGraphics;
 class VarPercent;
 
@@ -58,7 +59,18 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
+
+    /// Called when the position is set
+    virtual void onPositionChange();
+
+    /// Method called when the control is resized
+    virtual void onResize();
+
+    /// Method called to notify are to be updated
+    virtual void notifyLayout( int witdh = -1, int height = -1,
+                               int xOffSet = 0, int yOffSet = 0 );
+
 
     /// Get the text of the tooltip
     virtual UString getTooltipText() const { return m_tooltip; }
@@ -77,6 +89,7 @@ private:
     int m_width, m_height;
     /// Position of the cursor
     int m_xPosition, m_yPosition;
+    rect m_currentCursorRect;
     /// Callback objects
     DEFINE_CALLBACK( CtrlSliderCursor, OverDown )
     DEFINE_CALLBACK( CtrlSliderCursor, DownOver )
@@ -104,7 +117,7 @@ private:
     void getResizeFactors( float &rFactorX, float &rFactorY ) const;
 
     /// Call notifyLayout
-    void refreshLayout();
+    void refreshLayout( bool force = true );
 };
 
 
@@ -123,7 +136,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Handle an event
     virtual void handleEvent( EvtGeneric &rEvent );
@@ -150,6 +163,8 @@ private:
     int m_width, m_height;
     /// Background image sequence (optional)
     GenericBitmap *m_pImgSeq;
+    /// Scaled bitmap if needed
+    ScaledBitmap *m_pScaledBmp;
     /// Number of images in the background bitmap
     int m_nbHoriz, m_nbVert;
     /// Number of pixels between two images
index 867c6612367d814e530e8bbb486b1d412325b6dd..513028fe7cd91a58e6e1d6f6b1f8acd019e50688 100644 (file)
@@ -150,8 +150,10 @@ bool CtrlText::mouseOver( int x, int y ) const
 }
 
 
-void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
 {
+    rect clip( xDest, yDest, w, h );
+    const Position *pPos = getPosition();
     if( m_pCurrImg )
     {
         // Compute the dimensions to draw
@@ -178,12 +180,18 @@ void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
             else if( m_alignment == kCenter &&
                      width < getPosition()->getWidth() )
             {
-                    // The text is shorter than the width of the control, so we
-                    // can center it
+                // The text is shorter than the width of the control, so we
+                // can center it
                 offset = (getPosition()->getWidth() - width) / 2;
             }
-            rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest + offset,
-                               yDest, width, height, true );
+            rect region( pPos->getLeft() + offset,
+                         pPos->getTop(), width, height );
+            rect inter;
+            if( rect::intersect( region, clip, &inter ) )
+                rImage.drawBitmap( *m_pCurrImg, -m_xPos + inter.x - region.x,
+                                   inter.y - region.y,
+                                   inter.x, inter.y,
+                                   inter.width, inter.height, true );
         }
     }
 }
index eafdb8e1b9083d1bbda04dc156f90646b3bf3289..c0a35bb61911f5b2fe1604ee3a120d9e0ecaec27 100644 (file)
@@ -74,7 +74,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Set the text of the control, with an optional color
     /// This takes effect immediatly
index 27ffdd29d61c719171541247aada8157e1864b0c..b816d02b3f179b115ed918ff16b31006bf6dbc78 100644 (file)
@@ -636,10 +636,19 @@ bool CtrlTree::mouseOver( int x, int y ) const
         x >= 0 && x <= pPos->getWidth() && y >= 0 && y <= pPos->getHeight();
 }
 
-void CtrlTree::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlTree::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h)
 {
-    if( m_pImage )
-        rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
+    const Position *pPos = getPosition();
+    rect region( pPos->getLeft(), pPos->getTop(),
+                 pPos->getWidth(), pPos->getHeight() );
+    rect clip( xDest, yDest, w, h );
+    rect inter;
+
+    if( rect::intersect( region, clip, &inter ) && m_pImage )
+        rImage.drawGraphics( *m_pImage,
+                      inter.x - pPos->getLeft(),
+                      inter.y - pPos->getTop(),
+                      inter.x, inter.y, inter.width, inter.height );
 }
 
 bool CtrlTree::ensureVisible( VarTree::Iterator item )
index 76e43a2a827d698b94b643527b9a5b98afc405be..44ff222ffe8782edee9fe2846dd58e2bbaf16f44 100644 (file)
@@ -62,7 +62,7 @@ public:
     virtual bool mouseOver( int x, int y ) const;
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Called when the layout is resized
     virtual void onResize();
index 823cac46894955bf62fc484cef9de64c9bad1d90..5008d6de3ac3a3701fb935b332ad07cfcc884745 100644 (file)
@@ -85,14 +85,25 @@ void CtrlVideo::onPositionChange()
 }
 
 
-void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest )
+void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h)
 {
     const Position *pPos = getPosition();
-    if( pPos )
+    rect region( pPos->getLeft(), pPos->getTop(),
+                 pPos->getWidth(), pPos->getHeight() );
+    rect clip( xDest, yDest, w, h );
+    rect inter;
+
+    if( rect::intersect( region, clip, &inter ) )
     {
         // Draw a black rectangle under the video to avoid transparency
-        rImage.fillRect( pPos->getLeft(), pPos->getTop(), pPos->getWidth(),
-                         pPos->getHeight(), 0 );
+        rImage.fillRect( inter.x, inter.y, inter.width, inter.height, 0 );
+    }
+
+    if( m_pVoutWindow )
+    {
+        m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
+        m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
+        m_pVoutWindow->show();
     }
 }
 
index 2f9a19bb0bd323cfea1b0b2222ee49d2884ad980..1b5d37d4ec45f26212ee4db61d26f25555f477b1 100644 (file)
@@ -51,7 +51,7 @@ public:
     virtual void onPositionChange();
 
     /// Draw the control on the given graphics
-    virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+    virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
 
     /// Get the type of control (custom RTTI)
     virtual string getType() const { return "video"; }
index f09da66db806d1cfc06b0226f7a25e70b0afafef..32880183edd42f4af9224387e140b9df9bacb572 100644 (file)
@@ -69,7 +69,8 @@ void AnimBitmap::stopAnim()
 }
 
 
-void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest )
+void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h,
+                       int xOffset, int yOffset )
 {
     // Draw the current frame
     int height = m_pImage->getHeight() / m_nbFrames;
@@ -79,9 +80,9 @@ void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest )
     // rImage.drawGraphics( *m_pImage, 0, ySrc, xDest, yDest,
     //                      m_pImage->getWidth(), height );
 
-    // A new way .... needs to be tested thoroughly
-    rImage.drawBitmap( m_rBitmap, 0, ySrc, xDest, yDest,
-                       m_pImage->getWidth(), height, true );
+    rImage.drawBitmap( m_rBitmap,
+                       xOffset, ySrc + yOffset,
+                       xDest, yDest, w, h, true );
 }
 
 
index 6667ce118c51b2dd39db824ad985e233231bfb75..bc005a784f541db23a82061b2bcbb54e3af13fc5 100644 (file)
@@ -49,7 +49,7 @@ public:
     void stopAnim();
 
     /// Draw the current frame on another graphics
-    void draw( OSGraphics &rImage, int xDest, int yDest );
+    void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h, int xOffset = 0, int yOffset = 0 );
 
     /// Tell whether the pixel at the given position is visible
     bool hit( int x, int y ) const;
index 731d8dd75c1fe87147fb2f7c0e2348ea4d599914..cd7f6e2c280a3389be508ccdfa16772194b2bb74 100644 (file)
@@ -109,10 +109,6 @@ void GenericLayout::addControl( CtrlGeneric *pControl,
         // Associate this layout to the control
         pControl->setLayout( this, rPosition );
 
-        // Draw the control
-        if( pControl->isVisible() )
-            pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
-
         // Add the control in the list.
         // This list must remain sorted by layer order
         list<LayeredControl>::iterator it;
@@ -153,19 +149,23 @@ void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
                                      int width, int height,
                                      int xOffSet, int yOffSet )
 {
-    // The size is not valid, refresh the whole layout
-    if( width <= 0 || height <= 0 )
-    {
-        refreshAll();
+    // Do nothing if the layout or control is hidden
+    if( !m_visible )
         return;
-    }
 
     const Position *pPos = rCtrl.getPosition();
-    if( pPos )
+    if( width > 0 && height > 0 )
     {
-        refreshRect( pPos->getLeft() + xOffSet,
+        // make sure region is within the layout
+        rect region( pPos->getLeft() + xOffSet,
                      pPos->getTop() + yOffSet,
                      width, height );
+        rect layout( 0, 0, m_rect.getWidth(), m_rect.getHeight() );
+        rect inter;
+        if( rect::intersect( layout, region, &inter ) )
+        {
+            refreshRect( inter.x, inter.y, inter.width, inter.height );
+        }
     }
 }
 
@@ -223,10 +223,9 @@ void GenericLayout::refreshRect( int x, int y, int width, int height )
     for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
     {
         CtrlGeneric *pCtrl = (*iter).m_pControl;
-        const Position *pPos = pCtrl->getPosition();
-        if( pPos && pCtrl->isVisible() )
+        if( pCtrl->isVisible() )
         {
-            pCtrl->draw( *m_pImage, pPos->getLeft(), pPos->getTop() );
+            pCtrl->draw( *m_pImage, x, y, width, height );
         }
     }
 
@@ -237,16 +236,6 @@ void GenericLayout::refreshRect( int x, int y, int width, int height )
         // first apply new shape to the window
         pWindow->updateShape();
 
-        // Check boundaries
-        if( x < 0 )
-            x = 0;
-        if( y < 0)
-            y = 0;
-        if( x + width > m_rect.getWidth() )
-            width = m_rect.getWidth() - x;
-        if( y + height > m_rect.getHeight() )
-            height = m_rect.getHeight() - y;
-
         pWindow->refresh( x, y, width, height );
     }
 }
index 4d2aa29c25b9e6bb1bbcceab46d27c5c21591215..2a7e815210c2ee832df7f41cfab0e524e96fb1ff 100644 (file)
@@ -93,4 +93,110 @@ private:
 };
 
 
+class rect
+{
+public:
+    rect( int v_x = 0, int v_y = 0, int v_width = 0, int v_height = 0 )
+        : x( v_x ), y( v_y ), width( v_width ), height( v_height ) { }
+    ~rect() { }
+    int x;
+    int y;
+    int width;
+    int height;
+
+    // rect2 fully included in rect1
+    static bool isIncluded( rect& rect2, rect& rect1 )
+    {
+        int x1 = rect1.x;
+        int y1 = rect1.y;
+        int w1 = rect1.width;
+        int h1 = rect1.height;
+
+        int x2 = rect2.x;
+        int y2 = rect2.y;
+        int w2 = rect2.width;
+        int h2 = rect2.height;
+
+        return     x2 >= x1 && x2 < x1 + w1
+               &&  y2 >= y1 && y2 < y1 + h1
+               &&  w2 <= w1
+               &&  h2 <= h1;
+    }
+
+    static bool areDisjunct( rect& rect2, rect& rect1 )
+    {
+        int x1 = rect1.x;
+        int y1 = rect1.y;
+        int w1 = rect1.width;
+        int h1 = rect1.height;
+
+        int x2 = rect2.x;
+        int y2 = rect2.y;
+        int w2 = rect2.width;
+        int h2 = rect2.height;
+
+        return    y2 + h2 -1 < y1  // rect2 above rect1
+               || y2 > y1 + h1 - 1  // rect2 under rect1
+               || x2 > x1 + w1 -1  // rect2 right of rect1
+               || x2 + w2 - 1 < x1; // rect2 left of rect1
+    }
+
+    static bool intersect( rect& rect1, rect& rect2, rect* pRect )
+    {
+        int x1 = rect1.x;
+        int y1 = rect1.y;
+        int w1 = rect1.width;
+        int h1 = rect1.height;
+
+        int x2 = rect2.x;
+        int y2 = rect2.y;
+        int w2 = rect2.width;
+        int h2 = rect2.height;
+
+        if( areDisjunct( rect1, rect2 ) )
+            return false;
+        else
+        {
+            int left = max( x1, x2 );
+            int right = min( x1 + w1 - 1, x2 + w2 - 1 );
+            int top = max( y1, y2 );
+            int bottom = min( y1 + h1 - 1, y2 + h2 -1 );
+            pRect->x = left;
+            pRect->y = top;
+            pRect->width = right - left + 1;
+            pRect->height = bottom - top + 1;
+
+            return pRect->width > 0 && pRect->height > 0;
+        }
+    }
+
+    static bool join( rect& rect1, rect& rect2, rect* pRect )
+    {
+        int x1 = rect1.x;
+        int y1 = rect1.y;
+        int w1 = rect1.width;
+        int h1 = rect1.height;
+
+        int x2 = rect2.x;
+        int y2 = rect2.y;
+        int w2 = rect2.width;
+        int h2 = rect2.height;
+
+        int left = min( x1, x2 );
+        int right = max( x1 + w1 - 1, x2 + w2 - 1 );
+        int top = min( y1, y2 );
+        int bottom = max( y1 + h1 - 1, y2 + h2 -1 );
+        pRect->x = left;
+        pRect->y = top;
+        pRect->width = right - left + 1;
+        pRect->height = bottom - top + 1;
+
+        return pRect->width > 0 && pRect->height > 0;
+    }
+    static int min( int x, int y ) { return x < y ? x : y; }
+    static int max( int x, int y ) { return x < y ? y : x; }
+
+};
+
+
 #endif