1 #ifndef oxygenmenustatedata_h 2 #define oxygenmenustatedata_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 "oxygentimer.h" 29 #include "oxygentimeline.h" 30 31 #include <gtk/gtk.h> 32 33 #include <map> 34 35 namespace Oxygen 36 { 37 //! handles menu items animations 38 class MenuStateData: public FollowMouseData 39 { 40 41 public: 42 43 //! constructor MenuStateData(void)44 MenuStateData( void ): 45 _target( 0L ), 46 _dirtyRect( Gtk::gdk_rectangle() ), 47 _xPadding(0), 48 _yPadding(0) 49 {} 50 51 //! destructor ~MenuStateData(void)52 virtual ~MenuStateData( void ) 53 { disconnect( _target ); } 54 55 //! setup connections 56 using FollowMouseData::connect; 57 virtual void connect( GtkWidget* ); 58 59 //! disconnect 60 using FollowMouseData::disconnect; 61 virtual void disconnect( GtkWidget* ); 62 63 //!@name modifiers 64 //@{ 65 66 //! enable state setEnabled(bool value)67 void setEnabled( bool value ) 68 { 69 70 // base class 71 FollowMouseData::setEnabled( value ); 72 73 _current._timeLine.setEnabled( value ); 74 _previous._timeLine.setEnabled( value ); 75 76 if( !value ) 77 { 78 _current.clear(); 79 _previous.clear(); 80 } 81 82 } 83 84 //! duration setDuration(int value)85 void setDuration( int value ) 86 { 87 _current._timeLine.setDuration( value ); 88 _previous._timeLine.setDuration( value ); 89 } 90 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 //! true when fade out animation is locked (delayed) isLocked(void)122 virtual bool isLocked( void ) const 123 { return _timer.isRunning(); } 124 125 //@} 126 127 protected: 128 129 //! register child 130 void registerChild( GtkWidget* ); 131 132 //! disconnect child 133 void unregisterChild( GtkWidget* ); 134 135 //! update items 136 void updateItems( void ); 137 138 //! update state for given widget 139 bool updateState( GtkWidget*, const GdkRectangle&, int, int, bool state, bool delayed = false ); 140 141 //! true if menu item is active (pressed down) 142 bool menuItemIsActive( GtkWidget* ) const; 143 144 //! return dirty rect (for update) 145 GdkRectangle dirtyRect( void ); 146 147 //! animations data 148 class Data 149 { 150 151 public: 152 153 //! constructor Data(void)154 explicit Data( void ): 155 _widget( 0L ), 156 _rect( Gtk::gdk_rectangle() ), 157 _xOffset( 0 ), 158 _yOffset( 0 ) 159 {} 160 161 //! update data copy(const Data & other)162 void copy( const Data& other ) 163 { 164 _widget = other._widget; 165 _rect = other._rect; 166 _xOffset = other._xOffset; 167 _yOffset = other._yOffset; 168 } 169 170 //! update data update(GtkWidget * widget,const GdkRectangle & rect,int xOffset,int yOffset)171 void update( GtkWidget* widget, const GdkRectangle& rect, int xOffset, int yOffset ) 172 { 173 _widget = widget; 174 _rect = rect; 175 _xOffset = xOffset; 176 _yOffset = yOffset; 177 } 178 179 //! true if valid isValid(void)180 bool isValid( void ) const 181 { return _widget && Gtk::gdk_rectangle_is_valid( &_rect ); } 182 183 //! clear clear(void)184 void clear( void ) 185 { 186 if( _timeLine.isRunning() ) _timeLine.stop(); 187 _widget = 0L; 188 _rect = Gtk::gdk_rectangle(); 189 } 190 191 //! dirty rect 192 /*! properly adds offsets between widget window and painting window */ dirtyRect(void)193 GdkRectangle dirtyRect( void ) const 194 { 195 GdkRectangle rect( _rect ); 196 rect.x += _xOffset; 197 rect.y += _yOffset; 198 return rect; 199 } 200 201 //! timeline 202 TimeLine _timeLine; 203 204 //! widget 205 GtkWidget* _widget; 206 207 //! rectangle 208 GdkRectangle _rect; 209 210 //! offset between paint window and menu window 211 int _xOffset; 212 int _yOffset; 213 214 }; 215 216 //! get data for given animation type data(const WidgetType & type)217 Data& data( const WidgetType& type ) 218 { 219 switch( type ) 220 { 221 default: 222 case AnimationCurrent: return _current; 223 case AnimationPrevious: return _previous; 224 } 225 } 226 227 //! get data for given animation type data(const WidgetType & type)228 const Data& data( const WidgetType& type ) const 229 { 230 switch( type ) 231 { 232 default: 233 case AnimationCurrent: return _current; 234 case AnimationPrevious: return _previous; 235 } 236 } 237 238 //!@name callbacks 239 //@{ 240 241 //! child is destroyed 242 static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer ); 243 244 //! mouse motion events 245 static gboolean motionNotifyEvent( GtkWidget*, GdkEventMotion*, gpointer); 246 247 //! mouse leave events 248 static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer); 249 250 //! update widget for fade-in/fade-out animation 251 static gboolean delayedUpdate( gpointer ); 252 253 //! update widget for follow-mouse animation 254 static gboolean followMouseUpdate( gpointer ); 255 256 //! start delayed fade-out animation 257 static gboolean delayedAnimate( gpointer ); 258 259 //@} 260 261 private: 262 263 //! target 264 GtkWidget* _target; 265 266 //!@name signals 267 //@{ 268 Signal _motionId; 269 Signal _leaveId; 270 //@} 271 272 //!@name animation data 273 //@{ 274 275 //! additional dirty rect 276 GdkRectangle _dirtyRect; 277 278 Data _previous; 279 Data _current; 280 281 //@} 282 283 //!@name follow mouse animated data 284 //@{ 285 286 //! padding 287 gint _xPadding; 288 gint _yPadding; 289 290 //! delayed animation timeOut 291 static const int _timeOut; 292 293 //! timer of delayed animation 294 Timer _timer; 295 296 //@} 297 298 //! map children to destroy signal 299 typedef std::map<GtkWidget*, Signal> ChildrenMap; 300 ChildrenMap _children; 301 302 }; 303 304 } 305 306 #endif 307