Make everything compile with GTK_DISABLE_DEPRECATED declared.
[wxWidgets.git] / src / gtk / tglbtn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/gtk/tglbtn.cpp
3 // Purpose: Definition of the wxToggleButton class, which implements a
4 // toggle button under wxGTK.
5 // Author: John Norris, minor changes by Axel Schlueter
6 // Modified by:
7 // Created: 08.02.01
8 // RCS-ID: $Id$
9 // Copyright: (c) 2000 Johnny C. Norris II
10 // License: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
15
16 #include "wx/tglbtn.h"
17 #include "wx/button.h"
18
19 #if wxUSE_TOGGLEBTN
20
21 // FIXME: Use GtkImage instead of GtkPixmap.
22 #include <gtk/gtkversion.h>
23 #ifdef GTK_DISABLE_DEPRECATED
24 #undef GTK_DISABLE_DEPRECATED
25 #endif
26
27 #include "wx/gtk/private.h"
28
29 extern void wxapp_install_idle_handler();
30 extern bool g_isIdle;
31 extern bool g_blockEventsOnDrag;
32 extern wxCursor g_globalCursor;
33
34 extern "C" {
35 static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb)
36 {
37 if (g_isIdle)
38 wxapp_install_idle_handler();
39
40 if (!cb->m_hasVMT || g_blockEventsOnDrag)
41 return;
42
43 if (cb->m_blockEvent) return;
44
45 // Generate a wx event.
46 wxCommandEvent event(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, cb->GetId());
47 event.SetInt(cb->GetValue());
48 event.SetEventObject(cb);
49 cb->GetEventHandler()->ProcessEvent(event);
50 }
51 }
52
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED)
54
55 // ------------------------------------------------------------------------
56 // wxToggleBitmapButton
57 // ------------------------------------------------------------------------
58
59 IMPLEMENT_DYNAMIC_CLASS(wxToggleBitmapButton, wxControl)
60
61 bool wxToggleBitmapButton::Create(wxWindow *parent, wxWindowID id,
62 const wxBitmap &label, const wxPoint &pos,
63 const wxSize &size, long style,
64 const wxValidator& validator,
65 const wxString &name)
66 {
67 m_needParent = true;
68 m_acceptsFocus = true;
69
70 m_blockEvent = false;
71
72 if (!PreCreation(parent, pos, size) ||
73 !CreateBase(parent, id, pos, size, style, validator, name ))
74 {
75 wxFAIL_MSG(wxT("wxToggleBitmapButton creation failed"));
76 return false;
77 }
78
79 m_bitmap = label;
80
81 // Create the gtk widget.
82 m_widget = gtk_toggle_button_new();
83
84 if (style & wxNO_BORDER)
85 gtk_button_set_relief( GTK_BUTTON(m_widget), GTK_RELIEF_NONE );
86
87 if (m_bitmap.Ok())
88 {
89 OnSetBitmap();
90 }
91
92 g_signal_connect (m_widget, "clicked",
93 G_CALLBACK (gtk_togglebutton_clicked_callback),
94 this);
95
96 m_parent->DoAddChild(this);
97
98 PostCreation(size);
99
100 return true;
101 }
102
103 // void SetValue(bool state)
104 // Set the value of the toggle button.
105 void wxToggleBitmapButton::SetValue(bool state)
106 {
107 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
108
109 if (state == GetValue())
110 return;
111
112 m_blockEvent = true;
113
114 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
115
116 m_blockEvent = false;
117 }
118
119 // bool GetValue() const
120 // Get the value of the toggle button.
121 bool wxToggleBitmapButton::GetValue() const
122 {
123 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
124
125 return GTK_TOGGLE_BUTTON(m_widget)->active;
126 }
127
128 void wxToggleBitmapButton::SetLabel(const wxBitmap& label)
129 {
130 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
131
132 m_bitmap = label;
133 InvalidateBestSize();
134
135 OnSetBitmap();
136 }
137
138 void wxToggleBitmapButton::OnSetBitmap()
139 {
140 if (!m_bitmap.Ok()) return;
141
142 GdkBitmap *mask = (GdkBitmap *) NULL;
143 if (m_bitmap.GetMask()) mask = m_bitmap.GetMask()->GetBitmap();
144
145 GtkWidget *child = GTK_BIN(m_widget)->child;
146 if (child == NULL)
147 {
148 // initial bitmap
149 GtkWidget *pixmap = gtk_pixmap_new(m_bitmap.GetPixmap(), mask);
150 gtk_widget_show(pixmap);
151 gtk_container_add(GTK_CONTAINER(m_widget), pixmap);
152 }
153 else
154 { // subsequent bitmaps
155 GtkPixmap *g_pixmap = GTK_PIXMAP(child);
156 gtk_pixmap_set(g_pixmap, m_bitmap.GetPixmap(), mask);
157 }
158 }
159
160 bool wxToggleBitmapButton::Enable(bool enable /*=true*/)
161 {
162 if (!wxControl::Enable(enable))
163 return false;
164
165 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
166
167 return true;
168 }
169
170 void wxToggleBitmapButton::DoApplyWidgetStyle(GtkRcStyle *style)
171 {
172 gtk_widget_modify_style(m_widget, style);
173 gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
174 }
175
176 bool wxToggleBitmapButton::IsOwnGtkWindow(GdkWindow *window)
177 {
178 return window == GTK_BUTTON(m_widget)->event_window;
179 }
180
181 void wxToggleBitmapButton::OnInternalIdle()
182 {
183 wxCursor cursor = m_cursor;
184
185 if (g_globalCursor.Ok())
186 cursor = g_globalCursor;
187
188 GdkWindow *win = GTK_BUTTON(m_widget)->event_window;
189 if ( win && cursor.Ok() )
190 {
191 /* I now set the cursor the anew in every OnInternalIdle call
192 as setting the cursor in a parent window also effects the
193 windows above so that checking for the current cursor is
194 not possible. */
195
196 gdk_window_set_cursor(win, cursor.GetCursor());
197 }
198
199 if (wxUpdateUIEvent::CanUpdate(this))
200 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
201 }
202
203
204 // Get the "best" size for this control.
205 wxSize wxToggleBitmapButton::DoGetBestSize() const
206 {
207 wxSize best;
208
209 if (m_bitmap.Ok())
210 {
211 int border = HasFlag(wxNO_BORDER) ? 4 : 10;
212 best.x = m_bitmap.GetWidth()+border;
213 best.y = m_bitmap.GetHeight()+border;
214 }
215 CacheBestSize(best);
216 return best;
217 }
218
219
220 // static
221 wxVisualAttributes
222 wxToggleBitmapButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
223 {
224 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
225 }
226
227
228 // ------------------------------------------------------------------------
229 // wxToggleButton
230 // ------------------------------------------------------------------------
231
232 IMPLEMENT_DYNAMIC_CLASS(wxToggleButton, wxControl)
233
234 bool wxToggleButton::Create(wxWindow *parent, wxWindowID id,
235 const wxString &label, const wxPoint &pos,
236 const wxSize &size, long style,
237 const wxValidator& validator,
238 const wxString &name)
239 {
240 m_needParent = true;
241 m_acceptsFocus = true;
242
243 m_blockEvent = false;
244
245 if (!PreCreation(parent, pos, size) ||
246 !CreateBase(parent, id, pos, size, style, validator, name )) {
247 wxFAIL_MSG(wxT("wxToggleButton creation failed"));
248 return false;
249 }
250
251 wxControl::SetLabel(label);
252
253 // Create the gtk widget.
254 m_widget = gtk_toggle_button_new_with_label( wxGTK_CONV( m_label ) );
255
256 g_signal_connect (m_widget, "clicked",
257 G_CALLBACK (gtk_togglebutton_clicked_callback),
258 this);
259
260 m_parent->DoAddChild(this);
261
262 PostCreation(size);
263
264 return true;
265 }
266
267 // void SetValue(bool state)
268 // Set the value of the toggle button.
269 void wxToggleButton::SetValue(bool state)
270 {
271 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
272
273 if (state == GetValue())
274 return;
275
276 m_blockEvent = true;
277
278 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
279
280 m_blockEvent = false;
281 }
282
283 // bool GetValue() const
284 // Get the value of the toggle button.
285 bool wxToggleButton::GetValue() const
286 {
287 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
288
289 return GTK_TOGGLE_BUTTON(m_widget)->active;
290 }
291
292 void wxToggleButton::SetLabel(const wxString& label)
293 {
294 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
295
296 wxControl::SetLabel(label);
297
298 gtk_label_set_text(GTK_LABEL(GTK_BIN(m_widget)->child), wxGTK_CONV(GetLabel()));
299 }
300
301 bool wxToggleButton::Enable(bool enable /*=true*/)
302 {
303 if (!wxControl::Enable(enable))
304 return false;
305
306 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
307
308 return true;
309 }
310
311 void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle *style)
312 {
313 gtk_widget_modify_style(m_widget, style);
314 gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
315 }
316
317 bool wxToggleButton::IsOwnGtkWindow(GdkWindow *window)
318 {
319 return window == GTK_BUTTON(m_widget)->event_window;
320 }
321
322 void wxToggleButton::OnInternalIdle()
323 {
324 wxCursor cursor = m_cursor;
325
326 if (g_globalCursor.Ok())
327 cursor = g_globalCursor;
328
329 GdkWindow *win = GTK_BUTTON(m_widget)->event_window;
330 if ( win && cursor.Ok() )
331 {
332 /* I now set the cursor the anew in every OnInternalIdle call
333 as setting the cursor in a parent window also effects the
334 windows above so that checking for the current cursor is
335 not possible. */
336
337 gdk_window_set_cursor(win, cursor.GetCursor());
338 }
339
340 if (wxUpdateUIEvent::CanUpdate(this))
341 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
342 }
343
344
345 // Get the "best" size for this control.
346 wxSize wxToggleButton::DoGetBestSize() const
347 {
348 wxSize ret(wxControl::DoGetBestSize());
349
350 if (!HasFlag(wxBU_EXACTFIT))
351 {
352 if (ret.x < 80) ret.x = 80;
353 }
354
355 CacheBestSize(ret);
356 return ret;
357 }
358
359 // static
360 wxVisualAttributes
361 wxToggleButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
362 {
363 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
364 }
365
366 #endif // wxUSE_TOGGLEBTN
367