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