]>
git.saurik.com Git - wxWidgets.git/blob - src/motif/choice.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/choice.cpp
4 // Author: Julian Smart
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
16 #include "wx/choice.h"
20 #include "wx/arrstr.h"
24 #pragma message disable nosimpint
27 #include <Xm/PushBG.h>
29 #include <Xm/RowColumn.h>
31 #pragma message enable nosimpint
34 #include "wx/motif/private.h"
36 #define WIDTH_OVERHEAD 48
37 #define WIDTH_OVERHEAD_SUBTRACT 40
38 #define HEIGHT_OVERHEAD 15
40 void wxChoiceCallback (Widget w
, XtPointer clientData
,
50 m_buttonWidget
= (WXWidget
) 0;
51 m_menuWidget
= (WXWidget
) 0;
52 m_formWidget
= (WXWidget
) 0;
55 bool wxChoice::Create(wxWindow
*parent
, wxWindowID id
,
58 int n
, const wxString choices
[],
60 const wxValidator
& validator
,
63 if ( !CreateControl(parent
, id
, pos
, size
, style
, validator
, name
) )
67 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
69 m_formWidget
= (WXWidget
) XtVaCreateManagedWidget(name
.c_str(),
70 xmRowColumnWidgetClass
, parentWidget
,
73 XmNpacking
, XmPACK_TIGHT
,
74 XmNorientation
, XmHORIZONTAL
,
75 XmNresizeWidth
, False
,
76 XmNresizeHeight
, False
,
79 XtVaSetValues ((Widget
) m_formWidget
, XmNspacing
, 0, NULL
);
82 * Create the popup menu
84 m_menuWidget
= (WXWidget
) XmCreatePulldownMenu ((Widget
) m_formWidget
,
85 wxMOTIF_STR("choiceMenu"),
91 for (i
= 0; i
< n
; i
++)
101 XtSetArg (args
[argcnt
], XmNsubMenuId
, (Widget
) m_menuWidget
); ++argcnt
;
102 XtSetArg (args
[argcnt
], XmNmarginWidth
, 0); ++argcnt
;
103 XtSetArg (args
[argcnt
], XmNmarginHeight
, 0); ++argcnt
;
104 XtSetArg (args
[argcnt
], XmNpacking
, XmPACK_TIGHT
); ++argcnt
;
105 m_buttonWidget
= (WXWidget
) XmCreateOptionMenu ((Widget
) m_formWidget
,
106 wxMOTIF_STR("choiceButton"),
109 m_mainWidget
= m_buttonWidget
;
111 XtManageChild ((Widget
) m_buttonWidget
);
113 // New code from Roland Haenel (roland_haenel@ac.cybercity.de)
114 // Some time ago, I reported a problem with wxChoice-items under
115 // Linux and Motif 2.0 (they caused sporadic GPFs). Now it seems
116 // that I have found the code responsible for this behaviour.
117 #if XmVersion >= 1002
119 // JACS, 24/1/99: this seems to cause a malloc crash later on, e.g.
120 // in controls sample.
122 // Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget);
123 // XtUnmanageChild (optionLabel);
127 wxSize bestSize
= GetBestSize();
128 if( size
.x
> 0 ) bestSize
.x
= size
.x
;
129 if( size
.y
> 0 ) bestSize
.y
= size
.y
;
131 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
134 AttachWidget (parent
, m_buttonWidget
, m_formWidget
,
135 pos
.x
, pos
.y
, bestSize
.x
, bestSize
.y
);
140 bool wxChoice::Create(wxWindow
*parent
, wxWindowID id
,
143 const wxArrayString
& choices
,
145 const wxValidator
& validator
,
146 const wxString
& name
)
148 wxCArrayString
chs(choices
);
149 return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
150 style
, validator
, name
);
153 wxChoice::~wxChoice()
155 // For some reason destroying the menuWidget
156 // can cause crashes on some machines. It will
157 // be deleted implicitly by deleting the parent form
159 // XtDestroyWidget (menuWidget);
163 DetachWidget(GetMainWidget()); // Removes event handlers
164 DetachWidget(m_formWidget
);
166 XtDestroyWidget((Widget
) m_formWidget
);
167 m_formWidget
= (WXWidget
) 0;
169 // Presumably the other widgets have been deleted now, via the form
170 m_mainWidget
= (WXWidget
) 0;
171 m_buttonWidget
= (WXWidget
) 0;
175 static inline wxChar
* MYcopystring(const wxChar
* s
)
177 wxChar
* copy
= new wxChar
[wxStrlen(s
) + 1];
178 return wxStrcpy(copy
, s
);
181 // TODO auto-sorting is not supported by the code
182 int wxChoice::DoInsertItems(const wxArrayStringsAdapter
& items
,
184 void **clientData
, wxClientDataType type
)
186 #ifndef XmNpositionIndex
187 wxCHECK_MSG( pos
== GetCount(), -1, wxT("insert not implemented"));
190 const unsigned int numItems
= items
.GetCount();
191 AllocClientData(numItems
);
192 for( unsigned int i
= 0; i
< numItems
; ++i
, ++pos
)
194 Widget w
= XtVaCreateManagedWidget (GetLabelText(items
[i
]),
196 xmPushButtonGadgetClass
, (Widget
) m_menuWidget
,
198 xmPushButtonWidgetClass
, (Widget
) m_menuWidget
,
200 #ifdef XmNpositionIndex
201 XmNpositionIndex
, pos
,
205 wxDoChangeBackgroundColour((WXWidget
) w
, m_backgroundColour
);
208 wxDoChangeFont( w
, m_font
);
210 m_widgetArray
.Insert(w
, pos
);
212 char mnem
= wxFindMnemonic (items
[i
]);
214 XtVaSetValues (w
, XmNmnemonic
, mnem
, NULL
);
216 XtAddCallback (w
, XmNactivateCallback
,
217 (XtCallbackProc
) wxChoiceCallback
,
220 if (m_stringArray
.GetCount() == 0 && m_buttonWidget
)
222 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmenuHistory
, w
, NULL
);
223 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
224 wxXmString
text( items
[i
] );
225 XtVaSetValues (label
,
226 XmNlabelString
, text(),
230 m_stringArray
.Insert(items
[i
], pos
);
232 InsertNewItemClientData(pos
, clientData
, i
, type
);
238 void wxChoice::DoDeleteOneItem(unsigned int n
)
240 Widget w
= (Widget
)m_widgetArray
[n
];
241 XtRemoveCallback(w
, XmNactivateCallback
, (XtCallbackProc
)wxChoiceCallback
,
244 m_stringArray
.RemoveAt(size_t(n
));
245 m_widgetArray
.RemoveAt(size_t(n
));
246 wxChoiceBase::DoDeleteOneItem(n
);
251 void wxChoice::DoClear()
253 m_stringArray
.Clear();
256 for (i
= 0; i
< m_stringArray
.GetCount(); i
++)
258 XtRemoveCallback((Widget
) m_widgetArray
[i
],
259 XmNactivateCallback
, (XtCallbackProc
)wxChoiceCallback
,
261 XtUnmanageChild ((Widget
) m_widgetArray
[i
]);
262 XtDestroyWidget ((Widget
) m_widgetArray
[i
]);
265 m_widgetArray
.Clear();
267 XtVaSetValues ((Widget
) m_buttonWidget
,
268 XmNmenuHistory
, (Widget
) NULL
,
271 wxChoiceBase::DoClear();
274 int wxChoice::GetSelection() const
277 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
278 XtVaGetValues (label
,
279 XmNlabelString
, &text
,
281 wxXmString
freeMe(text
);
282 wxString s
= wxXmStringToString( text
);
286 for (size_t i
=0; i
<m_stringArray
.GetCount(); i
++)
287 if (m_stringArray
[i
] == s
)
296 void wxChoice::SetSelection(int n
)
301 Dimension selectionWidth
, selectionHeight
;
303 wxXmString
text( m_stringArray
[n
] );
304 // MBN: this seems silly, at best, and causes wxChoices to be clipped:
305 // will remove "soon"
307 XtVaGetValues ((Widget
) m_widgetArray
[n
],
308 XmNwidth
, &selectionWidth
,
309 XmNheight
, &selectionHeight
,
312 Widget label
= XmOptionButtonGadget ((Widget
) m_buttonWidget
);
313 XtVaSetValues (label
,
314 XmNlabelString
, text(),
317 XtVaSetValues ((Widget
) m_buttonWidget
,
318 XmNwidth
, selectionWidth
, XmNheight
, selectionHeight
,
319 XmNmenuHistory
, (Widget
) m_widgetArray
[n
], NULL
);
322 m_inSetValue
= false;
325 wxString
wxChoice::GetString(unsigned int n
) const
327 return m_stringArray
[n
];
330 void wxChoice::SetColumns(int n
)
334 short numColumns
= (short)n
;
337 XtSetArg(args
[0], XmNnumColumns
, numColumns
);
338 XtSetArg(args
[1], XmNpacking
, XmPACK_COLUMN
);
339 XtSetValues((Widget
) m_menuWidget
,args
,2) ;
342 int wxChoice::GetColumns(void) const
346 XtVaGetValues((Widget
) m_menuWidget
,XmNnumColumns
,&numColumns
,NULL
) ;
350 void wxChoice::SetFocus()
352 XmProcessTraversal(XtParent((Widget
)m_mainWidget
), XmTRAVERSE_CURRENT
);
355 void wxChoice::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
357 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
358 bool managed
= XtIsManaged((Widget
) m_formWidget
);
361 XtUnmanageChild ((Widget
) m_formWidget
);
363 int actualWidth
= width
- WIDTH_OVERHEAD_SUBTRACT
,
364 actualHeight
= height
- HEIGHT_OVERHEAD
;
369 for (i
= 0; i
< m_stringArray
.GetCount(); i
++)
370 XtVaSetValues ((Widget
) m_widgetArray
[i
],
371 XmNwidth
, actualWidth
,
373 XtVaSetValues ((Widget
) m_buttonWidget
, XmNwidth
, actualWidth
,
380 for (i
= 0; i
< m_stringArray
.GetCount(); i
++)
381 XtVaSetValues ((Widget
) m_widgetArray
[i
],
382 XmNheight
, actualHeight
,
385 XtVaSetValues ((Widget
) m_buttonWidget
, XmNheight
, actualHeight
,
390 XtManageChild ((Widget
) m_formWidget
);
391 XtVaSetValues((Widget
) m_formWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
393 wxControl::DoSetSize (x
, y
, width
, height
, sizeFlags
);
396 void wxChoice::Command(wxCommandEvent
& event
)
398 SetSelection (event
.GetInt());
399 ProcessCommand (event
);
402 void wxChoiceCallback (Widget w
, XtPointer clientData
, XtPointer
WXUNUSED(ptr
))
404 wxChoice
*item
= (wxChoice
*) clientData
;
407 if (item
->InSetValue())
410 int n
= item
->GetWidgets().Index(w
);
411 if (n
!= wxNOT_FOUND
)
413 wxCommandEvent
event(wxEVT_CHOICE
, item
->GetId());
414 event
.SetEventObject(item
);
416 event
.SetString( item
->GetStrings().Item(n
) );
417 if ( item
->HasClientObjectData() )
418 event
.SetClientObject( item
->GetClientObject(n
) );
419 else if ( item
->HasClientUntypedData() )
420 event
.SetClientData( item
->GetClientData(n
) );
421 item
->ProcessCommand (event
);
426 void wxChoice::ChangeFont(bool keepOriginalSize
)
428 // Note that this causes the widget to be resized back
429 // to its original size! We therefore have to set the size
430 // back again. TODO: a better way in Motif?
431 if (m_mainWidget
&& m_font
.IsOk())
433 Display
* dpy
= XtDisplay((Widget
) m_mainWidget
);
434 int width
, height
, width1
, height1
;
435 GetSize(& width
, & height
);
437 WXString fontTag
= wxFont::GetFontTag();
439 XtVaSetValues ((Widget
) m_formWidget
,
440 fontTag
, m_font
.GetFontTypeC(dpy
),
442 XtVaSetValues ((Widget
) m_buttonWidget
,
443 fontTag
, m_font
.GetFontTypeC(dpy
),
446 for( unsigned int i
= 0; i
< m_stringArray
.GetCount(); ++i
)
447 XtVaSetValues( (Widget
)m_widgetArray
[i
],
448 fontTag
, m_font
.GetFontTypeC(dpy
),
451 GetSize(& width1
, & height1
);
452 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
454 SetSize(wxDefaultCoord
, wxDefaultCoord
, width
, height
);
459 void wxChoice::ChangeBackgroundColour()
461 wxDoChangeBackgroundColour(m_formWidget
, m_backgroundColour
);
462 wxDoChangeBackgroundColour(m_buttonWidget
, m_backgroundColour
);
463 wxDoChangeBackgroundColour(m_menuWidget
, m_backgroundColour
);
465 for (i
= 0; i
< m_stringArray
.GetCount(); i
++)
466 wxDoChangeBackgroundColour(m_widgetArray
[i
], m_backgroundColour
);
469 void wxChoice::ChangeForegroundColour()
471 wxDoChangeForegroundColour(m_formWidget
, m_foregroundColour
);
472 wxDoChangeForegroundColour(m_buttonWidget
, m_foregroundColour
);
473 wxDoChangeForegroundColour(m_menuWidget
, m_foregroundColour
);
475 for (i
= 0; i
< m_stringArray
.GetCount(); i
++)
476 wxDoChangeForegroundColour(m_widgetArray
[i
], m_foregroundColour
);
479 unsigned int wxChoice::GetCount() const
481 return m_stringArray
.GetCount();
484 void wxChoice::SetString(unsigned int WXUNUSED(n
), const wxString
& WXUNUSED(s
))
486 wxFAIL_MSG( wxT("wxChoice::SetString not implemented") );
489 wxSize
wxChoice::GetItemsSize() const
491 int x
, y
, mx
= 0, my
= 0;
494 GetTextExtent( "|", &x
, &my
);
496 for (size_t i
=0; i
<m_stringArray
.GetCount(); i
++)
498 GetTextExtent( m_stringArray
[i
], &x
, &y
);
503 return wxSize( mx
, my
);
506 wxSize
wxChoice::DoGetBestSize() const
508 wxSize items
= GetItemsSize();
509 // FIXME arbitrary constants
510 return wxSize( ( items
.x
? items
.x
+ WIDTH_OVERHEAD
: 120 ),
511 items
.y
+ HEIGHT_OVERHEAD
);
514 #endif // wxUSE_CHOICE