]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/tglbtn.cpp
Added wxDataViewProgressCell with native 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
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
VZ
28
29extern void wxapp_install_idle_handler();
30extern bool g_isIdle;
31extern bool g_blockEventsOnDrag;
32extern wxCursor g_globalCursor;
33
865bb325 34extern "C" {
9864c56d 35static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb)
1db8dc4a 36{
91af0895
WS
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);
1db8dc4a 50}
865bb325 51}
1db8dc4a 52
1db8dc4a
VZ
53DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED)
54
4f856067
RR
55// ------------------------------------------------------------------------
56// wxToggleBitmapButton
57// ------------------------------------------------------------------------
58
59IMPLEMENT_DYNAMIC_CLASS(wxToggleBitmapButton, wxControl)
60
61bool 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{
91af0895
WS
67 m_needParent = true;
68 m_acceptsFocus = true;
69
70 m_blockEvent = false;
4f856067
RR
71
72 if (!PreCreation(parent, pos, size) ||
73 !CreateBase(parent, id, pos, size, style, validator, name ))
74 {
75 wxFAIL_MSG(wxT("wxToggleBitmapButton creation failed"));
91af0895 76 return false;
4f856067 77 }
91af0895 78
4f856067
RR
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 {
4f856067
RR
89 OnSetBitmap();
90 }
91
9fa72bd2
MR
92 g_signal_connect (m_widget, "clicked",
93 G_CALLBACK (gtk_togglebutton_clicked_callback),
94 this);
4f856067
RR
95
96 m_parent->DoAddChild(this);
97
abdeb9e7 98 PostCreation(size);
4f856067 99
91af0895 100 return true;
4f856067
RR
101}
102
103// void SetValue(bool state)
104// Set the value of the toggle button.
105void wxToggleBitmapButton::SetValue(bool state)
106{
91af0895 107 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
4f856067 108
91af0895
WS
109 if (state == GetValue())
110 return;
4f856067 111
91af0895 112 m_blockEvent = true;
4f856067 113
91af0895 114 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
4f856067 115
91af0895 116 m_blockEvent = false;
4f856067
RR
117}
118
119// bool GetValue() const
120// Get the value of the toggle button.
121bool wxToggleBitmapButton::GetValue() const
122{
91af0895 123 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
4f856067 124
91af0895 125 return GTK_TOGGLE_BUTTON(m_widget)->active;
4f856067
RR
126}
127
128void wxToggleBitmapButton::SetLabel(const wxBitmap& label)
129{
130 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
131
132 m_bitmap = label;
9f884528 133 InvalidateBestSize();
91af0895 134
4f856067
RR
135 OnSetBitmap();
136}
137
138void 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
afa7bd1e 145 GtkWidget *child = GTK_BIN(m_widget)->child;
4f856067
RR
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
91af0895 160bool wxToggleBitmapButton::Enable(bool enable /*=true*/)
4f856067
RR
161{
162 if (!wxControl::Enable(enable))
91af0895 163 return false;
4f856067 164
afa7bd1e 165 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
4f856067 166
91af0895 167 return true;
4f856067
RR
168}
169
f40fdaa3 170void wxToggleBitmapButton::DoApplyWidgetStyle(GtkRcStyle *style)
4f856067 171{
f40fdaa3 172 gtk_widget_modify_style(m_widget, style);
afa7bd1e 173 gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
4f856067
RR
174}
175
176bool wxToggleBitmapButton::IsOwnGtkWindow(GdkWindow *window)
177{
afa7bd1e 178 return window == GTK_BUTTON(m_widget)->event_window;
4f856067
RR
179}
180
181void wxToggleBitmapButton::OnInternalIdle()
182{
183 wxCursor cursor = m_cursor;
91af0895 184
4f856067
RR
185 if (g_globalCursor.Ok())
186 cursor = g_globalCursor;
187
afa7bd1e 188 GdkWindow *win = GTK_BUTTON(m_widget)->event_window;
4f856067
RR
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
9f884528 203
4f856067
RR
204// Get the "best" size for this control.
205wxSize wxToggleBitmapButton::DoGetBestSize() const
206{
abdeb9e7 207 wxSize best;
91af0895 208
abdeb9e7 209 if (m_bitmap.Ok())
4f856067 210 {
abdeb9e7
RD
211 int border = HasFlag(wxNO_BORDER) ? 4 : 10;
212 best.x = m_bitmap.GetWidth()+border;
213 best.y = m_bitmap.GetHeight()+border;
4f856067 214 }
9f884528 215 CacheBestSize(best);
abdeb9e7 216 return best;
4f856067 217}
9d522606
RD
218
219
220// static
221wxVisualAttributes
222wxToggleBitmapButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
223{
224 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
225}
226
227
4f856067
RR
228// ------------------------------------------------------------------------
229// wxToggleButton
230// ------------------------------------------------------------------------
231
232IMPLEMENT_DYNAMIC_CLASS(wxToggleButton, wxControl)
233
1db8dc4a
VZ
234bool 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{
91af0895
WS
240 m_needParent = true;
241 m_acceptsFocus = true;
1db8dc4a 242
91af0895 243 m_blockEvent = false;
1db8dc4a 244
91af0895
WS
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 }
1db8dc4a 250
91af0895 251 wxControl::SetLabel(label);
1db8dc4a 252
91af0895
WS
253 // Create the gtk widget.
254 m_widget = gtk_toggle_button_new_with_label( wxGTK_CONV( m_label ) );
1db8dc4a 255
9fa72bd2
MR
256 g_signal_connect (m_widget, "clicked",
257 G_CALLBACK (gtk_togglebutton_clicked_callback),
258 this);
1db8dc4a 259
91af0895 260 m_parent->DoAddChild(this);
1db8dc4a 261
91af0895
WS
262 PostCreation(size);
263
264 return true;
1db8dc4a
VZ
265}
266
267// void SetValue(bool state)
268// Set the value of the toggle button.
269void wxToggleButton::SetValue(bool state)
270{
91af0895 271 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
1db8dc4a 272
91af0895
WS
273 if (state == GetValue())
274 return;
1db8dc4a 275
91af0895 276 m_blockEvent = true;
1db8dc4a 277
91af0895 278 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
1db8dc4a 279
91af0895 280 m_blockEvent = false;
1db8dc4a
VZ
281}
282
283// bool GetValue() const
284// Get the value of the toggle button.
285bool wxToggleButton::GetValue() const
286{
91af0895 287 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
1db8dc4a 288
91af0895 289 return GTK_TOGGLE_BUTTON(m_widget)->active;
1db8dc4a
VZ
290}
291
1db8dc4a
VZ
292void wxToggleButton::SetLabel(const wxString& label)
293{
8ab696e0 294 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
1db8dc4a 295
8ab696e0 296 wxControl::SetLabel(label);
1db8dc4a 297
a7c12d28 298 gtk_label_set_text(GTK_LABEL(GTK_BIN(m_widget)->child), wxGTK_CONV(GetLabel()));
1db8dc4a
VZ
299}
300
91af0895 301bool wxToggleButton::Enable(bool enable /*=true*/)
1db8dc4a 302{
8ab696e0 303 if (!wxControl::Enable(enable))
91af0895 304 return false;
1db8dc4a 305
afa7bd1e 306 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
1db8dc4a 307
91af0895 308 return true;
1db8dc4a
VZ
309}
310
f40fdaa3 311void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle *style)
1db8dc4a 312{
f40fdaa3 313 gtk_widget_modify_style(m_widget, style);
afa7bd1e 314 gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
1db8dc4a
VZ
315}
316
1db8dc4a
VZ
317bool wxToggleButton::IsOwnGtkWindow(GdkWindow *window)
318{
afa7bd1e 319 return window == GTK_BUTTON(m_widget)->event_window;
1db8dc4a
VZ
320}
321
1db8dc4a
VZ
322void wxToggleButton::OnInternalIdle()
323{
8ab696e0 324 wxCursor cursor = m_cursor;
91af0895 325
8ab696e0
RR
326 if (g_globalCursor.Ok())
327 cursor = g_globalCursor;
1db8dc4a 328
afa7bd1e 329 GdkWindow *win = GTK_BUTTON(m_widget)->event_window;
9e691f46
VZ
330 if ( win && cursor.Ok() )
331 {
1db8dc4a
VZ
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
9e691f46 337 gdk_window_set_cursor(win, cursor.GetCursor());
8ab696e0 338 }
1db8dc4a 339
e39af974
JS
340 if (wxUpdateUIEvent::CanUpdate(this))
341 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
1db8dc4a
VZ
342}
343
9f884528 344
1db8dc4a
VZ
345// Get the "best" size for this control.
346wxSize wxToggleButton::DoGetBestSize() const
347{
8ab696e0 348 wxSize ret(wxControl::DoGetBestSize());
91af0895 349
8ab696e0
RR
350 if (!HasFlag(wxBU_EXACTFIT))
351 {
352 if (ret.x < 80) ret.x = 80;
353 }
91af0895 354
9f884528
RD
355 CacheBestSize(ret);
356 return ret;
1db8dc4a
VZ
357}
358
9d522606
RD
359// static
360wxVisualAttributes
361wxToggleButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
362{
363 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
364}
365
1db8dc4a
VZ
366#endif // wxUSE_TOGGLEBTN
367