1 #ifndef oxygentoolbarstatedata_h
2 #define oxygentoolbarstatedata_h
3 /*
4 * this file is part of the oxygen gtk engine
5 * Copyright (c) 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
6 *
7 * This  library is free  software; you can  redistribute it and/or
8 * modify it  under  the terms  of the  GNU Lesser  General  Public
9 * License  as published  by the Free  Software  Foundation; either
10 * version 2 of the License, or(at your option ) any later version.
11 *
12 * This library is distributed  in the hope that it will be useful,
13 * but  WITHOUT ANY WARRANTY; without even  the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License  along  with  this library;  if not,  write to  the Free
19 * Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
21 */
22 
23 #include "../oxygenanimationdata.h"
24 #include "../oxygenanimationmodes.h"
25 #include "../oxygengtkutils.h"
26 #include "oxygenfollowmousedata.h"
27 #include "oxygensignal.h"
28 #include "oxygentimeline.h"
29 #include "oxygentimer.h"
30 
31 #include <map>
32 #include <gtk/gtk.h>
33 
34 namespace Oxygen
35 {
36     class ToolBarStateData: public FollowMouseData
37     {
38 
39         public:
40 
41         //! constructor
ToolBarStateData(void)42         ToolBarStateData( void ):
43             _target( 0L ),
44             _dirtyRect( Gtk::gdk_rectangle() )
45         {}
46 
47         //! destructor
~ToolBarStateData(void)48         virtual ~ToolBarStateData( void )
49         { disconnect( _target ); }
50 
51         //! setup connections
52         using FollowMouseData::connect;
53         virtual void connect( GtkWidget* );
54 
55         //! disconnect
56         using FollowMouseData::disconnect;
57         virtual void disconnect( GtkWidget* );
58 
59         //! register child
60         void registerChild( GtkWidget*, bool = true );
61 
62         //!@name modifiers
63         //@{
64 
65         //! enable state
setEnabled(bool value)66         void setEnabled( bool value )
67         {
68             FollowMouseData::setEnabled( value );
69 
70             _current._timeLine.setEnabled( value );
71             _previous._timeLine.setEnabled( value );
72 
73             if( !value )
74             {
75                 _current.clear();
76                 _previous.clear();
77             }
78 
79         }
80 
81         //! duration
setDuration(int value)82         void setDuration( int value )
83         {
84             _current._timeLine.setDuration( value );
85             _previous._timeLine.setDuration( value );
86         }
87 
88         //@}
89 
90         //!@name accessors
91         //@{
92 
93         //! true if animated
isAnimated(void)94         bool isAnimated( void ) const
95         { return isAnimated( AnimationCurrent ) || isAnimated( AnimationPrevious ); }
96 
97         //! true if given animation type is animated
isAnimated(const WidgetType & type)98         bool isAnimated( const WidgetType& type ) const
99         { return data( type )._timeLine.isRunning(); }
100 
101         //! widget matching type
widget(const WidgetType & type)102         GtkWidget* widget( const WidgetType& type ) const
103         { return data( type )._widget; }
104 
105         //! rect for given animation type
rectangle(const WidgetType & type)106         const GdkRectangle& rectangle( const WidgetType& type ) const
107         { return data( type )._rect; }
108 
109         //! animation data
animationData(const WidgetType & type)110         AnimationData animationData( const WidgetType& type ) const
111         {
112             const Data& data( this->data( type ) );
113             return data._timeLine.isRunning() ?
114                 AnimationData( data._timeLine.value(), AnimationHover ):
115                 AnimationData();
116         }
117 
118         //! true when fade out animation is locked (delayed)
isLocked(void)119         bool isLocked( void ) const
120         { return _timer.isRunning(); }
121 
122         //@}
123 
124         protected:
125 
126         //! disconnect child
127         void unregisterChild( GtkWidget* );
128 
129         //! update state for given widget
130         bool updateState( GtkWidget*, bool state, bool delayed );
131 
132         //! return dirty rect (for update)
133         GdkRectangle dirtyRect( void );
134 
135         //! animations data
136         class Data
137         {
138 
139             public:
140 
141             //! constructor
Data(void)142             explicit Data( void ):
143                 _widget( 0L ),
144                 _rect( Gtk::gdk_rectangle() )
145             {}
146 
147             //! update data
copy(const Data & other)148             void copy( const Data& other )
149             {
150                 _widget = other._widget;
151                 _rect = other._rect;
152             }
153 
154             //! update data
update(GtkWidget * widget,const GdkRectangle & rect)155             void update( GtkWidget* widget, const GdkRectangle& rect )
156             {
157                 _widget = widget;
158                 _rect = rect;
159             }
160 
161             //! true if valid
isValid(void)162             bool isValid( void ) const
163             { return _widget && Gtk::gdk_rectangle_is_valid( &_rect ); }
164 
165             //! clear
clear(void)166             void clear( void )
167             {
168                 if( _timeLine.isRunning() ) _timeLine.stop();
169                 _widget = 0L;
170                 _rect = Gtk::gdk_rectangle();
171             }
172 
173             //! timeline
174             TimeLine _timeLine;
175 
176             //! widget
177             GtkWidget* _widget;
178 
179             //! rectangle
180             GdkRectangle _rect;
181 
182         };
183 
184         //! get data for given animation type
data(const WidgetType & type)185         Data& data( const WidgetType& type )
186         {
187             switch( type )
188             {
189                 default:
190                 case AnimationCurrent: return _current;
191                 case AnimationPrevious: return _previous;
192             }
193         }
194 
195         //! get data for given animation type
data(const WidgetType & type)196         const Data& data( const WidgetType& type ) const
197         {
198             switch( type )
199             {
200                 default:
201                 case AnimationCurrent: return _current;
202                 case AnimationPrevious: return _previous;
203             }
204         }
205 
206         //!@name callbacks
207         //@{
208 
209         //! child is destroyed
210         static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer );
211 
212         //! child entered
213         static gboolean childEnterNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer);
214 
215         //! child left
216         static gboolean childLeaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer);
217 
218         //! mouse leave events
219         static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer);
220 
221         //! update widget for fade-in/fade-out animation
222         static gboolean delayedUpdate( gpointer );
223 
224         //! update widget for follow-mouse animation
225         static gboolean followMouseUpdate( gpointer );
226 
227         //! start delayed fade-out animation
228         static gboolean delayedAnimate( gpointer );
229 
230         //@}
231 
232         private:
233 
234         //! target
235         GtkWidget* _target;
236 
237         //! signals
238         Signal _leaveId;
239 
240         //!@name animation data
241         //@{
242 
243         //! additional dirty rect
244         GdkRectangle _dirtyRect;
245 
246         //! previous button animation data
247         Data _previous;
248 
249         //! current button animation data
250         Data _current;
251 
252         //@}
253 
254         //!@name hover data
255         /*! need to keep track of enter/leave events in toolbar items */
256         class HoverData
257         {
258 
259             public:
260 
261             //! constructor
HoverData(void)262             explicit HoverData( void )
263             {}
264 
265             //! destructor
~HoverData(void)266             virtual ~HoverData( void )
267             {}
268 
269             //! disconnect
disconnect(void)270             virtual void disconnect( void )
271             {
272                 _destroyId.disconnect();
273                 _enterId.disconnect();
274                 _leaveId.disconnect();
275             }
276 
277             //!@name callback ids
278             //@{
279             Signal _destroyId;
280             Signal _enterId;
281             Signal _leaveId;
282             //@}
283 
284         };
285 
286         typedef std::map<GtkWidget*, HoverData> HoverDataMap;
287         HoverDataMap _hoverData;
288 
289         //! delayed animation timeOut
290         static const int _timeOut;
291 
292         //! timer of delayed animation
293         Timer _timer;
294 
295     };
296 
297 }
298 
299 #endif
300