Commit a1921136 authored by Erwan Tulou's avatar Erwan Tulou

skins2: improve refresh of layouts

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.
parent 6fad8bff
...@@ -114,16 +114,22 @@ bool CtrlButton::mouseOver( int x, int y ) const ...@@ -114,16 +114,22 @@ bool CtrlButton::mouseOver( int x, int y ) const
} }
void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest ) void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{ {
if( m_pImg ) 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 // 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 ) void CtrlButton::setImage( AnimBitmap *pImg )
{ {
AnimBitmap *pOldImg = m_pImg; AnimBitmap *pOldImg = m_pImg;
...@@ -147,7 +153,7 @@ void CtrlButton::setImage( AnimBitmap *pImg ) ...@@ -147,7 +153,7 @@ void CtrlButton::setImage( AnimBitmap *pImg )
void CtrlButton::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg ) void CtrlButton::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg )
{ {
notifyLayout(); notifyLayout( m_pImg->getWidth(), m_pImg->getHeight() );
} }
......
...@@ -57,7 +57,7 @@ public: ...@@ -57,7 +57,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Get the text of the tooltip
virtual UString getTooltipText() const { return m_tooltip; } virtual UString getTooltipText() const { return m_tooltip; }
......
...@@ -134,12 +134,25 @@ bool CtrlCheckbox::mouseOver( int x, int y ) const ...@@ -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 // 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 ) ...@@ -248,7 +261,7 @@ void CtrlCheckbox::onVarBoolUpdate( VarBool &rVariable )
void CtrlCheckbox::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg ) void CtrlCheckbox::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg )
{ {
notifyLayout(); notifyLayout( m_pImgCurrent->getWidth(), m_pImgCurrent->getHeight() );
} }
......
...@@ -61,7 +61,7 @@ public: ...@@ -61,7 +61,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Get the text of the tooltip XXX
virtual UString getTooltipText() const { return *m_pTooltip; } virtual UString getTooltipText() const { return *m_pTooltip; }
......
...@@ -74,8 +74,11 @@ void CtrlGeneric::unsetLayout() ...@@ -74,8 +74,11 @@ void CtrlGeneric::unsetLayout()
} }
void CtrlGeneric::notifyLayout( int width, int height, 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 // Notify the layout
if( m_pLayout ) if( m_pLayout )
{ {
......
...@@ -53,7 +53,7 @@ public: ...@@ -53,7 +53,7 @@ public:
virtual bool mouseOver( int x, int y ) const { return false; } virtual bool mouseOver( int x, int y ) const { return false; }
/// Draw the control on the given graphics /// 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 /// Set the position and the associated layout of the control
virtual void setLayout( GenericLayout *pLayout, virtual void setLayout( GenericLayout *pLayout,
...@@ -96,7 +96,7 @@ protected: ...@@ -96,7 +96,7 @@ protected:
* Use the default values to repaint the whole window * Use the default values to repaint the whole window
*/ */
virtual void notifyLayout( int witdh = -1, int height = -1, 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. * Same as notifyLayout(), but takes optional images as parameters.
......
...@@ -118,7 +118,7 @@ bool CtrlImage::mouseOver( int x, int y ) const ...@@ -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(); const Position *pPos = getPosition();
if( !pPos ) if( !pPos )
...@@ -129,6 +129,13 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest ) ...@@ -129,6 +129,13 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
if( width <= 0 || height <= 0 ) if( width <= 0 || height <= 0 )
return; 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 ) if( m_resizeMethod == kScale )
{ {
// Use scaling method // Use scaling method
...@@ -142,25 +149,40 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest ) ...@@ -142,25 +149,40 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
m_pImage = pOsFactory->createOSGraphics( width, height ); m_pImage = pOsFactory->createOSGraphics( width, height );
m_pImage->drawBitmap( bmp, 0, 0 ); 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 ) else if( m_resizeMethod == kMosaic )
{ {
int xDest0 = pPos->getLeft();
int yDest0 = pPos->getTop();
// Use mosaic method // Use mosaic method
while( width > 0 ) while( width > 0 )
{ {
int curWidth = __MIN( width, m_pImage->getWidth() ); int curWidth = __MIN( width, m_pImage->getWidth() );
height = pPos->getHeight(); height = pPos->getHeight();
int curYDest = yDest; int curYDest = yDest0;
while( height > 0 ) while( height > 0 )
{ {
int curHeight = __MIN( height, m_pImage->getHeight() ); int curHeight = __MIN( height, m_pImage->getHeight() );
rImage.drawGraphics( *m_pImage, 0, 0, xDest, curYDest, rect region1( xDest0, curYDest, curWidth, curHeight );
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; curYDest += curHeight;
height -= m_pImage->getHeight(); height -= m_pImage->getHeight();
} }
xDest += curWidth; xDest0 += curWidth;
width -= m_pImage->getWidth(); width -= m_pImage->getWidth();
} }
} }
...@@ -202,7 +224,16 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest ) ...@@ -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 // 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 );
}
} }
} }
......
...@@ -60,7 +60,7 @@ public: ...@@ -60,7 +60,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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) /// Get the type of control (custom RTTI)
virtual string getType() const { return "image"; } virtual string getType() const { return "image"; }
......
...@@ -349,11 +349,19 @@ bool CtrlList::mouseOver( int x, int y ) const ...@@ -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 );
} }
} }
......
...@@ -53,7 +53,7 @@ public: ...@@ -53,7 +53,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Called when the layout is resized
virtual void onResize(); virtual void onResize();
......
...@@ -66,9 +66,9 @@ bool CtrlMove::mouseOver( int x, int y ) const ...@@ -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 );
} }
......
...@@ -49,7 +49,7 @@ public: ...@@ -49,7 +49,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Set the position and the associated layout of the decorated control
virtual void setLayout( GenericLayout *pLayout, virtual void setLayout( GenericLayout *pLayout,
......
...@@ -90,18 +90,33 @@ bool CtrlRadialSlider::mouseOver( int x, int y ) const ...@@ -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, const Position *pPos = getPosition();
m_width, m_height ); 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 CtrlRadialSlider::onUpdate( Subject<VarPercent> &rVariable,
void *arg ) void *arg )
{ {
m_position = (int)( m_rVariable.get() * ( m_numImg - 1 ) ); if( &rVariable == &m_rVariable )
notifyLayout( m_width, m_height ); {
int position = (int)( m_rVariable.get() * ( m_numImg - 1 ) );
if( position == m_position )
return;
m_position = position;
notifyLayout( m_width, m_height );
}
} }
......
...@@ -55,7 +55,7 @@ public: ...@@ -55,7 +55,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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) /// Get the type of control (custom RTTI)
virtual string getType() const { return "radial_slider"; } virtual string getType() const { return "radial_slider"; }
......
...@@ -75,9 +75,9 @@ bool CtrlResize::mouseOver( int x, int y ) const ...@@ -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 );
} }
......
...@@ -50,7 +50,7 @@ public: ...@@ -50,7 +50,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Set the position and the associated layout of the decorated control
virtual void setLayout( GenericLayout *pLayout, virtual void setLayout( GenericLayout *pLayout,
......
...@@ -143,24 +143,65 @@ bool CtrlSliderCursor::mouseOver( int x, int y ) const ...@@ -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 ) if( m_pImg )
{ {
// Compute the position of the cursor // Draw the current image
int xPos, yPos; rect inter;
m_rCurve.getPoint( m_rVariable.get(), xPos, yPos ); 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 void CtrlSliderCursor::onPositionChange()
rImage.drawGraphics( *m_pImg, 0, 0, {
xDest + xPos - m_pImg->getWidth() / 2, // Compute the position of the cursor
yDest + yPos - m_pImg->getHeight() / 2 ); 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, ...@@ -169,7 +210,7 @@ void CtrlSliderCursor::onUpdate( Subject<VarPercent> &rVariable,
void *arg ) void *arg )
{ {
// The position has changed // The position has changed
refreshLayout(); refreshLayout( false );
} }
...@@ -280,20 +321,42 @@ void CtrlSliderCursor::getResizeFactors( float &rFactorX, ...@@ -280,20 +321,42 @@ void CtrlSliderCursor::getResizeFactors( float &rFactorX,
} }
void CtrlSliderCursor::refreshLayout() void CtrlSliderCursor::refreshLayout( bool force )
{ {
if( !m_pImg ) // Compute the position of the cursor
notifyLayout(); int xPos, yPos;
else 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 return;
float factorX, factorY; }
getResizeFactors( factorX, factorY );
notifyLayout( (int)(m_rCurve.getWidth() * factorX) + m_pImg->getWidth(), rect join;
(int)(m_rCurve.getHeight() * factorY) + m_pImg->getHeight(), if( rect::join( m_currentCursorRect, region, &join ) )
- m_pImg->getWidth() / 2, {
- m_pImg->getHeight() / 2 ); 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, ...@@ -308,9 +371,9 @@ CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ), m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
m_pImgSeq( pBackground ), m_nbHoriz( nbHoriz ), m_nbVert( nbVert ), m_pImgSeq( pBackground ), m_nbHoriz( nbHoriz ), m_nbVert( nbVert ),
m_padHoriz( padHoriz ), m_padVert( padVert ), m_bgWidth( 0 ), 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 // Build the background image sequence
// Note: we suppose that the last padding is not included in the // Note: we suppose that the last padding is not included in the
...@@ -332,7 +395,10 @@ CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf, ...@@ -332,7 +395,10 @@ CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
CtrlSliderBg::~CtrlSliderBg() 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 ...@@ -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 ) if( !m_pImgSeq || m_bgWidth <=0 || m_bgHeight <= 0 )
return; return;
...@@ -356,18 +422,35 @@ void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest ) ...@@ -356,18 +422,35 @@ void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest )
float factorX, factorY; float factorX, factorY;
getResizeFactors( factorX, factorY ); getResizeFactors( factorX, factorY );
// Rescale the image with the actual size of the control int width = m_bgWidth * m_nbHoriz - (int)(m_padHoriz * factorX);
ScaledBitmap bmp( getIntf(), *m_pImgSeq, int height = m_bgHeight * m_nbVert - (int)(m_padVert * factorY);
m_bgWidth * m_nbHoriz - (int)(m_padHoriz * factorX),
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 // Locate the right image in the background bitmap
int x = m_bgWidth * ( m_position % m_nbHoriz ); int x = m_bgWidth * ( m_position % m_nbHoriz );
int y = m_bgHeight * ( m_position / m_nbHoriz ); int y = m_bgHeight * ( m_position / m_nbHoriz );
// Draw the background image // Draw the background image
rImage.drawBitmap( bmp, x, y, xDest, yDest, const Position *pPos = getPosition();
m_bgWidth - (int)(m_padHoriz * factorX), rect region( pPos->getLeft(), pPos->getTop(),
m_bgHeight - (int)(m_padVert * factorY) ); 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 );
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
class GenericBitmap; class GenericBitmap;
class ScaledBitmap;
class OSGraphics; class OSGraphics;
class VarPercent; class VarPercent;
...@@ -58,7 +59,18 @@ public: ...@@ -58,7 +59,18 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Get the text of the tooltip
virtual UString getTooltipText() const { return m_tooltip; } virtual UString getTooltipText() const { return m_tooltip; }
...@@ -77,6 +89,7 @@ private: ...@@ -77,6 +89,7 @@ private:
int m_width, m_height; int m_width, m_height;
/// Position of the cursor /// Position of the cursor
int m_xPosition, m_yPosition; int m_xPosition, m_yPosition;
rect m_currentCursorRect;
/// Callback objects /// Callback objects
DEFINE_CALLBACK( CtrlSliderCursor, OverDown ) DEFINE_CALLBACK( CtrlSliderCursor, OverDown )
DEFINE_CALLBACK( CtrlSliderCursor, DownOver ) DEFINE_CALLBACK( CtrlSliderCursor, DownOver )
...@@ -104,7 +117,7 @@ private: ...@@ -104,7 +117,7 @@ private:
void getResizeFactors( float &rFactorX, float &rFactorY ) const; void getResizeFactors( float &rFactorX, float &rFactorY ) const;
/// Call notifyLayout /// Call notifyLayout
void refreshLayout(); void refreshLayout( bool force = true );
}; };
...@@ -123,7 +136,7 @@ public: ...@@ -123,7 +136,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Handle an event
virtual void handleEvent( EvtGeneric &rEvent ); virtual void handleEvent( EvtGeneric &rEvent );
...@@ -150,6 +163,8 @@ private: ...@@ -150,6 +163,8 @@ private:
int m_width, m_height; int m_width, m_height;
/// Background image sequence (optional) /// Background image sequence (optional)
GenericBitmap *m_pImgSeq; GenericBitmap *m_pImgSeq;
/// Scaled bitmap if needed
ScaledBitmap *m_pScaledBmp;
/// Number of images in the background bitmap /// Number of images in the background bitmap
int m_nbHoriz, m_nbVert; int m_nbHoriz, m_nbVert;
/// Number of pixels between two images /// Number of pixels between two images
......
...@@ -150,8 +150,10 @@ bool CtrlText::mouseOver( int x, int y ) const ...@@ -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 ) if( m_pCurrImg )
{ {
// Compute the dimensions to draw // Compute the dimensions to draw
...@@ -178,12 +180,18 @@ void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest ) ...@@ -178,12 +180,18 @@ void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
else if( m_alignment == kCenter && else if( m_alignment == kCenter &&
width < getPosition()->getWidth() ) width < getPosition()->getWidth() )
{ {
// The text is shorter than the width of the control, so we // The text is shorter than the width of the control, so we
// can center it // can center it
offset = (getPosition()->getWidth() - width) / 2; offset = (getPosition()->getWidth() - width) / 2;
} }
rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest + offset, rect region( pPos->getLeft() + offset,
yDest, width, height, true ); 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 );
} }
} }
} }
......
...@@ -74,7 +74,7 @@ public: ...@@ -74,7 +74,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Set the text of the control, with an optional color
/// This takes effect immediatly /// This takes effect immediatly
......
...@@ -636,10 +636,19 @@ bool CtrlTree::mouseOver( int x, int y ) const ...@@ -636,10 +636,19 @@ bool CtrlTree::mouseOver( int x, int y ) const
x >= 0 && x <= pPos->getWidth() && y >= 0 && y <= pPos->getHeight(); 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 ) const Position *pPos = getPosition();
rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest ); 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 ) bool CtrlTree::ensureVisible( VarTree::Iterator item )
......
...@@ -62,7 +62,7 @@ public: ...@@ -62,7 +62,7 @@ public:
virtual bool mouseOver( int x, int y ) const; virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics /// 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 /// Called when the layout is resized
virtual void onResize(); virtual void onResize();
......
...@@ -85,14 +85,25 @@ void CtrlVideo::onPositionChange() ...@@ -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(); 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 // Draw a black rectangle under the video to avoid transparency
rImage.fillRect( pPos->getLeft(), pPos->getTop(), pPos->getWidth(), rImage.fillRect( inter.x, inter.y, inter.width, inter.height, 0 );
pPos->getHeight(), 0 ); }
if( m_pVoutWindow )
{
m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
m_pVoutWindow->show();
} }
} }
......
...@@ -51,7 +51,7 @@ public: ...@@ -51,7 +51,7 @@ public:
virtual void onPositionChange(); virtual void onPositionChange();
/// Draw the control on the given graphics /// 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) /// Get the type of control (custom RTTI)
virtual string getType() const { return "video"; } virtual string getType() const { return "video"; }
......
...@@ -69,7 +69,8 @@ void AnimBitmap::stopAnim() ...@@ -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 // Draw the current frame
int height = m_pImage->getHeight() / m_nbFrames; int height = m_pImage->getHeight() / m_nbFrames;
...@@ -79,9 +80,9 @@ void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest ) ...@@ -79,9 +80,9 @@ void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest )
// rImage.drawGraphics( *m_pImage, 0, ySrc, xDest, yDest, // rImage.drawGraphics( *m_pImage, 0, ySrc, xDest, yDest,
// m_pImage->getWidth(), height ); // m_pImage->getWidth(), height );
// A new way .... needs to be tested thoroughly rImage.drawBitmap( m_rBitmap,
rImage.drawBitmap( m_rBitmap, 0, ySrc, xDest, yDest, xOffset, ySrc + yOffset,
m_pImage->getWidth(), height, true ); xDest, yDest, w, h, true );
} }
......
...@@ -49,7 +49,7 @@ public: ...@@ -49,7 +49,7 @@ public:
void stopAnim(); void stopAnim();
/// Draw the current frame on another graphics /// 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 /// Tell whether the pixel at the given position is visible
bool hit( int x, int y ) const; bool hit( int x, int y ) const;
......
...@@ -109,10 +109,6 @@ void GenericLayout::addControl( CtrlGeneric *pControl, ...@@ -109,10 +109,6 @@ void GenericLayout::addControl( CtrlGeneric *pControl,
// Associate this layout to the control // Associate this layout to the control
pControl->setLayout( this, rPosition ); pControl->setLayout( this, rPosition );
// Draw the control
if( pControl->isVisible() )
pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
// Add the control in the list. // Add the control in the list.
// This list must remain sorted by layer order // This list must remain sorted by layer order
list<LayeredControl>::iterator it; list<LayeredControl>::iterator it;
...@@ -153,19 +149,23 @@ void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl, ...@@ -153,19 +149,23 @@ void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
int width, int height, int width, int height,
int xOffSet, int yOffSet ) int xOffSet, int yOffSet )
{ {
// The size is not valid, refresh the whole layout // Do nothing if the layout or control is hidden
if( width <= 0 || height <= 0 ) if( !m_visible )
{
refreshAll();
return; return;
}
const Position *pPos = rCtrl.getPosition(); 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, pPos->getTop() + yOffSet,
width, height ); 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 ) ...@@ -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++ ) for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
{ {
CtrlGeneric *pCtrl = (*iter).m_pControl; CtrlGeneric *pCtrl = (*iter).m_pControl;
const Position *pPos = pCtrl->getPosition(); if( pCtrl->isVisible() )
if( pPos && 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 ) ...@@ -237,16 +236,6 @@ void GenericLayout::refreshRect( int x, int y, int width, int height )
// first apply new shape to the window // first apply new shape to the window
pWindow->updateShape(); 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 ); pWindow->refresh( x, y, width, height );
} }
} }
......
...@@ -93,4 +93,110 @@ private: ...@@ -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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment