]> git.sesse.net Git - vlc/blob - modules/gui/skins2/src/generic_layout.cpp
* modules/gui/wxwidgets/dialogs/playlist.cpp: remove fprintf()s and compilation warnings.
[vlc] / modules / gui / skins2 / src / generic_layout.cpp
1 /*****************************************************************************
2  * generic_layout.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
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"
30 #include "../controls/ctrl_generic.hpp"
31 #include "../controls/ctrl_video.hpp"
32 #include "../utils/var_bool.hpp"
33
34
35 GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
36                               int minWidth, int maxWidth, int minHeight,
37                               int maxHeight ):
38     SkinObject( pIntf ), m_pWindow( NULL ), m_width( width ),
39     m_height( height ), m_minWidth( minWidth ), m_maxWidth( maxWidth ),
40     m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_pVideoControl( NULL ),
41     m_visible( false ), m_pVarActive( NULL )
42 {
43     // Get the OSFactory
44     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
45     // Create the graphics buffer
46     m_pImage = pOsFactory->createOSGraphics( width, height );
47
48     // Create the "active layout" variable and register it in the manager
49     m_pVarActive = new VarBoolImpl( pIntf );
50     VarManager::instance( pIntf )->registerVar( VariablePtr( m_pVarActive ) );
51 }
52
53
54 GenericLayout::~GenericLayout()
55 {
56     if( m_pImage )
57     {
58         delete m_pImage;
59     }
60 }
61
62
63 void GenericLayout::setWindow( TopWindow *pWindow )
64 {
65     m_pWindow = pWindow;
66 }
67
68
69 void GenericLayout::onControlCapture( const CtrlGeneric &rCtrl )
70 {
71     // Just forward the request to the window
72     TopWindow *pWindow = getWindow();
73     if( pWindow )
74     {
75         pWindow->onControlCapture( rCtrl );
76     }
77 }
78
79
80 void GenericLayout::onControlRelease( const CtrlGeneric &rCtrl )
81 {
82     // Just forward the request to the window
83     TopWindow *pWindow = getWindow();
84     if( pWindow )
85     {
86         pWindow->onControlRelease( rCtrl );
87     }
88 }
89
90
91 void GenericLayout::addControl( CtrlGeneric *pControl,
92                                 const Position &rPosition, int layer )
93 {
94     if( pControl )
95     {
96         // Associate this layout to the control
97         pControl->setLayout( this, rPosition );
98
99         // Draw the control
100         pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
101
102         // Add the control in the list.
103         // This list must remain sorted by layer order 
104         list<LayeredControl>::iterator it;
105         for( it = m_controlList.begin(); it != m_controlList.end(); it++ )
106         {
107             if( layer < (*it).m_layer )
108             {
109                 m_controlList.insert( it, LayeredControl( pControl, layer ) );
110                 break;
111             }
112         }
113         // If this control is in front of all the previous ones
114         if( it == m_controlList.end() )
115         {
116             m_controlList.push_back( LayeredControl( pControl, layer ) );
117         }
118
119         // Check if it is a video control
120         if( pControl->getType() == "video" )
121         {
122             m_pVideoControl = (CtrlVideo*)pControl;
123         }
124     }
125     else
126     {
127         msg_Dbg( getIntf(), "adding NULL control in the layout" );
128     }
129 }
130
131
132 const list<LayeredControl> &GenericLayout::getControlList() const
133 {
134     return m_controlList;
135 }
136
137
138 void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
139                                      int width, int height,
140                                      int xOffSet, int yOffSet )
141 {
142     // The size is not valid, refresh the whole layout
143     if( width <= 0 || height <= 0 )
144     {
145         refreshAll();
146         return;
147     }
148
149     const Position *pPos = rCtrl.getPosition();
150     if( pPos )
151     {
152         refreshRect( pPos->getLeft() + xOffSet,
153                      pPos->getTop() + yOffSet,
154                      width, height );
155     }
156 }
157
158
159 void GenericLayout::resize( int width, int height )
160 {
161     // Update the window size
162     m_width = width;
163     m_height = height;
164
165     // Recreate a new image
166     if( m_pImage )
167     {
168         delete m_pImage;
169         OSFactory *pOsFactory = OSFactory::instance( getIntf() );
170         m_pImage = pOsFactory->createOSGraphics( width, height );
171     }
172
173     // Notify all the controls that the size has changed and redraw them
174     list<LayeredControl>::const_iterator iter;
175     for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
176     {
177         iter->m_pControl->onResize();
178     }
179
180     // Resize and refresh the associated window
181     TopWindow *pWindow = getWindow();
182     if( pWindow )
183     {
184         // Resize the window
185         pWindow->resize( width, height );
186         refreshAll();
187         // Change the shape of the window and redraw it
188         pWindow->updateShape();
189         refreshAll();
190     }
191 }
192
193
194 void GenericLayout::refreshAll()
195 {
196     refreshRect( 0, 0, m_width, m_height );
197 }
198
199
200 void GenericLayout::refreshRect( int x, int y, int width, int height )
201 {
202     // Do nothing if the layout is hidden
203     if( !m_visible )
204         return;
205
206     // Draw all the controls of the layout
207     list<LayeredControl>::const_iterator iter;
208     list<LayeredControl>::const_iterator iterVideo = m_controlList.end();
209     for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
210     {
211         CtrlGeneric *pCtrl = (*iter).m_pControl;
212         const Position *pPos = pCtrl->getPosition();
213         if( pPos && pCtrl->isVisible() )
214         {
215             pCtrl->draw( *m_pImage, pPos->getLeft(), pPos->getTop() );
216         }
217     }
218
219     // Refresh the associated window
220     TopWindow *pWindow = getWindow();
221     if( pWindow )
222     {
223         // Check boundaries
224         if( x < 0 )
225             x = 0;
226         if( y < 0)
227             y = 0;
228         if( x + width > m_width )
229             width = m_width - x;
230         if( y + height > m_height )
231             height = m_height - y;
232
233         // Refresh the window... but do not paint on a visible video control!
234         if( !m_pVideoControl || !m_pVideoControl->isVisible() )
235         {
236             // No video control, we can safely repaint the rectangle
237             pWindow->refresh( x, y, width, height );
238         }
239         else
240         {
241             // Bad luck, there is a video control somewhere (not necessarily
242             // in the repainting zone, btw).
243             // We will divide the repainting into 4 regions (top, left, bottom
244             // and right). The overlapping parts (i.e. the corners) of these
245             // regions will be painted twice, because otherwise the algorithm
246             // becomes a real mess :)
247
248             // Use short variable names for convenience
249             int xx = m_pVideoControl->getPosition()->getLeft();
250             int yy = m_pVideoControl->getPosition()->getTop();
251             int ww = m_pVideoControl->getPosition()->getWidth();
252             int hh = m_pVideoControl->getPosition()->getHeight();
253
254             // Top part:
255             if( y < yy )
256                 pWindow->refresh( x, y, width, yy - y );
257             // Left part:
258             if( x < xx )
259                 pWindow->refresh( x, y, xx - x, height );
260             // Bottom part
261             if( y + height > yy + hh )
262                 pWindow->refresh( x, yy + hh, width, y + height - (yy + hh) );
263             // Right part
264             if( x + width > xx + ww )
265                 pWindow->refresh( xx + ww, y, x + width - (xx + ww), height );
266         }
267     }
268 }
269
270
271 const list<Anchor*>& GenericLayout::getAnchorList() const
272 {
273     return m_anchorList;
274 }
275
276
277 void GenericLayout::addAnchor( Anchor *pAnchor )
278 {
279     m_anchorList.push_back( pAnchor );
280 }
281
282
283 void GenericLayout::onShow()
284 {
285     m_visible = true;
286
287     refreshAll();
288     // TODO find a better way to handle the vout ?
289     if( m_pVideoControl )
290     {
291         m_pVideoControl->setVisible( true );
292     }
293 }
294
295
296 void GenericLayout::onHide()
297 {
298     m_visible = false;
299
300     // TODO find a better way to handle the vout ?
301     if( m_pVideoControl )
302     {
303         m_pVideoControl->setVisible( false );
304     }
305 }
306