]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/tglbtn.cpp
don't expect errno to be set to EOVERFLOW if vsnprintf() fails
[wxWidgets.git] / src / gtk / tglbtn.cpp
... / ...
CommitLineData
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#include "wx/gtk/private.h"
22
23extern void wxapp_install_idle_handler();
24extern bool g_isIdle;
25extern bool g_blockEventsOnDrag;
26extern wxCursor g_globalCursor;
27
28extern "C" {
29static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb)
30{
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);
44}
45}
46
47DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED)
48
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{
61 m_needParent = true;
62 m_acceptsFocus = true;
63
64 m_blockEvent = false;
65
66 if (!PreCreation(parent, pos, size) ||
67 !CreateBase(parent, id, pos, size, style, validator, name ))
68 {
69 wxFAIL_MSG(wxT("wxToggleBitmapButton creation failed"));
70 return false;
71 }
72
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 {
83 OnSetBitmap();
84 }
85
86 gtk_signal_connect(GTK_OBJECT(m_widget), "clicked",
87 GTK_SIGNAL_FUNC(gtk_togglebutton_clicked_callback),
88 (gpointer *)this);
89
90 m_parent->DoAddChild(this);
91
92 PostCreation(size);
93
94 return true;
95}
96
97// void SetValue(bool state)
98// Set the value of the toggle button.
99void wxToggleBitmapButton::SetValue(bool state)
100{
101 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
102
103 if (state == GetValue())
104 return;
105
106 m_blockEvent = true;
107
108 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
109
110 m_blockEvent = false;
111}
112
113// bool GetValue() const
114// Get the value of the toggle button.
115bool wxToggleBitmapButton::GetValue() const
116{
117 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
118
119 return GTK_TOGGLE_BUTTON(m_widget)->active;
120}
121
122void wxToggleBitmapButton::SetLabel(const wxBitmap& label)
123{
124 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
125
126 m_bitmap = label;
127 InvalidateBestSize();
128
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
154bool wxToggleBitmapButton::Enable(bool enable /*=true*/)
155{
156 if (!wxControl::Enable(enable))
157 return false;
158
159 gtk_widget_set_sensitive(BUTTON_CHILD(m_widget), enable);
160
161 return true;
162}
163
164void wxToggleBitmapButton::DoApplyWidgetStyle(GtkRcStyle *style)
165{
166 gtk_widget_modify_style(m_widget, style);
167 gtk_widget_modify_style(BUTTON_CHILD(m_widget), style);
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;
178
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
197
198// Get the "best" size for this control.
199wxSize wxToggleBitmapButton::DoGetBestSize() const
200{
201 wxSize best;
202
203 if (m_bitmap.Ok())
204 {
205 int border = HasFlag(wxNO_BORDER) ? 4 : 10;
206 best.x = m_bitmap.GetWidth()+border;
207 best.y = m_bitmap.GetHeight()+border;
208 }
209 CacheBestSize(best);
210 return best;
211}
212
213
214// static
215wxVisualAttributes
216wxToggleBitmapButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
217{
218 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
219}
220
221
222// ------------------------------------------------------------------------
223// wxToggleButton
224// ------------------------------------------------------------------------
225
226IMPLEMENT_DYNAMIC_CLASS(wxToggleButton, wxControl)
227
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{
234 m_needParent = true;
235 m_acceptsFocus = true;
236
237 m_blockEvent = false;
238
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 }
244
245 wxControl::SetLabel(label);
246
247 // Create the gtk widget.
248 m_widget = gtk_toggle_button_new_with_label( wxGTK_CONV( m_label ) );
249
250 gtk_signal_connect(GTK_OBJECT(m_widget), "clicked",
251 GTK_SIGNAL_FUNC(gtk_togglebutton_clicked_callback),
252 (gpointer *)this);
253
254 m_parent->DoAddChild(this);
255
256 PostCreation(size);
257
258 return true;
259}
260
261// void SetValue(bool state)
262// Set the value of the toggle button.
263void wxToggleButton::SetValue(bool state)
264{
265 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
266
267 if (state == GetValue())
268 return;
269
270 m_blockEvent = true;
271
272 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
273
274 m_blockEvent = false;
275}
276
277// bool GetValue() const
278// Get the value of the toggle button.
279bool wxToggleButton::GetValue() const
280{
281 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
282
283 return GTK_TOGGLE_BUTTON(m_widget)->active;
284}
285
286void wxToggleButton::SetLabel(const wxString& label)
287{
288 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
289
290 wxControl::SetLabel(label);
291
292 gtk_label_set(GTK_LABEL(BUTTON_CHILD(m_widget)), wxGTK_CONV( GetLabel() ) );
293}
294
295bool wxToggleButton::Enable(bool enable /*=true*/)
296{
297 if (!wxControl::Enable(enable))
298 return false;
299
300 gtk_widget_set_sensitive(BUTTON_CHILD(m_widget), enable);
301
302 return true;
303}
304
305void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle *style)
306{
307 gtk_widget_modify_style(m_widget, style);
308 gtk_widget_modify_style(BUTTON_CHILD(m_widget), style);
309}
310
311bool wxToggleButton::IsOwnGtkWindow(GdkWindow *window)
312{
313 return window == TOGGLE_BUTTON_EVENT_WIN(m_widget);
314}
315
316void wxToggleButton::OnInternalIdle()
317{
318 wxCursor cursor = m_cursor;
319
320 if (g_globalCursor.Ok())
321 cursor = g_globalCursor;
322
323 GdkWindow *win = TOGGLE_BUTTON_EVENT_WIN(m_widget);
324 if ( win && cursor.Ok() )
325 {
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
331 gdk_window_set_cursor(win, cursor.GetCursor());
332 }
333
334 if (wxUpdateUIEvent::CanUpdate(this))
335 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
336}
337
338
339// Get the "best" size for this control.
340wxSize wxToggleButton::DoGetBestSize() const
341{
342 wxSize ret(wxControl::DoGetBestSize());
343
344 if (!HasFlag(wxBU_EXACTFIT))
345 {
346 if (ret.x < 80) ret.x = 80;
347 }
348
349 CacheBestSize(ret);
350 return ret;
351}
352
353// static
354wxVisualAttributes
355wxToggleButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
356{
357 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
358}
359
360#endif // wxUSE_TOGGLEBTN
361