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