1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
7 * Authors: Cyril Deguet <asmax@via.ecp.fr>
8 * Olivier Teulière <ipkiss@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 #include "generic_layout.hpp"
26 #include "top_window.hpp"
27 #include "os_factory.hpp"
28 #include "os_graphics.hpp"
29 #include "../controls/ctrl_generic.hpp"
32 GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
33 int minWidth, int maxWidth, int minHeight,
35 SkinObject( pIntf ), m_pWindow( NULL ), m_width( width ),
36 m_height( height ), m_minWidth( minWidth ), m_maxWidth( maxWidth ),
37 m_minHeight( minHeight ), m_maxHeight( maxHeight )
40 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
41 // Create the graphics buffer
42 m_pImage = pOsFactory->createOSGraphics( width, height );
46 GenericLayout::~GenericLayout()
55 void GenericLayout::setWindow( TopWindow *pWindow )
61 void GenericLayout::onControlCapture( const CtrlGeneric &rCtrl )
63 // Just forward the request to the window
64 TopWindow *pWindow = getWindow();
67 pWindow->onControlCapture( rCtrl );
72 void GenericLayout::onControlRelease( const CtrlGeneric &rCtrl )
74 // Just forward the request to the window
75 TopWindow *pWindow = getWindow();
78 pWindow->onControlRelease( rCtrl );
83 void GenericLayout::addControl( CtrlGeneric *pControl,
84 const Position &rPosition, int layer )
88 // Associate this layout to the control
89 pControl->setLayout( this, rPosition );
92 pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
94 // Add the control in the list.
95 // This list must remain sorted by layer order
96 list<LayeredControl>::iterator it;
97 for( it = m_controlList.begin(); it != m_controlList.end(); it++ )
99 if( layer < (*it).m_layer )
101 m_controlList.insert( it, LayeredControl( pControl, layer ) );
105 // If this control is in front of all the previous ones
106 if( it == m_controlList.end() )
108 m_controlList.push_back( LayeredControl( pControl, layer ) );
113 msg_Dbg( getIntf(), "Adding NULL control in the layout" );
118 const list<LayeredControl> &GenericLayout::getControlList() const
120 return m_controlList;
124 void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
125 int width, int height,
126 int xOffSet, int yOffSet )
128 // The size is not valid, refresh the whole layout
129 if( width <= 0 || height <= 0 )
135 const Position *pPos = rCtrl.getPosition();
138 refreshRect( pPos->getLeft() + xOffSet,
139 pPos->getTop() + yOffSet,
145 void GenericLayout::resize( int width, int height )
147 if( width == m_width && height == m_height )
152 // Update the window size
156 // Recreate a new image
160 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
161 m_pImage = pOsFactory->createOSGraphics( width, height );
164 // Notify all the controls that the size has changed and redraw them
165 list<LayeredControl>::const_iterator iter;
166 for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
168 (*iter).m_pControl->onResize();
169 const Position *pPos = (*iter).m_pControl->getPosition();
172 (*iter).m_pControl->draw( *m_pImage, pPos->getLeft(),
177 // Resize and refresh the associated window
178 TopWindow *pWindow = getWindow();
182 pWindow->refresh( 0, 0, width, height );
183 pWindow->resize( width, height );
184 pWindow->refresh( 0, 0, width, height );
186 // Change the shape of the window and redraw it
187 pWindow->updateShape();
188 pWindow->refresh( 0, 0, width, height );
193 void GenericLayout::refreshAll()
195 refreshRect( 0, 0, m_width, m_height );
199 void GenericLayout::refreshRect( int x, int y, int width, int height )
201 // Draw all the controls of the layout
202 list<LayeredControl>::const_iterator iter;
203 list<LayeredControl>::const_iterator iterVideo = m_controlList.end();
204 for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
206 CtrlGeneric *pCtrl = (*iter).m_pControl;
207 const Position *pPos = pCtrl->getPosition();
208 if( pCtrl->isVisible() && pPos )
210 pCtrl->draw( *m_pImage, pPos->getLeft(), pPos->getTop() );
211 // Remember the video control (we assume there is at most one video
212 // control per layout)
213 if( pCtrl->getType() == "video" && pCtrl->getPosition() )
218 // Refresh the associated window
219 TopWindow *pWindow = getWindow();
227 if( x + width > m_width )
229 if( y + height > m_height )
230 height = m_height - y;
232 // Refresh the window... but do not paint on a video control!
233 if( iterVideo == m_controlList.end() )
235 // No video control, we can safely repain the rectangle
236 pWindow->refresh( x, y, width, height );
240 // Bad luck, there is a video control somewhere (not necessarily
241 // in the repainting zone, btw).
242 // We will divide the repainting into 4 regions (top, left, bottom
243 // and right). The overlapping parts (i.e. the corners) of these
244 // regions will be painted twice, because otherwise the algorithm
245 // becomes a real mess :)
247 // Use short variable names for convenience
248 int xx = iterVideo->m_pControl->getPosition()->getLeft();
249 int yy = iterVideo->m_pControl->getPosition()->getTop();
250 int ww = iterVideo->m_pControl->getPosition()->getWidth();
251 int hh = iterVideo->m_pControl->getPosition()->getHeight();
255 pWindow->refresh( x, y, width, yy - y );
258 pWindow->refresh( x, y, xx - x, height );
260 if( y + height > yy + hh )
261 pWindow->refresh( x, yy + hh, width, y + height - (yy + hh) );
263 if( x + width > xx + ww )
264 pWindow->refresh( xx + ww, y, x + width - (xx + ww), height );
270 const list<Anchor*>& GenericLayout::getAnchorList() const
276 void GenericLayout::addAnchor( Anchor *pAnchor )
278 m_anchorList.push_back( pAnchor );