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