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 #if !USE_SHARED_LIBRARY
34 IMPLEMENT_DYNAMIC_CLASS(wxChoice
, wxControl
)
37 void wxChoiceCallback (Widget w
, XtPointer clientData
,
43 m_buttonWidget
= (WXWidget
) 0;
44 m_menuWidget
= (WXWidget
) 0;
45 m_widgetList
= (WXWidget
*) 0;
46 m_formWidget
= (WXWidget
) 0;
49 bool wxChoice::Create(wxWindow
*parent
, wxWindowID id
,
52 int n
, const wxString choices
[],
54 const wxValidator
& validator
,
58 SetValidator(validator
);
59 m_noStrings
= 0; // Starts off with none, incremented in Append
60 m_windowStyle
= style
;
61 m_buttonWidget
= (WXWidget
) 0;
62 m_menuWidget
= (WXWidget
) 0;
63 m_widgetList
= (WXWidget
*) 0;
64 m_formWidget
= (WXWidget
) 0;
66 if (parent
) parent
->AddChild(this);
69 m_windowId
= (int)NewControlId();
73 m_backgroundColour
= parent
->GetBackgroundColour();
74 m_foregroundColour
= parent
->GetForegroundColour();
75 m_font
= parent
->GetFont();
77 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
79 m_formWidget
= (WXWidget
) XtVaCreateManagedWidget(name
.c_str(),
80 xmRowColumnWidgetClass
, parentWidget
,
83 XmNpacking
, XmPACK_TIGHT
,
84 XmNorientation
, XmHORIZONTAL
,
87 XtVaSetValues ((Widget
) m_formWidget
, XmNspacing
, 0, NULL
);
90 * Create the popup menu
92 m_menuWidget
= (WXWidget
) XmCreatePulldownMenu ((Widget
) m_formWidget
, "choiceMenu", NULL
, 0);
98 for (i
= 0; i
< n
; i
++)
108 XtSetArg (args
[argcnt
], XmNsubMenuId
, (Widget
) m_menuWidget
);
110 XtSetArg (args
[argcnt
], XmNmarginWidth
, 0);
112 XtSetArg (args
[argcnt
], XmNmarginHeight
, 0);
114 XtSetArg (args
[argcnt
], XmNpacking
, XmPACK_TIGHT
);
116 m_buttonWidget
= (WXWidget
) XmCreateOptionMenu ((Widget
) m_formWidget
, "choiceButton", args
, argcnt
);
118 m_mainWidget
= m_buttonWidget
;
120 XtManageChild ((Widget
) m_buttonWidget
);
122 // New code from Roland Haenel (roland_haenel@ac.cybercity.de)
123 // Some time ago, I reported a problem with wxChoice-items under
124 // Linux and Motif 2.0 (they caused sporadic GPFs). Now it seems
125 // that I have found the code responsible for this behaviour.
126 #if XmVersion >= 1002
128 // JACS, 24/1/99: this seems to cause a malloc crash later on, e.g.
129 // in controls sample.
131 // Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget);
132 // XtUnmanageChild (optionLabel);
136 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
140 AttachWidget (parent
, m_buttonWidget
, m_formWidget
, pos
.x
, pos
.y
, size
.x
, size
.y
);
142 ChangeBackgroundColour();
147 wxChoice::~wxChoice()
149 // For some reason destroying the menuWidget
150 // can cause crashes on some machines. It will
151 // be deleted implicitly by deleting the parent form
153 // XtDestroyWidget (menuWidget);
155 delete[] m_widgetList
;
159 DetachWidget(GetMainWidget()); // Removes event handlers
160 DetachWidget(m_formWidget
);
162 XtDestroyWidget((Widget
) m_formWidget
);
163 m_formWidget
= (WXWidget
) 0;
165 // Presumably the other widgets have been deleted now, via the form
166 m_mainWidget
= (WXWidget
) 0;
167 m_buttonWidget
= (WXWidget
) 0;
171 void wxChoice::Append(const wxString
& item
)
173 Widget w
= XtVaCreateManagedWidget (wxStripMenuCodes(item
),
175 xmPushButtonGadgetClass
, (Widget
) m_menuWidget
,
177 xmPushButtonWidgetClass
, (Widget
) m_menuWidget
,
181 DoChangeBackgroundColour((WXWidget
) w
, m_backgroundColour
);
185 XmNfontList
, (XmFontList
) m_font
.GetFontList(1.0, XtDisplay((Widget
) m_formWidget
)),
188 WXWidget
*new_widgetList
= new WXWidget
[m_noStrings
+ 1];
191 for (i
= 0; i
< m_noStrings
; i
++)
192 new_widgetList
[i
] = m_widgetList
[i
];
194 new_widgetList
[m_noStrings
] = (WXWidget
) w
;
197 delete[] m_widgetList
;
198 m_widgetList
= new_widgetList
;
200 char mnem
= wxFindMnemonic ((char*) (const char*) item
);
202 XtVaSetValues (w
, XmNmnemonic
, mnem
, NULL
);
204 XtAddCallback (w
, XmNactivateCallback
, (XtCallbackProc
) wxChoiceCallback
, (XtPointer
) this);
206 if (m_noStrings
== 0 && m_buttonWidget
)
208 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmenuHistory
, w
, NULL
);
209 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
210 XmString text
= XmStringCreateSimple ((char*) (const char*) item
);
211 XtVaSetValues (label
,
212 XmNlabelString
, text
,
216 wxNode
*node
= m_stringList
.Add (item
);
217 XtVaSetValues (w
, XmNuserData
, node
->Data (), NULL
);
222 void wxChoice::Delete(int WXUNUSED(n
))
224 wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" );
226 // What should we do -- remove the callback for this button widget,
227 // delete the m_stringList entry, delete the button widget, construct a new widget list
234 void wxChoice::Clear()
236 m_stringList
.Clear ();
238 for (i
= 0; i
< m_noStrings
; i
++)
240 XtUnmanageChild ((Widget
) m_widgetList
[i
]);
241 XtDestroyWidget ((Widget
) m_widgetList
[i
]);
244 delete[] m_widgetList
;
245 m_widgetList
= (WXWidget
*) NULL
;
247 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmenuHistory
, (Widget
) NULL
, NULL
);
251 int wxChoice::GetSelection() const
255 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
256 XtVaGetValues (label
,
257 XmNlabelString
, &text
,
260 if (XmStringGetLtoR (text
, XmSTRING_DEFAULT_CHARSET
, &s
))
263 for (wxNode
* node
= m_stringList
.First (); node
; node
= node
->Next ())
265 char *s1
= (char *) node
->Data ();
266 if (s1
== s
|| strcmp (s1
, s
) == 0)
284 void wxChoice::SetSelection(int n
)
288 wxNode
*node
= m_stringList
.Nth (n
);
291 Dimension selectionWidth
, selectionHeight
;
293 char *s
= (char *) node
->Data ();
294 XmString text
= XmStringCreateSimple (s
);
295 XtVaGetValues ((Widget
) m_widgetList
[n
], XmNwidth
, &selectionWidth
, XmNheight
, &selectionHeight
, NULL
);
296 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
297 XtVaSetValues (label
,
298 XmNlabelString
, text
,
301 XtVaSetValues ((Widget
) m_buttonWidget
,
302 XmNwidth
, selectionWidth
, XmNheight
, selectionHeight
,
303 XmNmenuHistory
, (Widget
) m_widgetList
[n
], NULL
);
305 m_inSetValue
= FALSE
;
308 int wxChoice::FindString(const wxString
& s
) const
311 for (wxNode
* node
= m_stringList
.First (); node
; node
= node
->Next ())
313 char *s1
= (char *) node
->Data ();
324 wxString
wxChoice::GetString(int n
) const
326 wxNode
*node
= m_stringList
.Nth (n
);
328 return wxString((char *) node
->Data ());
330 return wxEmptyString
;
333 void wxChoice::SetColumns(int n
)
337 short numColumns
= n
;
340 XtSetArg(args
[0], XmNnumColumns
, numColumns
);
341 XtSetArg(args
[1], XmNpacking
, XmPACK_COLUMN
);
342 XtSetValues((Widget
) m_menuWidget
,args
,2) ;
345 int wxChoice::GetColumns(void) const
349 XtVaGetValues((Widget
) m_menuWidget
,XmNnumColumns
,&numColumns
,NULL
) ;
353 void wxChoice::SetFocus()
355 XmProcessTraversal(XtParent((Widget
)m_mainWidget
), XmTRAVERSE_CURRENT
);
358 void wxChoice::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
360 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
361 bool managed
= XtIsManaged((Widget
) m_formWidget
);
364 XtUnmanageChild ((Widget
) m_formWidget
);
366 int actualWidth
= width
, actualHeight
= height
;
371 for (i
= 0; i
< m_noStrings
; i
++)
372 XtVaSetValues ((Widget
) m_widgetList
[i
], XmNwidth
, actualWidth
, NULL
);
373 XtVaSetValues ((Widget
) m_buttonWidget
, XmNwidth
, actualWidth
,
379 for (i
= 0; i
< m_noStrings
; i
++)
380 XtVaSetValues ((Widget
) m_widgetList
[i
], XmNheight
, actualHeight
, NULL
);
381 XtVaSetValues ((Widget
) m_buttonWidget
, XmNheight
, actualHeight
,
386 XtManageChild ((Widget
) m_formWidget
);
387 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
389 wxControl::DoSetSize (x
, y
, width
, height
, sizeFlags
);
392 wxString
wxChoice::GetStringSelection () const
394 int sel
= GetSelection ();
396 return wxString(this->GetString (sel
));
398 return wxEmptyString
;
401 bool wxChoice::SetStringSelection (const wxString
& s
)
403 int sel
= FindString (s
);
413 void wxChoice::Command(wxCommandEvent
& event
)
415 SetSelection (event
.GetInt());
416 ProcessCommand (event
);
419 void wxChoiceCallback (Widget w
, XtPointer clientData
, XtPointer
WXUNUSED(ptr
))
421 wxChoice
*item
= (wxChoice
*) clientData
;
424 if (item
->InSetValue())
428 XtVaGetValues (w
, XmNuserData
, &s
, NULL
);
431 wxCommandEvent
event (wxEVT_COMMAND_CHOICE_SELECTED
, item
->GetId());
432 event
.SetEventObject(item
);
433 event
.m_commandInt
= item
->FindString (s
);
434 // event.m_commandString = s;
435 item
->ProcessCommand (event
);
440 void wxChoice::ChangeFont(bool keepOriginalSize
)
442 // Note that this causes the widget to be resized back
443 // to its original size! We therefore have to set the size
444 // back again. TODO: a better way in Motif?
447 int width
, height
, width1
, height1
;
448 GetSize(& width
, & height
);
450 XmFontList fontList
= (XmFontList
) m_font
.GetFontList(1.0, XtDisplay((Widget
) m_mainWidget
));
451 XtVaSetValues ((Widget
) m_mainWidget
, XmNfontList
, fontList
, NULL
);
452 XtVaSetValues ((Widget
) m_buttonWidget
, XmNfontList
, fontList
, NULL
);
454 /* TODO: why does this cause a crash in XtWidgetToApplicationContext?
456 for (i = 0; i < m_noStrings; i++)
457 XtVaSetValues ((Widget) m_widgetList[i], XmNfontList, fontList, NULL);
459 GetSize(& width1
, & height1
);
460 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
462 SetSize(-1, -1, width
, height
);
467 void wxChoice::ChangeBackgroundColour()
469 DoChangeBackgroundColour(m_formWidget
, m_backgroundColour
);
470 DoChangeBackgroundColour(m_buttonWidget
, m_backgroundColour
);
471 DoChangeBackgroundColour(m_menuWidget
, m_backgroundColour
);
473 for (i
= 0; i
< m_noStrings
; i
++)
474 DoChangeBackgroundColour(m_widgetList
[i
], m_backgroundColour
);
477 void wxChoice::ChangeForegroundColour()
479 DoChangeForegroundColour(m_formWidget
, m_foregroundColour
);
480 DoChangeForegroundColour(m_buttonWidget
, m_foregroundColour
);
481 DoChangeForegroundColour(m_menuWidget
, m_foregroundColour
);
483 for (i
= 0; i
< m_noStrings
; i
++)
484 DoChangeForegroundColour(m_widgetList
[i
], m_foregroundColour
);
488 // These implement functions needed by wxControlWithItems.
489 // Unfortunately, they're not all implemented yet.
491 int wxChoice::GetCount() const
496 int wxChoice::DoAppend(const wxString
& item
)
499 return GetCount() - 1;
502 // Just appends, doesn't yet insert
503 void wxChoice::DoInsertItems(const wxArrayString
& items
, int WXUNUSED(pos
))
505 size_t nItems
= items
.GetCount();
507 for ( size_t n
= 0; n
< nItems
; n
++ )
513 void wxChoice::DoSetItems(const wxArrayString
& items
, void **WXUNUSED(clientData
))
516 size_t nItems
= items
.GetCount();
518 for ( size_t n
= 0; n
< nItems
; n
++ )
524 void wxChoice::DoSetFirstItem(int WXUNUSED(n
))
526 wxFAIL_MSG( wxT("wxChoice::DoSetFirstItem not implemented") );
529 void wxChoice::DoSetItemClientData(int WXUNUSED(n
), void* WXUNUSED(clientData
))
531 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientData not implemented") );
534 void* wxChoice::DoGetItemClientData(int WXUNUSED(n
)) const
536 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientData not implemented") );
540 void wxChoice::DoSetItemClientObject(int WXUNUSED(n
), wxClientData
* WXUNUSED(clientData
))
542 wxFAIL_MSG( wxT("wxChoice::DoSetItemClientObject not implemented") );
545 wxClientData
* wxChoice::DoGetItemClientObject(int WXUNUSED(n
)) const
547 wxFAIL_MSG( wxT("wxChoice::DoGetItemClientObject not implemented") );
548 return (wxClientData
*) NULL
;
551 void wxChoice::Select(int n
)
556 void wxChoice::SetString(int WXUNUSED(n
), const wxString
& WXUNUSED(s
))
558 wxFAIL_MSG( wxT("wxChoice::SetString not implemented") );