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