wxPython updates (SWIG really works, cannot believe it)
[wxWidgets.git] / src / gtk1 / radiobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: radiobox.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "radiobox.h"
13 #endif
14
15 #include "wx/radiobox.h"
16 #include "wx/dialog.h"
17 #include "wx/frame.h"
18 #include "wx/gtk/win_gtk.h"
19
20 //-----------------------------------------------------------------------------
21 // data
22 //-----------------------------------------------------------------------------
23
24 extern bool g_blockEventsOnDrag;
25
26 //-----------------------------------------------------------------------------
27 // "clicked"
28 //-----------------------------------------------------------------------------
29
30 static void gtk_radiobutton_clicked_callback( GtkWidget *WXUNUSED(widget), wxRadioBox *rb )
31 {
32 if (!rb->HasVMT()) return;
33 if (g_blockEventsOnDrag) return;
34
35 if (rb->m_alreadySent)
36 {
37 rb->m_alreadySent = FALSE;
38 return;
39 }
40
41 rb->m_alreadySent = TRUE;
42
43 wxCommandEvent event( wxEVT_COMMAND_RADIOBOX_SELECTED, rb->GetId() );
44 event.SetInt( rb->GetSelection() );
45 wxString tmp( rb->GetStringSelection() );
46 event.SetString( WXSTRINGCAST(tmp) );
47 event.SetEventObject( rb );
48 rb->GetEventHandler()->ProcessEvent(event);
49 }
50
51 //-----------------------------------------------------------------------------
52 // wxRadioBox
53 //-----------------------------------------------------------------------------
54
55 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox,wxControl)
56
57 BEGIN_EVENT_TABLE(wxRadioBox, wxControl)
58 EVT_SIZE(wxRadioBox::OnSize)
59 END_EVENT_TABLE()
60
61 wxRadioBox::wxRadioBox(void)
62 {
63 }
64
65 bool wxRadioBox::Create( wxWindow *parent, wxWindowID id, const wxString& title,
66 const wxPoint &pos, const wxSize &size,
67 int n, const wxString choices[], int majorDim,
68 long style, const wxValidator& validator,
69 const wxString &name )
70 {
71 m_alreadySent = FALSE;
72 m_needParent = TRUE;
73 m_acceptsFocus = TRUE;
74
75 PreCreation( parent, id, pos, size, style, name );
76
77 SetValidator( validator );
78
79 m_widget = gtk_frame_new( title );
80
81 m_majorDim = majorDim;
82
83 GtkRadioButton *m_radio = (GtkRadioButton*) NULL;
84
85 GSList *radio_button_group = (GSList *) NULL;
86 for (int i = 0; i < n; i++)
87 {
88 if (i) radio_button_group = gtk_radio_button_group( GTK_RADIO_BUTTON(m_radio) );
89
90 m_radio = GTK_RADIO_BUTTON( gtk_radio_button_new_with_label( radio_button_group, choices[i] ) );
91
92 m_boxes.Append( (wxObject*) m_radio );
93
94 ConnectWidget( GTK_WIDGET(m_radio) );
95
96 if (!i) gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(m_radio), TRUE );
97
98 gtk_signal_connect( GTK_OBJECT(m_radio), "clicked",
99 GTK_SIGNAL_FUNC(gtk_radiobutton_clicked_callback), (gpointer*)this );
100
101 gtk_myfixed_put( GTK_MYFIXED(m_parent->m_wxwindow), GTK_WIDGET(m_radio), m_x+10, m_y+10+(i*24) );
102
103 }
104
105 wxSize ls = LayoutItems();
106
107 wxSize newSize = size;
108 if (newSize.x == -1) newSize.x = ls.x;
109 if (newSize.y == -1) newSize.y = ls.y;
110 SetSize( newSize.x, newSize.y );
111
112 m_parent->AddChild( this );
113
114 (m_parent->m_insertCallback)( m_parent, this );
115
116 PostCreation();
117
118 SetLabel( title );
119
120 SetBackgroundColour( parent->GetBackgroundColour() );
121 SetForegroundColour( parent->GetForegroundColour() );
122
123 Show( TRUE );
124
125 return TRUE;
126 }
127
128 wxRadioBox::~wxRadioBox(void)
129 {
130 wxNode *node = m_boxes.First();
131 while (node)
132 {
133 GtkWidget *button = GTK_WIDGET( node->Data() );
134 gtk_widget_destroy( button );
135 node = node->Next();
136 }
137 }
138
139 void wxRadioBox::OnSize( wxSizeEvent &event )
140 {
141 wxControl::OnSize( event );
142
143 LayoutItems();
144 }
145
146 wxSize wxRadioBox::LayoutItems()
147 {
148 int x = m_x+7;
149 int y = m_y+15;
150
151 int num_per_major = (m_boxes.GetCount() - 1) / m_majorDim +1;
152
153 wxSize res( 0, 0 );
154
155 if (m_windowStyle & wxRA_HORIZONTAL)
156 {
157
158 for (int j = 0; j < m_majorDim; j++)
159 {
160 y = m_y+15;
161
162 int max_len = 0;
163 wxNode *node = m_boxes.Nth( j*num_per_major );
164 for (int i = 0; i< num_per_major; i++)
165 {
166 GtkWidget *button = GTK_WIDGET( node->Data() );
167 GtkLabel *label = GTK_LABEL( GTK_BUTTON(button)->child );
168 GdkFont *font = m_widget->style->font;
169 int len = 27+gdk_string_measure( font, label->label );
170 if (len > max_len) max_len = len;
171
172 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), button, x, y );
173 y += 22;
174
175 node = node->Next();
176 if (!node) break;
177 }
178
179 // we don't know the max_len before
180
181 node = m_boxes.Nth( j*num_per_major );
182 for (int i = 0; i< num_per_major; i++)
183 {
184 GtkWidget *button = GTK_WIDGET( node->Data() );
185
186 gtk_widget_set_usize( button, max_len, 22 );
187
188 node = node->Next();
189 if (!node) break;
190 }
191
192 if (y > res.y) res.y = y;
193
194 x += max_len + 2;
195 }
196
197 res.y -= 3;
198 res.x = x-2;
199 }
200 else
201 {
202 int max = 0;
203
204 wxNode *node = m_boxes.First();
205 while (node)
206 {
207 GtkButton *button = GTK_BUTTON( node->Data() );
208 GtkLabel *label = GTK_LABEL( button->child );
209
210 GdkFont *font = m_widget->style->font;
211 int len = 27+gdk_string_measure( font, label->label );
212 if (len > max) max = len;
213
214 node = node->Next();
215 }
216
217 node = m_boxes.First();
218 while (node)
219 {
220 GtkWidget *button = GTK_WIDGET( node->Data() );
221
222 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), button, x, y );
223 x += max;
224 gtk_widget_set_usize( button, max, 20 );
225
226 node = node->Next();
227 }
228 res.x = x-2;
229 res.y = 42;
230 }
231
232 return res;
233 }
234
235 bool wxRadioBox::Show( bool show )
236 {
237 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid radiobox" );
238
239 wxWindow::Show( show );
240
241 wxNode *node = m_boxes.First();
242 while (node)
243 {
244 GtkWidget *button = GTK_WIDGET( node->Data() );
245
246 if (show) gtk_widget_show( button ); else gtk_widget_hide( button );
247
248 node = node->Next();
249 }
250
251 return TRUE;
252 }
253
254 int wxRadioBox::FindString( const wxString &s ) const
255 {
256 wxCHECK_MSG( m_widget != NULL, -1, "invalid radiobox" );
257
258 int count = 0;
259
260 wxNode *node = m_boxes.First();
261 while (node)
262 {
263 GtkButton *button = GTK_BUTTON( node->Data() );
264
265 GtkLabel *label = GTK_LABEL( button->child );
266 if (s == label->label) return count;
267 count++;
268
269 node = node->Next();
270 }
271
272 return -1;
273 }
274
275 void wxRadioBox::SetFocus()
276 {
277 wxCHECK_RET( m_widget != NULL, "invalid radiobox" );
278
279 if (m_boxes.GetCount() == 0) return;
280
281 wxNode *node = m_boxes.First();
282 while (node)
283 {
284 GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->Data() );
285 if (button->active)
286 {
287 gtk_widget_grab_focus( GTK_WIDGET(button) );
288
289 return;
290 }
291 node = node->Next();
292 }
293
294 }
295
296 void wxRadioBox::SetSelection( int n )
297 {
298 wxCHECK_RET( m_widget != NULL, "invalid radiobox" );
299
300 wxNode *node = m_boxes.Nth( n );
301
302 wxCHECK_RET( node, "radiobox wrong index" );
303
304 GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->Data() );
305
306 gtk_toggle_button_set_state( button, 1 );
307 }
308
309 int wxRadioBox::GetSelection(void) const
310 {
311 wxCHECK_MSG( m_widget != NULL, -1, "invalid radiobox" );
312
313 int count = 0;
314
315 wxNode *node = m_boxes.First();
316 while (node)
317 {
318 GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->Data() );
319 if (button->active) return count;
320 count++;
321 node = node->Next();
322 }
323
324 wxFAIL_MSG( "wxRadioBox none selected" );
325
326 return -1;
327 }
328
329 wxString wxRadioBox::GetString( int n ) const
330 {
331 wxCHECK_MSG( m_widget != NULL, "", "invalid radiobox" );
332
333 wxNode *node = m_boxes.Nth( n );
334
335 wxCHECK_MSG( node, "", "radiobox wrong index" );
336
337 GtkButton *button = GTK_BUTTON( node->Data() );
338 GtkLabel *label = GTK_LABEL( button->child );
339
340 return wxString( label->label );
341 }
342
343 wxString wxRadioBox::GetLabel( int item ) const
344 {
345 wxCHECK_MSG( m_widget != NULL, "", "invalid radiobox" );
346
347 return GetString( item );
348 }
349
350 void wxRadioBox::SetLabel( const wxString& label )
351 {
352 wxCHECK_RET( m_widget != NULL, "invalid radiobox" );
353
354 wxControl::SetLabel( label );
355
356 gtk_frame_set_label( GTK_FRAME(m_widget), wxControl::GetLabel() );
357 }
358
359 void wxRadioBox::SetLabel( int item, const wxString& label )
360 {
361 wxCHECK_RET( m_widget != NULL, "invalid radiobox" );
362
363 wxNode *node = m_boxes.Nth( item );
364
365 wxCHECK_RET( node, "radiobox wrong index" );
366
367 GtkButton *button = GTK_BUTTON( node->Data() );
368 GtkLabel *g_label = GTK_LABEL( button->child );
369
370 gtk_label_set( g_label, label );
371 }
372
373 void wxRadioBox::SetLabel( int WXUNUSED(item), wxBitmap *WXUNUSED(bitmap) )
374 {
375 wxFAIL_MSG("wxRadioBox::SetLabel not implemented.");
376 }
377
378 void wxRadioBox::Enable( bool enable )
379 {
380 wxControl::Enable( enable );
381
382 wxNode *node = m_boxes.First();
383 while (node)
384 {
385 GtkButton *button = GTK_BUTTON( node->Data() );
386 GtkWidget *label = button->child;
387 gtk_widget_set_sensitive( GTK_WIDGET(button), enable );
388 gtk_widget_set_sensitive( label, enable );
389 node = node->Next();
390 }
391 }
392
393 void wxRadioBox::Enable( int item, bool enable )
394 {
395 wxCHECK_RET( m_widget != NULL, "invalid radiobox" );
396
397 wxNode *node = m_boxes.Nth( item );
398
399 wxCHECK_RET( node, "radiobox wrong index" );
400
401 GtkButton *button = GTK_BUTTON( node->Data() );
402 GtkWidget *label = button->child;
403 gtk_widget_set_sensitive( GTK_WIDGET(button), enable );
404 gtk_widget_set_sensitive( label, enable );
405 }
406
407 void wxRadioBox::Show( int item, bool show )
408 {
409 wxCHECK_RET( m_widget != NULL, "invalid radiobox" );
410
411 wxNode *node = m_boxes.Nth( item );
412
413 wxCHECK_RET( node, "radiobox wrong index" );
414
415 GtkWidget *button = GTK_WIDGET( node->Data() );
416
417 if (show)
418 gtk_widget_show( button );
419 else
420 gtk_widget_hide( button );
421 }
422
423 wxString wxRadioBox::GetStringSelection(void) const
424 {
425 wxCHECK_MSG( m_widget != NULL, "", "invalid radiobox" );
426
427 wxNode *node = m_boxes.First();
428 while (node)
429 {
430 GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->Data() );
431 if (button->active)
432 {
433 GtkLabel *label = GTK_LABEL( GTK_BUTTON(button)->child );
434 return label->label;
435 }
436 node = node->Next();
437 }
438
439 wxFAIL_MSG( "wxRadioBox none selected" );
440 return "";
441 }
442
443 bool wxRadioBox::SetStringSelection( const wxString &s )
444 {
445 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid radiobox" );
446
447 int res = FindString( s );
448 if (res == -1) return FALSE;
449 SetSelection( res );
450
451 return TRUE;
452 }
453
454 int wxRadioBox::Number(void) const
455 {
456 return m_boxes.Number();
457 }
458
459 int wxRadioBox::GetNumberOfRowsOrCols(void) const
460 {
461 return 1;
462 }
463
464 void wxRadioBox::SetNumberOfRowsOrCols( int WXUNUSED(n) )
465 {
466 wxFAIL_MSG("wxRadioBox::SetNumberOfRowsOrCols not implemented.");
467 }
468
469 void wxRadioBox::ApplyWidgetStyle()
470 {
471 SetWidgetStyle();
472
473 gtk_widget_set_style( m_widget, m_widgetStyle );
474
475 wxNode *node = m_boxes.First();
476 while (node)
477 {
478 GtkWidget *widget = GTK_WIDGET( node->Data() );
479 gtk_widget_set_style( widget, m_widgetStyle );
480
481 GtkButton *button = GTK_BUTTON( node->Data() );
482 gtk_widget_set_style( button->child, m_widgetStyle );
483
484 node = node->Next();
485 }
486 }
487
488 bool wxRadioBox::IsOwnGtkWindow( GdkWindow *window )
489 {
490 if (window == m_widget->window) return TRUE;
491
492 wxNode *node = m_boxes.First();
493 while (node)
494 {
495 GtkWidget *button = GTK_WIDGET( node->Data() );
496
497 if (window == button->window) return TRUE;
498
499 node = node->Next();
500 }
501
502 return FALSE;
503 }