1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "choice.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/choice.h"
21 #include <Xm/PushBG.h>
23 #include <Xm/RowColumn.h>
25 #include "wx/motif/private.h"
27 #if !USE_SHARED_LIBRARY
28 IMPLEMENT_DYNAMIC_CLASS(wxChoice
, wxControl
)
31 void wxChoiceCallback (Widget w
, XtPointer clientData
,
37 m_buttonWidget
= (WXWidget
) 0;
38 m_menuWidget
= (WXWidget
) 0;
39 m_widgetList
= (WXWidget
*) 0;
40 m_formWidget
= (WXWidget
) 0;
43 bool wxChoice::Create(wxWindow
*parent
, wxWindowID id
,
46 int n
, const wxString choices
[],
48 const wxValidator
& validator
,
52 SetValidator(validator
);
53 m_noStrings
= 0; // Starts off with none, incremented in Append
54 m_windowStyle
= style
;
55 m_buttonWidget
= (WXWidget
) 0;
56 m_menuWidget
= (WXWidget
) 0;
57 m_widgetList
= (WXWidget
*) 0;
58 m_formWidget
= (WXWidget
) 0;
60 if (parent
) parent
->AddChild(this);
63 m_windowId
= (int)NewControlId();
67 m_backgroundColour
= parent
->GetBackgroundColour();
68 m_foregroundColour
= parent
->GetForegroundColour();
69 m_font
= parent
->GetFont();
71 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
73 m_formWidget
= (WXWidget
) XtVaCreateManagedWidget ((char*) (const char*) name
,
74 xmRowColumnWidgetClass
, parentWidget
,
77 XmNpacking
, XmPACK_TIGHT
,
78 XmNorientation
, XmHORIZONTAL
,
81 XtVaSetValues ((Widget
) m_formWidget
, XmNspacing
, 0, NULL
);
84 * Create the popup menu
86 m_menuWidget
= (WXWidget
) XmCreatePulldownMenu ((Widget
) m_formWidget
, "choiceMenu", NULL
, 0);
92 for (i
= 0; i
< n
; i
++)
102 XtSetArg (args
[argcnt
], XmNsubMenuId
, (Widget
) m_menuWidget
);
104 XtSetArg (args
[argcnt
], XmNmarginWidth
, 0);
106 XtSetArg (args
[argcnt
], XmNmarginHeight
, 0);
108 XtSetArg (args
[argcnt
], XmNpacking
, XmPACK_TIGHT
);
110 m_buttonWidget
= (WXWidget
) XmCreateOptionMenu ((Widget
) m_formWidget
, "choiceButton", args
, argcnt
);
112 m_mainWidget
= m_buttonWidget
;
114 XtManageChild ((Widget
) m_buttonWidget
);
116 // New code from Roland Haenel (roland_haenel@ac.cybercity.de)
117 // Some time ago, I reported a problem with wxChoice-items under
118 // Linux and Motif 2.0 (they caused sporadic GPFs). Now it seems
119 // that I have found the code responsible for this behaviour.
120 #if XmVersion >= 1002
122 // JACS, 24/1/99: this seems to cause a malloc crash later on, e.g.
123 // in controls sample.
125 // Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget);
126 // XtUnmanageChild (optionLabel);
130 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
134 AttachWidget (parent
, m_buttonWidget
, m_formWidget
, pos
.x
, pos
.y
, size
.x
, size
.y
);
136 ChangeBackgroundColour();
141 wxChoice::~wxChoice()
143 // For some reason destroying the menuWidget
144 // can cause crashes on some machines. It will
145 // be deleted implicitly by deleting the parent form
147 // XtDestroyWidget (menuWidget);
149 delete[] m_widgetList
;
153 DetachWidget(GetMainWidget()); // Removes event handlers
154 DetachWidget(m_formWidget
);
156 XtDestroyWidget((Widget
) m_formWidget
);
157 m_formWidget
= (WXWidget
) 0;
159 // Presumably the other widgets have been deleted now, via the form
160 m_mainWidget
= (WXWidget
) 0;
161 m_buttonWidget
= (WXWidget
) 0;
165 void wxChoice::Append(const wxString
& item
)
167 wxStripMenuCodes ((char *)(const char *)item
, wxBuffer
);
168 Widget w
= XtVaCreateManagedWidget (wxBuffer
,
170 xmPushButtonGadgetClass
, (Widget
) m_menuWidget
,
172 xmPushButtonWidgetClass
, (Widget
) m_menuWidget
,
176 DoChangeBackgroundColour((WXWidget
) w
, m_backgroundColour
);
180 XmNfontList
, (XmFontList
) m_font
.GetFontList(1.0, XtDisplay((Widget
) m_formWidget
)),
183 WXWidget
*new_widgetList
= new WXWidget
[m_noStrings
+ 1];
186 for (i
= 0; i
< m_noStrings
; i
++)
187 new_widgetList
[i
] = m_widgetList
[i
];
189 new_widgetList
[m_noStrings
] = (WXWidget
) w
;
192 delete[] m_widgetList
;
193 m_widgetList
= new_widgetList
;
195 char mnem
= wxFindMnemonic ((char*) (const char*) item
);
197 XtVaSetValues (w
, XmNmnemonic
, mnem
, NULL
);
199 XtAddCallback (w
, XmNactivateCallback
, (XtCallbackProc
) wxChoiceCallback
, (XtPointer
) this);
201 if (m_noStrings
== 0 && m_buttonWidget
)
203 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmenuHistory
, w
, NULL
);
204 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
205 XmString text
= XmStringCreateSimple ((char*) (const char*) item
);
206 XtVaSetValues (label
,
207 XmNlabelString
, text
,
211 wxNode
*node
= m_stringList
.Add (item
);
212 XtVaSetValues (w
, XmNuserData
, node
->Data (), NULL
);
217 void wxChoice::Delete(int WXUNUSED(n
))
219 wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" );
221 // What should we do -- remove the callback for this button widget,
222 // delete the m_stringList entry, delete the button widget, construct a new widget list
229 void wxChoice::Clear()
231 m_stringList
.Clear ();
233 for (i
= 0; i
< m_noStrings
; i
++)
235 XtUnmanageChild ((Widget
) m_widgetList
[i
]);
236 XtDestroyWidget ((Widget
) m_widgetList
[i
]);
239 delete[] m_widgetList
;
240 m_widgetList
= (WXWidget
*) NULL
;
242 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmenuHistory
, (Widget
) NULL
, NULL
);
246 int wxChoice::GetSelection() const
250 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
251 XtVaGetValues (label
,
252 XmNlabelString
, &text
,
255 if (XmStringGetLtoR (text
, XmSTRING_DEFAULT_CHARSET
, &s
))
258 for (wxNode
* node
= m_stringList
.First (); node
; node
= node
->Next ())
260 char *s1
= (char *) node
->Data ();
261 if (s1
== s
|| strcmp (s1
, s
) == 0)
279 void wxChoice::SetSelection(int n
)
283 wxNode
*node
= m_stringList
.Nth (n
);
286 Dimension selectionWidth
, selectionHeight
;
288 char *s
= (char *) node
->Data ();
289 XmString text
= XmStringCreateSimple (s
);
290 XtVaGetValues ((Widget
) m_widgetList
[n
], XmNwidth
, &selectionWidth
, XmNheight
, &selectionHeight
, NULL
);
291 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
292 XtVaSetValues (label
,
293 XmNlabelString
, text
,
296 XtVaSetValues ((Widget
) m_buttonWidget
,
297 XmNwidth
, selectionWidth
, XmNheight
, selectionHeight
,
298 XmNmenuHistory
, (Widget
) m_widgetList
[n
], NULL
);
300 m_inSetValue
= FALSE
;
303 int wxChoice::FindString(const wxString
& s
) const
306 for (wxNode
* node
= m_stringList
.First (); node
; node
= node
->Next ())
308 char *s1
= (char *) node
->Data ();
319 wxString
wxChoice::GetString(int n
) const
321 wxNode
*node
= m_stringList
.Nth (n
);
323 return wxString((char *) node
->Data ());
325 return wxEmptyString
;
328 void wxChoice::SetColumns(int n
)
332 short numColumns
= n
;
335 XtSetArg(args
[0], XmNnumColumns
, numColumns
);
336 XtSetArg(args
[1], XmNpacking
, XmPACK_COLUMN
);
337 XtSetValues((Widget
) m_menuWidget
,args
,2) ;
340 int wxChoice::GetColumns(void) const
344 XtVaGetValues((Widget
) m_menuWidget
,XmNnumColumns
,&numColumns
,NULL
) ;
348 void wxChoice::SetFocus()
350 XmProcessTraversal(XtParent((Widget
)m_mainWidget
), XmTRAVERSE_CURRENT
);
353 void wxChoice::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
355 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
356 bool managed
= XtIsManaged((Widget
) m_formWidget
);
359 XtUnmanageChild ((Widget
) m_formWidget
);
361 int actualWidth
= width
, actualHeight
= height
;
366 for (i
= 0; i
< m_noStrings
; i
++)
367 XtVaSetValues ((Widget
) m_widgetList
[i
], XmNwidth
, actualWidth
, NULL
);
368 XtVaSetValues ((Widget
) m_buttonWidget
, XmNwidth
, actualWidth
,
374 for (i
= 0; i
< m_noStrings
; i
++)
375 XtVaSetValues ((Widget
) m_widgetList
[i
], XmNheight
, actualHeight
, NULL
);
376 XtVaSetValues ((Widget
) m_buttonWidget
, XmNheight
, actualHeight
,
381 XtManageChild ((Widget
) m_formWidget
);
382 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
384 wxControl::DoSetSize (x
, y
, width
, height
, sizeFlags
);
387 wxString
wxChoice::GetStringSelection () const
389 int sel
= GetSelection ();
391 return wxString(this->GetString (sel
));
393 return wxEmptyString
;
396 bool wxChoice::SetStringSelection (const wxString
& s
)
398 int sel
= FindString (s
);
408 void wxChoice::Command(wxCommandEvent
& event
)
410 SetSelection (event
.GetInt());
411 ProcessCommand (event
);
414 void wxChoiceCallback (Widget w
, XtPointer clientData
, XtPointer
WXUNUSED(ptr
))
416 wxChoice
*item
= (wxChoice
*) clientData
;
419 if (item
->InSetValue())
423 XtVaGetValues (w
, XmNuserData
, &s
, NULL
);
426 wxCommandEvent
event (wxEVT_COMMAND_CHOICE_SELECTED
, item
->GetId());
427 event
.SetEventObject(item
);
428 event
.m_commandInt
= item
->FindString (s
);
429 // event.m_commandString = s;
430 item
->ProcessCommand (event
);
435 void wxChoice::ChangeFont(bool keepOriginalSize
)
437 // Note that this causes the widget to be resized back
438 // to its original size! We therefore have to set the size
439 // back again. TODO: a better way in Motif?
442 int width
, height
, width1
, height1
;
443 GetSize(& width
, & height
);
445 XmFontList fontList
= (XmFontList
) m_font
.GetFontList(1.0, XtDisplay((Widget
) m_mainWidget
));
446 XtVaSetValues ((Widget
) m_mainWidget
, XmNfontList
, fontList
, NULL
);
447 XtVaSetValues ((Widget
) m_buttonWidget
, XmNfontList
, fontList
, NULL
);
449 /* TODO: why does this cause a crash in XtWidgetToApplicationContext?
451 for (i = 0; i < m_noStrings; i++)
452 XtVaSetValues ((Widget) m_widgetList[i], XmNfontList, fontList, NULL);
454 GetSize(& width1
, & height1
);
455 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
457 SetSize(-1, -1, width
, height
);
462 void wxChoice::ChangeBackgroundColour()
464 DoChangeBackgroundColour(m_formWidget
, m_backgroundColour
);
465 DoChangeBackgroundColour(m_buttonWidget
, m_backgroundColour
);
466 DoChangeBackgroundColour(m_menuWidget
, m_backgroundColour
);
468 for (i
= 0; i
< m_noStrings
; i
++)
469 DoChangeBackgroundColour(m_widgetList
[i
], m_backgroundColour
);
472 void wxChoice::ChangeForegroundColour()
474 DoChangeForegroundColour(m_formWidget
, m_foregroundColour
);
475 DoChangeForegroundColour(m_buttonWidget
, m_foregroundColour
);
476 DoChangeForegroundColour(m_menuWidget
, m_foregroundColour
);
478 for (i
= 0; i
< m_noStrings
; i
++)
479 DoChangeForegroundColour(m_widgetList
[i
], m_foregroundColour
);