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