]> git.sesse.net Git - vlc/blob - modules/gui/skins2/controls/ctrl_button.cpp
skins2: cosmetic
[vlc] / modules / gui / skins2 / controls / ctrl_button.cpp
1 /*****************************************************************************
2  * ctrl_button.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 "ctrl_button.hpp"
26 #include "../events/evt_generic.hpp"
27 #include "../src/generic_bitmap.hpp"
28 #include "../src/generic_layout.hpp"
29 #include "../src/os_factory.hpp"
30 #include "../src/os_graphics.hpp"
31 #include "../commands/cmd_generic.hpp"
32
33
34 CtrlButton::CtrlButton( intf_thread_t *pIntf, const GenericBitmap &rBmpUp,
35                         const GenericBitmap &rBmpOver,
36                         const GenericBitmap &rBmpDown, CmdGeneric &rCommand,
37                         const UString &rTooltip, const UString &rHelp,
38                         VarBool *pVisible ):
39     CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
40     m_rCommand( rCommand ), m_tooltip( rTooltip ),
41     m_imgUp( pIntf, rBmpUp ), m_imgOver( pIntf, rBmpOver ),
42     m_imgDown( pIntf, rBmpDown ), m_pImg( NULL ), m_cmdUpOverDownOver( this ),
43     m_cmdDownOverUpOver( this ), m_cmdDownOverDown( this ),
44     m_cmdDownDownOver( this ), m_cmdUpOverUp( this ), m_cmdUpUpOver( this ),
45     m_cmdDownUp( this ), m_cmdUpHidden( this ), m_cmdHiddenUp( this )
46 {
47     // States
48     m_fsm.addState( "up" );
49     m_fsm.addState( "down" );
50     m_fsm.addState( "upOver" );
51     m_fsm.addState( "downOver" );
52     m_fsm.addState( "hidden" );
53
54     // Transitions
55     m_fsm.addTransition( "upOver", "mouse:left:down", "downOver",
56                          &m_cmdUpOverDownOver );
57     m_fsm.addTransition( "upOver", "mouse:left:dblclick", "downOver",
58                          &m_cmdUpOverDownOver );
59     m_fsm.addTransition( "downOver", "mouse:left:up", "upOver",
60                          &m_cmdDownOverUpOver );
61     m_fsm.addTransition( "downOver", "leave", "down", &m_cmdDownOverDown );
62     m_fsm.addTransition( "down", "enter", "downOver", &m_cmdDownDownOver );
63     m_fsm.addTransition( "upOver", "leave", "up", &m_cmdUpOverUp );
64     m_fsm.addTransition( "up", "enter", "upOver", &m_cmdUpUpOver );
65     m_fsm.addTransition( "down", "mouse:left:up", "up", &m_cmdDownUp );
66     // XXX: It would be easy to use a "ANY" initial state to handle these
67     // four lines in only one. But till now it isn't worthwhile...
68     m_fsm.addTransition( "up", "special:hide", "hidden", &m_cmdUpHidden );
69     m_fsm.addTransition( "down", "special:hide", "hidden", &m_cmdUpHidden );
70     m_fsm.addTransition( "upOver", "special:hide", "hidden", &m_cmdUpHidden );
71     m_fsm.addTransition( "downOver", "special:hide", "hidden", &m_cmdUpHidden );
72     m_fsm.addTransition( "hidden", "special:show", "up", &m_cmdHiddenUp );
73
74     // Initial state
75     m_fsm.setState( "up" );
76     setImage( &m_imgUp );
77 }
78
79
80 CtrlButton::~CtrlButton()
81 {
82     if( m_pImg )
83     {
84         m_pImg->stopAnim();
85         m_pImg->delObserver( this );
86     }
87 }
88
89 void CtrlButton::setLayout( GenericLayout *pLayout,
90                            const Position &rPosition )
91 {
92     CtrlGeneric::setLayout( pLayout, rPosition );
93     m_pLayout->getActiveVar().addObserver( this );
94 }
95
96
97 void CtrlButton::unsetLayout()
98 {
99     m_pLayout->getActiveVar().delObserver( this );
100     CtrlGeneric::unsetLayout();
101 }
102
103 void CtrlButton::handleEvent( EvtGeneric &rEvent )
104 {
105     m_fsm.handleTransition( rEvent.getAsString() );
106 }
107
108
109 bool CtrlButton::mouseOver( int x, int y ) const
110 {
111     if( m_pImg )
112     {
113         return m_pImg->hit( x, y );
114     }
115     else
116     {
117         return false;
118     }
119 }
120
121
122 void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
123 {
124     const Position *pPos = getPosition();
125     rect region( pPos->getLeft(), pPos->getTop(),
126                  pPos->getWidth(), pPos->getHeight() );
127     rect clip( xDest, yDest, w, h );
128     rect inter;
129     if( rect::intersect( region, clip, &inter ) && m_pImg )
130     {
131         // Draw the current image
132         m_pImg->draw( rImage, inter.x, inter.y, inter.width, inter.height,
133                       inter.x - pPos->getLeft(),
134                       inter.y - pPos->getTop() );
135     }
136 }
137
138 void CtrlButton::setImage( AnimBitmap *pImg )
139 {
140     if( pImg == m_pImg )
141         return;
142
143     AnimBitmap *pOldImg = m_pImg;
144     m_pImg = pImg;
145
146     if( pOldImg )
147     {
148         pOldImg->stopAnim();
149         pOldImg->delObserver( this );
150     }
151
152     if( pImg )
153     {
154         pImg->startAnim();
155         pImg->addObserver( this );
156     }
157
158     notifyLayoutMaxSize( pOldImg, pImg );
159 }
160
161
162 void CtrlButton::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg )
163 {
164     (void)rBitmap;(void)arg;
165     notifyLayout( m_pImg->getWidth(), m_pImg->getHeight() );
166 }
167
168
169 void CtrlButton::CmdUpOverDownOver::execute()
170 {
171     m_pParent->captureMouse();
172     m_pParent->setImage( &m_pParent->m_imgDown );
173 }
174
175
176 void CtrlButton::CmdDownOverUpOver::execute()
177 {
178     m_pParent->releaseMouse();
179     m_pParent->setImage( &m_pParent->m_imgUp );
180     // Execute the command associated to this button
181     m_pParent->m_rCommand.execute();
182 }
183
184
185 void CtrlButton::CmdDownOverDown::execute()
186 {
187     m_pParent->setImage( &m_pParent->m_imgUp );
188 }
189
190
191 void CtrlButton::CmdDownDownOver::execute()
192 {
193     m_pParent->setImage( &m_pParent->m_imgDown );
194 }
195
196
197 void CtrlButton::CmdUpUpOver::execute()
198 {
199     m_pParent->setImage( &m_pParent->m_imgOver );
200 }
201
202
203 void CtrlButton::CmdUpOverUp::execute()
204 {
205     m_pParent->setImage( &m_pParent->m_imgUp );
206 }
207
208
209 void CtrlButton::CmdDownUp::execute()
210 {
211     m_pParent->releaseMouse();
212 }
213
214
215 void CtrlButton::CmdUpHidden::execute()
216 {
217     m_pParent->setImage( NULL );
218 }
219
220
221 void CtrlButton::CmdHiddenUp::execute()
222 {
223     m_pParent->setImage( &m_pParent->m_imgUp );
224 }
225
226 void CtrlButton::onUpdate( Subject<VarBool> &rVariable, void *arg  )
227 {
228     // restart animation
229     if(     &rVariable == m_pVisible
230         ||  &rVariable == &m_pLayout->getActiveVar()
231       )
232     {
233         if( m_pImg )
234         {
235             m_pImg->stopAnim();
236             m_pImg->startAnim();
237         }
238     }
239     CtrlGeneric::onUpdate( rVariable, arg );
240 }
241