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