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