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