]> git.saurik.com Git - wxWidgets.git/blob - src/motif/choice.cpp
Added an #ifdef
[wxWidgets.git] / src / motif / choice.cpp
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"
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"
26
27 #if !USE_SHARED_LIBRARY
28 IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
29 #endif
30
31 void wxChoiceCallback (Widget w, XtPointer clientData,
32 XtPointer ptr);
33
34 wxChoice::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;
41 }
42
43 bool 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 = 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;
59
60 if (parent) parent->AddChild(this);
61
62 if ( id == -1 )
63 m_windowId = (int)NewControlId();
64 else
65 m_windowId = id;
66
67 m_backgroundColour = parent->GetBackgroundColour();
68 m_foregroundColour = parent->GetForegroundColour();
69 m_font = parent->GetFont();
70
71 Widget parentWidget = (Widget) parent->GetClientWidget();
72
73 m_formWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name,
74 xmRowColumnWidgetClass, parentWidget,
75 XmNmarginHeight, 0,
76 XmNmarginWidth, 0,
77 XmNpacking, XmPACK_TIGHT,
78 XmNorientation, XmHORIZONTAL,
79 NULL);
80
81 XtVaSetValues ((Widget) m_formWidget, XmNspacing, 0, NULL);
82
83 /*
84 * Create the popup menu
85 */
86 m_menuWidget = (WXWidget) XmCreatePulldownMenu ((Widget) m_formWidget, "choiceMenu", NULL, 0);
87
88 // int i;
89 if (n > 0)
90 {
91 int i;
92 for (i = 0; i < n; i++)
93 Append (choices[i]);
94 }
95
96 /*
97 * Create button
98 */
99 Arg args[10];
100 Cardinal argcnt = 0;
101
102 XtSetArg (args[argcnt], XmNsubMenuId, (Widget) m_menuWidget);
103 argcnt++;
104 XtSetArg (args[argcnt], XmNmarginWidth, 0);
105 argcnt++;
106 XtSetArg (args[argcnt], XmNmarginHeight, 0);
107 argcnt++;
108 XtSetArg (args[argcnt], XmNpacking, XmPACK_TIGHT);
109 argcnt++;
110 m_buttonWidget = (WXWidget) XmCreateOptionMenu ((Widget) m_formWidget, "choiceButton", args, argcnt);
111
112 m_mainWidget = m_buttonWidget;
113
114 XtManageChild ((Widget) m_buttonWidget);
115
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
121 #if XmVersion < 2000
122 // JACS, 24/1/99: this seems to cause a malloc crash later on, e.g.
123 // in controls sample.
124 //
125 // Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget);
126 // XtUnmanageChild (optionLabel);
127 #endif
128 #endif
129
130 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
131
132 ChangeFont(FALSE);
133
134 AttachWidget (parent, m_buttonWidget, m_formWidget, pos.x, pos.y, size.x, size.y);
135
136 ChangeBackgroundColour();
137
138 return TRUE;
139 }
140
141 wxChoice::~wxChoice()
142 {
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
146 // anyway.
147 // XtDestroyWidget (menuWidget);
148 if (m_widgetList)
149 delete[] m_widgetList;
150
151 if (GetMainWidget())
152 {
153 DetachWidget(GetMainWidget()); // Removes event handlers
154 DetachWidget(m_formWidget);
155
156 XtDestroyWidget((Widget) m_formWidget);
157 m_formWidget = (WXWidget) 0;
158
159 // Presumably the other widgets have been deleted now, via the form
160 m_mainWidget = (WXWidget) 0;
161 m_buttonWidget = (WXWidget) 0;
162 }
163 }
164
165 void wxChoice::Append(const wxString& item)
166 {
167 wxStripMenuCodes ((char *)(const char *)item, wxBuffer);
168 Widget w = XtVaCreateManagedWidget (wxBuffer,
169 #if USE_GADGETS
170 xmPushButtonGadgetClass, (Widget) m_menuWidget,
171 #else
172 xmPushButtonWidgetClass, (Widget) m_menuWidget,
173 #endif
174 NULL);
175
176 DoChangeBackgroundColour((WXWidget) w, m_backgroundColour);
177
178 if (m_font.Ok())
179 XtVaSetValues (w,
180 XmNfontList, (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) m_formWidget)),
181 NULL);
182
183 WXWidget *new_widgetList = new WXWidget[m_noStrings + 1];
184 int i;
185 if (m_widgetList)
186 for (i = 0; i < m_noStrings; i++)
187 new_widgetList[i] = m_widgetList[i];
188
189 new_widgetList[m_noStrings] = (WXWidget) w;
190
191 if (m_widgetList)
192 delete[] m_widgetList;
193 m_widgetList = new_widgetList;
194
195 char mnem = wxFindMnemonic ((char*) (const char*) item);
196 if (mnem != 0)
197 XtVaSetValues (w, XmNmnemonic, mnem, NULL);
198
199 XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) wxChoiceCallback, (XtPointer) this);
200
201 if (m_noStrings == 0 && m_buttonWidget)
202 {
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,
208 NULL);
209 XmStringFree (text);
210 }
211 wxNode *node = m_stringList.Add (item);
212 XtVaSetValues (w, XmNuserData, node->Data (), NULL);
213
214 m_noStrings ++;
215 }
216
217 void wxChoice::Delete(int WXUNUSED(n))
218 {
219 wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" );
220
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
223 // (see Append)
224
225 // TODO
226 m_noStrings --;
227 }
228
229 void wxChoice::Clear()
230 {
231 m_stringList.Clear ();
232 int i;
233 for (i = 0; i < m_noStrings; i++)
234 {
235 XtUnmanageChild ((Widget) m_widgetList[i]);
236 XtDestroyWidget ((Widget) m_widgetList[i]);
237 }
238 if (m_noStrings)
239 delete[] m_widgetList;
240 m_widgetList = (WXWidget*) NULL;
241 if (m_buttonWidget)
242 XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, (Widget) NULL, NULL);
243 m_noStrings = 0;
244 }
245
246 int wxChoice::GetSelection() const
247 {
248 XmString text;
249 char *s;
250 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
251 XtVaGetValues (label,
252 XmNlabelString, &text,
253 NULL);
254
255 if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s))
256 {
257 int i = 0;
258 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
259 {
260 char *s1 = (char *) node->Data ();
261 if (s1 == s || strcmp (s1, s) == 0)
262 {
263 XmStringFree(text) ;
264 XtFree (s);
265 return i;
266 }
267 else
268 i++;
269 } // for()
270
271 XmStringFree(text) ;
272 XtFree (s);
273 return -1;
274 }
275 XmStringFree(text) ;
276 return -1;
277 }
278
279 void wxChoice::SetSelection(int n)
280 {
281 m_inSetValue = TRUE;
282
283 wxNode *node = m_stringList.Nth (n);
284 if (node)
285 {
286 Dimension selectionWidth, selectionHeight;
287
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,
294 NULL);
295 XmStringFree (text);
296 XtVaSetValues ((Widget) m_buttonWidget,
297 XmNwidth, selectionWidth, XmNheight, selectionHeight,
298 XmNmenuHistory, (Widget) m_widgetList[n], NULL);
299 }
300 m_inSetValue = FALSE;
301 }
302
303 int wxChoice::FindString(const wxString& s) const
304 {
305 int i = 0;
306 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
307 {
308 char *s1 = (char *) node->Data ();
309 if (s == s1)
310 {
311 return i;
312 }
313 else
314 i++;
315 }
316 return -1;
317 }
318
319 wxString wxChoice::GetString(int n) const
320 {
321 wxNode *node = m_stringList.Nth (n);
322 if (node)
323 return wxString((char *) node->Data ());
324 else
325 return wxEmptyString;
326 }
327
328 void wxChoice::SetColumns(int n)
329 {
330 if (n<1) n = 1 ;
331
332 short numColumns = n ;
333 Arg args[3];
334
335 XtSetArg(args[0], XmNnumColumns, numColumns);
336 XtSetArg(args[1], XmNpacking, XmPACK_COLUMN);
337 XtSetValues((Widget) m_menuWidget,args,2) ;
338 }
339
340 int wxChoice::GetColumns(void) const
341 {
342 short numColumns ;
343
344 XtVaGetValues((Widget) m_menuWidget,XmNnumColumns,&numColumns,NULL) ;
345 return numColumns ;
346 }
347
348 void wxChoice::SetFocus()
349 {
350 XmProcessTraversal(XtParent((Widget)m_mainWidget), XmTRAVERSE_CURRENT);
351 }
352
353 void wxChoice::DoSetSize(int x, int y, int width, int height, int sizeFlags)
354 {
355 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_ANY, NULL);
356 bool managed = XtIsManaged((Widget) m_formWidget);
357
358 if (managed)
359 XtUnmanageChild ((Widget) m_formWidget);
360
361 int actualWidth = width, actualHeight = height;
362
363 if (width > -1)
364 {
365 int i;
366 for (i = 0; i < m_noStrings; i++)
367 XtVaSetValues ((Widget) m_widgetList[i], XmNwidth, actualWidth, NULL);
368 XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, actualWidth,
369 NULL);
370 }
371 if (height > -1)
372 {
373 int i;
374 for (i = 0; i < m_noStrings; i++)
375 XtVaSetValues ((Widget) m_widgetList[i], XmNheight, actualHeight, NULL);
376 XtVaSetValues ((Widget) m_buttonWidget, XmNheight, actualHeight,
377 NULL);
378 }
379
380 if (managed)
381 XtManageChild ((Widget) m_formWidget);
382 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
383
384 wxControl::DoSetSize (x, y, width, height, sizeFlags);
385 }
386
387 wxString wxChoice::GetStringSelection () const
388 {
389 int sel = GetSelection ();
390 if (sel > -1)
391 return wxString(this->GetString (sel));
392 else
393 return wxEmptyString;
394 }
395
396 bool wxChoice::SetStringSelection (const wxString& s)
397 {
398 int sel = FindString (s);
399 if (sel > -1)
400 {
401 SetSelection (sel);
402 return TRUE;
403 }
404 else
405 return FALSE;
406 }
407
408 void wxChoice::Command(wxCommandEvent & event)
409 {
410 SetSelection (event.GetInt());
411 ProcessCommand (event);
412 }
413
414 void wxChoiceCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
415 {
416 wxChoice *item = (wxChoice *) clientData;
417 if (item)
418 {
419 if (item->InSetValue())
420 return;
421
422 char *s = NULL;
423 XtVaGetValues (w, XmNuserData, &s, NULL);
424 if (s)
425 {
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);
431 }
432 }
433 }
434
435 void wxChoice::ChangeFont(bool keepOriginalSize)
436 {
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?
440 if (m_font.Ok())
441 {
442 int width, height, width1, height1;
443 GetSize(& width, & height);
444
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);
448
449 /* TODO: why does this cause a crash in XtWidgetToApplicationContext?
450 int i;
451 for (i = 0; i < m_noStrings; i++)
452 XtVaSetValues ((Widget) m_widgetList[i], XmNfontList, fontList, NULL);
453 */
454 GetSize(& width1, & height1);
455 if (keepOriginalSize && (width != width1 || height != height1))
456 {
457 SetSize(-1, -1, width, height);
458 }
459 }
460 }
461
462 void wxChoice::ChangeBackgroundColour()
463 {
464 DoChangeBackgroundColour(m_formWidget, m_backgroundColour);
465 DoChangeBackgroundColour(m_buttonWidget, m_backgroundColour);
466 DoChangeBackgroundColour(m_menuWidget, m_backgroundColour);
467 int i;
468 for (i = 0; i < m_noStrings; i++)
469 DoChangeBackgroundColour(m_widgetList[i], m_backgroundColour);
470 }
471
472 void wxChoice::ChangeForegroundColour()
473 {
474 DoChangeForegroundColour(m_formWidget, m_foregroundColour);
475 DoChangeForegroundColour(m_buttonWidget, m_foregroundColour);
476 DoChangeForegroundColour(m_menuWidget, m_foregroundColour);
477 int i;
478 for (i = 0; i < m_noStrings; i++)
479 DoChangeForegroundColour(m_widgetList[i], m_foregroundColour);
480 }