1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/motif/radiobox.cpp
3 // Purpose:     wxRadioBox
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     17/09/98
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13 
14 #if wxUSE_RADIOBOX
15 
16 #include "wx/radiobox.h"
17 
18 #ifndef WX_PRECOMP
19     #include "wx/utils.h"
20     #include "wx/arrstr.h"
21 #endif
22 
23 #ifdef __VMS__
24 #pragma message disable nosimpint
25 #endif
26 #include <Xm/Label.h>
27 #include <Xm/LabelG.h>
28 #include <Xm/ToggleB.h>
29 #include <Xm/ToggleBG.h>
30 #include <Xm/RowColumn.h>
31 #include <Xm/Frame.h>
32 #ifdef __VMS__
33 #pragma message enable nosimpint
34 #endif
35 
36 #include "wx/motif/private.h"
37 
38 void wxRadioBoxCallback (Widget w, XtPointer clientData,
39                     XmToggleButtonCallbackStruct * cbs);
40 
IMPLEMENT_DYNAMIC_CLASS(wxRadioBox,wxControl)41 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
42 
43 // Radio box item
44 void wxRadioBox::Init()
45 {
46     m_selectedButton = -1;
47     m_noItems = 0;
48     m_noRowsOrCols = 0;
49     m_labelWidget = (WXWidget) 0;
50 }
51 
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 & val,const wxString & name)52 bool wxRadioBox::Create(wxWindow *parent, wxWindowID id, const wxString& title,
53              const wxPoint& pos, const wxSize& size,
54              int n, const wxString choices[],
55              int majorDim, long style,
56              const wxValidator& val, const wxString& name)
57 {
58     if( !CreateControl( parent, id, pos, size, style, val, name ) )
59         return false;
60     PreCreation();
61 
62     m_noItems = (unsigned int)n;
63     m_noRowsOrCols = majorDim;
64 
65     SetMajorDim(majorDim == 0 ? n : majorDim, style);
66 
67     Widget parentWidget = (Widget) parent->GetClientWidget();
68     Display* dpy = XtDisplay(parentWidget);
69 
70     m_mainWidget = XtVaCreateWidget ("radioboxframe",
71                                      xmFrameWidgetClass, parentWidget,
72                                      XmNresizeHeight, True,
73                                      XmNresizeWidth, True,
74                                      NULL);
75 
76     wxString label1(GetLabelText(title));
77 
78     if (!label1.empty())
79     {
80         wxXmString text(label1);
81         m_labelWidget = (WXWidget)
82             XtVaCreateManagedWidget( label1.mb_str(),
83 #if wxUSE_GADGETS
84                 style & wxCOLOURED ? xmLabelWidgetClass
85                                    : xmLabelGadgetClass,
86                 (Widget)m_mainWidget,
87 #else
88                 xmLabelWidgetClass, (Widget)m_mainWidget,
89 #endif
90                 wxFont::GetFontTag(), m_font.GetFontTypeC(dpy),
91                 XmNlabelString, text(),
92 // XmNframeChildType is not in Motif 1.2, nor in Lesstif,
93 // if it was compiled with 1.2 compatibility
94 // TODO: check this still looks OK for Motif 1.2.
95 #if (XmVersion > 1200)
96                 XmNframeChildType, XmFRAME_TITLE_CHILD,
97 #else
98                 XmNchildType, XmFRAME_TITLE_CHILD,
99 #endif
100                 XmNchildVerticalAlignment, XmALIGNMENT_CENTER,
101                 NULL);
102     }
103 
104     Arg args[3];
105 
106     XtSetArg (args[0], XmNorientation, ((style & wxHORIZONTAL) == wxHORIZONTAL ?
107                                           XmHORIZONTAL : XmVERTICAL));
108     XtSetArg (args[1], XmNnumColumns, GetMajorDim());
109     XtSetArg (args[2], XmNadjustLast, False);
110 
111     Widget radioBoxWidget =
112         XmCreateRadioBox ((Widget)m_mainWidget, wxMOTIF_STR("radioBoxWidget"), args, 3);
113 
114     m_radioButtons.reserve(n);
115     m_radioButtonLabels.reserve(n);
116 
117     int i;
118     for (i = 0; i < n; i++)
119     {
120         wxString str(GetLabelText(choices[i]));
121         m_radioButtonLabels.push_back(str);
122         Widget radioItem =  XtVaCreateManagedWidget (
123                                 str.mb_str(),
124 #if wxUSE_GADGETS
125                                 xmToggleButtonGadgetClass, radioBoxWidget,
126 #else
127                                 xmToggleButtonWidgetClass, radioBoxWidget,
128 #endif
129                                 wxFont::GetFontTag(), m_font.GetFontTypeC(dpy),
130                                 NULL);
131         m_radioButtons.push_back((WXWidget)radioItem);
132         XtAddCallback (radioItem, XmNvalueChangedCallback,
133                        (XtCallbackProc) wxRadioBoxCallback,
134                        (XtPointer) this);
135     }
136 
137     SetSelection (0);
138 
139     XtRealizeWidget((Widget)m_mainWidget);
140     XtManageChild (radioBoxWidget);
141     XtManageChild ((Widget)m_mainWidget);
142 
143     PostCreation();
144     AttachWidget (parent, m_mainWidget, NULL, pos.x, pos.y, size.x, size.y);
145 
146     return true;
147 }
148 
Create(wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,const wxArrayString & choices,int majorDim,long style,const wxValidator & val,const wxString & name)149 bool wxRadioBox::Create(wxWindow *parent, wxWindowID id, const wxString& title,
150              const wxPoint& pos, const wxSize& size,
151              const wxArrayString& choices,
152              int majorDim, long style,
153              const wxValidator& val, const wxString& name)
154 {
155     wxCArrayString chs(choices);
156     return Create(parent, id, title, pos, size, chs.GetCount(),
157                   chs.GetStrings(), majorDim, style, val, name);
158 }
159 
~wxRadioBox()160 wxRadioBox::~wxRadioBox()
161 {
162     DetachWidget(m_mainWidget);
163     XtDestroyWidget((Widget) m_mainWidget);
164 
165     m_mainWidget = (WXWidget) 0;
166 }
167 
SetString(unsigned int item,const wxString & label)168 void wxRadioBox::SetString(unsigned int item, const wxString& label)
169 {
170     if (!IsValid(item))
171         return;
172 
173     Widget widget = (Widget)m_radioButtons[item];
174     if (!label.empty())
175     {
176         wxString label1(GetLabelText(label));
177         wxXmString text( label1 );
178         m_radioButtonLabels[item] = label1;
179         XtVaSetValues (widget,
180                         XmNlabelString, text(),
181                         XmNlabelType, XmSTRING,
182                         NULL);
183     }
184 }
185 
SetSelection(int n)186 void wxRadioBox::SetSelection(int n)
187 {
188     if (!IsValid(n))
189         return;
190 
191     m_selectedButton = n;
192 
193     m_inSetValue = true;
194 
195     XmToggleButtonSetState ((Widget) m_radioButtons[n], True, False);
196 
197     for (unsigned int i = 0; i < m_noItems; i++)
198         if (i != (unsigned int)n)
199             XmToggleButtonSetState ((Widget) m_radioButtons[i], False, False);
200 
201     m_inSetValue = false;
202 }
203 
204 // Get single selection, for single choice list items
GetSelection() const205 int wxRadioBox::GetSelection() const
206 {
207     return m_selectedButton;
208 }
209 
210 // Find string for position
GetString(unsigned int n) const211 wxString wxRadioBox::GetString(unsigned int n) const
212 {
213     if (!IsValid(n))
214         return wxEmptyString;
215     return m_radioButtonLabels[n];
216 }
217 
DoSetSize(int x,int y,int width,int height,int sizeFlags)218 void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
219 {
220     bool managed = XtIsManaged((Widget) m_mainWidget);
221 
222     if (managed)
223         XtUnmanageChild ((Widget) m_mainWidget);
224 
225     int xx = x; int yy = y;
226     AdjustForParentClientOrigin(xx, yy, sizeFlags);
227 
228     if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
229         XtVaSetValues ((Widget) m_mainWidget, XmNx, xx, NULL);
230     if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
231         XtVaSetValues ((Widget) m_mainWidget, XmNy, yy, NULL);
232 
233     if (width > 0)
234         XtVaSetValues ((Widget) m_mainWidget, XmNwidth, width, NULL);
235     if (height > 0)
236         XtVaSetValues ((Widget) m_mainWidget, XmNheight, height, NULL);
237 
238     if (managed)
239         XtManageChild ((Widget) m_mainWidget);
240 }
241 
242 // Enable a specific button
Enable(unsigned int n,bool enable)243 bool wxRadioBox::Enable(unsigned int n, bool enable)
244 {
245     if (!IsValid(n))
246         return false;
247 
248     XtSetSensitive ((Widget) m_radioButtons[n], (Boolean) enable);
249     return true;
250 }
251 
252 // Enable all controls
Enable(bool enable)253 bool wxRadioBox::Enable(bool enable)
254 {
255     if ( !wxControl::Enable(enable) )
256         return false;
257 
258     for (unsigned int i = 0; i < m_noItems; i++)
259         XtSetSensitive ((Widget) m_radioButtons[i], (Boolean) enable);
260 
261     return true;
262 }
263 
Show(bool show)264 bool wxRadioBox::Show(bool show)
265 {
266     // TODO: show/hide all children
267     return wxControl::Show(show);
268 }
269 
270 // Show a specific button
Show(unsigned int n,bool show)271 bool wxRadioBox::Show(unsigned int n, bool show)
272 {
273   // This method isn't complete, and we try do do our best...
274   // It's main purpose isn't for allowing Show/Unshow dynamically,
275   // but rather to provide a way to design wxRadioBox such:
276   //
277   //        o Val1  o Val2   o Val3
278   //        o Val4           o Val6
279   //        o Val7  o Val8   o Val9
280   //
281   // In my case, this is a 'direction' box, and the Show(5,False) is
282   // coupled with an Enable(5,False)
283   //
284     if (!IsValid(n))
285         return false;
286 
287     XtVaSetValues ((Widget) m_radioButtons[n],
288         XmNindicatorOn, (unsigned char) show,
289         NULL);
290 
291     // Please note that this is all we can do: removing the label
292     // if switching to unshow state. However, when switching
293     // to the on state, it's the prog. resp. to call SetString(item,...)
294     // after this call!!
295     if (!show)
296         wxRadioBox::SetString (n, " ");
297 
298     return true;
299 }
300 
301 // For single selection items only
GetStringSelection() const302 wxString wxRadioBox::GetStringSelection () const
303 {
304     int sel = GetSelection ();
305     if (sel != wxNOT_FOUND)
306         return this->GetString((unsigned int)sel);
307     else
308         return wxEmptyString;
309 }
310 
SetStringSelection(const wxString & s)311 bool wxRadioBox::SetStringSelection (const wxString& s)
312 {
313     int sel = FindString (s);
314     if (sel > -1)
315     {
316         SetSelection (sel);
317         return true;
318     }
319     else
320         return false;
321 }
322 
Command(wxCommandEvent & event)323 void wxRadioBox::Command (wxCommandEvent & event)
324 {
325     SetSelection (event.GetInt());
326     ProcessCommand (event);
327 }
328 
ChangeFont(bool keepOriginalSize)329 void wxRadioBox::ChangeFont(bool keepOriginalSize)
330 {
331     wxWindow::ChangeFont(keepOriginalSize);
332 
333     for (unsigned int i = 0; i < m_noItems; i++)
334     {
335         WXWidget radioButton = m_radioButtons[i];
336 
337         XtVaSetValues ((Widget) radioButton,
338                        wxFont::GetFontTag(), m_font.GetFontTypeC(XtDisplay((Widget) GetTopWidget())),
339                        NULL);
340     }
341 }
342 
ChangeBackgroundColour()343 void wxRadioBox::ChangeBackgroundColour()
344 {
345     wxWindow::ChangeBackgroundColour();
346 
347     wxColour colour = *wxBLACK;
348     WXPixel selectPixel = colour.AllocColour(XtDisplay((Widget)m_mainWidget));
349 
350     for (unsigned int i = 0; i < m_noItems; i++)
351     {
352         WXWidget radioButton = m_radioButtons[i];
353 
354         wxDoChangeBackgroundColour(radioButton, m_backgroundColour, true);
355 
356         XtVaSetValues ((Widget) radioButton,
357           XmNselectColor, selectPixel,
358           NULL);
359     }
360 }
361 
ChangeForegroundColour()362 void wxRadioBox::ChangeForegroundColour()
363 {
364     wxWindow::ChangeForegroundColour();
365 
366     for (unsigned int i = 0; i < m_noItems; i++)
367     {
368         WXWidget radioButton = m_radioButtons[i];
369 
370         wxDoChangeForegroundColour(radioButton, m_foregroundColour);
371     }
372 }
373 
wxRadioBoxCallback(Widget w,XtPointer clientData,XmToggleButtonCallbackStruct * cbs)374 void wxRadioBoxCallback (Widget w, XtPointer clientData,
375                     XmToggleButtonCallbackStruct * cbs)
376 {
377   if (!cbs->set)
378     return;
379 
380   wxRadioBox *item = (wxRadioBox *) clientData;
381   int sel = -1;
382   unsigned int i;
383   const wxWidgetArray& buttons = item->GetRadioButtons();
384   for (i = 0; i < item->GetCount(); i++)
385     if (((Widget)buttons[i]) == w)
386       sel = (int)i;
387   item->SetSel(sel);
388 
389   if (item->InSetValue())
390     return;
391 
392   wxCommandEvent event (wxEVT_RADIOBOX, item->GetId());
393   event.SetInt(sel);
394   event.SetString(item->GetStringSelection());
395   event.SetEventObject(item);
396   item->ProcessCommand (event);
397 }
398 
399 #endif // wxUSE_RADIOBOX
400