1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "choice.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/choice.h"
21 #pragma message disable nosimpint
24 #include <Xm/PushBG.h>
26 #include <Xm/RowColumn.h>
28 #pragma message enable nosimpint
31 #include "wx/motif/private.h"
33 IMPLEMENT_DYNAMIC_CLASS(wxChoice
, wxControl
)
35 void wxChoiceCallback (Widget w
, XtPointer clientData
,
41 m_buttonWidget
= (WXWidget
) 0;
42 m_menuWidget
= (WXWidget
) 0;
43 m_widgetList
= (WXWidget
*) 0;
44 m_formWidget
= (WXWidget
) 0;
47 bool wxChoice::Create(wxWindow
*parent
, wxWindowID id
,
50 int n
, const wxString choices
[],
52 const wxValidator
& validator
,
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;
64 if (parent
) parent
->AddChild(this);
67 m_windowId
= (int)NewControlId();
71 m_backgroundColour
= parent
->GetBackgroundColour();
72 m_foregroundColour
= parent
->GetForegroundColour();
73 m_font
= parent
->GetFont();
75 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
77 m_formWidget
= (WXWidget
) XtVaCreateManagedWidget(name
.c_str(),
78 xmRowColumnWidgetClass
, parentWidget
,
81 XmNpacking
, XmPACK_TIGHT
,
82 XmNorientation
, XmHORIZONTAL
,
85 XtVaSetValues ((Widget
) m_formWidget
, XmNspacing
, 0, NULL
);
88 * Create the popup menu
90 m_menuWidget
= (WXWidget
) XmCreatePulldownMenu ((Widget
) m_formWidget
, "choiceMenu", NULL
, 0);
96 for (i
= 0; i
< n
; i
++)
106 XtSetArg (args
[argcnt
], XmNsubMenuId
, (Widget
) m_menuWidget
);
108 XtSetArg (args
[argcnt
], XmNmarginWidth
, 0);
110 XtSetArg (args
[argcnt
], XmNmarginHeight
, 0);
112 XtSetArg (args
[argcnt
], XmNpacking
, XmPACK_TIGHT
);
114 m_buttonWidget
= (WXWidget
) XmCreateOptionMenu ((Widget
) m_formWidget
, "choiceButton", args
, argcnt
);
116 m_mainWidget
= m_buttonWidget
;
118 XtManageChild ((Widget
) m_buttonWidget
);
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
126 // JACS, 24/1/99: this seems to cause a malloc crash later on, e.g.
127 // in controls sample.
129 // Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget);
130 // XtUnmanageChild (optionLabel);
134 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
138 AttachWidget (parent
, m_buttonWidget
, m_formWidget
, pos
.x
, pos
.y
, size
.x
, size
.y
);
140 ChangeBackgroundColour();
145 wxChoice::~wxChoice()
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
151 // XtDestroyWidget (menuWidget);
153 delete[] m_widgetList
;
157 DetachWidget(GetMainWidget()); // Removes event handlers
158 DetachWidget(m_formWidget
);
160 XtDestroyWidget((Widget
) m_formWidget
);
161 m_formWidget
= (WXWidget
) 0;
163 // Presumably the other widgets have been deleted now, via the form
164 m_mainWidget
= (WXWidget
) 0;
165 m_buttonWidget
= (WXWidget
) 0;
169 void wxChoice::Append(const wxString
& item
)
171 Widget w
= XtVaCreateManagedWidget (wxStripMenuCodes(item
),
173 xmPushButtonGadgetClass
, (Widget
) m_menuWidget
,
175 xmPushButtonWidgetClass
, (Widget
) m_menuWidget
,
179 DoChangeBackgroundColour((WXWidget
) w
, m_backgroundColour
);
183 XmNfontList
, (XmFontList
) m_font
.GetFontList(1.0, XtDisplay((Widget
) m_formWidget
)),
186 WXWidget
*new_widgetList
= new WXWidget
[m_noStrings
+ 1];
189 for (i
= 0; i
< m_noStrings
; i
++)
190 new_widgetList
[i
] = m_widgetList
[i
];
192 new_widgetList
[m_noStrings
] = (WXWidget
) w
;
195 delete[] m_widgetList
;
196 m_widgetList
= new_widgetList
;
198 char mnem
= wxFindMnemonic ((char*) (const char*) item
);
200 XtVaSetValues (w
, XmNmnemonic
, mnem
, NULL
);
202 XtAddCallback (w
, XmNactivateCallback
, (XtCallbackProc
) wxChoiceCallback
, (XtPointer
) this);
204 if (m_noStrings
== 0 && m_buttonWidget
)
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
,
214 wxNode
*node
= m_stringList
.Add (item
);
215 XtVaSetValues (w
, XmNuserData
, node
->Data (), NULL
);
220 void wxChoice::Delete(int WXUNUSED(n
))
222 wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" );
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
232 void wxChoice::Clear()
234 m_stringList
.Clear ();
236 for (i
= 0; i
< m_noStrings
; i
++)
238 XtUnmanageChild ((Widget
) m_widgetList
[i
]);
239 XtDestroyWidget ((Widget
) m_widgetList
[i
]);
242 delete[] m_widgetList
;
243 m_widgetList
= (WXWidget
*) NULL
;
245 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmenuHistory
, (Widget
) NULL
, NULL
);
249 int wxChoice::GetSelection() const
253 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
254 XtVaGetValues (label
,
255 XmNlabelString
, &text
,
258 if (XmStringGetLtoR (text
, XmSTRING_DEFAULT_CHARSET
, &s
))
261 for (wxNode
* node
= m_stringList
.First (); node
; node
= node
->Next ())
263 char *s1
= (char *) node
->Data ();
264 if (s1
== s
|| strcmp (s1
, s
) == 0)
282 void wxChoice::SetSelection(int n
)
286 wxNode
*node
= m_stringList
.Nth (n
);
289 Dimension selectionWidth
, selectionHeight
;
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
,
299 XtVaSetValues ((Widget
) m_buttonWidget
,
300 XmNwidth
, selectionWidth
, XmNheight
, selectionHeight
,
301 XmNmenuHistory
, (Widget
) m_widgetList
[n
], NULL
);
303 m_inSetValue
= FALSE
;
306 int wxChoice::FindString(const wxString
& s
) const
309 for (wxNode
* node
= m_stringList
.First (); node
; node
= node
->Next ())
311 char *s1
= (char *) node
->Data ();
322 wxString
wxChoice::GetString(int n
) const
324 wxNode
*node
= m_stringList
.Nth (n
);
326 return wxString((char *) node
->Data ());
328 return wxEmptyString
;
331 void wxChoice::SetColumns(int n
)
335 short numColumns
= n
;
338 XtSetArg(args
[0], XmNnumColumns
, numColumns
);
339 XtSetArg(args
[1], XmNpacking
, XmPACK_COLUMN
);
340 XtSetValues((Widget
) m_menuWidget
,args
,2) ;
343 int wxChoice::GetColumns(void) const
347 XtVaGetValues((Widget
) m_menuWidget
,XmNnumColumns
,&numColumns
,NULL
) ;
351 void wxChoice::SetFocus()
353 XmProcessTraversal(XtParent((Widget
)m_mainWidget
), XmTRAVERSE_CURRENT
);
356 void wxChoice::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
358 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
359 bool managed
= XtIsManaged((Widget
) m_formWidget
);
362 XtUnmanageChild ((Widget
) m_formWidget
);
364 int actualWidth
= width
, actualHeight
= height
;
369 for (i
= 0; i
< m_noStrings
; i
++)
370 XtVaSetValues ((Widget
) m_widgetList
[i
], XmNwidth
, actualWidth
, NULL
);
371 XtVaSetValues ((Widget
) m_buttonWidget
, XmNwidth
, actualWidth
,
377 for (i
= 0; i
< m_noStrings
; i
++)
378 XtVaSetValues ((Widget
) m_widgetList
[i
], XmNheight
, actualHeight
, NULL
);
379 XtVaSetValues ((Widget
) m_buttonWidget
, XmNheight
, actualHeight
,
384 XtManageChild ((Widget
) m_formWidget
);
385 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
387 wxControl::DoSetSize (x
, y
, width
, height
, sizeFlags
);
390 wxString
wxChoice::GetStringSelection () const
392 int sel
= GetSelection ();
394 return wxString(this->GetString (sel
));
396 return wxEmptyString
;
399 bool wxChoice::SetStringSelection (const wxString
& s
)
401 int sel
= FindString (s
);
411 void wxChoice::Command(wxCommandEvent
& event
)
413 SetSelection (event
.GetInt());
414 ProcessCommand (event
);
417 void wxChoiceCallback (Widget w
, XtPointer clientData
, XtPointer
WXUNUSED(ptr
))
419 wxChoice
*item
= (wxChoice
*) clientData
;
422 if (item
->InSetValue())
426 XtVaGetValues (w
, XmNuserData
, &s
, NULL
);
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
);
438 void wxChoice::ChangeFont(bool keepOriginalSize
)
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?
445 int width
, height
, width1
, height1
;
446 GetSize(& width
, & height
);
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
);
452 /* TODO: why does this cause a crash in XtWidgetToApplicationContext?
454 for (i = 0; i < m_noStrings; i++)
455 XtVaSetValues ((Widget) m_widgetList[i], XmNfontList, fontList, NULL);
457 GetSize(& width1
, & height1
);
458 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
460 SetSize(-1, -1, width
, height
);
465 void wxChoice::ChangeBackgroundColour()
467 DoChangeBackgroundColour(m_formWidget
, m_backgroundColour
);
468 DoChangeBackgroundColour(m_buttonWidget
, m_backgroundColour
);
469 DoChangeBackgroundColour(m_menuWidget
, m_backgroundColour
);
471 for (i
= 0; i
< m_noStrings
; i
++)
472 DoChangeBackgroundColour(m_widgetList
[i
], m_backgroundColour
);
475 void wxChoice::ChangeForegroundColour()
477 DoChangeForegroundColour(m_formWidget
, m_foregroundColour
);
478 DoChangeForegroundColour(m_buttonWidget
, m_foregroundColour
);
479 DoChangeForegroundColour(m_menuWidget
, m_foregroundColour
);
481 for (i
= 0; i
< m_noStrings
; i
++)
482 DoChangeForegroundColour(m_widgetList
[i
], m_foregroundColour
);
486 // These implement functions needed by wxControlWithItems.
487 // Unfortunately, they're not all implemented yet.
489 int wxChoice::GetCount() const
494 int wxChoice::DoAppend(const wxString
& item
)
497 return GetCount() - 1;
500 // Just appends, doesn't yet insert
501 void wxChoice::DoInsertItems(const wxArrayString
& items
, int WXUNUSED(pos
))
503 size_t nItems
= items
.GetCount();
505 for ( size_t n
= 0; n
< nItems
; n
++ )
511 void wxChoice::DoSetItems(const wxArrayString
& items
, void **WXUNUSED(clientData
))
514 size_t nItems
= items
.GetCount();
516 for ( size_t n
= 0; n
< nItems
; n
++ )
522 void wxChoice::DoSetFirstItem(int WXUNUSED(n
))
524 wxFAIL_MSG( wxT("wxChoice::DoSetFirstItem not implemented") );
527 void wxChoice::DoSetItemClientData(int WXUNUSED(n
), void* WXUNUSED(clientData
))
529 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientData not implemented") );
532 void* wxChoice::DoGetItemClientData(int WXUNUSED(n
)) const
534 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientData not implemented") );
538 void wxChoice::DoSetItemClientObject(int WXUNUSED(n
), wxClientData
* WXUNUSED(clientData
))
540 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientObject not implemented") );
543 wxClientData
* wxChoice::DoGetItemClientObject(int WXUNUSED(n
)) const
545 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientObject not implemented") );
546 return (wxClientData
*) NULL
;
549 void wxChoice::Select(int n
)
554 void wxChoice::SetString(int WXUNUSED(n
), const wxString
& WXUNUSED(s
))
556 wxFAIL_MSG( wxT("wxChoice::SetString not implemented") );