1 #ifndef oxygenwidgetstateengine_h
2 #define oxygenwidgetstateengine_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 
24 #include "../oxygenanimationdata.h"
25 #include "../oxygenstyleoptions.h"
26 #include "oxygenanimationengine.h"
27 #include "oxygenbaseengine.h"
28 #include "oxygendatamap.h"
29 #include "oxygenwidgetstatedata.h"
30 
31 #include "../config.h"
32 
33 #include <gtk/gtk.h>
34 #include <iostream>
35 
36 namespace Oxygen
37 {
38     //! forward declaration
39     class Animations;
40 
41     //! associates widgets with some type of data
42     class WidgetStateEngine: public BaseEngine, public AnimationEngine
43     {
44 
45         public:
46 
47         //! constructor
WidgetStateEngine(Animations * widget)48         WidgetStateEngine( Animations* widget ):
49             BaseEngine( widget )
50             {}
51 
52         //! destructor
~WidgetStateEngine(void)53         virtual ~WidgetStateEngine( void )
54         {}
55 
56         //! unregister widget
unregisterWidget(GtkWidget * widget)57         virtual void unregisterWidget( GtkWidget* widget )
58         {
59             unregisterWidget( widget, _hoverData );
60             unregisterWidget( widget, _focusData );
61         }
62 
63         //! enabled state
setEnabled(bool value)64         virtual bool setEnabled( bool value )
65         {
66 
67             if( !BaseEngine::setEnabled( value ) ) return false;
68 
69             // hover data map
70             for( DataMap<WidgetStateData>::Map::iterator iter = _hoverData.map().begin(); iter != _hoverData.map().end(); iter++ )
71             {
72                 iter->second.setEnabled( value );
73                 if( enabled() && !widgetIsBlackListed( iter->first ) ) iter->second.connect( iter->first );
74                 else iter->second.disconnect( iter->first );
75             }
76 
77             // focus data map
78             for( DataMap<WidgetStateData>::Map::iterator iter = _focusData.map().begin(); iter != _focusData.map().end(); iter++ )
79             {
80                 iter->second.setEnabled( value );
81                 if( enabled() && !widgetIsBlackListed( iter->first ) ) iter->second.connect( iter->first );
82                 else iter->second.disconnect( iter->first );
83             }
84 
85             return true;
86         }
87 
88         //! transition duration
setDuration(int value)89         virtual bool setDuration( int value )
90         {
91 
92             if( !AnimationEngine::setDuration( value ) ) return false;
93 
94             // hover data map
95             for( DataMap<WidgetStateData>::Map::iterator iter = _hoverData.map().begin(); iter != _hoverData.map().end(); iter++ )
96             { iter->second.setDuration( value ); }
97 
98             // focus data map
99             for( DataMap<WidgetStateData>::Map::iterator iter = _focusData.map().begin(); iter != _focusData.map().end(); iter++ )
100             { iter->second.setDuration( value ); }
101 
102             return true;
103 
104         }
105 
106         //!@name accessors
107         //@{
108 
109         //! true if widget is included
contains(GtkWidget * widget,AnimationMode mode)110         virtual bool contains( GtkWidget* widget, AnimationMode mode )
111         {
112             switch( mode )
113             {
114                 case AnimationHover: return _hoverData.contains( widget );
115                 case AnimationFocus: return _focusData.contains( widget );
116                 default: return false;
117             }
118         }
119 
120         //! retrieve animation data matching a given widget for provided options
121         /*! note: for convenience, this method also calls ::registerWidget and ::updateState */
122         virtual AnimationData get( GtkWidget* widget, const StyleOptions& options, AnimationModes modes = AnimationHover|AnimationFocus, AnimationMode precedence = AnimationHover )
123         { return get( widget, Gtk::gdk_rectangle(), options, modes, precedence ); }
124 
125         //! retrieve animation data matching a given widget for provided options
126         /*! note: for convenience, this method also calls ::registerWidget and ::updateState */
127         virtual AnimationData get( GtkWidget* widget, const GdkRectangle& rect, const StyleOptions& options, AnimationModes modes = AnimationHover|AnimationFocus, AnimationMode precedence = AnimationHover )
128         {
129 
130             // check widget
131             if( !( enabled() && widget ) ) return AnimationData();
132 
133             // register
134             registerWidget( widget, modes, options );
135 
136             // stores WidgetStateData locally for speedup
137             WidgetStateData* hoverData( (modes&AnimationHover) ? &_hoverData.value( widget ):0L );
138             WidgetStateData* focusData( (modes&AnimationFocus) ? &_focusData.value( widget ):0L );
139 
140             // update state
141             if( hoverData ) hoverData->updateState( (options&Hover) && !(options&Disabled), rect );
142             if( focusData ) focusData->updateState( (options&Focus) && !(options&Disabled), rect );
143 
144             // assume hover takes precedence over focus
145             switch( precedence )
146             {
147                 default:
148                 case AnimationHover:
149                 if( hoverData && hoverData->isAnimated() ) return AnimationData( hoverData->opacity(), AnimationHover );
150                 else if( focusData && focusData->isAnimated() ) return AnimationData( focusData->opacity(), AnimationFocus );
151                 else return AnimationData();
152 
153                 case AnimationFocus:
154                 if( focusData && focusData->isAnimated() ) return AnimationData( focusData->opacity(), AnimationFocus );
155                 else if( hoverData && hoverData->isAnimated() ) return AnimationData( hoverData->opacity(), AnimationHover );
156                 else return AnimationData();
157 
158             }
159 
160         }
161 
162         //@}
163 
164         protected:
165 
166         //! register widget
167         using BaseEngine::registerWidget;
168         virtual bool registerWidget( GtkWidget*, AnimationModes, const StyleOptions& = StyleOptions() );
169 
170         //! register widget in given map
171         bool registerWidget( GtkWidget*, DataMap<WidgetStateData>&, const bool& = false ) const;
172 
173         //! register widget in given map
unregisterWidget(GtkWidget * widget,DataMap<WidgetStateData> & data)174         void unregisterWidget( GtkWidget* widget, DataMap<WidgetStateData>& data ) const
175         {
176             if( !data.contains( widget ) ) return;
177             data.value( widget ).disconnect( widget );
178             data.erase( widget );
179         }
180 
181         private:
182 
183         //!@name maps
184         //@{
185         DataMap<WidgetStateData> _hoverData;
186         DataMap<WidgetStateData> _focusData;
187         //@}
188 
189     };
190 
191 }
192 
193 #endif
194