1 #ifndef oxygentabwidgetdata_h
2 #define oxygentabwidgetdata_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 <vector>
27 #include <map>
28 
29 namespace Oxygen
30 {
31 
32     //! detects and stores tab widget hovered tab
33     class TabWidgetData
34     {
35 
36         public:
37 
38         //! constructor
TabWidgetData(void)39         TabWidgetData( void ):
40             _target(0L),
41             _hoveredTab(-1),
42             _dragInProgress( false ),
43             _dirty( false )
44         {}
45 
46         //! destructor
~TabWidgetData(void)47         virtual ~TabWidgetData( void )
48         { disconnect( _target ); }
49 
50         //! setup connections
51         void connect( GtkWidget* );
52 
53         //! disconnect
54         void disconnect( GtkWidget* );
55 
56         //!@name modifiers
57         //@{
58 
59         //! update tab rectangle
60         /* this is used to decide when a tab is hovered or not */
61         void updateTabRect( GtkWidget*, int, const GdkRectangle& );
62 
63         //! update hovered tab
64         void updateHoveredTab( GtkWidget* = 0L );
65 
66         //! true when drag is in progress
setDragInProgress(bool value)67         void setDragInProgress( bool value )
68         { _dragInProgress = value; }
69 
70         //! toggle dirty state
toggleDirty(void)71         void toggleDirty( void )
72         { setDirty( !isDirty() ); }
73 
74         //! mark as dirty
75         void setDirty( bool );
76 
77         //@}
78 
79         //@name accessors
80         //@{
81 
82         //! true if hovered
hoveredTab(void)83         int hoveredTab( void ) const
84         { return _hoveredTab; }
85 
86         //! true when drag is in progress
dragInProgress(void)87         bool dragInProgress( void ) const
88         { return _dragInProgress; }
89 
90         //! true if is dirty
isDirty(void)91         bool isDirty( void ) const
92         { return _dirty; }
93 
94         //! returns true if provided point is in one tab of the widget
95         bool isInTab( int x, int y ) const;
96 
97         //@]
98 
99         protected:
100 
101         //! set current tab
102         void setHoveredTab( GtkWidget*, int );
103 
104         //! child registration
105         //@{
106 
107         void updateRegisteredChildren( GtkWidget* = 0L );
108         void registerChild( GtkWidget* );
109         void unregisterChild( GtkWidget* );
110 
111         //@}
112 
113         //!@name static callbacks
114         //@{
115         static gboolean motionNotifyEvent( GtkWidget*, GdkEventMotion*, gpointer );
116         static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer );
117         static void pageAddedEvent( GtkNotebook*, GtkWidget*, guint, gpointer );
118         static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer );
119         static gboolean childCrossingNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer );
120         static void childAddedEvent( GtkContainer*, GtkWidget*, gpointer );
121         //@}
122 
123         private:
124 
125         //! default tabRect size
defaultRect(void)126         GdkRectangle defaultRect( void ) const
127         {
128             GdkRectangle out = {0, 0, -1, -1};
129             return out;
130         }
131 
132         //! target widget
133         GtkWidget* _target;
134 
135         //!@name callbacks IDs
136         //@{
137         Signal _motionId;
138         Signal _leaveId;
139         Signal _pageAddedId;
140         //@}
141 
142         //! index of currently hovered tab
143         int _hoveredTab;
144 
145         //! true when there is a drag in progress
146         bool _dragInProgress;
147 
148         //! true when tabbar is dirty
149         /*! a repaint is triggered of the full tabbar when set to true.
150         This forces the tabbar base to be redrawn event if the selected tab
151         has not been primarily damaged */
152         bool _dirty;
153 
154         //! store rectangles matching tabs
155         typedef std::vector<GdkRectangle> RectangleList;
156         RectangleList _tabRects;
157 
158         //! child data
159         /*!
160         one must keep track of the tab widgets children enter/leave event
161         to properly update tab hover because some tabs have embedded children.
162         This is notably the case for gimp, nautilus (in tabbed mode), etc.
163         */
164         class ChildData
165         {
166             public:
167 
168             //! constructor
ChildData(void)169             ChildData( void )
170             {}
171 
172             //! destructor
~ChildData(void)173             virtual ~ChildData( void )
174             {}
175 
176             //! disconnect all signals
177             void disconnect( void );
178 
179             Signal _destroyId;
180             Signal _addId;
181             Signal _enterId;
182             Signal _leaveId;
183         };
184 
185         //! map registered children and corresponding data
186         typedef std::map<GtkWidget*, ChildData> ChildDataMap;
187         ChildDataMap _childrenData;
188 
189     };
190 
191 }
192 
193 #endif
194