fixed camera freemove shortcuts bug
[xonotic/netradiant.git] / libs / gtkutil / widget.h
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant 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
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #if !defined(INCLUDED_GTKUTIL_WIDGET_H)
23 #define INCLUDED_GTKUTIL_WIDGET_H
24
25 #include <list>
26 #include <gtk/gtkwidget.h>
27 #include "generic/callback.h"
28 #include "warnings.h"
29 #include "debugging/debugging.h"
30
31 inline void widget_set_visible(GtkWidget* widget, bool shown)
32 {
33   if(shown)
34   {
35     gtk_widget_show(widget);
36   }
37   else
38   {
39     gtk_widget_hide(widget);
40   }
41 }
42
43 inline bool widget_is_visible(GtkWidget* widget)
44 {
45   return GTK_WIDGET_VISIBLE(widget) != FALSE;
46 }
47
48 inline void widget_toggle_visible(GtkWidget* widget)
49 {
50   widget_set_visible(widget, !widget_is_visible(widget));
51 }
52
53 class ToggleItem
54 {
55   BoolExportCallback m_exportCallback;
56   typedef std::list<BoolImportCallback> ImportCallbacks;
57   ImportCallbacks m_importCallbacks;
58 public:
59   ToggleItem(const BoolExportCallback& exportCallback) : m_exportCallback(exportCallback)
60   {
61   }
62
63   void update()
64   {
65     for(ImportCallbacks::iterator i = m_importCallbacks.begin(); i != m_importCallbacks.end(); ++i)
66     {
67       m_exportCallback(*i);
68     }
69   }
70
71   void addCallback(const BoolImportCallback& callback)
72   {
73     m_importCallbacks.push_back(callback);
74     m_exportCallback(callback);
75   }
76   typedef MemberCaller1<ToggleItem, const BoolImportCallback&, &ToggleItem::addCallback> AddCallbackCaller;
77 };
78
79 class ToggleShown
80 {
81   bool m_shownDeferred;
82
83   ToggleShown(const ToggleShown& other); // NOT COPYABLE
84   ToggleShown& operator=(const ToggleShown& other); // NOT ASSIGNABLE
85
86   static gboolean notify_visible(GtkWidget* widget, gpointer dummy, ToggleShown* self)
87   {
88     self->update();
89     return FALSE;
90   }
91   static gboolean destroy(GtkWidget* widget, ToggleShown* self)
92   {
93     self->m_shownDeferred = GTK_WIDGET_VISIBLE(self->m_widget) != FALSE;
94     self->m_widget = 0;
95     return FALSE;
96   }
97 public:
98   GtkWidget* m_widget;
99   ToggleItem m_item;
100
101   ToggleShown(bool shown)
102     : m_shownDeferred(shown), m_widget(0), m_item(ActiveCaller(*this))
103   {
104   }
105   void update()
106   {
107     m_item.update();
108   }
109   bool active() const
110   {
111     if(m_widget == 0)
112     {
113       return m_shownDeferred;
114     }
115     else
116     {
117       return GTK_WIDGET_VISIBLE(m_widget) != FALSE;
118     }
119   }
120   void exportActive(const BoolImportCallback& importCallback)
121   {
122     importCallback(active());
123   }
124   typedef MemberCaller1<ToggleShown, const BoolImportCallback&, &ToggleShown::exportActive> ActiveCaller;
125   void set(bool shown)
126   {
127     if(m_widget == 0)
128     {
129       m_shownDeferred = shown;
130     }
131     else
132     {
133       widget_set_visible(m_widget, shown);
134     }
135   }
136   void toggle()
137   {
138     widget_toggle_visible(m_widget);
139   }
140   typedef MemberCaller<ToggleShown, &ToggleShown::toggle> ToggleCaller;
141   void connect(GtkWidget* widget)
142   {
143     m_widget = widget;
144     widget_set_visible(m_widget, m_shownDeferred);
145     g_signal_connect(G_OBJECT(m_widget), "notify::visible", G_CALLBACK(notify_visible), this);
146     g_signal_connect(G_OBJECT(m_widget), "destroy", G_CALLBACK(destroy), this);
147     update();
148   }
149 };
150
151
152 inline void widget_queue_draw(GtkWidget& widget)
153 {
154   gtk_widget_queue_draw(&widget);
155 }
156 typedef ReferenceCaller<GtkWidget, widget_queue_draw> WidgetQueueDrawCaller;
157
158
159 inline void widget_make_default(GtkWidget* widget)
160 {
161   GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
162   gtk_widget_grab_default(widget);
163 }
164
165 class WidgetFocusPrinter
166 {
167   const char* m_name;
168
169   static gboolean focus_in(GtkWidget *widget, GdkEventFocus *event, WidgetFocusPrinter* self)
170   {
171     globalOutputStream() << self->m_name << " takes focus\n";
172     return FALSE;
173   }
174   static gboolean focus_out(GtkWidget *widget, GdkEventFocus *event, WidgetFocusPrinter* self)
175   {
176     globalOutputStream() << self->m_name << " loses focus\n";
177     return FALSE;
178   }
179 public:
180   WidgetFocusPrinter(const char* name) : m_name(name)
181   {
182   }
183   void connect(GtkWidget* widget)
184   {
185     g_signal_connect(G_OBJECT(widget), "focus_in_event", G_CALLBACK(focus_in), this);
186     g_signal_connect(G_OBJECT(widget), "focus_out_event", G_CALLBACK(focus_out), this);
187   }
188 };
189
190 #endif