]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/choice.cpp
VTK wrapper of vtkRenderWindow for wxPython. Tested on MSW so far.
[wxWidgets.git] / src / motif / choice.cpp
... / ...
CommitLineData
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
28IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
29#endif
30
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;
41}
42
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 = 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(name.c_str(),
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
141wxChoice::~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
165void wxChoice::Append(const wxString& item)
166{
167 Widget w = XtVaCreateManagedWidget (wxStripMenuCodes(item),
168#if USE_GADGETS
169 xmPushButtonGadgetClass, (Widget) m_menuWidget,
170#else
171 xmPushButtonWidgetClass, (Widget) m_menuWidget,
172#endif
173 NULL);
174
175 DoChangeBackgroundColour((WXWidget) w, m_backgroundColour);
176
177 if (m_font.Ok())
178 XtVaSetValues (w,
179 XmNfontList, (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) m_formWidget)),
180 NULL);
181
182 WXWidget *new_widgetList = new WXWidget[m_noStrings + 1];
183 int i;
184 if (m_widgetList)
185 for (i = 0; i < m_noStrings; i++)
186 new_widgetList[i] = m_widgetList[i];
187
188 new_widgetList[m_noStrings] = (WXWidget) w;
189
190 if (m_widgetList)
191 delete[] m_widgetList;
192 m_widgetList = new_widgetList;
193
194 char mnem = wxFindMnemonic ((char*) (const char*) item);
195 if (mnem != 0)
196 XtVaSetValues (w, XmNmnemonic, mnem, NULL);
197
198 XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) wxChoiceCallback, (XtPointer) this);
199
200 if (m_noStrings == 0 && m_buttonWidget)
201 {
202 XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL);
203 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
204 XmString text = XmStringCreateSimple ((char*) (const char*) item);
205 XtVaSetValues (label,
206 XmNlabelString, text,
207 NULL);
208 XmStringFree (text);
209 }
210 wxNode *node = m_stringList.Add (item);
211 XtVaSetValues (w, XmNuserData, node->Data (), NULL);
212
213 m_noStrings ++;
214}
215
216void wxChoice::Delete(int WXUNUSED(n))
217{
218 wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" );
219
220 // What should we do -- remove the callback for this button widget,
221 // delete the m_stringList entry, delete the button widget, construct a new widget list
222 // (see Append)
223
224 // TODO
225 m_noStrings --;
226}
227
228void wxChoice::Clear()
229{
230 m_stringList.Clear ();
231 int i;
232 for (i = 0; i < m_noStrings; i++)
233 {
234 XtUnmanageChild ((Widget) m_widgetList[i]);
235 XtDestroyWidget ((Widget) m_widgetList[i]);
236 }
237 if (m_noStrings)
238 delete[] m_widgetList;
239 m_widgetList = (WXWidget*) NULL;
240 if (m_buttonWidget)
241 XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, (Widget) NULL, NULL);
242 m_noStrings = 0;
243}
244
245int wxChoice::GetSelection() const
246{
247 XmString text;
248 char *s;
249 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
250 XtVaGetValues (label,
251 XmNlabelString, &text,
252 NULL);
253
254 if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s))
255 {
256 int i = 0;
257 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
258 {
259 char *s1 = (char *) node->Data ();
260 if (s1 == s || strcmp (s1, s) == 0)
261 {
262 XmStringFree(text) ;
263 XtFree (s);
264 return i;
265 }
266 else
267 i++;
268 } // for()
269
270 XmStringFree(text) ;
271 XtFree (s);
272 return -1;
273 }
274 XmStringFree(text) ;
275 return -1;
276}
277
278void wxChoice::SetSelection(int n)
279{
280 m_inSetValue = TRUE;
281
282 wxNode *node = m_stringList.Nth (n);
283 if (node)
284 {
285 Dimension selectionWidth, selectionHeight;
286
287 char *s = (char *) node->Data ();
288 XmString text = XmStringCreateSimple (s);
289 XtVaGetValues ((Widget) m_widgetList[n], XmNwidth, &selectionWidth, XmNheight, &selectionHeight, NULL);
290 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
291 XtVaSetValues (label,
292 XmNlabelString, text,
293 NULL);
294 XmStringFree (text);
295 XtVaSetValues ((Widget) m_buttonWidget,
296 XmNwidth, selectionWidth, XmNheight, selectionHeight,
297 XmNmenuHistory, (Widget) m_widgetList[n], NULL);
298 }
299 m_inSetValue = FALSE;
300}
301
302int wxChoice::FindString(const wxString& s) const
303{
304 int i = 0;
305 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
306 {
307 char *s1 = (char *) node->Data ();
308 if (s == s1)
309 {
310 return i;
311 }
312 else
313 i++;
314 }
315 return -1;
316}
317
318wxString wxChoice::GetString(int n) const
319{
320 wxNode *node = m_stringList.Nth (n);
321 if (node)
322 return wxString((char *) node->Data ());
323 else
324 return wxEmptyString;
325}
326
327void wxChoice::SetColumns(int n)
328{
329 if (n<1) n = 1 ;
330
331 short numColumns = n ;
332 Arg args[3];
333
334 XtSetArg(args[0], XmNnumColumns, numColumns);
335 XtSetArg(args[1], XmNpacking, XmPACK_COLUMN);
336 XtSetValues((Widget) m_menuWidget,args,2) ;
337}
338
339int wxChoice::GetColumns(void) const
340{
341 short numColumns ;
342
343 XtVaGetValues((Widget) m_menuWidget,XmNnumColumns,&numColumns,NULL) ;
344 return numColumns ;
345}
346
347void wxChoice::SetFocus()
348{
349 XmProcessTraversal(XtParent((Widget)m_mainWidget), XmTRAVERSE_CURRENT);
350}
351
352void wxChoice::DoSetSize(int x, int y, int width, int height, int sizeFlags)
353{
354 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_ANY, NULL);
355 bool managed = XtIsManaged((Widget) m_formWidget);
356
357 if (managed)
358 XtUnmanageChild ((Widget) m_formWidget);
359
360 int actualWidth = width, actualHeight = height;
361
362 if (width > -1)
363 {
364 int i;
365 for (i = 0; i < m_noStrings; i++)
366 XtVaSetValues ((Widget) m_widgetList[i], XmNwidth, actualWidth, NULL);
367 XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, actualWidth,
368 NULL);
369 }
370 if (height > -1)
371 {
372 int i;
373 for (i = 0; i < m_noStrings; i++)
374 XtVaSetValues ((Widget) m_widgetList[i], XmNheight, actualHeight, NULL);
375 XtVaSetValues ((Widget) m_buttonWidget, XmNheight, actualHeight,
376 NULL);
377 }
378
379 if (managed)
380 XtManageChild ((Widget) m_formWidget);
381 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
382
383 wxControl::DoSetSize (x, y, width, height, sizeFlags);
384}
385
386wxString wxChoice::GetStringSelection () const
387{
388 int sel = GetSelection ();
389 if (sel > -1)
390 return wxString(this->GetString (sel));
391 else
392 return wxEmptyString;
393}
394
395bool wxChoice::SetStringSelection (const wxString& s)
396{
397 int sel = FindString (s);
398 if (sel > -1)
399 {
400 SetSelection (sel);
401 return TRUE;
402 }
403 else
404 return FALSE;
405}
406
407void wxChoice::Command(wxCommandEvent & event)
408{
409 SetSelection (event.GetInt());
410 ProcessCommand (event);
411}
412
413void wxChoiceCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
414{
415 wxChoice *item = (wxChoice *) clientData;
416 if (item)
417 {
418 if (item->InSetValue())
419 return;
420
421 char *s = NULL;
422 XtVaGetValues (w, XmNuserData, &s, NULL);
423 if (s)
424 {
425 wxCommandEvent event (wxEVT_COMMAND_CHOICE_SELECTED, item->GetId());
426 event.SetEventObject(item);
427 event.m_commandInt = item->FindString (s);
428 // event.m_commandString = s;
429 item->ProcessCommand (event);
430 }
431 }
432}
433
434void wxChoice::ChangeFont(bool keepOriginalSize)
435{
436 // Note that this causes the widget to be resized back
437 // to its original size! We therefore have to set the size
438 // back again. TODO: a better way in Motif?
439 if (m_font.Ok())
440 {
441 int width, height, width1, height1;
442 GetSize(& width, & height);
443
444 XmFontList fontList = (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) m_mainWidget));
445 XtVaSetValues ((Widget) m_mainWidget, XmNfontList, fontList, NULL);
446 XtVaSetValues ((Widget) m_buttonWidget, XmNfontList, fontList, NULL);
447
448 /* TODO: why does this cause a crash in XtWidgetToApplicationContext?
449 int i;
450 for (i = 0; i < m_noStrings; i++)
451 XtVaSetValues ((Widget) m_widgetList[i], XmNfontList, fontList, NULL);
452 */
453 GetSize(& width1, & height1);
454 if (keepOriginalSize && (width != width1 || height != height1))
455 {
456 SetSize(-1, -1, width, height);
457 }
458 }
459}
460
461void wxChoice::ChangeBackgroundColour()
462{
463 DoChangeBackgroundColour(m_formWidget, m_backgroundColour);
464 DoChangeBackgroundColour(m_buttonWidget, m_backgroundColour);
465 DoChangeBackgroundColour(m_menuWidget, m_backgroundColour);
466 int i;
467 for (i = 0; i < m_noStrings; i++)
468 DoChangeBackgroundColour(m_widgetList[i], m_backgroundColour);
469}
470
471void wxChoice::ChangeForegroundColour()
472{
473 DoChangeForegroundColour(m_formWidget, m_foregroundColour);
474 DoChangeForegroundColour(m_buttonWidget, m_foregroundColour);
475 DoChangeForegroundColour(m_menuWidget, m_foregroundColour);
476 int i;
477 for (i = 0; i < m_noStrings; i++)
478 DoChangeForegroundColour(m_widgetList[i], m_foregroundColour);
479}
480
481
482// These implement functions needed by wxControlWithItems.
483// Unfortunately, they're not all implemented yet.
484
485int wxChoice::GetCount() const
486{
487 return Number();
488}
489
490int wxChoice::DoAppend(const wxString& item)
491{
492 Append(item);
493 return GetCount() - 1;
494}
495
496// Just appends, doesn't yet insert
497void wxChoice::DoInsertItems(const wxArrayString& items, int WXUNUSED(pos))
498{
499 size_t nItems = items.GetCount();
500
501 for ( size_t n = 0; n < nItems; n++ )
502 {
503 Append( items[n]);
504 }
505}
506
507void wxChoice::DoSetItems(const wxArrayString& items, void **WXUNUSED(clientData))
508{
509 Clear();
510 size_t nItems = items.GetCount();
511
512 for ( size_t n = 0; n < nItems; n++ )
513 {
514 Append(items[n]);
515 }
516}
517
518void wxChoice::DoSetFirstItem(int WXUNUSED(n))
519{
520 wxFAIL_MSG( wxT("wxChoice::DoSetFirstItem not implemented") );
521}
522
523void wxChoice::DoSetItemClientData(int WXUNUSED(n), void* WXUNUSED(clientData))
524{
525 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientData not implemented") );
526}
527
528void* wxChoice::DoGetItemClientData(int WXUNUSED(n)) const
529{
530 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientData not implemented") );
531 return (void*) NULL;
532}
533
534void wxChoice::DoSetItemClientObject(int WXUNUSED(n), wxClientData* WXUNUSED(clientData))
535{
536 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientObject not implemented") );
537}
538
539wxClientData* wxChoice::DoGetItemClientObject(int WXUNUSED(n)) const
540{
541 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientObject not implemented") );
542 return (wxClientData*) NULL;
543}
544
545void wxChoice::Select(int n)
546{
547 SetSelection(n);
548}
549
550void wxChoice::SetString(int WXUNUSED(n), const wxString& WXUNUSED(s))
551{
552 wxFAIL_MSG( wxT("wxChoice::SetString not implemented") );
553}