]> git.saurik.com Git - wxWidgets.git/blame - src/motif/choice.cpp
More Motif additions: mdi and sashtest samples now just about work!
[wxWidgets.git] / src / motif / choice.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: choice.cpp
3// Purpose: wxChoice
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 "choice.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/choice.h"
f97c9854
JS
18#include "wx/utils.h"
19
20#include <Xm/Xm.h>
21#include <Xm/PushBG.h>
22#include <Xm/PushB.h>
23#include <Xm/RowColumn.h>
24
25#include "wx/motif/private.h"
4bb6408c
JS
26
27#if !USE_SHARED_LIBRARY
28IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
29#endif
30
f97c9854
JS
31void wxChoiceCallback (Widget w, XtPointer clientData,
32 XtPointer ptr);
33
34wxChoice::wxChoice()
35{
36 m_noStrings = 0;
37 m_buttonWidget = (WXWidget) 0;
38 m_menuWidget = (WXWidget) 0;
39 m_widgetList = (WXWidget*) 0;
40 m_formWidget = (WXWidget) 0;
f97c9854
JS
41}
42
4bb6408c
JS
43bool wxChoice::Create(wxWindow *parent, wxWindowID id,
44 const wxPoint& pos,
45 const wxSize& size,
46 int n, const wxString choices[],
47 long style,
48 const wxValidator& validator,
49 const wxString& name)
50{
51 SetName(name);
52 SetValidator(validator);
53 m_noStrings = n;
54 m_windowStyle = style;
f97c9854
JS
55 m_buttonWidget = (WXWidget) 0;
56 m_menuWidget = (WXWidget) 0;
57 m_widgetList = (WXWidget*) 0;
58 m_formWidget = (WXWidget) 0;
4bb6408c
JS
59
60 if (parent) parent->AddChild(this);
61
62 if ( id == -1 )
63 m_windowId = (int)NewControlId();
64 else
f97c9854
JS
65 m_windowId = id;
66
67 Widget parentWidget = (Widget) parent->GetClientWidget();
68
69 m_formWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name,
70 xmRowColumnWidgetClass, parentWidget,
71 XmNmarginHeight, 0,
72 XmNmarginWidth, 0,
73 XmNpacking, XmPACK_TIGHT,
74 XmNorientation, XmHORIZONTAL,
75 NULL);
76
77 XtVaSetValues ((Widget) m_formWidget, XmNspacing, 0, NULL);
78
79 /*
80 * Create the popup menu
81 */
82 m_menuWidget = (WXWidget) XmCreatePulldownMenu ((Widget) m_formWidget, "choiceMenu", NULL, 0);
83
84 int i;
85 if (n > 0)
86 {
87 int i;
88 for (i = 0; i < n; i++)
89 Append (choices[i]);
90 }
91
92 /*
93 * Create button
94 */
95 Arg args[10];
96 Cardinal argcnt = 0;
97
98 XtSetArg (args[argcnt], XmNsubMenuId, (Widget) m_menuWidget);
99 argcnt++;
100 XtSetArg (args[argcnt], XmNmarginWidth, 0);
101 argcnt++;
102 XtSetArg (args[argcnt], XmNmarginHeight, 0);
103 argcnt++;
104 XtSetArg (args[argcnt], XmNpacking, XmPACK_TIGHT);
105 argcnt++;
106 m_buttonWidget = (WXWidget) XmCreateOptionMenu ((Widget) m_formWidget, "choiceButton", args, argcnt);
107
108 m_mainWidget = m_buttonWidget;
109
110 XtManageChild ((Widget) m_buttonWidget);
111
112 // New code from Roland Haenel (roland_haenel@ac.cybercity.de)
113 // Some time ago, I reported a problem with wxChoice-items under
114 // Linux and Motif 2.0 (they caused sporadic GPFs). Now it seems
115 // that I have found the code responsible for this behaviour.
116#if XmVersion >= 1002
117#if XmVersion < 2000
118 Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget);
119 XtUnmanageChild (optionLabel);
120#endif
121#endif
4bb6408c 122
f97c9854
JS
123 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
124
125 AttachWidget (parent, m_buttonWidget, m_formWidget, pos.x, pos.y, size.x, size.y);
126
127 SetFont(* parent->GetFont());
128 ChangeColour(m_mainWidget);
129
130 return TRUE;
131}
132
133wxChoice::~wxChoice()
134{
135 // For some reason destroying the menuWidget
136 // can cause crashes on some machines. It will
137 // be deleted implicitly by deleting the parent form
138 // anyway.
139// XtDestroyWidget (menuWidget);
140 if (m_widgetList)
141 delete[] m_widgetList;
142
143 DetachWidget(GetMainWidget()); // Removes event handlers
144
145 XtDestroyWidget((Widget) m_formWidget);
146 m_formWidget = (WXWidget) 0;
147
148 // Presumably the other widgets have been deleted now, via the form
149 m_mainWidget = (WXWidget) 0;
150 m_buttonWidget = (WXWidget) 0;
4bb6408c
JS
151}
152
153void wxChoice::Append(const wxString& item)
154{
f97c9854
JS
155 wxStripMenuCodes ((char *)(const char *)item, wxBuffer);
156 Widget w = XtVaCreateManagedWidget (wxBuffer,
157#if USE_GADGETS
158 xmPushButtonGadgetClass, (Widget) m_menuWidget,
159#else
160 xmPushButtonWidgetClass, (Widget) m_menuWidget,
161#endif
162 NULL);
163
164 if (m_windowFont.Ok())
165 XtVaSetValues (w,
166 XmNfontList, (XmFontList) m_windowFont.GetFontList(1.0, XtDisplay((Widget) m_formWidget)),
167 NULL);
168
169 WXWidget *new_widgetList = new WXWidget[m_noStrings + 1];
170 int i;
171 for (i = 0; i < m_noStrings; i++)
172 new_widgetList[i] = m_widgetList[i];
173 new_widgetList[m_noStrings] = (WXWidget) w;
174 if (m_widgetList)
175 delete[] m_widgetList;
176 m_widgetList = new_widgetList;
177
178 char mnem = wxFindMnemonic ((char*) (const char*) item);
179 if (mnem != 0)
180 XtVaSetValues (w, XmNmnemonic, mnem, NULL);
181
182 XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) wxChoiceCallback, (XtPointer) this);
183
184 if (m_noStrings == 0 && m_buttonWidget)
185 {
186 XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL);
187 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
188 XmString text = XmStringCreateSimple ((char*) (const char*) item);
189 XtVaSetValues (label,
190 XmNlabelString, text,
191 NULL);
192 XmStringFree (text);
193 }
194 wxNode *node = m_stringList.Add (item);
195 XtVaSetValues (w, XmNuserData, node->Data (), NULL);
196
197 m_noStrings ++;
4bb6408c
JS
198}
199
200void wxChoice::Delete(int n)
201{
f97c9854
JS
202 wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" );
203
204 // What should we do -- remove the callback for this button widget,
205 // delete the m_stringList entry, delete the button widget, construct a new widget list
206 // (see Append)
207
4bb6408c
JS
208 // TODO
209 m_noStrings --;
210}
211
212void wxChoice::Clear()
213{
f97c9854
JS
214 m_stringList.Clear ();
215 int i;
216 for (i = 0; i < m_noStrings; i++)
217 {
218 XtUnmanageChild ((Widget) m_widgetList[i]);
219 XtDestroyWidget ((Widget) m_widgetList[i]);
220 }
221 if (m_noStrings)
222 delete[] m_widgetList;
223 m_widgetList = (WXWidget*) NULL;
224 if (m_buttonWidget)
225 XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, (Widget) NULL, NULL);
4bb6408c
JS
226 m_noStrings = 0;
227}
228
229int wxChoice::GetSelection() const
230{
f97c9854
JS
231 XmString text;
232 char *s;
233 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
234 XtVaGetValues (label,
235 XmNlabelString, &text,
236 NULL);
237
238 if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s))
239 {
240 int i = 0;
241 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
242 {
243 char *s1 = (char *) node->Data ();
244 if (s1 == s || strcmp (s1, s) == 0)
245 {
246 XmStringFree(text) ;
247 XtFree (s);
248 return i;
249 }
250 else
251 i++;
252 } // for()
253
254 XmStringFree(text) ;
255 XtFree (s);
256 return -1;
257 }
258 XmStringFree(text) ;
259 return -1;
4bb6408c
JS
260}
261
262void wxChoice::SetSelection(int n)
263{
f97c9854
JS
264 m_inSetValue = TRUE;
265
266 wxNode *node = m_stringList.Nth (n);
267 if (node)
268 {
269 Dimension selectionWidth, selectionHeight;
270
271 char *s = (char *) node->Data ();
272 XmString text = XmStringCreateSimple (s);
273 XtVaGetValues ((Widget) m_widgetList[n], XmNwidth, &selectionWidth, XmNheight, &selectionHeight, NULL);
274 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
275 XtVaSetValues (label,
276 XmNlabelString, text,
277 NULL);
278 XmStringFree (text);
279 XtVaSetValues ((Widget) m_buttonWidget,
280 XmNwidth, selectionWidth, XmNheight, selectionHeight,
281 XmNmenuHistory, (Widget) m_widgetList[n], NULL);
282 }
283 m_inSetValue = FALSE;
4bb6408c
JS
284}
285
286int wxChoice::FindString(const wxString& s) const
287{
f97c9854
JS
288 int i = 0;
289 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
290 {
291 char *s1 = (char *) node->Data ();
292 if (s == s1)
293 {
294 return i;
295 }
296 else
297 i++;
298 }
299 return -1;
4bb6408c
JS
300}
301
302wxString wxChoice::GetString(int n) const
303{
f97c9854
JS
304 wxNode *node = m_stringList.Nth (n);
305 if (node)
306 return wxString((char *) node->Data ());
307 else
308 return wxEmptyString;
309}
310
311void wxChoice::SetColumns(int n)
312{
313 if (n<1) n = 1 ;
314
315 short numColumns = n ;
316 Arg args[3];
317
318 XtSetArg(args[0], XmNnumColumns, numColumns);
319 XtSetArg(args[1], XmNpacking, XmPACK_COLUMN);
320 XtSetValues((Widget) m_menuWidget,args,2) ;
321}
322
323int wxChoice::GetColumns(void) const
324{
325 short numColumns ;
326
327 XtVaGetValues((Widget) m_menuWidget,XmNnumColumns,&numColumns,NULL) ;
328 return numColumns ;
329}
330
331void wxChoice::SetFocus()
332{
333 XmProcessTraversal(XtParent((Widget)m_mainWidget), XmTRAVERSE_CURRENT);
4bb6408c
JS
334}
335
336void wxChoice::SetSize(int x, int y, int width, int height, int sizeFlags)
337{
f97c9854
JS
338 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_ANY, NULL);
339 bool managed = XtIsManaged((Widget) m_formWidget);
340
341 if (managed)
342 XtUnmanageChild ((Widget) m_formWidget);
343
344 int actualWidth = width, actualHeight = height;
345
346 if (width > -1)
347 {
348 int i;
349 for (i = 0; i < m_noStrings; i++)
350 XtVaSetValues ((Widget) m_widgetList[i], XmNwidth, actualWidth, NULL);
351 XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, actualWidth,
352 NULL);
353 }
354 if (height > -1)
355 {
356 int i;
357 for (i = 0; i < m_noStrings; i++)
358 XtVaSetValues ((Widget) m_widgetList[i], XmNheight, actualHeight, NULL);
359 XtVaSetValues ((Widget) m_buttonWidget, XmNheight, actualHeight,
360 NULL);
361 }
362
363 if (managed)
364 XtManageChild ((Widget) m_formWidget);
365 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
366
367 wxControl::SetSize (x, y, width, height, sizeFlags);
4bb6408c
JS
368}
369
370wxString wxChoice::GetStringSelection () const
371{
372 int sel = GetSelection ();
373 if (sel > -1)
374 return wxString(this->GetString (sel));
375 else
f97c9854 376 return wxEmptyString;
4bb6408c
JS
377}
378
379bool wxChoice::SetStringSelection (const wxString& s)
380{
381 int sel = FindString (s);
382 if (sel > -1)
383 {
384 SetSelection (sel);
385 return TRUE;
386 }
387 else
388 return FALSE;
389}
390
391void wxChoice::Command(wxCommandEvent & event)
392{
393 SetSelection (event.GetInt());
394 ProcessCommand (event);
395}
396
f97c9854
JS
397void wxChoiceCallback (Widget w, XtPointer clientData,
398 XtPointer ptr)
399{
400 wxChoice *item = (wxChoice *) clientData;
401 if (item)
402 {
a4294b78 403 if (item->InSetValue())
f97c9854
JS
404 return;
405
406 char *s = NULL;
407 XtVaGetValues (w, XmNuserData, &s, NULL);
408 if (s)
409 {
410 wxCommandEvent event (wxEVT_COMMAND_CHOICE_SELECTED);
411 event.m_commandInt = item->FindString (s);
412// event.m_commandString = s;
413 item->ProcessCommand (event);
414 }
415 }
416}
417