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