1 #ifndef oxygendatamap_h
2 #define oxygendatamap_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 <cassert>
24 #include <map>
25 #include <gtk/gtk.h>
26 
27 namespace Oxygen
28 {
29 
30     //! generic class to map data to widgets
31     /*
32     Note: I'm not sure about memory management. At some point one might need to allocate the registered
33     data on the heap rather than on the stack, to be able to safely pass the data pointer around via callbacks.
34     The current implementation should make that possible without external code change, provided that the map
35     content is properly deleted (as opposed to erased) in destructor and 'unregister' method.
36     */
37     template <typename T>
38     class DataMap
39     {
40 
41         public:
42 
43         //! constructor
DataMap(void)44         DataMap( void ):
45             _lastWidget( 0L ),
46             _lastData( 0L )
47         {}
48 
~DataMap()49         virtual ~DataMap(){}
50 
51         //! insert new widget
registerWidget(GtkWidget * widget)52         inline T& registerWidget( GtkWidget* widget )
53         {
54             T& data( _map.insert( std::make_pair( widget, T() ) ).first->second );
55             _lastWidget = widget;
56             _lastData = &data;
57             return data;
58         }
59 
60         //! true if widget is in list
contains(GtkWidget * widget)61         virtual bool contains( GtkWidget* widget )
62         {
63 
64             // check against last widget
65             if( widget == _lastWidget ) return true;
66 
67             // find in map, returns false if not found
68             typename Map::iterator iter = _map.find( widget );
69             if( iter == _map.end() ) return false;
70 
71             // store as last widget/last data, to speed up lookup.
72             _lastWidget = widget;
73             _lastData = &iter->second;
74             return true;
75 
76         }
77 
78         //! return value
value(GtkWidget * widget)79         virtual T& value( GtkWidget* widget )
80         {
81 
82             // check against last widget
83             if( widget == _lastWidget ) return *_lastData;
84 
85             // find in map, abort if not found
86             typename Map::iterator iter(  _map.find( widget ) );
87             assert( iter != _map.end() );
88 
89             // store as last widget/last data, to speed up lookup.
90             _lastWidget = widget;
91             _lastData = &iter->second;
92             return iter->second;
93 
94         }
95 
96         //! erase
erase(GtkWidget * widget)97         virtual void erase( GtkWidget* widget )
98         {
99 
100             // clear last widget and data, if match
101             if( _lastWidget == widget )
102             {
103                 _lastWidget = 0L;
104                 _lastData = 0L;
105             }
106 
107             // erase from map
108             _map.erase( widget );
109 
110         }
111 
112         //! connect all widgets in map
connectAll(void)113         void connectAll( void )
114         {
115             for( typename Map::iterator iter = _map.begin(); iter != _map.end(); iter++ )
116             { iter->second.connect( iter->first ); }
117         }
118 
119 
120         //! connect all widgets in map
disconnectAll(void)121         void disconnectAll( void )
122         {
123             for( typename Map::iterator iter = _map.begin(); iter != _map.end(); iter++ )
124             { iter->second.disconnect( iter->first ); }
125         }
126 
127         //! erase
clear(void)128         virtual void clear( void )
129         {
130 
131             _lastWidget = 0L;
132             _lastData = 0L;
133             _map.clear();
134 
135         }
136 
137         //! retrieve internal map
138         typedef std::map<GtkWidget*, T> Map;
map(void)139         Map& map( void )
140         { return _map; }
141 
142         //! retrieve internal map
map(void)143         const Map& map( void ) const
144         { return _map; }
145 
146         protected:
147 
148         //! copy constructor is private
DataMap(const DataMap &)149         DataMap( const DataMap& )
150         { assert( false ); }
151 
152         //! assignment operator
153         DataMap& operator = ( const DataMap& )
154         {
155             assert( false );
156             return *this;
157         }
158 
159         private:
160 
161         //! pointer to last inquired widget
162         GtkWidget* _lastWidget;
163 
164         //! pointer to last retrieved data
165         T* _lastData;
166 
167         //! internal map between widget and data
168         Map _map;
169 
170     };
171 
172 }
173 
174 #endif
175