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