1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2003 the VideoLAN team
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #include "generic_layout.hpp"
26 #include "top_window.hpp"
27 #include "os_factory.hpp"
28 #include "os_graphics.hpp"
29 #include "var_manager.hpp"
31 #include "../controls/ctrl_generic.hpp"
32 #include "../controls/ctrl_video.hpp"
33 #include "../utils/var_bool.hpp"
36 GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
37 int minWidth, int maxWidth, int minHeight,
39 SkinObject( pIntf ), m_pWindow( NULL ), m_rect( 0, 0, width, height ),
40 m_minWidth( minWidth ), m_maxWidth( maxWidth ),
41 m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_pVideoControl( NULL ),
42 m_visible( false ), m_pVarActive( NULL )
45 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
46 // Create the graphics buffer
47 m_pImage = pOsFactory->createOSGraphics( width, height );
49 // Create the "active layout" variable and register it in the manager
50 m_pVarActive = new VarBoolImpl( pIntf );
51 VarManager::instance( pIntf )->registerVar( VariablePtr( m_pVarActive ) );
55 GenericLayout::~GenericLayout()
61 list<Anchor*>::const_iterator it;
62 for( it = m_anchorList.begin(); it != m_anchorList.end(); it++ )
69 void GenericLayout::setWindow( TopWindow *pWindow )
75 void GenericLayout::onControlCapture( const CtrlGeneric &rCtrl )
77 // Just forward the request to the window
78 TopWindow *pWindow = getWindow();
81 pWindow->onControlCapture( rCtrl );
86 void GenericLayout::onControlRelease( const CtrlGeneric &rCtrl )
88 // Just forward the request to the window
89 TopWindow *pWindow = getWindow();
92 pWindow->onControlRelease( rCtrl );
97 void GenericLayout::addControl( CtrlGeneric *pControl,
98 const Position &rPosition, int layer )
102 // Associate this layout to the control
103 pControl->setLayout( this, rPosition );
106 pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
108 // Add the control in the list.
109 // This list must remain sorted by layer order
110 list<LayeredControl>::iterator it;
111 for( it = m_controlList.begin(); it != m_controlList.end(); it++ )
113 if( layer < (*it).m_layer )
115 m_controlList.insert( it, LayeredControl( pControl, layer ) );
119 // If this control is in front of all the previous ones
120 if( it == m_controlList.end() )
122 m_controlList.push_back( LayeredControl( pControl, layer ) );
125 // Check if it is a video control
126 if( pControl->getType() == "video" )
128 m_pVideoControl = (CtrlVideo*)pControl;
133 msg_Dbg( getIntf(), "adding NULL control in the layout" );
138 const list<LayeredControl> &GenericLayout::getControlList() const
140 return m_controlList;
144 void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
145 int width, int height,
146 int xOffSet, int yOffSet )
148 // The size is not valid, refresh the whole layout
149 if( width <= 0 || height <= 0 )
155 const Position *pPos = rCtrl.getPosition();
158 refreshRect( pPos->getLeft() + xOffSet,
159 pPos->getTop() + yOffSet,
165 void GenericLayout::resize( int width, int height )
167 // Update the window size
168 m_rect = SkinsRect( 0, 0 , width, height );
170 // Recreate a new image
174 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
175 m_pImage = pOsFactory->createOSGraphics( width, height );
178 // Notify all the controls that the size has changed and redraw them
179 list<LayeredControl>::const_iterator iter;
180 for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
182 iter->m_pControl->onResize();
185 // Resize and refresh the associated window
186 TopWindow *pWindow = getWindow();
190 pWindow->resize( width, height );
192 // Change the shape of the window and redraw it
193 pWindow->updateShape();
199 void GenericLayout::refreshAll()
201 refreshRect( 0, 0, m_rect.getWidth(), m_rect.getHeight() );
205 void GenericLayout::refreshRect( int x, int y, int width, int height )
207 // Do nothing if the layout is hidden
211 // Draw all the controls of the layout
212 list<LayeredControl>::const_iterator iter;
213 list<LayeredControl>::const_iterator iterVideo = m_controlList.end();
214 for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
216 CtrlGeneric *pCtrl = (*iter).m_pControl;
217 const Position *pPos = pCtrl->getPosition();
218 if( pPos && pCtrl->isVisible() )
220 pCtrl->draw( *m_pImage, pPos->getLeft(), pPos->getTop() );
224 // Refresh the associated window
225 TopWindow *pWindow = getWindow();
233 if( x + width > m_rect.getWidth() )
234 width = m_rect.getWidth() - x;
235 if( y + height > m_rect.getHeight() )
236 height = m_rect.getHeight() - y;
238 // Refresh the window... but do not paint on a visible video control!
239 if( !m_pVideoControl || !m_pVideoControl->isVisible() )
241 // No video control, we can safely repaint the rectangle
242 pWindow->refresh( x, y, width, height );
246 // Bad luck, there is a video control somewhere (not necessarily
247 // in the repainting zone, btw).
248 // We will divide the repainting into 4 regions (top, left, bottom
249 // and right). The overlapping parts (i.e. the corners) of these
250 // regions will be painted twice, because otherwise the algorithm
251 // becomes a real mess :)
253 // Use short variable names for convenience
254 int xx = m_pVideoControl->getPosition()->getLeft();
255 int yy = m_pVideoControl->getPosition()->getTop();
256 int ww = m_pVideoControl->getPosition()->getWidth();
257 int hh = m_pVideoControl->getPosition()->getHeight();
261 pWindow->refresh( x, y, width, yy - y );
264 pWindow->refresh( x, y, xx - x, height );
266 if( y + height > yy + hh )
267 pWindow->refresh( x, yy + hh, width, y + height - (yy + hh) );
269 if( x + width > xx + ww )
270 pWindow->refresh( xx + ww, y, x + width - (xx + ww), height );
276 const list<Anchor*>& GenericLayout::getAnchorList() const
282 void GenericLayout::addAnchor( Anchor *pAnchor )
284 m_anchorList.push_back( pAnchor );
288 void GenericLayout::onShow()
293 // TODO find a better way to handle the vout ?
294 if( m_pVideoControl )
296 m_pVideoControl->setVisible( true );
301 void GenericLayout::onHide()
305 // TODO find a better way to handle the vout ?
306 if( m_pVideoControl )
308 m_pVideoControl->setVisible( false );