File indexing completed on 2024-05-12 05:34:37
0001 #ifndef oxygenwidgetstateengine_h 0002 #define oxygenwidgetstateengine_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 0011 #include "../oxygenanimationdata.h" 0012 #include "../oxygenstyleoptions.h" 0013 #include "oxygenanimationengine.h" 0014 #include "oxygenbaseengine.h" 0015 #include "oxygendatamap.h" 0016 #include "oxygenwidgetstatedata.h" 0017 0018 #include "../config.h" 0019 0020 #include <gtk/gtk.h> 0021 #include <iostream> 0022 0023 namespace Oxygen 0024 { 0025 //! forward declaration 0026 class Animations; 0027 0028 //! associates widgets with some type of data 0029 class WidgetStateEngine: public BaseEngine, public AnimationEngine 0030 { 0031 0032 public: 0033 0034 //! constructor 0035 WidgetStateEngine( Animations* widget ): 0036 BaseEngine( widget ) 0037 {} 0038 0039 //! destructor 0040 virtual ~WidgetStateEngine( void ) 0041 {} 0042 0043 //! unregister widget 0044 virtual void unregisterWidget( GtkWidget* widget ) 0045 { 0046 unregisterWidget( widget, _hoverData ); 0047 unregisterWidget( widget, _focusData ); 0048 } 0049 0050 //! enabled state 0051 virtual bool setEnabled( bool value ) 0052 { 0053 0054 if( !BaseEngine::setEnabled( value ) ) return false; 0055 0056 // hover data map 0057 for( DataMap<WidgetStateData>::Map::iterator iter = _hoverData.map().begin(); iter != _hoverData.map().end(); iter++ ) 0058 { 0059 iter->second.setEnabled( value ); 0060 if( enabled() && !widgetIsBlackListed( iter->first ) ) iter->second.connect( iter->first ); 0061 else iter->second.disconnect( iter->first ); 0062 } 0063 0064 // focus data map 0065 for( DataMap<WidgetStateData>::Map::iterator iter = _focusData.map().begin(); iter != _focusData.map().end(); iter++ ) 0066 { 0067 iter->second.setEnabled( value ); 0068 if( enabled() && !widgetIsBlackListed( iter->first ) ) iter->second.connect( iter->first ); 0069 else iter->second.disconnect( iter->first ); 0070 } 0071 0072 return true; 0073 } 0074 0075 //! transition duration 0076 virtual bool setDuration( int value ) 0077 { 0078 0079 if( !AnimationEngine::setDuration( value ) ) return false; 0080 0081 // hover data map 0082 for( DataMap<WidgetStateData>::Map::iterator iter = _hoverData.map().begin(); iter != _hoverData.map().end(); iter++ ) 0083 { iter->second.setDuration( value ); } 0084 0085 // focus data map 0086 for( DataMap<WidgetStateData>::Map::iterator iter = _focusData.map().begin(); iter != _focusData.map().end(); iter++ ) 0087 { iter->second.setDuration( value ); } 0088 0089 return true; 0090 0091 } 0092 0093 //!@name accessors 0094 //@{ 0095 0096 //! true if widget is included 0097 virtual bool contains( GtkWidget* widget, AnimationMode mode ) 0098 { 0099 switch( mode ) 0100 { 0101 case AnimationHover: return _hoverData.contains( widget ); 0102 case AnimationFocus: return _focusData.contains( widget ); 0103 default: return false; 0104 } 0105 } 0106 0107 //! retrieve animation data matching a given widget for provided options 0108 /*! note: for convenience, this method also calls ::registerWidget and ::updateState */ 0109 virtual AnimationData get( GtkWidget* widget, const StyleOptions& options, AnimationModes modes = AnimationHover|AnimationFocus, AnimationMode precedence = AnimationHover ) 0110 { return get( widget, Gtk::gdk_rectangle(), options, modes, precedence ); } 0111 0112 //! retrieve animation data matching a given widget for provided options 0113 /*! note: for convenience, this method also calls ::registerWidget and ::updateState */ 0114 virtual AnimationData get( GtkWidget* widget, const GdkRectangle& rect, const StyleOptions& options, AnimationModes modes = AnimationHover|AnimationFocus, AnimationMode precedence = AnimationHover ) 0115 { 0116 0117 // check widget 0118 if( !( enabled() && widget ) ) return AnimationData(); 0119 0120 // register 0121 registerWidget( widget, modes, options ); 0122 0123 // stores WidgetStateData locally for speedup 0124 WidgetStateData* hoverData( (modes&AnimationHover) ? &_hoverData.value( widget ):0L ); 0125 WidgetStateData* focusData( (modes&AnimationFocus) ? &_focusData.value( widget ):0L ); 0126 0127 // update state 0128 if( hoverData ) hoverData->updateState( (options&Hover) && !(options&Disabled), rect ); 0129 if( focusData ) focusData->updateState( (options&Focus) && !(options&Disabled), rect ); 0130 0131 // assume hover takes precedence over focus 0132 switch( precedence ) 0133 { 0134 default: 0135 case AnimationHover: 0136 if( hoverData && hoverData->isAnimated() ) return AnimationData( hoverData->opacity(), AnimationHover ); 0137 else if( focusData && focusData->isAnimated() ) return AnimationData( focusData->opacity(), AnimationFocus ); 0138 else return AnimationData(); 0139 0140 case AnimationFocus: 0141 if( focusData && focusData->isAnimated() ) return AnimationData( focusData->opacity(), AnimationFocus ); 0142 else if( hoverData && hoverData->isAnimated() ) return AnimationData( hoverData->opacity(), AnimationHover ); 0143 else return AnimationData(); 0144 0145 } 0146 0147 } 0148 0149 //@} 0150 0151 protected: 0152 0153 //! register widget 0154 using BaseEngine::registerWidget; 0155 virtual bool registerWidget( GtkWidget*, AnimationModes, const StyleOptions& = StyleOptions() ); 0156 0157 //! register widget in given map 0158 bool registerWidget( GtkWidget*, DataMap<WidgetStateData>&, const bool& = false ) const; 0159 0160 //! register widget in given map 0161 void unregisterWidget( GtkWidget* widget, DataMap<WidgetStateData>& data ) const 0162 { 0163 if( !data.contains( widget ) ) return; 0164 data.value( widget ).disconnect( widget ); 0165 data.erase( widget ); 0166 } 0167 0168 private: 0169 0170 //!@name maps 0171 //@{ 0172 DataMap<WidgetStateData> _hoverData; 0173 DataMap<WidgetStateData> _focusData; 0174 //@} 0175 0176 }; 0177 0178 } 0179 0180 #endif