]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/choice.cpp
Improved selection mode handling in wxGrid::SelectBlock
[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#ifdef __VMS__
21#pragma message disable nosimpint
22#endif
23#include <Xm/Xm.h>
24#include <Xm/PushBG.h>
25#include <Xm/PushB.h>
26#include <Xm/RowColumn.h>
27#ifdef __VMS__
28#pragma message enable nosimpint
29#endif
30
31#include "wx/motif/private.h"
32
33IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
34
35void wxChoiceCallback (Widget w, XtPointer clientData,
36 XtPointer ptr);
37
38wxChoice::wxChoice()
39{
40 m_noStrings = 0;
41 m_buttonWidget = (WXWidget) 0;
42 m_menuWidget = (WXWidget) 0;
43 m_widgetList = (WXWidget*) 0;
44 m_formWidget = (WXWidget) 0;
45}
46
47bool wxChoice::Create(wxWindow *parent, wxWindowID id,
48 const wxPoint& pos,
49 const wxSize& size,
50 int n, const wxString choices[],
51 long style,
52 const wxValidator& validator,
53 const wxString& name)
54{
55 SetName(name);
56 SetValidator(validator);
57 m_noStrings = 0; // Starts off with none, incremented in Append
58 m_windowStyle = style;
59 m_buttonWidget = (WXWidget) 0;
60 m_menuWidget = (WXWidget) 0;
61 m_widgetList = (WXWidget*) 0;
62 m_formWidget = (WXWidget) 0;
63
64 if (parent) parent->AddChild(this);
65
66 if ( id == -1 )
67 m_windowId = (int)NewControlId();
68 else
69 m_windowId = id;
70
71 m_backgroundColour = parent->GetBackgroundColour();
72 m_foregroundColour = parent->GetForegroundColour();
73 m_font = parent->GetFont();
74
75 Widget parentWidget = (Widget) parent->GetClientWidget();
76
77 m_formWidget = (WXWidget) XtVaCreateManagedWidget(name.c_str(),
78 xmRowColumnWidgetClass, parentWidget,
79 XmNmarginHeight, 0,
80 XmNmarginWidth, 0,
81 XmNpacking, XmPACK_TIGHT,
82 XmNorientation, XmHORIZONTAL,
83 NULL);
84
85 XtVaSetValues ((Widget) m_formWidget, XmNspacing, 0, NULL);
86
87 /*
88 * Create the popup menu
89 */
90 m_menuWidget = (WXWidget) XmCreatePulldownMenu ((Widget) m_formWidget, "choiceMenu", NULL, 0);
91
92 // int i;
93 if (n > 0)
94 {
95 int i;
96 for (i = 0; i < n; i++)
97 Append (choices[i]);
98 }
99
100 /*
101 * Create button
102 */
103 Arg args[10];
104 Cardinal argcnt = 0;
105
106 XtSetArg (args[argcnt], XmNsubMenuId, (Widget) m_menuWidget);
107 argcnt++;
108 XtSetArg (args[argcnt], XmNmarginWidth, 0);
109 argcnt++;
110 XtSetArg (args[argcnt], XmNmarginHeight, 0);
111 argcnt++;
112 XtSetArg (args[argcnt], XmNpacking, XmPACK_TIGHT);
113 argcnt++;
114 m_buttonWidget = (WXWidget) XmCreateOptionMenu ((Widget) m_formWidget, "choiceButton", args, argcnt);
115
116 m_mainWidget = m_buttonWidget;
117
118 XtManageChild ((Widget) m_buttonWidget);
119
120 // New code from Roland Haenel (roland_haenel@ac.cybercity.de)
121 // Some time ago, I reported a problem with wxChoice-items under
122 // Linux and Motif 2.0 (they caused sporadic GPFs). Now it seems
123 // that I have found the code responsible for this behaviour.
124#if XmVersion >= 1002
125#if XmVersion < 2000
126 // JACS, 24/1/99: this seems to cause a malloc crash later on, e.g.
127 // in controls sample.
128 //
129 // Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget);
130 // XtUnmanageChild (optionLabel);
131#endif
132#endif
133
134 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
135
136 ChangeFont(FALSE);
137
138 AttachWidget (parent, m_buttonWidget, m_formWidget, pos.x, pos.y, size.x, size.y);
139
140 ChangeBackgroundColour();
141
142 return TRUE;
143}
144
145wxChoice::~wxChoice()
146{
147 // For some reason destroying the menuWidget
148 // can cause crashes on some machines. It will
149 // be deleted implicitly by deleting the parent form
150 // anyway.
151 // XtDestroyWidget (menuWidget);
152 if (m_widgetList)
153 delete[] m_widgetList;
154
155 if (GetMainWidget())
156 {
157 DetachWidget(GetMainWidget()); // Removes event handlers
158 DetachWidget(m_formWidget);
159
160 XtDestroyWidget((Widget) m_formWidget);
161 m_formWidget = (WXWidget) 0;
162
163 // Presumably the other widgets have been deleted now, via the form
164 m_mainWidget = (WXWidget) 0;
165 m_buttonWidget = (WXWidget) 0;
166 }
167}
168
169void wxChoice::Append(const wxString& item)
170{
171 Widget w = XtVaCreateManagedWidget (wxStripMenuCodes(item),
172#if USE_GADGETS
173 xmPushButtonGadgetClass, (Widget) m_menuWidget,
174#else
175 xmPushButtonWidgetClass, (Widget) m_menuWidget,
176#endif
177 NULL);
178
179 DoChangeBackgroundColour((WXWidget) w, m_backgroundColour);
180
181 if (m_font.Ok())
182 XtVaSetValues (w,
183 XmNfontList, (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) m_formWidget)),
184 NULL);
185
186 WXWidget *new_widgetList = new WXWidget[m_noStrings + 1];
187 int i;
188 if (m_widgetList)
189 for (i = 0; i < m_noStrings; i++)
190 new_widgetList[i] = m_widgetList[i];
191
192 new_widgetList[m_noStrings] = (WXWidget) w;
193
194 if (m_widgetList)
195 delete[] m_widgetList;
196 m_widgetList = new_widgetList;
197
198 char mnem = wxFindMnemonic ((char*) (const char*) item);
199 if (mnem != 0)
200 XtVaSetValues (w, XmNmnemonic, mnem, NULL);
201
202 XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) wxChoiceCallback, (XtPointer) this);
203
204 if (m_noStrings == 0 && m_buttonWidget)
205 {
206 XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL);
207 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
208 XmString text = XmStringCreateSimple ((char*) (const char*) item);
209 XtVaSetValues (label,
210 XmNlabelString, text,
211 NULL);
212 XmStringFree (text);
213 }
214 wxNode *node = m_stringList.Add (item);
215 XtVaSetValues (w, XmNuserData, node->Data (), NULL);
216
217 m_noStrings ++;
218}
219
220void wxChoice::Delete(int WXUNUSED(n))
221{
222 wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" );
223
224 // What should we do -- remove the callback for this button widget,
225 // delete the m_stringList entry, delete the button widget, construct a new widget list
226 // (see Append)
227
228 // TODO
229 m_noStrings --;
230}
231
232void wxChoice::Clear()
233{
234 m_stringList.Clear ();
235 int i;
236 for (i = 0; i < m_noStrings; i++)
237 {
238 XtUnmanageChild ((Widget) m_widgetList[i]);
239 XtDestroyWidget ((Widget) m_widgetList[i]);
240 }
241 if (m_noStrings)
242 delete[] m_widgetList;
243 m_widgetList = (WXWidget*) NULL;
244 if (m_buttonWidget)
245 XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, (Widget) NULL, NULL);
246 m_noStrings = 0;
247}
248
249int wxChoice::GetSelection() const
250{
251 XmString text;
252 char *s;
253 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
254 XtVaGetValues (label,
255 XmNlabelString, &text,
256 NULL);
257
258 if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s))
259 {
260 int i = 0;
261 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
262 {
263 char *s1 = (char *) node->Data ();
264 if (s1 == s || strcmp (s1, s) == 0)
265 {
266 XmStringFree(text) ;
267 XtFree (s);
268 return i;
269 }
270 else
271 i++;
272 } // for()
273
274 XmStringFree(text) ;
275 XtFree (s);
276 return -1;
277 }
278 XmStringFree(text) ;
279 return -1;
280}
281
282void wxChoice::SetSelection(int n)
283{
284 m_inSetValue = TRUE;
285
286 wxNode *node = m_stringList.Nth (n);
287 if (node)
288 {
289 Dimension selectionWidth, selectionHeight;
290
291 char *s = (char *) node->Data ();
292 XmString text = XmStringCreateSimple (s);
293 XtVaGetValues ((Widget) m_widgetList[n], XmNwidth, &selectionWidth, XmNheight, &selectionHeight, NULL);
294 Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
295 XtVaSetValues (label,
296 XmNlabelString, text,
297 NULL);
298 XmStringFree (text);
299 XtVaSetValues ((Widget) m_buttonWidget,
300 XmNwidth, selectionWidth, XmNheight, selectionHeight,
301 XmNmenuHistory, (Widget) m_widgetList[n], NULL);
302 }
303 m_inSetValue = FALSE;
304}
305
306int wxChoice::FindString(const wxString& s) const
307{
308 int i = 0;
309 for (wxNode * node = m_stringList.First (); node; node = node->Next ())
310 {
311 char *s1 = (char *) node->Data ();
312 if (s == s1)
313 {
314 return i;
315 }
316 else
317 i++;
318 }
319 return -1;
320}
321
322wxString wxChoice::GetString(int n) const
323{
324 wxNode *node = m_stringList.Nth (n);
325 if (node)
326 return wxString((char *) node->Data ());
327 else
328 return wxEmptyString;
329}
330
331void wxChoice::SetColumns(int n)
332{
333 if (n<1) n = 1 ;
334
335 short numColumns = n ;
336 Arg args[3];
337
338 XtSetArg(args[0], XmNnumColumns, numColumns);
339 XtSetArg(args[1], XmNpacking, XmPACK_COLUMN);
340 XtSetValues((Widget) m_menuWidget,args,2) ;
341}
342
343int wxChoice::GetColumns(void) const
344{
345 short numColumns ;
346
347 XtVaGetValues((Widget) m_menuWidget,XmNnumColumns,&numColumns,NULL) ;
348 return numColumns ;
349}
350
351void wxChoice::SetFocus()
352{
353 XmProcessTraversal(XtParent((Widget)m_mainWidget), XmTRAVERSE_CURRENT);
354}
355
356void wxChoice::DoSetSize(int x, int y, int width, int height, int sizeFlags)
357{
358 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_ANY, NULL);
359 bool managed = XtIsManaged((Widget) m_formWidget);
360
361 if (managed)
362 XtUnmanageChild ((Widget) m_formWidget);
363
364 int actualWidth = width, actualHeight = height;
365
366 if (width > -1)
367 {
368 int i;
369 for (i = 0; i < m_noStrings; i++)
370 XtVaSetValues ((Widget) m_widgetList[i], XmNwidth, actualWidth, NULL);
371 XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, actualWidth,
372 NULL);
373 }
374 if (height > -1)
375 {
376 int i;
377 for (i = 0; i < m_noStrings; i++)
378 XtVaSetValues ((Widget) m_widgetList[i], XmNheight, actualHeight, NULL);
379 XtVaSetValues ((Widget) m_buttonWidget, XmNheight, actualHeight,
380 NULL);
381 }
382
383 if (managed)
384 XtManageChild ((Widget) m_formWidget);
385 XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
386
387 wxControl::DoSetSize (x, y, width, height, sizeFlags);
388}
389
390wxString wxChoice::GetStringSelection () const
391{
392 int sel = GetSelection ();
393 if (sel > -1)
394 return wxString(this->GetString (sel));
395 else
396 return wxEmptyString;
397}
398
399bool wxChoice::SetStringSelection (const wxString& s)
400{
401 int sel = FindString (s);
402 if (sel > -1)
403 {
404 SetSelection (sel);
405 return TRUE;
406 }
407 else
408 return FALSE;
409}
410
411void wxChoice::Command(wxCommandEvent & event)
412{
413 SetSelection (event.GetInt());
414 ProcessCommand (event);
415}
416
417void wxChoiceCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
418{
419 wxChoice *item = (wxChoice *) clientData;
420 if (item)
421 {
422 if (item->InSetValue())
423 return;
424
425 char *s = NULL;
426 XtVaGetValues (w, XmNuserData, &s, NULL);
427 if (s)
428 {
429 wxCommandEvent event (wxEVT_COMMAND_CHOICE_SELECTED, item->GetId());
430 event.SetEventObject(item);
431 event.m_commandInt = item->FindString (s);
432 // event.m_commandString = s;
433 item->ProcessCommand (event);
434 }
435 }
436}
437
438void wxChoice::ChangeFont(bool keepOriginalSize)
439{
440 // Note that this causes the widget to be resized back
441 // to its original size! We therefore have to set the size
442 // back again. TODO: a better way in Motif?
443 if (m_font.Ok())
444 {
445 int width, height, width1, height1;
446 GetSize(& width, & height);
447
448 XmFontList fontList = (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) m_mainWidget));
449 XtVaSetValues ((Widget) m_mainWidget, XmNfontList, fontList, NULL);
450 XtVaSetValues ((Widget) m_buttonWidget, XmNfontList, fontList, NULL);
451
452 /* TODO: why does this cause a crash in XtWidgetToApplicationContext?
453 int i;
454 for (i = 0; i < m_noStrings; i++)
455 XtVaSetValues ((Widget) m_widgetList[i], XmNfontList, fontList, NULL);
456 */
457 GetSize(& width1, & height1);
458 if (keepOriginalSize && (width != width1 || height != height1))
459 {
460 SetSize(-1, -1, width, height);
461 }
462 }
463}
464
465void wxChoice::ChangeBackgroundColour()
466{
467 DoChangeBackgroundColour(m_formWidget, m_backgroundColour);
468 DoChangeBackgroundColour(m_buttonWidget, m_backgroundColour);
469 DoChangeBackgroundColour(m_menuWidget, m_backgroundColour);
470 int i;
471 for (i = 0; i < m_noStrings; i++)
472 DoChangeBackgroundColour(m_widgetList[i], m_backgroundColour);
473}
474
475void wxChoice::ChangeForegroundColour()
476{
477 DoChangeForegroundColour(m_formWidget, m_foregroundColour);
478 DoChangeForegroundColour(m_buttonWidget, m_foregroundColour);
479 DoChangeForegroundColour(m_menuWidget, m_foregroundColour);
480 int i;
481 for (i = 0; i < m_noStrings; i++)
482 DoChangeForegroundColour(m_widgetList[i], m_foregroundColour);
483}
484
485
486// These implement functions needed by wxControlWithItems.
487// Unfortunately, they're not all implemented yet.
488
489int wxChoice::GetCount() const
490{
491 return Number();
492}
493
494int wxChoice::DoAppend(const wxString& item)
495{
496 Append(item);
497 return GetCount() - 1;
498}
499
500// Just appends, doesn't yet insert
501void wxChoice::DoInsertItems(const wxArrayString& items, int WXUNUSED(pos))
502{
503 size_t nItems = items.GetCount();
504
505 for ( size_t n = 0; n < nItems; n++ )
506 {
507 Append( items[n]);
508 }
509}
510
511void wxChoice::DoSetItems(const wxArrayString& items, void **WXUNUSED(clientData))
512{
513 Clear();
514 size_t nItems = items.GetCount();
515
516 for ( size_t n = 0; n < nItems; n++ )
517 {
518 Append(items[n]);
519 }
520}
521
522void wxChoice::DoSetFirstItem(int WXUNUSED(n))
523{
524 wxFAIL_MSG( wxT("wxChoice::DoSetFirstItem not implemented") );
525}
526
527void wxChoice::DoSetItemClientData(int WXUNUSED(n), void* WXUNUSED(clientData))
528{
529 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientData not implemented") );
530}
531
532void* wxChoice::DoGetItemClientData(int WXUNUSED(n)) const
533{
534 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientData not implemented") );
535 return (void*) NULL;
536}
537
538void wxChoice::DoSetItemClientObject(int WXUNUSED(n), wxClientData* WXUNUSED(clientData))
539{
540 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientObject not implemented") );
541}
542
543wxClientData* wxChoice::DoGetItemClientObject(int WXUNUSED(n)) const
544{
545 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientObject not implemented") );
546 return (wxClientData*) NULL;
547}
548
549void wxChoice::Select(int n)
550{
551 SetSelection(n);
552}
553
554void wxChoice::SetString(int WXUNUSED(n), const wxString& WXUNUSED(s))
555{
556 wxFAIL_MSG( wxT("wxChoice::SetString not implemented") );
557}