File indexing completed on 2024-05-12 17:05:49
0001 #ifndef oxygenmenustatedata_h 0002 #define oxygenmenustatedata_h 0003 /* 0004 * this file is part of the oxygen gtk engine 0005 * SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0006 * 0007 * SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "../oxygenanimationdata.h" 0011 #include "../oxygenanimationmodes.h" 0012 #include "../oxygengtkutils.h" 0013 #include "oxygenfollowmousedata.h" 0014 #include "oxygensignal.h" 0015 #include "oxygentimer.h" 0016 #include "oxygentimeline.h" 0017 0018 #include <gtk/gtk.h> 0019 0020 #include <map> 0021 0022 namespace Oxygen 0023 { 0024 //! handles menu items animations 0025 class MenuStateData: public FollowMouseData 0026 { 0027 0028 public: 0029 0030 //! constructor 0031 MenuStateData( void ): 0032 _target( 0L ), 0033 _dirtyRect( Gtk::gdk_rectangle() ), 0034 _xPadding(0), 0035 _yPadding(0) 0036 {} 0037 0038 //! destructor 0039 virtual ~MenuStateData( void ) 0040 { disconnect( _target ); } 0041 0042 //! setup connections 0043 using FollowMouseData::connect; 0044 virtual void connect( GtkWidget* ); 0045 0046 //! disconnect 0047 using FollowMouseData::disconnect; 0048 virtual void disconnect( GtkWidget* ); 0049 0050 //!@name modifiers 0051 //@{ 0052 0053 //! enable state 0054 void setEnabled( bool value ) 0055 { 0056 0057 // base class 0058 FollowMouseData::setEnabled( value ); 0059 0060 _current._timeLine.setEnabled( value ); 0061 _previous._timeLine.setEnabled( value ); 0062 0063 if( !value ) 0064 { 0065 _current.clear(); 0066 _previous.clear(); 0067 } 0068 0069 } 0070 0071 //! duration 0072 void setDuration( int value ) 0073 { 0074 _current._timeLine.setDuration( value ); 0075 _previous._timeLine.setDuration( value ); 0076 } 0077 0078 //@} 0079 0080 //!@name accessors 0081 //@{ 0082 0083 //! true if animated 0084 bool isAnimated( void ) const 0085 { return isAnimated( AnimationCurrent ) || isAnimated( AnimationPrevious ); } 0086 0087 //! true if given animation type is animated 0088 bool isAnimated( const WidgetType& type ) const 0089 { return data( type )._timeLine.isRunning(); } 0090 0091 //! widget for current animation type 0092 GtkWidget* widget( const WidgetType& type ) const 0093 { return data( type )._widget; } 0094 0095 //! rect for given animation type 0096 const GdkRectangle& rectangle( const WidgetType& type ) const 0097 { return data( type )._rect; } 0098 0099 //! animation data 0100 AnimationData animationData( const WidgetType& type ) const 0101 { 0102 const Data& data( this->data( type ) ); 0103 return data._timeLine.isRunning() ? 0104 AnimationData( data._timeLine.value(), AnimationHover ): 0105 AnimationData(); 0106 } 0107 0108 //! true when fade out animation is locked (delayed) 0109 virtual bool isLocked( void ) const 0110 { return _timer.isRunning(); } 0111 0112 //@} 0113 0114 protected: 0115 0116 //! register child 0117 void registerChild( GtkWidget* ); 0118 0119 //! disconnect child 0120 void unregisterChild( GtkWidget* ); 0121 0122 //! update items 0123 void updateItems( void ); 0124 0125 //! update state for given widget 0126 bool updateState( GtkWidget*, const GdkRectangle&, int, int, bool state, bool delayed = false ); 0127 0128 //! true if menu item is active (pressed down) 0129 bool menuItemIsActive( GtkWidget* ) const; 0130 0131 //! return dirty rect (for update) 0132 GdkRectangle dirtyRect( void ); 0133 0134 //! animations data 0135 class Data 0136 { 0137 0138 public: 0139 0140 //! constructor 0141 explicit Data( void ): 0142 _widget( 0L ), 0143 _rect( Gtk::gdk_rectangle() ), 0144 _xOffset( 0 ), 0145 _yOffset( 0 ) 0146 {} 0147 0148 //! update data 0149 void copy( const Data& other ) 0150 { 0151 _widget = other._widget; 0152 _rect = other._rect; 0153 _xOffset = other._xOffset; 0154 _yOffset = other._yOffset; 0155 } 0156 0157 //! update data 0158 void update( GtkWidget* widget, const GdkRectangle& rect, int xOffset, int yOffset ) 0159 { 0160 _widget = widget; 0161 _rect = rect; 0162 _xOffset = xOffset; 0163 _yOffset = yOffset; 0164 } 0165 0166 //! true if valid 0167 bool isValid( void ) const 0168 { return _widget && Gtk::gdk_rectangle_is_valid( &_rect ); } 0169 0170 //! clear 0171 void clear( void ) 0172 { 0173 if( _timeLine.isRunning() ) _timeLine.stop(); 0174 _widget = 0L; 0175 _rect = Gtk::gdk_rectangle(); 0176 } 0177 0178 //! dirty rect 0179 /*! properly adds offsets between widget window and painting window */ 0180 GdkRectangle dirtyRect( void ) const 0181 { 0182 GdkRectangle rect( _rect ); 0183 rect.x += _xOffset; 0184 rect.y += _yOffset; 0185 return rect; 0186 } 0187 0188 //! timeline 0189 TimeLine _timeLine; 0190 0191 //! widget 0192 GtkWidget* _widget; 0193 0194 //! rectangle 0195 GdkRectangle _rect; 0196 0197 //! offset between paint window and menu window 0198 int _xOffset; 0199 int _yOffset; 0200 0201 }; 0202 0203 //! get data for given animation type 0204 Data& data( const WidgetType& type ) 0205 { 0206 switch( type ) 0207 { 0208 default: 0209 case AnimationCurrent: return _current; 0210 case AnimationPrevious: return _previous; 0211 } 0212 } 0213 0214 //! get data for given animation type 0215 const Data& data( const WidgetType& type ) const 0216 { 0217 switch( type ) 0218 { 0219 default: 0220 case AnimationCurrent: return _current; 0221 case AnimationPrevious: return _previous; 0222 } 0223 } 0224 0225 //!@name callbacks 0226 //@{ 0227 0228 //! child is destroyed 0229 static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer ); 0230 0231 //! mouse motion events 0232 static gboolean motionNotifyEvent( GtkWidget*, GdkEventMotion*, gpointer); 0233 0234 //! mouse leave events 0235 static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer); 0236 0237 //! update widget for fade-in/fade-out animation 0238 static gboolean delayedUpdate( gpointer ); 0239 0240 //! update widget for follow-mouse animation 0241 static gboolean followMouseUpdate( gpointer ); 0242 0243 //! start delayed fade-out animation 0244 static gboolean delayedAnimate( gpointer ); 0245 0246 //@} 0247 0248 private: 0249 0250 //! target 0251 GtkWidget* _target; 0252 0253 //!@name signals 0254 //@{ 0255 Signal _motionId; 0256 Signal _leaveId; 0257 //@} 0258 0259 //!@name animation data 0260 //@{ 0261 0262 //! additional dirty rect 0263 GdkRectangle _dirtyRect; 0264 0265 Data _previous; 0266 Data _current; 0267 0268 //@} 0269 0270 //!@name follow mouse animated data 0271 //@{ 0272 0273 //! padding 0274 gint _xPadding; 0275 gint _yPadding; 0276 0277 //! delayed animation timeOut 0278 static const int _timeOut; 0279 0280 //! timer of delayed animation 0281 Timer _timer; 0282 0283 //@} 0284 0285 //! map children to destroy signal 0286 typedef std::map<GtkWidget*, Signal> ChildrenMap; 0287 ChildrenMap _children; 0288 0289 }; 0290 0291 } 0292 0293 #endif