1 #ifndef oxygencomboboxdata_h 2 #define oxygencomboboxdata_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 "oxygensignal.h" 24 25 #include <gtk/gtk.h> 26 #include <algorithm> 27 #include <map> 28 #include <iostream> 29 30 namespace Oxygen 31 { 32 33 // handles focus and hover and pressed down state for comboboxes 34 class ComboBoxData 35 { 36 37 public: 38 39 //! constructor ComboBoxData(void)40 ComboBoxData( void ): 41 _target( 0L ), 42 _list( 0L ) 43 {} 44 45 //! destructor ~ComboBoxData(void)46 virtual ~ComboBoxData( void ) 47 { disconnect( _target ); } 48 49 //! setup connections 50 /*! does nothing. Only kept here for consistency with other data */ 51 void connect( GtkWidget* ); 52 53 //! disconnect 54 void disconnect( GtkWidget* ); 55 56 //!@name modifiers 57 //@{ 58 59 //! list setList(GtkWidget * widget)60 void setList( GtkWidget* widget ) 61 { _list = widget; } 62 63 //! assign button 64 void setButton( GtkWidget* value ); 65 66 //! button focus setButtonFocus(bool value)67 void setButtonFocus( bool value ) 68 { 69 if( _button._focus == value ) return; 70 _button._focus = value; 71 72 // trigger update 73 if( _target ) gtk_widget_queue_draw( _target ); 74 75 return; 76 } 77 78 //! register child 79 void registerChild( GtkWidget*, bool recursive = true ); 80 81 //@} 82 83 //!@name accessors 84 //@{ 85 86 //! list list(void)87 GtkWidget* list( void ) const 88 { return _list; } 89 90 //! pressed pressed(void)91 bool pressed( void ) const 92 { return _button._pressed; } 93 94 //! true if either button or entry has focus hasFocus(void)95 bool hasFocus( void ) const 96 { return _button._focus; } 97 98 //! true if either button or entry has hover hovered(void)99 bool hovered( void ) const 100 { return std::find_if( _hoverData.begin(), _hoverData.end(), HoveredFTor() ) != _hoverData.end(); } 101 102 //@} 103 104 protected: 105 106 //! initialize cell view 107 void initializeCellView( GtkWidget* value ); 108 109 //! update cell view color 110 void updateCellViewColor( void ) const; 111 112 //! update button event window 113 /*! 114 the trick is to extend the button event window by 6 pixels to the left, 115 in order to fill a dead area created by the Combobox's GtkFrame's margin. 116 */ 117 void updateButtonEventWindow( void ) const; 118 119 //! set hover flag for given widget 120 void setPressed( GtkWidget*, bool ); 121 122 //! set hover flag for given widget 123 void setHovered( GtkWidget*, bool ); 124 125 //! disconnect child 126 void unregisterChild( GtkWidget* ); 127 128 //!@name callbacks 129 //@{ 130 131 static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer ); 132 static void childToggledEvent( GtkWidget*, gpointer ); 133 static void childSizeAllocateEvent( GtkWidget*, GtkAllocation*, gpointer ); 134 135 static gboolean enterNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer ); 136 static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer ); 137 static void stateChangeEvent( GtkWidget*, GtkStateType, gpointer ); 138 static void styleSetEvent( GtkWidget*, GtkStyle*, gpointer ); 139 140 //@} 141 142 private: 143 144 //! target widget 145 GtkWidget* _target; 146 147 //! drop-down list, if set 148 GtkWidget* _list; 149 150 //!@name signals 151 //@{ 152 153 //! state change signal 154 Signal _stateChangeId; 155 156 //! style set 157 Signal _styleSetId; 158 159 //@} 160 161 // handle child registration 162 class ChildData 163 { 164 165 public: 166 167 //! constructor ChildData(void)168 explicit ChildData( void ): 169 _widget(0L) 170 {} 171 172 //! destructor ~ChildData(void)173 virtual ~ChildData( void ) 174 {} 175 176 //! disconnect 177 virtual void disconnect( void ); 178 179 //! widget 180 GtkWidget* _widget; 181 182 //!callback id 183 Signal _destroyId; 184 185 }; 186 187 // handle focus and toggle state 188 class ButtonData: public ChildData 189 { 190 191 public: 192 193 //! constructor ButtonData(void)194 explicit ButtonData( void ): 195 _pressed( false ), 196 _focus( false ) 197 {} 198 199 //! destructor ~ButtonData(void)200 virtual ~ButtonData( void ) 201 {} 202 203 //! disconnect 204 virtual void disconnect( void ); 205 206 //! true if widget is down 207 bool _pressed; 208 209 //! true if widget has focus 210 bool _focus; 211 212 //! toggled callback Id 213 Signal _toggledId; 214 Signal _sizeAllocateId; 215 216 }; 217 218 class HoverData: public ChildData 219 { 220 public: 221 222 //! constructor HoverData(void)223 explicit HoverData( void ): 224 _hovered( false ) 225 {} 226 227 //! destructor ~HoverData(void)228 virtual ~HoverData( void ) 229 {} 230 231 //! disconnect 232 virtual void disconnect( void ); 233 234 //! true if widget is hovered 235 bool _hovered; 236 237 //!@name callback ids 238 //@{ 239 Signal _enterId; 240 Signal _leaveId; 241 //@} 242 243 }; 244 245 //! need to detect hovered child 246 class HoveredFTor 247 { 248 public: 249 operator()250 bool operator () ( const std::pair<GtkWidget*, HoverData>& dataPair ) 251 { return dataPair.second._hovered; } 252 253 }; 254 255 typedef std::map<GtkWidget*, HoverData> HoverDataMap; 256 HoverDataMap _hoverData; 257 258 //! true if cell layout has been initialized 259 bool _cellLayoutInitialized; 260 261 //! cell data 262 ChildData _cell; 263 264 //! button data 265 ButtonData _button; 266 267 }; 268 269 } 270 271 #endif 272