1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/radiobox.cpp
3 // Purpose:
4 // Author:      Robert Roebling
5 // Copyright:   (c) 1998 Robert Roebling
6 // Licence:     wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
11 
12 #if wxUSE_RADIOBOX
13 
14 #include "wx/radiobox.h"
15 
16 #if wxUSE_TOOLTIPS
17     #include "wx/tooltip.h"
18 #endif
19 
20 #include <gtk/gtk.h>
21 #include "wx/gtk/private.h"
22 #include "wx/gtk/private/gtk2-compat.h"
23 
24 #include <gdk/gdkkeysyms.h>
25 #if GTK_CHECK_VERSION(3,0,0)
26 #include <gdk/gdkkeysyms-compat.h>
27 #endif
28 
29 //-----------------------------------------------------------------------------
30 // wxGTKRadioButtonInfo
31 //-----------------------------------------------------------------------------
32 // structure internally used by wxRadioBox to store its child buttons
33 
34 class wxGTKRadioButtonInfo : public wxObject
35 {
36 public:
wxGTKRadioButtonInfo(GtkRadioButton * abutton,const wxRect & arect)37     wxGTKRadioButtonInfo( GtkRadioButton * abutton, const wxRect & arect )
38     : button( abutton ), rect( arect ) {}
39 
40     GtkRadioButton * button;
41     wxRect           rect;
42 };
43 
44 //-----------------------------------------------------------------------------
45 // data
46 //-----------------------------------------------------------------------------
47 
48 #include "wx/listimpl.cpp"
49 WX_DEFINE_LIST( wxRadioBoxButtonsInfoList )
50 
51 extern bool          g_blockEventsOnDrag;
52 
53 //-----------------------------------------------------------------------------
54 // "clicked"
55 //-----------------------------------------------------------------------------
56 
57 extern "C" {
gtk_radiobutton_clicked_callback(GtkToggleButton * button,wxRadioBox * rb)58 static void gtk_radiobutton_clicked_callback( GtkToggleButton *button, wxRadioBox *rb )
59 {
60     if (g_blockEventsOnDrag) return;
61 
62     if (!gtk_toggle_button_get_active(button)) return;
63 
64     wxCommandEvent event( wxEVT_RADIOBOX, rb->GetId() );
65     event.SetInt( rb->GetSelection() );
66     event.SetString( rb->GetStringSelection() );
67     event.SetEventObject( rb );
68     rb->HandleWindowEvent(event);
69 }
70 }
71 
72 //-----------------------------------------------------------------------------
73 // "key_press_event"
74 //-----------------------------------------------------------------------------
75 
76 extern "C" {
gtk_radiobox_keypress_callback(GtkWidget * widget,GdkEventKey * gdk_event,wxRadioBox * rb)77 static gint gtk_radiobox_keypress_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxRadioBox *rb )
78 {
79     if (g_blockEventsOnDrag) return FALSE;
80 
81     if ( ((gdk_event->keyval == GDK_Tab) ||
82           (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
83          rb->GetParent() && (rb->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
84     {
85         wxNavigationKeyEvent new_event;
86         new_event.SetEventObject( rb->GetParent() );
87         // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB
88         new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
89         // CTRL-TAB changes the (parent) window, i.e. switch notebook page
90         new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) != 0 );
91         new_event.SetCurrentFocus( rb );
92         return rb->GetParent()->HandleWindowEvent(new_event);
93     }
94 
95     if ((gdk_event->keyval != GDK_Up) &&
96         (gdk_event->keyval != GDK_Down) &&
97         (gdk_event->keyval != GDK_Left) &&
98         (gdk_event->keyval != GDK_Right))
99     {
100         return FALSE;
101     }
102 
103     wxRadioBoxButtonsInfoList::compatibility_iterator node = rb->m_buttonsInfo.GetFirst();
104     while( node && GTK_WIDGET( node->GetData()->button ) != widget )
105     {
106         node = node->GetNext();
107     }
108     if (!node)
109     {
110         return FALSE;
111     }
112 
113     if ((gdk_event->keyval == GDK_Up) ||
114         (gdk_event->keyval == GDK_Left))
115     {
116         if (node == rb->m_buttonsInfo.GetFirst())
117             node = rb->m_buttonsInfo.GetLast();
118         else
119             node = node->GetPrevious();
120     }
121     else
122     {
123         if (node == rb->m_buttonsInfo.GetLast())
124             node = rb->m_buttonsInfo.GetFirst();
125         else
126             node = node->GetNext();
127     }
128 
129     GtkWidget *button = (GtkWidget*) node->GetData()->button;
130 
131     gtk_widget_grab_focus( button );
132 
133     return TRUE;
134 }
135 }
136 
137 extern "C" {
gtk_radiobutton_focus_out(GtkWidget * WXUNUSED (widget),GdkEventFocus * WXUNUSED (event),wxRadioBox * win)138 static gint gtk_radiobutton_focus_out( GtkWidget * WXUNUSED(widget),
139                                        GdkEventFocus *WXUNUSED(event),
140                                        wxRadioBox *win )
141 {
142     // NB: This control is composed of several GtkRadioButton widgets and
143     //     when focus changes from one of them to another in the same
144     //     wxRadioBox, we get a focus-out event followed by focus-in for
145     //     another GtkRadioButton owned by the same control. We don't want
146     //     to generate two spurious wxEVT_SET_FOCUS events in this case,
147     //     so we defer sending wx events until idle time.
148     win->GTKHandleFocusOut();
149 
150     // never stop the signal emission, it seems to break the kbd handling
151     // inside the radiobox
152     return FALSE;
153 }
154 }
155 
156 extern "C" {
gtk_radiobutton_focus_in(GtkWidget * WXUNUSED (widget),GdkEventFocus * WXUNUSED (event),wxRadioBox * win)157 static gint gtk_radiobutton_focus_in( GtkWidget * WXUNUSED(widget),
158                                       GdkEventFocus *WXUNUSED(event),
159                                       wxRadioBox *win )
160 {
161     win->GTKHandleFocusIn();
162 
163     // never stop the signal emission, it seems to break the kbd handling
164     // inside the radiobox
165     return FALSE;
166 }
167 }
168 
169 extern "C" {
gtk_radiobutton_size_allocate(GtkWidget * widget,GtkAllocation * alloc,wxRadioBox * win)170 static void gtk_radiobutton_size_allocate( GtkWidget *widget,
171                                            GtkAllocation * alloc,
172                                            wxRadioBox *win )
173 {
174     for ( wxRadioBoxButtonsInfoList::compatibility_iterator node = win->m_buttonsInfo.GetFirst();
175           node;
176           node = node->GetNext())
177     {
178         if (widget == GTK_WIDGET(node->GetData()->button))
179         {
180             const wxPoint origin = win->GetPosition();
181             wxRect rect = wxRect( alloc->x - origin.x, alloc->y - origin.y,
182                                   alloc->width, alloc->height );
183             node->GetData()->rect = rect;
184             break;
185         }
186     }
187 }
188 }
189 
190 #ifndef __WXGTK3__
191 extern "C" {
expose_event(GtkWidget * widget,GdkEventExpose *,wxWindow *)192 static gboolean expose_event(GtkWidget* widget, GdkEventExpose*, wxWindow*)
193 {
194     const GtkAllocation& a = widget->allocation;
195     gtk_paint_flat_box(gtk_widget_get_style(widget), gtk_widget_get_window(widget),
196         GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, widget, "", a.x, a.y, a.width, a.height);
197     return false;
198 }
199 }
200 #endif
201 
202 //-----------------------------------------------------------------------------
203 // wxRadioBox
204 //-----------------------------------------------------------------------------
205 
IMPLEMENT_DYNAMIC_CLASS(wxRadioBox,wxControl)206 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox,wxControl)
207 
208 bool wxRadioBox::Create( wxWindow *parent, wxWindowID id,
209                          const wxString& title,
210                          const wxPoint &pos, const wxSize &size,
211                          const wxArrayString& choices, int majorDim,
212                          long style, const wxValidator& validator,
213                          const wxString &name )
214 {
215     wxCArrayString chs(choices);
216 
217     return Create( parent, id, title, pos, size, chs.GetCount(),
218                    chs.GetStrings(), majorDim, style, validator, name );
219 }
220 
Create(wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,int n,const wxString choices[],int majorDim,long style,const wxValidator & validator,const wxString & name)221 bool wxRadioBox::Create( wxWindow *parent, wxWindowID id, const wxString& title,
222                          const wxPoint &pos, const wxSize &size,
223                          int n, const wxString choices[], int majorDim,
224                          long style, const wxValidator& validator,
225                          const wxString &name )
226 {
227     if (!PreCreation( parent, pos, size ) ||
228         !CreateBase( parent, id, pos, size, style, validator, name ))
229     {
230         wxFAIL_MSG( wxT("wxRadioBox creation failed") );
231         return false;
232     }
233 
234     m_widget = GTKCreateFrame(title);
235     g_object_ref(m_widget);
236     wxControl::SetLabel(title);
237     if ( HasFlag(wxNO_BORDER) )
238     {
239         // If we don't do this here, the wxNO_BORDER style is ignored in Show()
240         gtk_frame_set_shadow_type(GTK_FRAME(m_widget), GTK_SHADOW_NONE);
241     }
242 
243 
244     // majorDim may be 0 if all trailing parameters were omitted, so don't
245     // assert here but just use the correct value for it
246     SetMajorDim(majorDim == 0 ? n : majorDim, style);
247 
248 
249     unsigned int num_of_cols = GetColumnCount();
250     unsigned int num_of_rows = GetRowCount();
251 
252     GtkRadioButton *rbtn = NULL;
253 
254     GtkWidget *table = gtk_table_new( num_of_rows, num_of_cols, FALSE );
255     gtk_table_set_col_spacings( GTK_TABLE(table), 1 );
256     gtk_table_set_row_spacings( GTK_TABLE(table), 1 );
257     gtk_widget_show( table );
258     gtk_container_add( GTK_CONTAINER(m_widget), table );
259 
260     GSList *radio_button_group = NULL;
261     for (unsigned int i = 0; i < (unsigned int)n; i++)
262     {
263         if ( i != 0 )
264             radio_button_group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(rbtn) );
265 
266         // Process mnemonic in the label
267         wxString label;
268         bool hasMnemonic = false;
269         for ( wxString::const_iterator pc = choices[i].begin();
270               pc != choices[i].end(); ++pc )
271         {
272             if ( *pc == wxS('_') )
273             {
274                 // If we have a literal underscore character in the label
275                 // containing mnemonic, two underscores should be used.
276                 if ( hasMnemonic )
277                     label += wxS('_');
278             }
279             else if ( *pc == wxS('&') )
280             {
281                 ++pc; // skip it
282                  if ( pc == choices[i].end() )
283                  {
284                      break;
285                  }
286                  else if ( *pc != wxS('&') )
287                  {
288                      if ( !hasMnemonic )
289                      {
290                          hasMnemonic = true;
291                          // So far we assumed that label doesn't contain mnemonic
292                          // and therefore single underscore characters were not
293                          // replaced by two underscores. Now we have to double
294                          // all exisiting underscore characters.
295                          label.Replace(wxS("_"), wxS("__"));
296                          label += wxS('_');
297                      }
298                      else
299                      {
300                          wxFAIL_MSG(wxT("duplicate mnemonic char in radio button label"));
301                      }
302                  }
303             }
304 
305             label += *pc;
306         }
307         if ( hasMnemonic )
308             rbtn = GTK_RADIO_BUTTON( gtk_radio_button_new_with_mnemonic( radio_button_group, wxGTK_CONV( label ) ) );
309         else
310             rbtn = GTK_RADIO_BUTTON( gtk_radio_button_new_with_label( radio_button_group, wxGTK_CONV( label ) ) );
311 
312         gtk_widget_show( GTK_WIDGET(rbtn) );
313 
314         g_signal_connect (rbtn, "key_press_event",
315                           G_CALLBACK (gtk_radiobox_keypress_callback), this);
316 
317         m_buttonsInfo.Append( new wxGTKRadioButtonInfo( rbtn, wxRect() ) );
318 
319         if (HasFlag(wxRA_SPECIFY_COLS))
320         {
321             int left = i%num_of_cols;
322             int right = (i%num_of_cols) + 1;
323             int top = i/num_of_cols;
324             int bottom = (i/num_of_cols)+1;
325             gtk_table_attach( GTK_TABLE(table), GTK_WIDGET(rbtn), left, right, top, bottom,
326                   GTK_FILL, GTK_FILL, 1, 1 );
327         }
328         else
329         {
330             int left = i/num_of_rows;
331             int right = (i/num_of_rows) + 1;
332             int top = i%num_of_rows;
333             int bottom = (i%num_of_rows)+1;
334             gtk_table_attach( GTK_TABLE(table), GTK_WIDGET(rbtn), left, right, top, bottom,
335                   GTK_FILL, GTK_FILL, 1, 1 );
336         }
337 
338         ConnectWidget( GTK_WIDGET(rbtn) );
339 
340         if (!i)
341             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rbtn), TRUE );
342 
343         g_signal_connect (rbtn, "clicked",
344                           G_CALLBACK (gtk_radiobutton_clicked_callback), this);
345         g_signal_connect (rbtn, "focus_in_event",
346                           G_CALLBACK (gtk_radiobutton_focus_in), this);
347         g_signal_connect (rbtn, "focus_out_event",
348                           G_CALLBACK (gtk_radiobutton_focus_out), this);
349         g_signal_connect (rbtn, "size_allocate",
350                           G_CALLBACK (gtk_radiobutton_size_allocate), this);
351     }
352 
353     m_parent->DoAddChild( this );
354 
355     PostCreation(size);
356 
357     return true;
358 }
359 
~wxRadioBox()360 wxRadioBox::~wxRadioBox()
361 {
362     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
363     while (node)
364     {
365         GtkWidget *button = GTK_WIDGET( node->GetData()->button );
366         GTKDisconnect(button);
367         gtk_widget_destroy( button );
368         node = node->GetNext();
369     }
370     WX_CLEAR_LIST( wxRadioBoxButtonsInfoList, m_buttonsInfo );
371 }
372 
Show(bool show)373 bool wxRadioBox::Show( bool show )
374 {
375     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid radiobox") );
376 
377     if (!wxControl::Show(show))
378     {
379         // nothing to do
380         return false;
381     }
382 
383     if ( HasFlag(wxNO_BORDER) )
384         gtk_widget_hide( m_widget );
385 
386     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
387     while (node)
388     {
389         GtkWidget *button = GTK_WIDGET( node->GetData()->button );
390 
391         if (show)
392             gtk_widget_show( button );
393         else
394             gtk_widget_hide( button );
395 
396         node = node->GetNext();
397     }
398 
399     return true;
400 }
401 
SetSelection(int n)402 void wxRadioBox::SetSelection( int n )
403 {
404     wxCHECK_RET( m_widget != NULL, wxT("invalid radiobox") );
405 
406     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( n );
407 
408     wxCHECK_RET( node, wxT("radiobox wrong index") );
409 
410     GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->GetData()->button );
411 
412     GtkDisableEvents();
413 
414     gtk_toggle_button_set_active( button, 1 );
415 
416     GtkEnableEvents();
417 }
418 
GetSelection(void) const419 int wxRadioBox::GetSelection(void) const
420 {
421     wxCHECK_MSG( m_widget != NULL, wxNOT_FOUND, wxT("invalid radiobox") );
422 
423     int count = 0;
424 
425     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
426     while (node)
427     {
428         GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->GetData()->button );
429         if (gtk_toggle_button_get_active(button)) return count;
430         count++;
431         node = node->GetNext();
432     }
433 
434     wxFAIL_MSG( wxT("wxRadioBox none selected") );
435 
436     return wxNOT_FOUND;
437 }
438 
GetString(unsigned int n) const439 wxString wxRadioBox::GetString(unsigned int n) const
440 {
441     wxCHECK_MSG( m_widget != NULL, wxEmptyString, wxT("invalid radiobox") );
442 
443     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( n );
444 
445     wxCHECK_MSG( node, wxEmptyString, wxT("radiobox wrong index") );
446 
447     GtkLabel* label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(node->GetData()->button)));
448 
449     wxString str( wxGTK_CONV_BACK( gtk_label_get_text(label) ) );
450 
451     return str;
452 }
453 
SetLabel(const wxString & label)454 void wxRadioBox::SetLabel( const wxString& label )
455 {
456     wxCHECK_RET( m_widget != NULL, wxT("invalid radiobox") );
457 
458     GTKSetLabelForFrame(GTK_FRAME(m_widget), label);
459 }
460 
SetString(unsigned int item,const wxString & label)461 void wxRadioBox::SetString(unsigned int item, const wxString& label)
462 {
463     wxCHECK_RET( m_widget != NULL, wxT("invalid radiobox") );
464 
465     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
466 
467     wxCHECK_RET( node, wxT("radiobox wrong index") );
468 
469     GtkLabel* g_label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(node->GetData()->button)));
470 
471     gtk_label_set_text( g_label, wxGTK_CONV( label ) );
472 }
473 
Enable(bool enable)474 bool wxRadioBox::Enable( bool enable )
475 {
476     if ( !wxControl::Enable( enable ) )
477         return false;
478 
479     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
480     while (node)
481     {
482         GtkButton *button = GTK_BUTTON( node->GetData()->button );
483         GtkLabel *label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(button)));
484 
485         gtk_widget_set_sensitive( GTK_WIDGET(button), enable );
486         gtk_widget_set_sensitive( GTK_WIDGET(label), enable );
487         node = node->GetNext();
488     }
489 
490     if (enable)
491         GTKFixSensitivity();
492 
493     return true;
494 }
495 
Enable(unsigned int item,bool enable)496 bool wxRadioBox::Enable(unsigned int item, bool enable)
497 {
498     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid radiobox") );
499 
500     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
501 
502     wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
503 
504     GtkButton *button = GTK_BUTTON( node->GetData()->button );
505     GtkLabel *label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(button)));
506 
507     gtk_widget_set_sensitive( GTK_WIDGET(button), enable );
508     gtk_widget_set_sensitive( GTK_WIDGET(label), enable );
509 
510     return true;
511 }
512 
IsItemEnabled(unsigned int item) const513 bool wxRadioBox::IsItemEnabled(unsigned int item) const
514 {
515     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid radiobox") );
516 
517     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
518 
519     wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
520 
521     GtkButton *button = GTK_BUTTON( node->GetData()->button );
522 
523     // don't use GTK_WIDGET_IS_SENSITIVE() here, we want to return true even if
524     // the parent radiobox is disabled
525     return gtk_widget_get_sensitive(GTK_WIDGET(button)) != 0;
526 }
527 
Show(unsigned int item,bool show)528 bool wxRadioBox::Show(unsigned int item, bool show)
529 {
530     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid radiobox") );
531 
532     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
533 
534     wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
535 
536     GtkWidget *button = GTK_WIDGET( node->GetData()->button );
537 
538     if (show)
539         gtk_widget_show( button );
540     else
541         gtk_widget_hide( button );
542 
543     return true;
544 }
545 
IsItemShown(unsigned int item) const546 bool wxRadioBox::IsItemShown(unsigned int item) const
547 {
548     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid radiobox") );
549 
550     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
551 
552     wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
553 
554     GtkButton *button = GTK_BUTTON( node->GetData()->button );
555 
556     return gtk_widget_get_visible(GTK_WIDGET(button)) != 0;
557 }
558 
GetCount() const559 unsigned int wxRadioBox::GetCount() const
560 {
561     return m_buttonsInfo.GetCount();
562 }
563 
GtkDisableEvents()564 void wxRadioBox::GtkDisableEvents()
565 {
566     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
567     while (node)
568     {
569         g_signal_handlers_block_by_func(node->GetData()->button,
570             (gpointer)gtk_radiobutton_clicked_callback, this);
571 
572         node = node->GetNext();
573     }
574 }
575 
GtkEnableEvents()576 void wxRadioBox::GtkEnableEvents()
577 {
578     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
579     while (node)
580     {
581         g_signal_handlers_unblock_by_func(node->GetData()->button,
582             (gpointer)gtk_radiobutton_clicked_callback, this);
583 
584         node = node->GetNext();
585     }
586 }
587 
DoApplyWidgetStyle(GtkRcStyle * style)588 void wxRadioBox::DoApplyWidgetStyle(GtkRcStyle *style)
589 {
590     GTKFrameApplyWidgetStyle(GTK_FRAME(m_widget), style);
591 
592     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
593     while (node)
594     {
595         GtkWidget *widget = GTK_WIDGET( node->GetData()->button );
596 
597         GTKApplyStyle(widget, style);
598         GTKApplyStyle(gtk_bin_get_child(GTK_BIN(widget)), style);
599 
600         node = node->GetNext();
601     }
602 
603 #ifndef __WXGTK3__
604     g_signal_handlers_disconnect_by_func(m_widget, (void*)expose_event, this);
605     if (m_backgroundColour.IsOk())
606         g_signal_connect(m_widget, "expose-event", G_CALLBACK(expose_event), this);
607 #endif
608 }
609 
GTKWidgetNeedsMnemonic() const610 bool wxRadioBox::GTKWidgetNeedsMnemonic() const
611 {
612     return true;
613 }
614 
GTKWidgetDoSetMnemonic(GtkWidget * w)615 void wxRadioBox::GTKWidgetDoSetMnemonic(GtkWidget* w)
616 {
617     GTKFrameSetMnemonicWidget(GTK_FRAME(m_widget), w);
618 }
619 
620 #if wxUSE_TOOLTIPS
GTKApplyToolTip(const char * tip)621 void wxRadioBox::GTKApplyToolTip(const char* tip)
622 {
623     // set this tooltip for all radiobuttons which don't have their own tips
624     unsigned n = 0;
625     for ( wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
626           node;
627           node = node->GetNext(), n++ )
628     {
629         if ( !GetItemToolTip(n) )
630         {
631             wxToolTip::GTKApply(GTK_WIDGET(node->GetData()->button), tip);
632         }
633     }
634 }
635 
DoSetItemToolTip(unsigned int n,wxToolTip * tooltip)636 void wxRadioBox::DoSetItemToolTip(unsigned int n, wxToolTip *tooltip)
637 {
638     wxCharBuffer buf;
639     if ( !tooltip )
640         tooltip = GetToolTip();
641     if ( tooltip )
642         buf = wxGTK_CONV(tooltip->GetTip());
643 
644     wxToolTip::GTKApply(GTK_WIDGET(m_buttonsInfo[n]->button), buf);
645 }
646 
647 #endif // wxUSE_TOOLTIPS
648 
GTKGetWindow(wxArrayGdkWindows & windows) const649 GdkWindow *wxRadioBox::GTKGetWindow(wxArrayGdkWindows& windows) const
650 {
651     windows.push_back(gtk_widget_get_window(m_widget));
652 
653     wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
654     while (node)
655     {
656         GtkWidget *button = GTK_WIDGET( node->GetData()->button );
657 
658         // don't put NULL pointers in the 'windows' array!
659         if (gtk_widget_get_window(button))
660             windows.push_back(gtk_widget_get_window(button));
661 
662         node = node->GetNext();
663     }
664 
665     return NULL;
666 }
667 
668 // static
669 wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant WXUNUSED (variant))670 wxRadioBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
671 {
672     return GetDefaultAttributesFromGTKWidget(gtk_radio_button_new_with_label(NULL, ""));
673 }
674 
GetItemFromPoint(const wxPoint & point) const675 int wxRadioBox::GetItemFromPoint(const wxPoint& point) const
676 {
677     const wxPoint pt = ScreenToClient(point);
678     unsigned n = 0;
679     for ( wxRadioBoxButtonsInfoList::compatibility_iterator
680             node = m_buttonsInfo.GetFirst(); node; node = node->GetNext(), n++ )
681     {
682         if ( m_buttonsInfo[n]->rect.Contains(pt) )
683             return n;
684     }
685 
686     return wxNOT_FOUND;
687 }
688 
689 #endif // wxUSE_RADIOBOX
690