]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/menuitem.cpp
fixed incorrect GetTextExtent for wxTELETYPE font
[wxWidgets.git] / src / motif / menuitem.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: menuitem.cpp
3// Purpose: wxMenuItem implementation
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// ============================================================================
13// declarations
14// ============================================================================
15
16#ifdef __GNUG__
17 #pragma implementation "menuitem.h"
18#endif
19
20// ----------------------------------------------------------------------------
21// headers
22// ----------------------------------------------------------------------------
23
24#include "wx/menu.h"
25#include "wx/menuitem.h"
26#include "wx/utils.h"
27#include "wx/frame.h"
28
29#ifdef __VMS__
30#pragma message disable nosimpint
31#endif
32#include <Xm/Label.h>
33#include <Xm/LabelG.h>
34#include <Xm/CascadeBG.h>
35#include <Xm/CascadeB.h>
36#include <Xm/SeparatoG.h>
37#include <Xm/PushBG.h>
38#include <Xm/ToggleB.h>
39#include <Xm/ToggleBG.h>
40#include <Xm/RowColumn.h>
41#ifdef __VMS__
42#pragma message enable nosimpint
43#endif
44
45#include "wx/motif/private.h"
46
47// ----------------------------------------------------------------------------
48// functions prototypes
49// ----------------------------------------------------------------------------
50
51static void wxMenuItemCallback(Widget w, XtPointer clientData, XtPointer ptr);
52static void wxMenuItemArmCallback(Widget w, XtPointer clientData, XtPointer ptr);
53static void wxMenuItemDisarmCallback(Widget w, XtPointer clientData, XtPointer ptr);
54
55// ============================================================================
56// implementation
57// ============================================================================
58
59// ----------------------------------------------------------------------------
60// dynamic classes implementation
61// ----------------------------------------------------------------------------
62
63 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
64
65// ----------------------------------------------------------------------------
66// wxMenuItem
67// ----------------------------------------------------------------------------
68
69// ctor & dtor
70// -----------
71
72wxMenuItem::wxMenuItem(wxMenu *pParentMenu, int id,
73 const wxString& strName, const wxString& strHelp,
74 bool bCheckable,
75 wxMenu *pSubMenu)
76{
77 wxASSERT_MSG( pParentMenu != NULL, wxT("menuitem should have a menu") );
78
79 // common init
80 m_parentMenu = pParentMenu;
81 m_subMenu = pSubMenu;
82 m_id = id;
83 m_isEnabled = TRUE;
84 m_isChecked = FALSE;
85 m_help = strHelp;
86 m_isCheckable = bCheckable;
87 m_text = strName;
88
89 // Motif-specific
90 m_menuBar = NULL;
91 m_buttonWidget = (WXWidget) NULL;
92 m_topMenu = NULL;
93}
94
95wxMenuItem::~wxMenuItem()
96{
97}
98
99// misc
100// ----
101
102// delete the sub menu
103void wxMenuItem::DeleteSubMenu()
104{
105 wxASSERT( m_subMenu != NULL );
106
107 delete m_subMenu;
108 m_subMenu = NULL;
109}
110
111// change item state
112// -----------------
113
114void wxMenuItem::Enable(bool bDoEnable)
115{
116 if ( m_isEnabled != bDoEnable )
117 {
118 if ( !IsSubMenu() )
119 {
120 // normal menu item
121 if (m_buttonWidget)
122 XtSetSensitive( (Widget) m_buttonWidget, (Boolean) bDoEnable);
123 }
124 else // submenu
125 {
126 // Maybe we should apply this to all items in the submenu?
127 // Or perhaps it works anyway.
128 if (m_buttonWidget)
129 XtSetSensitive( (Widget) m_buttonWidget, (Boolean) bDoEnable);
130 }
131
132 wxMenuItemBase::Enable(bDoEnable);
133 }
134}
135
136void wxMenuItem::Check(bool bDoCheck)
137{
138 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
139
140 if ( m_isChecked != bDoCheck )
141 {
142 if ( m_buttonWidget )
143 {
144 wxASSERT_MSG( XtIsSubclass((Widget)m_buttonWidget,
145 xmToggleButtonGadgetClass),
146 wxT("checkable menu item must be a toggle button") );
147
148 XtVaSetValues((Widget)m_buttonWidget,
149 XmNset, (Boolean)bDoCheck,
150 NULL);
151 }
152
153 wxMenuItemBase::Check(bDoCheck);
154 }
155}
156
157/* static */
158wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
159{
160 return wxStripMenuCodes(text);
161}
162
163// ----------------------------------------------------------------------------
164// wxMenuItemBase
165// ----------------------------------------------------------------------------
166
167wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
168 int id,
169 const wxString& name,
170 const wxString& help,
171 bool isCheckable,
172 wxMenu *subMenu)
173{
174 return new wxMenuItem(parentMenu, id, name, help, isCheckable, subMenu);
175}
176
177// ----------------------------------------------------------------------------
178// Motif-specific
179// ----------------------------------------------------------------------------
180
181void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar, wxMenu * topMenu)
182{
183 m_menuBar = menuBar;
184 m_topMenu = topMenu;
185
186 if (GetId() == -2)
187 {
188 // Id=-2 identifies a Title item.
189 m_buttonWidget = (WXWidget) XtVaCreateManagedWidget
190 (wxStripMenuCodes(m_text),
191 xmLabelGadgetClass, (Widget) menu, NULL);
192 }
193 else if ((!m_text.IsNull() && m_text != "") && (!m_subMenu))
194 {
195 wxString strName = wxStripMenuCodes(m_text);
196 if (IsCheckable())
197 {
198 m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (strName,
199 xmToggleButtonGadgetClass, (Widget) menu,
200 NULL);
201 XtVaSetValues ((Widget) m_buttonWidget, XmNset, (Boolean) IsChecked(), NULL);
202 }
203 else
204 m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (strName,
205 xmPushButtonGadgetClass, (Widget) menu,
206 NULL);
207 char mnem = wxFindMnemonic (m_text);
208 if (mnem != 0)
209 XtVaSetValues ((Widget) m_buttonWidget, XmNmnemonic, mnem, NULL);
210
211 //// TODO: proper accelerator treatment. What does wxFindAccelerator
212 //// look for?
213 strName = m_text;
214 char *accel = wxFindAccelerator (strName);
215 if (accel)
216 XtVaSetValues ((Widget) m_buttonWidget, XmNaccelerator, accel, NULL);
217
218 // TODO: What does this do?
219 XmString accel_str = wxFindAcceleratorText (strName);
220 if (accel_str)
221 {
222 XtVaSetValues ((Widget) m_buttonWidget, XmNacceleratorText, accel_str, NULL);
223 XmStringFree (accel_str);
224 }
225
226 if (IsCheckable())
227 XtAddCallback ((Widget) m_buttonWidget,
228 XmNvalueChangedCallback,
229 (XtCallbackProc) wxMenuItemCallback,
230 (XtPointer) this);
231 else
232 XtAddCallback ((Widget) m_buttonWidget,
233 XmNactivateCallback,
234 (XtCallbackProc) wxMenuItemCallback,
235 (XtPointer) this);
236 XtAddCallback ((Widget) m_buttonWidget,
237 XmNarmCallback,
238 (XtCallbackProc) wxMenuItemArmCallback,
239 (XtPointer) this);
240 XtAddCallback ((Widget) m_buttonWidget,
241 XmNdisarmCallback,
242 (XtCallbackProc) wxMenuItemDisarmCallback,
243 (XtPointer) this);
244 }
245 else if (GetId() == -1)
246 {
247 m_buttonWidget = (WXWidget) XtVaCreateManagedWidget ("separator",
248 xmSeparatorGadgetClass, (Widget) menu, NULL);
249 }
250 else if (m_subMenu)
251 {
252 m_buttonWidget = m_subMenu->CreateMenu (menuBar, menu, topMenu, m_text, TRUE);
253 m_subMenu->SetButtonWidget(m_buttonWidget);
254 XtAddCallback ((Widget) m_buttonWidget,
255 XmNcascadingCallback,
256 (XtCallbackProc) wxMenuItemArmCallback,
257 (XtPointer) this);
258 }
259 if (m_buttonWidget)
260 XtSetSensitive ((Widget) m_buttonWidget, (Boolean) IsEnabled());
261}
262
263void wxMenuItem::DestroyItem(bool full)
264{
265 if (GetId() == -2)
266 {
267 ; // Nothing
268
269 }
270 else if ((!m_text.IsNull() && (m_text != "")) && !m_subMenu)
271 {
272 if (m_buttonWidget)
273 {
274 if (IsCheckable())
275 XtRemoveCallback ((Widget) m_buttonWidget, XmNvalueChangedCallback,
276 wxMenuItemCallback, (XtPointer) this);
277 else
278 XtRemoveCallback ((Widget) m_buttonWidget, XmNactivateCallback,
279 wxMenuItemCallback, (XtPointer) this);
280 XtRemoveCallback ((Widget) m_buttonWidget, XmNarmCallback,
281 wxMenuItemArmCallback, (XtPointer) this);
282 XtRemoveCallback ((Widget) m_buttonWidget, XmNdisarmCallback,
283 wxMenuItemDisarmCallback, (XtPointer) this);
284 }
285 }
286 else if (GetId() == -1)
287 {
288 ; // Nothing
289
290 }
291 else if (GetSubMenu())
292 {
293 if (m_buttonWidget)
294 {
295 XtRemoveCallback ((Widget) m_buttonWidget, XmNcascadingCallback,
296 wxMenuItemArmCallback, (XtPointer) this);
297 }
298 m_subMenu->DestroyMenu(full);
299 if (full)
300 m_buttonWidget = NULL;
301 }
302
303 if (m_buttonWidget && full)
304 {
305 XtDestroyWidget ((Widget) m_buttonWidget);
306 m_buttonWidget = (WXWidget) 0;
307 }
308}
309
310void wxMenuItem::SetText(const wxString& label)
311{
312 char mnem = wxFindMnemonic (label);
313 wxString label2 = wxStripMenuCodes(label);
314
315 m_text = label;
316
317 if (m_buttonWidget)
318 {
319 wxXmString label_str(label2);
320 XtVaSetValues ((Widget) m_buttonWidget,
321 XmNlabelString, label_str(),
322 NULL);
323 if (mnem != 0)
324 XtVaSetValues ((Widget) m_buttonWidget, XmNmnemonic, mnem, NULL);
325 char *accel = wxFindAccelerator (label2);
326 if (accel)
327 XtVaSetValues ((Widget) m_buttonWidget, XmNaccelerator, accel, NULL);
328
329 XmString accel_str = wxFindAcceleratorText (label2);
330 if (accel_str)
331 {
332 XtVaSetValues ((Widget) m_buttonWidget, XmNacceleratorText, accel_str, NULL);
333 XmStringFree (accel_str);
334 }
335 }
336}
337
338// ----------------------------------------------------------------------------
339// Motif callbacks
340// ----------------------------------------------------------------------------
341
342void wxMenuItemCallback (Widget WXUNUSED(w), XtPointer clientData,
343 XtPointer WXUNUSED(ptr))
344{
345 wxMenuItem *item = (wxMenuItem *) clientData;
346 if (item)
347 {
348 if (item->IsCheckable())
349 {
350 Boolean isChecked = FALSE;
351 XtVaGetValues ((Widget) item->GetButtonWidget(), XmNset, & isChecked, NULL);
352
353 // only set the flag, don't actually check anything
354 item->wxMenuItemBase::Check(isChecked);
355 }
356 if (item->GetMenuBar() && item->GetMenuBar()->GetMenuBarFrame())
357 {
358 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, item->GetId());
359 commandEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame());
360 commandEvent.SetInt( item->GetId() );
361
362 item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(commandEvent);
363 }
364 else if (item->GetTopMenu())
365 {
366 wxCommandEvent event (wxEVT_COMMAND_MENU_SELECTED, item->GetId());
367 event.SetEventObject(item->GetTopMenu());
368 event.SetInt( item->GetId() );
369
370 item->GetTopMenu()->ProcessCommand (event);
371 }
372 }
373}
374
375void wxMenuItemArmCallback (Widget WXUNUSED(w), XtPointer clientData,
376 XtPointer WXUNUSED(ptr))
377{
378 wxMenuItem *item = (wxMenuItem *) clientData;
379 if (item)
380 {
381 if (item->GetMenuBar() && item->GetMenuBar()->GetMenuBarFrame())
382 {
383 wxMenuEvent menuEvent(wxEVT_MENU_HIGHLIGHT, item->GetId());
384 menuEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame());
385
386 item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(menuEvent);
387 }
388 }
389}
390
391void
392wxMenuItemDisarmCallback (Widget WXUNUSED(w), XtPointer clientData,
393 XtPointer WXUNUSED(ptr))
394{
395 wxMenuItem *item = (wxMenuItem *) clientData;
396 if (item)
397 {
398 if (item->GetMenuBar() && item->GetMenuBar()->GetMenuBarFrame())
399 {
400 // TODO: not sure this is correct, since -1 means something
401 // special to event system
402 wxMenuEvent menuEvent(wxEVT_MENU_HIGHLIGHT, -1);
403 menuEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame());
404
405 item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(menuEvent);
406 }
407 }
408}
409