]> git.sesse.net Git - vlc/blob - modules/gui/skins2/controls/ctrl_checkbox.cpp
f0daae0e1d8e6f99d5051b4abf0d22977c0f96f1
[vlc] / modules / gui / skins2 / controls / ctrl_checkbox.cpp
1 /*****************************************************************************
2  * ctrl_checkbox.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #include "ctrl_checkbox.hpp"
26 #include "../events/evt_generic.hpp"
27 #include "../commands/cmd_generic.hpp"
28 #include "../src/generic_bitmap.hpp"
29 #include "../src/os_factory.hpp"
30 #include "../src/os_graphics.hpp"
31 #include "../utils/var_bool.hpp"
32
33
34 CtrlCheckbox::CtrlCheckbox( intf_thread_t *pIntf,
35                             const GenericBitmap &rBmpUp1,
36                             const GenericBitmap &rBmpOver1,
37                             const GenericBitmap &rBmpDown1,
38                             const GenericBitmap &rBmpUp2,
39                             const GenericBitmap &rBmpOver2,
40                             const GenericBitmap &rBmpDown2,
41                             CmdGeneric &rCommand1, CmdGeneric &rCommand2,
42                             const UString &rTooltip1,
43                             const UString &rTooltip2,
44                             VarBool &rVariable, const UString &rHelp,
45                             VarBool *pVisible ):
46     CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
47     m_rVariable( rVariable ),
48     m_rCommand1( rCommand1 ), m_rCommand2( rCommand2 ),
49     m_tooltip1( rTooltip1 ), m_tooltip2( rTooltip2 ),
50     m_cmdUpOverDownOver( this, &transUpOverDownOver ),
51     m_cmdDownOverUpOver( this, &transDownOverUpOver ),
52     m_cmdDownOverDown( this, &transDownOverDown ),
53     m_cmdDownDownOver( this, &transDownDownOver ),
54     m_cmdUpOverUp( this, &transUpOverUp ),
55     m_cmdUpUpOver( this, &transUpUpOver ),
56     m_cmdDownUp( this, &transDownUp ),
57     m_cmdUpHidden( this, &transUpHidden ),
58     m_cmdHiddenUp( this, &transHiddenUp )
59 {
60     // Build the images of the checkbox
61     OSFactory *pOsFactory = OSFactory::instance( pIntf );
62     m_pImgUp1 = pOsFactory->createOSGraphics( rBmpUp1.getWidth(),
63                                               rBmpUp1.getHeight() );
64     m_pImgUp1->drawBitmap( rBmpUp1, 0, 0 );
65     m_pImgDown1 = pOsFactory->createOSGraphics( rBmpDown1.getWidth(),
66                                                 rBmpDown1.getHeight() );
67     m_pImgDown1->drawBitmap( rBmpDown1, 0, 0 );
68     m_pImgOver1 = pOsFactory->createOSGraphics( rBmpOver1.getWidth(),
69                                                 rBmpOver1.getHeight() );
70     m_pImgOver1->drawBitmap( rBmpOver1, 0, 0 );
71
72     m_pImgUp2 = pOsFactory->createOSGraphics( rBmpUp2.getWidth(),
73                                               rBmpUp2.getHeight() );
74     m_pImgUp2->drawBitmap( rBmpUp2, 0, 0 );
75     m_pImgDown2 = pOsFactory->createOSGraphics( rBmpDown2.getWidth(),
76                                                 rBmpDown2.getHeight() );
77     m_pImgDown2->drawBitmap( rBmpDown2, 0, 0 );
78     m_pImgOver2 = pOsFactory->createOSGraphics( rBmpOver2.getWidth(),
79                                                 rBmpOver2.getHeight() );
80     m_pImgOver2->drawBitmap( rBmpOver2, 0, 0 );
81
82     // States
83     m_fsm.addState( "up" );
84     m_fsm.addState( "down" );
85     m_fsm.addState( "upOver" );
86     m_fsm.addState( "downOver" );
87     m_fsm.addState( "hidden" );
88
89     // Transitions
90     m_fsm.addTransition( "upOver", "mouse:left:down", "downOver",
91                          &m_cmdUpOverDownOver );
92     m_fsm.addTransition( "upOver", "mouse:left:dblclick", "downOver",
93                          &m_cmdUpOverDownOver );
94     m_fsm.addTransition( "downOver", "mouse:left:up", "upOver",
95                          &m_cmdDownOverUpOver );
96     m_fsm.addTransition( "downOver", "leave", "down", &m_cmdDownOverDown );
97     m_fsm.addTransition( "down", "enter", "downOver", &m_cmdDownDownOver );
98     m_fsm.addTransition( "upOver", "leave", "up", &m_cmdUpOverUp );
99     m_fsm.addTransition( "up", "enter", "upOver", &m_cmdUpUpOver );
100     m_fsm.addTransition( "down", "mouse:left:up", "up", &m_cmdDownUp );
101     // XXX: It would be easy to use a "ANY" initial state to handle these
102     // four lines in only one. But till now it isn't worthwhile...
103     m_fsm.addTransition( "up", "special:hide", "hidden", &m_cmdUpHidden );
104     m_fsm.addTransition( "down", "special:hide", "hidden", &m_cmdUpHidden );
105     m_fsm.addTransition( "upOver", "special:hide", "hidden", &m_cmdUpHidden );
106     m_fsm.addTransition( "downOver", "special:hide", "hidden", &m_cmdUpHidden );
107     m_fsm.addTransition( "hidden", "special:show", "up", &m_cmdHiddenUp );
108
109     // Observe the variable
110     m_rVariable.addObserver( this );
111
112     // Initial state
113     m_fsm.setState( "up" );
114     if( !m_rVariable.get() )
115     {
116         m_pImgUp = m_pImgUp1;
117         m_pImgOver = m_pImgOver1;
118         m_pImgDown = m_pImgDown1;
119         m_pImgCurrent = m_pImgUp;
120         m_pCommand = &m_rCommand1;
121         m_pTooltip = &m_tooltip1;
122     }
123     else
124     {
125         m_pImgUp = m_pImgUp2;
126         m_pImgOver = m_pImgOver2;
127         m_pImgDown = m_pImgDown2;
128         m_pImgCurrent = m_pImgDown;
129         m_pCommand = &m_rCommand2;
130         m_pTooltip = &m_tooltip2;
131     }
132 }
133
134
135 CtrlCheckbox::~CtrlCheckbox()
136 {
137     m_rVariable.delObserver( this );
138     SKINS_DELETE( m_pImgUp1 );
139     SKINS_DELETE( m_pImgDown1 );
140     SKINS_DELETE( m_pImgOver1 );
141     SKINS_DELETE( m_pImgUp2 );
142     SKINS_DELETE( m_pImgDown2 );
143     SKINS_DELETE( m_pImgOver2 );
144 }
145
146
147 void CtrlCheckbox::handleEvent( EvtGeneric &rEvent )
148 {
149     m_fsm.handleTransition( rEvent.getAsString() );
150 }
151
152
153 bool CtrlCheckbox::mouseOver( int x, int y ) const
154 {
155     if( m_pImgCurrent )
156     {
157         return m_pImgCurrent->hit( x, y );
158     }
159     else
160     {
161         return false;
162     }
163 }
164
165
166 void CtrlCheckbox::draw( OSGraphics &rImage, int xDest, int yDest )
167 {
168     if( m_pImgCurrent )
169     {
170         // Draw the current image
171         rImage.drawGraphics( *m_pImgCurrent, 0, 0, xDest, yDest );
172     }
173 }
174
175
176 void CtrlCheckbox::transUpOverDownOver( SkinObject *pCtrl )
177 {
178     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
179     pThis->captureMouse();
180     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
181     pThis->m_pImgCurrent = pThis->m_pImgDown;
182     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
183 }
184
185
186 void CtrlCheckbox::transDownOverUpOver( SkinObject *pCtrl )
187 {
188     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
189     pThis->releaseMouse();
190
191     // Invert the state variable
192     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
193     pThis->m_pImgCurrent = pThis->m_pImgUp;
194     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
195
196     // Execute the command
197     pThis->m_pCommand->execute();
198 }
199
200
201 void CtrlCheckbox::transDownOverDown( SkinObject *pCtrl )
202 {
203     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
204     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
205     pThis->m_pImgCurrent = pThis->m_pImgUp;
206     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
207 }
208
209
210 void CtrlCheckbox::transDownDownOver( SkinObject *pCtrl )
211 {
212     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
213     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
214     pThis->m_pImgCurrent = pThis->m_pImgDown;
215     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
216 }
217
218
219 void CtrlCheckbox::transUpUpOver( SkinObject *pCtrl )
220 {
221     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
222     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
223     pThis->m_pImgCurrent = pThis->m_pImgOver;
224     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
225 }
226
227
228 void CtrlCheckbox::transUpOverUp( SkinObject *pCtrl )
229 {
230     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
231     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
232     pThis->m_pImgCurrent = pThis->m_pImgUp;
233     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
234 }
235
236
237 void CtrlCheckbox::transDownUp( SkinObject *pCtrl )
238 {
239     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
240     pThis->releaseMouse();
241 }
242
243
244 void CtrlCheckbox::transUpHidden( SkinObject *pCtrl )
245 {
246     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
247     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
248     pThis->m_pImgCurrent = NULL;
249     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
250 }
251
252
253 void CtrlCheckbox::transHiddenUp( SkinObject *pCtrl )
254 {
255     CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
256     const OSGraphics *pOldImg = pThis->m_pImgCurrent;
257     pThis->m_pImgCurrent = pThis->m_pImgUp;
258     pThis->notifyLayoutMaxSize( pOldImg, pThis->m_pImgCurrent );
259 }
260
261
262 void CtrlCheckbox::onVarBoolUpdate( VarBool &rVariable )
263 {
264     changeButton();
265 }
266
267
268 void CtrlCheckbox::changeButton()
269 {
270     // Are we using the first set of images or the second one?
271     if( m_pImgUp == m_pImgUp1 )
272     {
273         m_pImgUp = m_pImgUp2;
274         m_pImgOver = m_pImgOver2;
275         m_pImgDown = m_pImgDown2;
276         m_pTooltip = &m_tooltip2;
277         m_pCommand = &m_rCommand2;
278     }
279     else
280     {
281         m_pImgUp = m_pImgUp1;
282         m_pImgOver = m_pImgOver1;
283         m_pImgDown = m_pImgDown1;
284         m_pTooltip = &m_tooltip1;
285         m_pCommand = &m_rCommand1;
286     }
287     // XXX: We assume that the checkbox is up
288     m_pImgCurrent = m_pImgUp;
289
290     // Notify the window the tooltip has changed
291     notifyTooltipChange();
292     // Refresh
293     notifyLayout();
294 }
295