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