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