File indexing completed on 2024-05-12 17:05:47
0001 #ifndef oxygencomboboxdata_h 0002 #define oxygencomboboxdata_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 #include "oxygensignal.h" 0011 0012 #include <gtk/gtk.h> 0013 #include <algorithm> 0014 #include <map> 0015 #include <iostream> 0016 0017 namespace Oxygen 0018 { 0019 0020 // handles focus and hover and pressed down state for comboboxes 0021 class ComboBoxData 0022 { 0023 0024 public: 0025 0026 //! constructor 0027 ComboBoxData( void ): 0028 _target( 0L ), 0029 _list( 0L ) 0030 {} 0031 0032 //! destructor 0033 virtual ~ComboBoxData( void ) 0034 { disconnect( _target ); } 0035 0036 //! setup connections 0037 /*! does nothing. Only kept here for consistency with other data */ 0038 void connect( GtkWidget* ); 0039 0040 //! disconnect 0041 void disconnect( GtkWidget* ); 0042 0043 //!@name modifiers 0044 //@{ 0045 0046 //! list 0047 void setList( GtkWidget* widget ) 0048 { _list = widget; } 0049 0050 //! assign button 0051 void setButton( GtkWidget* value ); 0052 0053 //! button focus 0054 void setButtonFocus( bool value ) 0055 { 0056 if( _button._focus == value ) return; 0057 _button._focus = value; 0058 0059 // trigger update 0060 if( _target ) gtk_widget_queue_draw( _target ); 0061 0062 return; 0063 } 0064 0065 //! register child 0066 void registerChild( GtkWidget*, bool recursive = true ); 0067 0068 //@} 0069 0070 //!@name accessors 0071 //@{ 0072 0073 //! list 0074 GtkWidget* list( void ) const 0075 { return _list; } 0076 0077 //! pressed 0078 bool pressed( void ) const 0079 { return _button._pressed; } 0080 0081 //! true if either button or entry has focus 0082 bool hasFocus( void ) const 0083 { return _button._focus; } 0084 0085 //! true if either button or entry has hover 0086 bool hovered( void ) const 0087 { return std::find_if( _hoverData.begin(), _hoverData.end(), HoveredFTor() ) != _hoverData.end(); } 0088 0089 //@} 0090 0091 protected: 0092 0093 //! initialize cell view 0094 void initializeCellView( GtkWidget* value ); 0095 0096 //! update cell view color 0097 void updateCellViewColor( void ) const; 0098 0099 //! update button event window 0100 /*! 0101 the trick is to extend the button event window by 6 pixels to the left, 0102 in order to fill a dead area created by the Combobox's GtkFrame's margin. 0103 */ 0104 void updateButtonEventWindow( void ) const; 0105 0106 //! set hover flag for given widget 0107 void setPressed( GtkWidget*, bool ); 0108 0109 //! set hover flag for given widget 0110 void setHovered( GtkWidget*, bool ); 0111 0112 //! disconnect child 0113 void unregisterChild( GtkWidget* ); 0114 0115 //!@name callbacks 0116 //@{ 0117 0118 static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer ); 0119 static void childToggledEvent( GtkWidget*, gpointer ); 0120 static void childSizeAllocateEvent( GtkWidget*, GtkAllocation*, gpointer ); 0121 0122 static gboolean enterNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer ); 0123 static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer ); 0124 static void stateChangeEvent( GtkWidget*, GtkStateType, gpointer ); 0125 static void styleSetEvent( GtkWidget*, GtkStyle*, gpointer ); 0126 0127 //@} 0128 0129 private: 0130 0131 //! target widget 0132 GtkWidget* _target; 0133 0134 //! drop-down list, if set 0135 GtkWidget* _list; 0136 0137 //!@name signals 0138 //@{ 0139 0140 //! state change signal 0141 Signal _stateChangeId; 0142 0143 //! style set 0144 Signal _styleSetId; 0145 0146 //@} 0147 0148 // handle child registration 0149 class ChildData 0150 { 0151 0152 public: 0153 0154 //! constructor 0155 explicit ChildData( void ): 0156 _widget(0L) 0157 {} 0158 0159 //! destructor 0160 virtual ~ChildData( void ) 0161 {} 0162 0163 //! disconnect 0164 virtual void disconnect( void ); 0165 0166 //! widget 0167 GtkWidget* _widget; 0168 0169 //!callback id 0170 Signal _destroyId; 0171 0172 }; 0173 0174 // handle focus and toggle state 0175 class ButtonData: public ChildData 0176 { 0177 0178 public: 0179 0180 //! constructor 0181 explicit ButtonData( void ): 0182 _pressed( false ), 0183 _focus( false ) 0184 {} 0185 0186 //! destructor 0187 virtual ~ButtonData( void ) 0188 {} 0189 0190 //! disconnect 0191 virtual void disconnect( void ); 0192 0193 //! true if widget is down 0194 bool _pressed; 0195 0196 //! true if widget has focus 0197 bool _focus; 0198 0199 //! toggled callback Id 0200 Signal _toggledId; 0201 Signal _sizeAllocateId; 0202 0203 }; 0204 0205 class HoverData: public ChildData 0206 { 0207 public: 0208 0209 //! constructor 0210 explicit HoverData( void ): 0211 _hovered( false ) 0212 {} 0213 0214 //! destructor 0215 virtual ~HoverData( void ) 0216 {} 0217 0218 //! disconnect 0219 virtual void disconnect( void ); 0220 0221 //! true if widget is hovered 0222 bool _hovered; 0223 0224 //!@name callback ids 0225 //@{ 0226 Signal _enterId; 0227 Signal _leaveId; 0228 //@} 0229 0230 }; 0231 0232 //! need to detect hovered child 0233 class HoveredFTor 0234 { 0235 public: 0236 0237 bool operator () ( const std::pair<GtkWidget*, HoverData>& dataPair ) 0238 { return dataPair.second._hovered; } 0239 0240 }; 0241 0242 typedef std::map<GtkWidget*, HoverData> HoverDataMap; 0243 HoverDataMap _hoverData; 0244 0245 //! true if cell layout has been initialized 0246 bool _cellLayoutInitialized; 0247 0248 //! cell data 0249 ChildData _cell; 0250 0251 //! button data 0252 ButtonData _button; 0253 0254 }; 0255 0256 } 0257 0258 #endif