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