Reorganize idle system code.
[wxWidgets.git] / src / gtk / tglbtn.cpp
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 #include "wx/gtk/private.h"
25
26 extern bool g_blockEventsOnDrag;
27
28 extern "C" {
29 static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb)
30 {
31 if (!cb->m_hasVMT || g_blockEventsOnDrag)
32 return;
33
34 if (cb->m_blockEvent) return;
35
36 // Generate a wx event.
37 wxCommandEvent event(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, cb->GetId());
38 event.SetInt(cb->GetValue());
39 event.SetEventObject(cb);
40 cb->GetEventHandler()->ProcessEvent(event);
41 }
42 }
43
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED)
45
46 // ------------------------------------------------------------------------
47 // wxToggleBitmapButton
48 // ------------------------------------------------------------------------
49
50 IMPLEMENT_DYNAMIC_CLASS(wxToggleBitmapButton, wxControl)
51
52 bool wxToggleBitmapButton::Create(wxWindow *parent, wxWindowID id,
53 const wxBitmap &label, const wxPoint &pos,
54 const wxSize &size, long style,
55 const wxValidator& validator,
56 const wxString &name)
57 {
58 m_needParent = true;
59
60 m_blockEvent = false;
61
62 if (!PreCreation(parent, pos, size) ||
63 !CreateBase(parent, id, pos, size, style, validator, name ))
64 {
65 wxFAIL_MSG(wxT("wxToggleBitmapButton creation failed"));
66 return false;
67 }
68
69 // Create the gtk widget.
70 m_widget = gtk_toggle_button_new();
71
72 if (style & wxNO_BORDER)
73 gtk_button_set_relief( GTK_BUTTON(m_widget), GTK_RELIEF_NONE );
74
75 m_bitmap = label;
76 OnSetBitmap();
77
78 g_signal_connect (m_widget, "clicked",
79 G_CALLBACK (gtk_togglebutton_clicked_callback),
80 this);
81
82 m_parent->DoAddChild(this);
83
84 PostCreation(size);
85
86 return true;
87 }
88
89 // void SetValue(bool state)
90 // Set the value of the toggle button.
91 void wxToggleBitmapButton::SetValue(bool state)
92 {
93 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
94
95 if (state == GetValue())
96 return;
97
98 m_blockEvent = true;
99
100 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
101
102 m_blockEvent = false;
103 }
104
105 // bool GetValue() const
106 // Get the value of the toggle button.
107 bool wxToggleBitmapButton::GetValue() const
108 {
109 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
110
111 return gtk_toggle_button_get_active((GtkToggleButton*)m_widget);
112 }
113
114 void wxToggleBitmapButton::SetLabel(const wxBitmap& label)
115 {
116 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
117
118 m_bitmap = label;
119 InvalidateBestSize();
120
121 OnSetBitmap();
122 }
123
124 void wxToggleBitmapButton::OnSetBitmap()
125 {
126 if (!m_bitmap.Ok()) return;
127
128 GtkWidget* image = ((GtkBin*)m_widget)->child;
129 if (image == NULL)
130 {
131 // initial bitmap
132 image = gtk_image_new_from_pixbuf(m_bitmap.GetPixbuf());
133 gtk_widget_show(image);
134 gtk_container_add((GtkContainer*)m_widget, image);
135 }
136 else
137 { // subsequent bitmaps
138 gtk_image_set_from_pixbuf((GtkImage*)image, m_bitmap.GetPixbuf());
139 }
140 }
141
142 bool wxToggleBitmapButton::Enable(bool enable /*=true*/)
143 {
144 if (!wxControl::Enable(enable))
145 return false;
146
147 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
148
149 return true;
150 }
151
152 void wxToggleBitmapButton::DoApplyWidgetStyle(GtkRcStyle *style)
153 {
154 gtk_widget_modify_style(m_widget, style);
155 gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
156 }
157
158 GdkWindow *
159 wxToggleBitmapButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
160 {
161 return GTK_BUTTON(m_widget)->event_window;
162 }
163
164 // Get the "best" size for this control.
165 wxSize wxToggleBitmapButton::DoGetBestSize() const
166 {
167 wxSize best;
168
169 if (m_bitmap.Ok())
170 {
171 int border = HasFlag(wxNO_BORDER) ? 4 : 10;
172 best.x = m_bitmap.GetWidth()+border;
173 best.y = m_bitmap.GetHeight()+border;
174 }
175 CacheBestSize(best);
176 return best;
177 }
178
179
180 // static
181 wxVisualAttributes
182 wxToggleBitmapButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
183 {
184 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
185 }
186
187
188 // ------------------------------------------------------------------------
189 // wxToggleButton
190 // ------------------------------------------------------------------------
191
192 IMPLEMENT_DYNAMIC_CLASS(wxToggleButton, wxControl)
193
194 bool wxToggleButton::Create(wxWindow *parent, wxWindowID id,
195 const wxString &label, const wxPoint &pos,
196 const wxSize &size, long style,
197 const wxValidator& validator,
198 const wxString &name)
199 {
200 m_needParent = true;
201
202 m_blockEvent = false;
203
204 if (!PreCreation(parent, pos, size) ||
205 !CreateBase(parent, id, pos, size, style, validator, name ))
206 {
207 wxFAIL_MSG(wxT("wxToggleButton creation failed"));
208 return false;
209 }
210
211 // Create the gtk widget.
212 m_widget = gtk_toggle_button_new_with_mnemonic("");
213
214 SetLabel(label);
215
216 g_signal_connect (m_widget, "clicked",
217 G_CALLBACK (gtk_togglebutton_clicked_callback),
218 this);
219
220 m_parent->DoAddChild(this);
221
222 PostCreation(size);
223
224 return true;
225 }
226
227 // void SetValue(bool state)
228 // Set the value of the toggle button.
229 void wxToggleButton::SetValue(bool state)
230 {
231 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
232
233 if (state == GetValue())
234 return;
235
236 m_blockEvent = true;
237
238 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
239
240 m_blockEvent = false;
241 }
242
243 // bool GetValue() const
244 // Get the value of the toggle button.
245 bool wxToggleButton::GetValue() const
246 {
247 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
248
249 return GTK_TOGGLE_BUTTON(m_widget)->active;
250 }
251
252 void wxToggleButton::SetLabel(const wxString& label)
253 {
254 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
255
256 wxControl::SetLabel(label);
257
258 const wxString labelGTK = GTKConvertMnemonics(label);
259
260 gtk_button_set_label(GTK_BUTTON(m_widget), wxGTK_CONV(labelGTK));
261
262 ApplyWidgetStyle( false );
263 }
264
265 bool wxToggleButton::Enable(bool enable /*=true*/)
266 {
267 if (!wxControl::Enable(enable))
268 return false;
269
270 gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable);
271
272 return true;
273 }
274
275 void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle *style)
276 {
277 gtk_widget_modify_style(m_widget, style);
278 gtk_widget_modify_style(GTK_BIN(m_widget)->child, style);
279 }
280
281 GdkWindow *
282 wxToggleButton::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
283 {
284 return GTK_BUTTON(m_widget)->event_window;
285 }
286
287 // Get the "best" size for this control.
288 wxSize wxToggleButton::DoGetBestSize() const
289 {
290 wxSize ret(wxControl::DoGetBestSize());
291
292 if (!HasFlag(wxBU_EXACTFIT))
293 {
294 if (ret.x < 80) ret.x = 80;
295 }
296
297 CacheBestSize(ret);
298 return ret;
299 }
300
301 // static
302 wxVisualAttributes
303 wxToggleButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
304 {
305 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
306 }
307
308 #endif // wxUSE_TOGGLEBTN