1 #ifndef oxygenmenubarstatedata_h
2 #define oxygenmenubarstatedata_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 * Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
7 *
8 * MenuBarState prelight effect is based on
9 * Redmond95 - a cairo based GTK+ engine
10 * Copyright (C) 2001 Red Hat, Inc. <@redhat.com>
11 * Copyright (C) 2006 Andrew Johnson <acjgenius@earthlink.net>
12 * Copyright (C) 2006-2007 Benjamin Berg <benjamin@sipsolutions.net>
13 *
14 * This  library is free  software; you can  redistribute it and/or
15 * modify it  under  the terms  of the  GNU Lesser  General  Public
16 * License  as published  by the Free  Software  Foundation; either
17 * version 2 of the License, or(at your option ) any later version.
18 *
19 * This library is distributed  in the hope that it will be useful,
20 * but  WITHOUT ANY WARRANTY; without even  the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License  along  with  this library;  if not,  write to  the Free
26 * Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
27 * MA 02110-1301, USA.
28 */
29 
30 #include "../oxygenanimationdata.h"
31 #include "../oxygenanimationmodes.h"
32 #include "../oxygengtkutils.h"
33 #include "oxygenfollowmousedata.h"
34 #include "oxygensignal.h"
35 #include "oxygentimeline.h"
36 
37 #include <gtk/gtk.h>
38 
39 #include <map>
40 
41 namespace Oxygen
42 {
43     class MenuBarStateData: public FollowMouseData
44     {
45 
46         public:
47 
48         //! constructor
MenuBarStateData(void)49         MenuBarStateData( void ):
50             _target( 0L ),
51             _animationsEnabled( true ),
52             _dirtyRect( Gtk::gdk_rectangle() )
53             {}
54 
55         //! destructor
~MenuBarStateData(void)56         virtual ~MenuBarStateData( void )
57         { disconnect( _target ); }
58 
59         //! setup connections
60         using FollowMouseData::connect;
61         virtual void connect( GtkWidget* );
62 
63         //! disconnect
64         using FollowMouseData::disconnect;
65         virtual void disconnect( GtkWidget* );
66 
67         //! enable state
setAnimationsEnabled(bool value)68         void setAnimationsEnabled( bool value )
69         {
70 
71             // base class
72             FollowMouseData::setEnabled( value );
73 
74             _animationsEnabled = value;
75             _current._timeLine.setEnabled( value );
76             _previous._timeLine.setEnabled( value );
77 
78             if( !value )
79             {
80                 _current.clear();
81                 _previous.clear();
82             }
83 
84         }
85 
86         //! duration
setDuration(int value)87         void setDuration( int value )
88         {
89             _current._timeLine.setDuration( value );
90             _previous._timeLine.setDuration( value );
91         }
92 
93         //!@name accessors
94         //@{
95 
96         //! true if animated
isAnimated(void)97         bool isAnimated( void ) const
98         { return isAnimated( AnimationCurrent ) || isAnimated( AnimationPrevious ); }
99 
100         //! true if given animation type is animated
isAnimated(const WidgetType & type)101         bool isAnimated( const WidgetType& type ) const
102         { return data( type )._timeLine.isRunning(); }
103 
104         //! widget for current animation type
widget(const WidgetType & type)105         GtkWidget* widget( const WidgetType& type ) const
106         { return data( type )._widget; }
107 
108         //! rect for given animation type
rectangle(const WidgetType & type)109         const GdkRectangle& rectangle( const WidgetType& type ) const
110         { return data( type )._rect; }
111 
112         //! animation data
animationData(const WidgetType & type)113         AnimationData animationData( const WidgetType& type ) const
114         {
115             const Data& data( this->data( type ) );
116             return data._timeLine.isRunning() ?
117                 AnimationData( data._timeLine.value(), AnimationHover ):
118                 AnimationData();
119         }
120 
121         //@}
122 
123         protected:
124 
125         //! register child
126         void registerChild( GtkWidget* );
127 
128         //! disconnect child
129         void unregisterChild( GtkWidget* );
130 
131         //! update items
132         void updateItems( GdkEventType );
133 
134         //! update state for given widget
135         bool updateState( GtkWidget*, const GdkRectangle&, bool );
136 
137         //! true if menu item is active (pressed down)
138         bool menuItemIsActive( GtkWidget* ) const;
139 
140         //! return dirty rect (for update)
141         GdkRectangle dirtyRect( void );
142 
143         //@}
144 
145         //! animations data
146         class Data
147         {
148 
149             public:
150 
151             //! constructor
Data(void)152             explicit Data( void ):
153                 _widget( 0L ),
154                 _rect( Gtk::gdk_rectangle() )
155             {}
156 
157             //! update data
copy(const Data & other)158             void copy( const Data& other )
159             {
160                 _widget = other._widget;
161                 _rect = other._rect;
162             }
163 
164             //! update data
update(GtkWidget * widget,const GdkRectangle & rect)165             void update( GtkWidget* widget, const GdkRectangle& rect )
166             {
167                 _widget = widget;
168                 _rect = rect;
169             }
170 
171             //! true if valid
isValid(void)172             bool isValid( void ) const
173             { return _widget && Gtk::gdk_rectangle_is_valid( &_rect ); }
174 
175             //! clear
clear(void)176             void clear( void )
177             {
178                 if( _timeLine.isRunning() ) _timeLine.stop();
179                 _widget = 0L;
180                 _rect = Gtk::gdk_rectangle();
181             }
182 
183             //! timeline
184             TimeLine _timeLine;
185 
186             //! widget
187             GtkWidget* _widget;
188 
189             //! rectangle
190             GdkRectangle _rect;
191 
192         };
193 
194         //! get data for given animation type
data(const WidgetType & type)195         Data& data( const WidgetType& type )
196         {
197             switch( type )
198             {
199                 default:
200                 case AnimationCurrent: return _current;
201                 case AnimationPrevious: return _previous;
202             }
203         }
204 
205         //! get data for given animation type
data(const WidgetType & type)206         const Data& data( const WidgetType& type ) const
207         {
208             switch( type )
209             {
210                 default:
211                 case AnimationCurrent: return _current;
212                 case AnimationPrevious: return _previous;
213             }
214         }
215 
216         //!@name callbacks
217         //@{
218 
219         //! child is destroyed
220         static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer );
221 
222         //! mouse motion events
223         static gboolean motionNotifyEvent( GtkWidget*, GdkEventMotion*, gpointer);
224 
225         //! mouse leave events
226         static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer);
227 
228         //! update widget for fade-in/fade-out animation
229         static gboolean delayedUpdate( gpointer );
230 
231         //! update widget for follow-mouse animation
232         static gboolean followMouseUpdate( gpointer );
233 
234         //@}
235 
236         private:
237 
238         //! target
239         GtkWidget* _target;
240 
241         //!@name signals
242         //@{
243         Signal _motionId;
244         Signal _leaveId;
245         //@}
246 
247         //!@name animation data
248         //@{
249 
250         //! true if menubar item mouse-over is animated
251         bool _animationsEnabled;
252 
253         //! additional dirty rect
254         GdkRectangle _dirtyRect;
255 
256         Data _previous;
257         Data _current;
258 
259         //@}
260 
261         //! map children to destroy signal
262         typedef std::map<GtkWidget*, Signal> ChildrenMap;
263         ChildrenMap _children;
264 
265     };
266 
267 }
268 
269 #endif
270