Committing in .
[wxWidgets.git] / src / motif / radiobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 #ifdef __GNUG__
13 #pragma implementation "radiobox.h"
14 #endif
15
16 #include "wx/radiobox.h"
17 #include "wx/utils.h"
18
19 #ifdef __VMS__
20 #pragma message disable nosimpint
21 #endif
22 #include <Xm/Label.h>
23 #include <Xm/LabelG.h>
24 #include <Xm/ToggleB.h>
25 #include <Xm/ToggleBG.h>
26 #include <Xm/RowColumn.h>
27 #include <Xm/Form.h>
28 #include <Xm/Frame.h>
29 #ifdef __VMS__
30 #pragma message enable nosimpint
31 #endif
32
33 #include "wx/motif/private.h"
34
35 void wxRadioBoxCallback (Widget w, XtPointer clientData,
36 XmToggleButtonCallbackStruct * cbs);
37
38 #if !USE_SHARED_LIBRARY
39 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
40 #endif
41
42 // Radio box item
43 wxRadioBox::wxRadioBox()
44 {
45 m_selectedButton = -1;
46 m_noItems = 0;
47 m_noRowsOrCols = 0;
48 m_majorDim = 0 ;
49
50 m_formWidget = (WXWidget) 0;
51 m_frameWidget = (WXWidget) 0;
52 m_labelWidget = (WXWidget) 0;
53 m_radioButtons = (WXWidget*) NULL;
54 m_radioButtonLabels = (wxString*) NULL;
55 }
56
57 bool wxRadioBox::Create(wxWindow *parent, wxWindowID id, const wxString& title,
58 const wxPoint& pos, const wxSize& size,
59 int n, const wxString choices[],
60 int majorDim, long style,
61 const wxValidator& val, const wxString& name)
62 {
63 m_selectedButton = -1;
64 m_noItems = n;
65 m_formWidget = (WXWidget) 0;
66 m_frameWidget = (WXWidget) 0;
67 m_labelWidget = (WXWidget) 0;
68 m_radioButtons = (WXWidget*) NULL;
69 m_radioButtonLabels = (wxString*) NULL;
70 m_backgroundColour = parent->GetBackgroundColour();
71 m_foregroundColour = parent->GetForegroundColour();
72 m_font = parent->GetFont();
73
74 SetName(name);
75 SetValidator(val);
76
77 parent->AddChild(this);
78
79 m_windowStyle = (long&)style;
80
81 if (id == -1)
82 m_windowId = NewControlId();
83 else
84 m_windowId = id;
85
86 m_noRowsOrCols = majorDim;
87
88 if (majorDim==0)
89 m_majorDim = n ;
90 else
91 m_majorDim = majorDim ;
92
93 Widget parentWidget = (Widget) parent->GetClientWidget();
94
95 wxString label1(wxStripMenuCodes(title));
96
97 Widget formWidget = XtVaCreateManagedWidget (name.c_str(),
98 xmFormWidgetClass, parentWidget,
99 XmNmarginHeight, 0,
100 XmNmarginWidth, 0,
101 NULL);
102
103 m_formWidget = (WXWidget) formWidget;
104
105 XmFontList fontList = (XmFontList) m_font.GetFontList(1.0, XtDisplay(parentWidget));
106 if (label1 != "")
107 {
108 wxXmString text(label1);
109 (void)XtVaCreateManagedWidget(label1.c_str(),
110 #if wxUSE_GADGETS
111 style & wxCOLOURED ? xmLabelWidgetClass
112 : xmLabelGadgetClass,
113 formWidget,
114 #else
115 xmLabelWidgetClass, formWidget,
116 #endif
117 XmNfontList, fontList,
118 XmNlabelString, text(),
119 NULL);
120 }
121
122 Widget frameWidget = XtVaCreateManagedWidget ("frame",
123 xmFrameWidgetClass, formWidget,
124 XmNshadowType, XmSHADOW_IN,
125 // XmNmarginHeight, 0,
126 // XmNmarginWidth, 0,
127 NULL);
128
129 m_frameWidget = (WXWidget) frameWidget;
130
131 Arg args[3];
132
133 m_majorDim = (n + m_majorDim - 1) / m_majorDim;
134
135 XtSetArg (args[0], XmNorientation, ((style & wxHORIZONTAL) == wxHORIZONTAL ?
136 XmHORIZONTAL : XmVERTICAL));
137 XtSetArg (args[1], XmNnumColumns, m_majorDim);
138
139 Widget radioBoxWidget = XmCreateRadioBox (frameWidget, "radioBoxWidget", args, 2);
140 m_mainWidget = (WXWidget) radioBoxWidget;
141
142
143 if (m_labelWidget)
144 XtVaSetValues ((Widget) m_labelWidget,
145 XmNtopAttachment, XmATTACH_FORM,
146 XmNleftAttachment, XmATTACH_FORM,
147 XmNalignment, XmALIGNMENT_BEGINNING,
148 NULL);
149
150 XtVaSetValues (radioBoxWidget,
151 XmNtopAttachment, m_labelWidget ? XmATTACH_WIDGET : XmATTACH_FORM,
152 XmNtopWidget, m_labelWidget ? (Widget) m_labelWidget : formWidget,
153 XmNbottomAttachment, XmATTACH_FORM,
154 XmNleftAttachment, XmATTACH_FORM,
155 XmNrightAttachment, XmATTACH_FORM,
156 NULL);
157
158 // if (style & wxFLAT)
159 // XtVaSetValues (radioBoxWidget, XmNborderWidth, 1, NULL);
160
161 m_radioButtons = new WXWidget[n];
162 m_radioButtonLabels = new wxString[n];
163 int i;
164 for (i = 0; i < n; i++)
165 {
166 wxString str(wxStripMenuCodes(choices[i]));
167 m_radioButtonLabels[i] = str;
168 m_radioButtons[i] = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) str,
169 #if wxUSE_GADGETS
170 xmToggleButtonGadgetClass, radioBoxWidget,
171 #else
172 xmToggleButtonWidgetClass, radioBoxWidget,
173 #endif
174 XmNfontList, fontList,
175 NULL);
176 #ifdef __VMS__
177 #pragma message disable voiincconext
178 // VMS gives here the compiler warning:
179 // conversion from pointer to function to void* permitted
180 // as an extension
181 #endif
182 XtAddCallback ((Widget) m_radioButtons[i], XmNvalueChangedCallback, (XtCallbackProc) wxRadioBoxCallback,
183 (XtCallbackProc) this);
184 #ifdef __VMS__
185 #pragma message enable voiincconext
186 #endif
187
188 }
189 SetSelection (0);
190
191 m_font = parent->GetFont();
192 ChangeFont(FALSE);
193
194 // XtManageChild((Widget) m_formWidget);
195 XtManageChild (radioBoxWidget);
196
197 SetCanAddEventHandler(TRUE);
198 AttachWidget (parent, m_mainWidget, m_formWidget, pos.x, pos.y, size.x, size.y);
199
200 ChangeBackgroundColour();
201
202 return TRUE;
203 }
204
205
206 wxRadioBox::~wxRadioBox()
207 {
208 delete[] m_radioButtonLabels;
209 delete[] m_radioButtons;
210
211 DetachWidget(m_formWidget);
212 DetachWidget(m_mainWidget);
213
214 if (m_labelWidget)
215 XtDestroyWidget((Widget) m_labelWidget);
216 XtDestroyWidget((Widget) m_mainWidget);
217 XtDestroyWidget((Widget) m_formWidget);
218
219 m_mainWidget = (WXWidget) 0;
220 m_formWidget = (WXWidget) 0;
221 m_labelWidget = (WXWidget) 0;
222 }
223
224 wxString wxRadioBox::GetLabel(int item) const
225 {
226 if (item < 0 || item >= m_noItems)
227 return wxEmptyString;
228
229 Widget widget = (Widget) m_radioButtons[item];
230 XmString text;
231 char *s;
232 XtVaGetValues (widget,
233 XmNlabelString, &text,
234 NULL);
235
236 if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s))
237 {
238 // Should we free 'text'???
239 XmStringFree(text);
240 wxString str(s);
241 XtFree (s);
242 return str;
243 }
244 else
245 {
246 XmStringFree(text);
247 return wxEmptyString;
248 }
249 }
250
251 void wxRadioBox::SetLabel(int item, const wxString& label)
252 {
253 if (item < 0 || item >= m_noItems)
254 return;
255
256 Widget widget = (Widget) m_radioButtons[item];
257 if (label != "")
258 {
259 wxString label1(wxStripMenuCodes(label));
260 XmString text = XmStringCreateSimple ((char*) (const char*) label1);
261 XtVaSetValues (widget,
262 XmNlabelString, text,
263 XmNlabelType, XmSTRING,
264 NULL);
265 XmStringFree (text);
266 }
267 }
268
269 int wxRadioBox::FindString(const wxString& s) const
270 {
271 int i;
272 for (i = 0; i < m_noItems; i++)
273 if (s == m_radioButtonLabels[i])
274 return i;
275 return -1;
276 }
277
278 void wxRadioBox::SetSelection(int n)
279 {
280 if ((n < 0) || (n >= m_noItems))
281 return;
282
283 m_selectedButton = n;
284
285 m_inSetValue = TRUE;
286
287 XmToggleButtonSetState ((Widget) m_radioButtons[n], TRUE, FALSE);
288
289 int i;
290 for (i = 0; i < m_noItems; i++)
291 if (i != n)
292 XmToggleButtonSetState ((Widget) m_radioButtons[i], FALSE, FALSE);
293
294 m_inSetValue = FALSE;
295 }
296
297 // Get single selection, for single choice list items
298 int wxRadioBox::GetSelection() const
299 {
300 return m_selectedButton;
301 }
302
303 // Find string for position
304 wxString wxRadioBox::GetString(int n) const
305 {
306 if ((n < 0) || (n >= m_noItems))
307 return wxEmptyString;
308 return m_radioButtonLabels[n];
309 }
310
311 void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
312 {
313 bool managed = XtIsManaged((Widget) m_formWidget);
314
315 if (managed)
316 XtUnmanageChild ((Widget) m_formWidget);
317
318 int xx = x; int yy = y;
319 AdjustForParentClientOrigin(xx, yy, sizeFlags);
320
321 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
322 XtVaSetValues ((Widget) m_formWidget, XmNleftAttachment, XmATTACH_SELF,
323 XmNx, xx, NULL);
324 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
325 XtVaSetValues ((Widget) m_formWidget, XmNtopAttachment, XmATTACH_SELF,
326 XmNy, yy, NULL);
327
328 // Must set the actual RadioBox to be desired size MINUS label size
329 Dimension labelWidth = 0, labelHeight = 0, actualWidth = 0, actualHeight = 0;
330
331 if (m_labelWidget)
332 XtVaGetValues ((Widget) m_labelWidget, XmNwidth, &labelWidth, XmNheight, &labelHeight, NULL);
333
334 actualWidth = width;
335 actualHeight = height - labelHeight;
336
337 if (width > -1)
338 {
339 XtVaSetValues ((Widget) m_mainWidget, XmNwidth, actualWidth, NULL);
340 }
341 if (height > -1)
342 {
343 XtVaSetValues ((Widget) m_mainWidget, XmNheight, actualHeight, NULL);
344 }
345 if (managed)
346 XtManageChild ((Widget) m_formWidget);
347 }
348
349 // Enable a specific button
350 void wxRadioBox::Enable(int n, bool enable)
351 {
352 if ((n < 0) || (n >= m_noItems))
353 return;
354
355 XtSetSensitive ((Widget) m_radioButtons[n], (Boolean) enable);
356 }
357
358 // Enable all controls
359 bool wxRadioBox::Enable(bool enable)
360 {
361 if ( !wxControl::Enable(enable) )
362 return FALSE;
363
364 int i;
365 for (i = 0; i < m_noItems; i++)
366 XtSetSensitive ((Widget) m_radioButtons[i], (Boolean) enable);
367
368 return TRUE;
369 }
370
371 bool wxRadioBox::Show(bool show)
372 {
373 // TODO: show/hide all children
374 return wxControl::Show(show);
375 }
376
377 // Show a specific button
378 void wxRadioBox::Show(int n, bool show)
379 {
380 // This method isn't complete, and we try do do our best...
381 // It's main purpose isn't for allowing Show/Unshow dynamically,
382 // but rather to provide a way to design wxRadioBox such:
383 //
384 // o Val1 o Val2 o Val3
385 // o Val4 o Val6
386 // o Val7 o Val8 o Val9
387 //
388 // In my case, this is a 'direction' box, and the Show(5,False) is
389 // coupled with an Enable(5,False)
390 //
391 if ((n < 0) || (n >= m_noItems))
392 return;
393
394 XtVaSetValues ((Widget) m_radioButtons[n],
395 XmNindicatorOn, (unsigned char) show,
396 NULL);
397
398 // Please note that this is all we can do: removing the label
399 // if switching to unshow state. However, when switching
400 // to the on state, it's the prog. resp. to call SetLabel(item,...)
401 // after this call!!
402 if (!show)
403 wxRadioBox::SetLabel (n, " ");
404 }
405
406 // For single selection items only
407 wxString wxRadioBox::GetStringSelection () const
408 {
409 int sel = GetSelection ();
410 if (sel > -1)
411 return this->GetString (sel);
412 else
413 return wxString("");
414 }
415
416 bool wxRadioBox::SetStringSelection (const wxString& s)
417 {
418 int sel = FindString (s);
419 if (sel > -1)
420 {
421 SetSelection (sel);
422 return TRUE;
423 }
424 else
425 return FALSE;
426 }
427
428 void wxRadioBox::Command (wxCommandEvent & event)
429 {
430 SetSelection (event.m_commandInt);
431 ProcessCommand (event);
432 }
433
434 void wxRadioBox::ChangeFont(bool keepOriginalSize)
435 {
436 wxWindow::ChangeFont(keepOriginalSize);
437
438 XmFontList fontList = (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) GetTopWidget()));
439
440 int i;
441 for (i = 0; i < m_noItems; i++)
442 {
443 WXWidget radioButton = m_radioButtons[i];
444
445 XtVaSetValues ((Widget) radioButton,
446 XmNfontList, fontList,
447 XmNtopAttachment, XmATTACH_FORM,
448 NULL);
449 }
450 }
451
452 void wxRadioBox::ChangeBackgroundColour()
453 {
454 wxWindow::ChangeBackgroundColour();
455
456 DoChangeBackgroundColour((Widget) m_frameWidget, m_backgroundColour);
457
458 int selectPixel = wxBLACK->AllocColour(wxGetDisplay());
459
460 int i;
461 for (i = 0; i < m_noItems; i++)
462 {
463 WXWidget radioButton = m_radioButtons[i];
464
465 DoChangeBackgroundColour(radioButton, m_backgroundColour, TRUE);
466
467 XtVaSetValues ((Widget) radioButton,
468 XmNselectColor, selectPixel,
469 NULL);
470 }
471 }
472
473 void wxRadioBox::ChangeForegroundColour()
474 {
475 wxWindow::ChangeForegroundColour();
476
477 int i;
478 for (i = 0; i < m_noItems; i++)
479 {
480 WXWidget radioButton = m_radioButtons[i];
481
482 DoChangeForegroundColour(radioButton, m_foregroundColour);
483 }
484 }
485
486 void wxRadioBoxCallback (Widget w, XtPointer clientData,
487 XmToggleButtonCallbackStruct * cbs)
488 {
489 if (!cbs->set)
490 return;
491
492 wxRadioBox *item = (wxRadioBox *) clientData;
493 int sel = -1;
494 int i;
495 for (i = 0; i < item->Number(); i++)
496 if (item->GetRadioButtons() && ((Widget) (item->GetRadioButtons()[i]) == w))
497 sel = i;
498 item->SetSel(sel);
499
500 if (item->InSetValue())
501 return;
502
503 wxCommandEvent event (wxEVT_COMMAND_RADIOBOX_SELECTED, item->GetId());
504 event.m_commandInt = sel;
505 event.SetEventObject(item);
506 item->ProcessCommand (event);
507 }
508