]> git.saurik.com Git - wxWidgets.git/blame - src/motif/radiobox.cpp
rewrite to avoid unnecessary redraws
[wxWidgets.git] / src / motif / radiobox.cpp
CommitLineData
4bb6408c
JS
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
af0bb3b1 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "radiobox.h"
14#endif
15
bcd055ae
JJ
16#ifdef __VMS
17#define XtDisplay XTDISPLAY
18#endif
19
4bb6408c 20#include "wx/radiobox.h"
a4294b78
JS
21#include "wx/utils.h"
22
338dd992
JJ
23#ifdef __VMS__
24#pragma message disable nosimpint
25#endif
a4294b78
JS
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>
9838df2c 32#include <Xm/Frame.h>
338dd992
JJ
33#ifdef __VMS__
34#pragma message enable nosimpint
35#endif
a4294b78 36
3096bd2f 37#include "wx/motif/private.h"
a4294b78
JS
38
39void wxRadioBoxCallback (Widget w, XtPointer clientData,
af0bb3b1 40 XmToggleButtonCallbackStruct * cbs);
4bb6408c 41
4bb6408c 42IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
4bb6408c
JS
43
44// Radio box item
45wxRadioBox::wxRadioBox()
46{
47 m_selectedButton = -1;
48 m_noItems = 0;
49 m_noRowsOrCols = 0;
50 m_majorDim = 0 ;
a4294b78
JS
51
52 m_formWidget = (WXWidget) 0;
9838df2c 53 m_frameWidget = (WXWidget) 0;
a4294b78
JS
54 m_labelWidget = (WXWidget) 0;
55 m_radioButtons = (WXWidget*) NULL;
56 m_radioButtonLabels = (wxString*) NULL;
4bb6408c
JS
57}
58
59bool 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;
9838df2c
JS
67 m_formWidget = (WXWidget) 0;
68 m_frameWidget = (WXWidget) 0;
a4294b78
JS
69 m_labelWidget = (WXWidget) 0;
70 m_radioButtons = (WXWidget*) NULL;
71 m_radioButtonLabels = (wxString*) NULL;
0d57be45
JS
72 m_backgroundColour = parent->GetBackgroundColour();
73 m_foregroundColour = parent->GetForegroundColour();
da175b2c 74 m_font = parent->GetFont();
4bb6408c
JS
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
a4294b78
JS
95 Widget parentWidget = (Widget) parent->GetClientWidget();
96
97 wxString label1(wxStripMenuCodes(title));
98
31528cd3 99 Widget formWidget = XtVaCreateManagedWidget (name.c_str(),
af0bb3b1
VZ
100 xmFormWidgetClass, parentWidget,
101 XmNmarginHeight, 0,
102 XmNmarginWidth, 0,
103 NULL);
a4294b78
JS
104
105 m_formWidget = (WXWidget) formWidget;
106
da175b2c 107 XmFontList fontList = (XmFontList) m_font.GetFontList(1.0, XtDisplay(parentWidget));
a4294b78
JS
108 if (label1 != "")
109 {
31528cd3
VZ
110 wxXmString text(label1);
111 (void)XtVaCreateManagedWidget(label1.c_str(),
a4294b78 112#if wxUSE_GADGETS
31528cd3
VZ
113 style & wxCOLOURED ? xmLabelWidgetClass
114 : xmLabelGadgetClass,
af0bb3b1 115 formWidget,
a4294b78 116#else
af0bb3b1 117 xmLabelWidgetClass, formWidget,
a4294b78 118#endif
ea57084d 119 XmNfontList, fontList,
98300330 120 XmNlabelString, text(),
af0bb3b1 121 NULL);
a4294b78
JS
122 }
123
9838df2c 124 Widget frameWidget = XtVaCreateManagedWidget ("frame",
af0bb3b1 125 xmFrameWidgetClass, formWidget,
9838df2c 126 XmNshadowType, XmSHADOW_IN,
af0bb3b1
VZ
127// XmNmarginHeight, 0,
128// XmNmarginWidth, 0,
129 NULL);
9838df2c
JS
130
131 m_frameWidget = (WXWidget) frameWidget;
132
a4294b78
JS
133 Arg args[3];
134
978db70e 135 m_majorDim = (n + m_majorDim - 1) / m_majorDim;
a4294b78
JS
136
137 XtSetArg (args[0], XmNorientation, ((style & wxHORIZONTAL) == wxHORIZONTAL ?
af0bb3b1 138 XmHORIZONTAL : XmVERTICAL));
98300330 139 XtSetArg (args[1], XmNnumColumns, m_majorDim);
a4294b78 140
9838df2c 141 Widget radioBoxWidget = XmCreateRadioBox (frameWidget, "radioBoxWidget", args, 2);
a4294b78 142 m_mainWidget = (WXWidget) radioBoxWidget;
4bb6408c 143
a4294b78
JS
144
145 if (m_labelWidget)
af0bb3b1
VZ
146 XtVaSetValues ((Widget) m_labelWidget,
147 XmNtopAttachment, XmATTACH_FORM,
148 XmNleftAttachment, XmATTACH_FORM,
149 XmNalignment, XmALIGNMENT_BEGINNING,
150 NULL);
a4294b78
JS
151
152 XtVaSetValues (radioBoxWidget,
af0bb3b1
VZ
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);
a4294b78
JS
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
af0bb3b1 172 xmToggleButtonGadgetClass, radioBoxWidget,
a4294b78 173#else
af0bb3b1 174 xmToggleButtonWidgetClass, radioBoxWidget,
a4294b78 175#endif
ea57084d 176 XmNfontList, fontList,
af0bb3b1 177 NULL);
a4294b78 178 XtAddCallback ((Widget) m_radioButtons[i], XmNvalueChangedCallback, (XtCallbackProc) wxRadioBoxCallback,
d7dcb939 179 (XtPointer) this);
a4294b78
JS
180 }
181 SetSelection (0);
182
da175b2c 183 m_font = parent->GetFont();
4b5f3fe6
JS
184 ChangeFont(FALSE);
185
9838df2c 186 // XtManageChild((Widget) m_formWidget);
a4294b78
JS
187 XtManageChild (radioBoxWidget);
188
189 SetCanAddEventHandler(TRUE);
190 AttachWidget (parent, m_mainWidget, m_formWidget, pos.x, pos.y, size.x, size.y);
191
0d57be45 192 ChangeBackgroundColour();
a4294b78
JS
193
194 return TRUE;
4bb6408c
JS
195}
196
197
198wxRadioBox::~wxRadioBox()
199{
a4294b78
JS
200 delete[] m_radioButtonLabels;
201 delete[] m_radioButtons;
15d5ab67 202
b412f9be 203 DetachWidget(m_formWidget);
15d5ab67
JS
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;
4bb6408c
JS
214}
215
216wxString wxRadioBox::GetLabel(int item) const
217{
a4294b78
JS
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,
af0bb3b1
VZ
225 XmNlabelString, &text,
226 NULL);
a4294b78
JS
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 }
4bb6408c
JS
241}
242
243void wxRadioBox::SetLabel(int item, const wxString& label)
244{
a4294b78
JS
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,
af0bb3b1
VZ
254 XmNlabelString, text,
255 XmNlabelType, XmSTRING,
256 NULL);
a4294b78
JS
257 XmStringFree (text);
258 }
4bb6408c
JS
259}
260
261int wxRadioBox::FindString(const wxString& s) const
262{
a4294b78
JS
263 int i;
264 for (i = 0; i < m_noItems; i++)
265 if (s == m_radioButtonLabels[i])
266 return i;
4bb6408c
JS
267 return -1;
268}
269
270void wxRadioBox::SetSelection(int n)
271{
272 if ((n < 0) || (n >= m_noItems))
273 return;
4bb6408c
JS
274
275 m_selectedButton = n;
a4294b78
JS
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;
4bb6408c
JS
287}
288
289// Get single selection, for single choice list items
290int wxRadioBox::GetSelection() const
291{
292 return m_selectedButton;
293}
294
295// Find string for position
296wxString wxRadioBox::GetString(int n) const
297{
a4294b78
JS
298 if ((n < 0) || (n >= m_noItems))
299 return wxEmptyString;
300 return m_radioButtonLabels[n];
4bb6408c
JS
301}
302
bfc6fde4 303void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
4bb6408c 304{
a4294b78 305 bool managed = XtIsManaged((Widget) m_formWidget);
4bb6408c 306
a4294b78
JS
307 if (managed)
308 XtUnmanageChild ((Widget) m_formWidget);
4bb6408c 309
a4294b78
JS
310 int xx = x; int yy = y;
311 AdjustForParentClientOrigin(xx, yy, sizeFlags);
4bb6408c 312
a4294b78
JS
313 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
314 XtVaSetValues ((Widget) m_formWidget, XmNleftAttachment, XmATTACH_SELF,
af0bb3b1 315 XmNx, xx, NULL);
a4294b78
JS
316 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
317 XtVaSetValues ((Widget) m_formWidget, XmNtopAttachment, XmATTACH_SELF,
af0bb3b1 318 XmNy, yy, NULL);
4bb6408c 319
a4294b78
JS
320 // Must set the actual RadioBox to be desired size MINUS label size
321 Dimension labelWidth = 0, labelHeight = 0, actualWidth = 0, actualHeight = 0;
4bb6408c 322
a4294b78
JS
323 if (m_labelWidget)
324 XtVaGetValues ((Widget) m_labelWidget, XmNwidth, &labelWidth, XmNheight, &labelHeight, NULL);
4bb6408c 325
a4294b78
JS
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);
4bb6408c
JS
339}
340
341// Enable a specific button
a4294b78 342void wxRadioBox::Enable(int n, bool enable)
4bb6408c 343{
a4294b78
JS
344 if ((n < 0) || (n >= m_noItems))
345 return;
346
347 XtSetSensitive ((Widget) m_radioButtons[n], (Boolean) enable);
4bb6408c
JS
348}
349
350// Enable all controls
af0bb3b1 351bool wxRadioBox::Enable(bool enable)
4bb6408c 352{
af0bb3b1
VZ
353 if ( !wxControl::Enable(enable) )
354 return FALSE;
4bb6408c 355
a4294b78
JS
356 int i;
357 for (i = 0; i < m_noItems; i++)
358 XtSetSensitive ((Widget) m_radioButtons[i], (Boolean) enable);
af0bb3b1
VZ
359
360 return TRUE;
4bb6408c
JS
361}
362
9838df2c
JS
363bool wxRadioBox::Show(bool show)
364{
365 // TODO: show/hide all children
366 return wxControl::Show(show);
367}
368
4bb6408c 369// Show a specific button
a4294b78 370void wxRadioBox::Show(int n, bool show)
4bb6408c 371{
a4294b78
JS
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, " ");
4bb6408c
JS
396}
397
398// For single selection items only
399wxString wxRadioBox::GetStringSelection () const
400{
401 int sel = GetSelection ();
402 if (sel > -1)
403 return this->GetString (sel);
404 else
405 return wxString("");
406}
407
408bool 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
420void wxRadioBox::Command (wxCommandEvent & event)
421{
422 SetSelection (event.m_commandInt);
423 ProcessCommand (event);
424}
425
4b5f3fe6 426void wxRadioBox::ChangeFont(bool keepOriginalSize)
0d57be45 427{
94b49b93
JS
428 wxWindow::ChangeFont(keepOriginalSize);
429
da175b2c 430 XmFontList fontList = (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) GetTopWidget()));
94b49b93
JS
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,
af0bb3b1 439 XmNtopAttachment, XmATTACH_FORM,
94b49b93
JS
440 NULL);
441 }
0d57be45
JS
442}
443
444void wxRadioBox::ChangeBackgroundColour()
445{
94b49b93
JS
446 wxWindow::ChangeBackgroundColour();
447
9838df2c
JS
448 DoChangeBackgroundColour((Widget) m_frameWidget, m_backgroundColour);
449
450 int selectPixel = wxBLACK->AllocColour(wxGetDisplay());
451
94b49b93
JS
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);
9838df2c
JS
458
459 XtVaSetValues ((Widget) radioButton,
460 XmNselectColor, selectPixel,
461 NULL);
94b49b93 462 }
0d57be45
JS
463}
464
465void wxRadioBox::ChangeForegroundColour()
466{
94b49b93
JS
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 }
0d57be45
JS
476}
477
a4294b78 478void wxRadioBoxCallback (Widget w, XtPointer clientData,
af0bb3b1 479 XmToggleButtonCallbackStruct * cbs)
a4294b78
JS
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}
4bb6408c 500