1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMenuItem implementation
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17 #pragma implementation "menuitem.h"
20 // ----------------------------------------------------------------------------
22 // ----------------------------------------------------------------------------
27 #include "wx/menuitem.h"
32 #pragma message disable nosimpint
35 #include <Xm/LabelG.h>
36 #include <Xm/CascadeBG.h>
37 #include <Xm/CascadeB.h>
38 #include <Xm/SeparatoG.h>
39 #include <Xm/PushBG.h>
40 #include <Xm/ToggleB.h>
41 #include <Xm/ToggleBG.h>
42 #include <Xm/RowColumn.h>
44 #pragma message enable nosimpint
47 #include "wx/motif/private.h"
49 // ----------------------------------------------------------------------------
50 // functions prototypes
51 // ----------------------------------------------------------------------------
53 static void wxMenuItemCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
54 static void wxMenuItemArmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
55 static void wxMenuItemDisarmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
57 // ============================================================================
59 // ============================================================================
61 // ----------------------------------------------------------------------------
62 // dynamic classes implementation
63 // ----------------------------------------------------------------------------
65 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
74 wxMenuItem::wxMenuItem(wxMenu
*pParentMenu
,
76 const wxString
& strName
,
77 const wxString
& strHelp
,
80 : wxMenuItemBase(pParentMenu
, id
, strName
, strHelp
, kind
, pSubMenu
)
84 m_buttonWidget
= (WXWidget
) NULL
;
88 wxMenuItem::~wxMenuItem()
95 // delete the sub menu
96 void wxMenuItem::DeleteSubMenu()
98 wxASSERT( m_subMenu
!= NULL
);
107 void wxMenuItem::Enable(bool bDoEnable
)
109 if ( m_isEnabled
!= bDoEnable
)
115 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
119 // Maybe we should apply this to all items in the submenu?
120 // Or perhaps it works anyway.
122 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
125 wxMenuItemBase::Enable(bDoEnable
);
129 void wxMenuItem::Check(bool bDoCheck
)
131 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
133 if ( m_isChecked
!= bDoCheck
)
135 if ( m_buttonWidget
)
137 wxASSERT_MSG( XtIsSubclass((Widget
)m_buttonWidget
,
138 xmToggleButtonGadgetClass
),
139 wxT("checkable menu item must be a toggle button") );
141 XtVaSetValues((Widget
)m_buttonWidget
,
142 XmNset
, (Boolean
)bDoCheck
,
146 wxMenuItemBase::Check(bDoCheck
);
151 wxString
wxMenuItemBase::GetLabelFromText(const wxString
& text
)
153 return wxStripMenuCodes(text
);
156 // ----------------------------------------------------------------------------
158 // ----------------------------------------------------------------------------
160 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
162 const wxString
& name
,
163 const wxString
& help
,
167 return new wxMenuItem(parentMenu
, id
, name
, help
, kind
, subMenu
);
170 // ----------------------------------------------------------------------------
172 // ----------------------------------------------------------------------------
174 void wxMenuItem::CreateItem (WXWidget menu
, wxMenuBar
* menuBar
, wxMenu
* topMenu
)
181 // Id=-2 identifies a Title item.
182 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget
183 (wxStripMenuCodes(m_text
),
184 xmLabelGadgetClass
, (Widget
) menu
, NULL
);
186 else if ((!m_text
.IsNull() && m_text
!= "") && (!m_subMenu
))
188 wxString strName
= wxStripMenuCodes(m_text
);
191 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
192 xmToggleButtonGadgetClass
, (Widget
) menu
,
194 XtVaSetValues ((Widget
) m_buttonWidget
, XmNset
, (Boolean
) IsChecked(), NULL
);
197 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
198 xmPushButtonGadgetClass
, (Widget
) menu
,
200 char mnem
= wxFindMnemonic (m_text
);
202 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
204 //// TODO: proper accelerator treatment. What does wxFindAccelerator
207 char *accel
= wxFindAccelerator (strName
);
209 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
211 // TODO: What does this do?
212 XmString accel_str
= wxFindAcceleratorText (strName
);
215 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
216 XmStringFree (accel_str
);
220 XtAddCallback ((Widget
) m_buttonWidget
,
221 XmNvalueChangedCallback
,
222 (XtCallbackProc
) wxMenuItemCallback
,
225 XtAddCallback ((Widget
) m_buttonWidget
,
227 (XtCallbackProc
) wxMenuItemCallback
,
229 XtAddCallback ((Widget
) m_buttonWidget
,
231 (XtCallbackProc
) wxMenuItemArmCallback
,
233 XtAddCallback ((Widget
) m_buttonWidget
,
235 (XtCallbackProc
) wxMenuItemDisarmCallback
,
238 else if (GetId() == -1)
240 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget ("separator",
241 xmSeparatorGadgetClass
, (Widget
) menu
, NULL
);
245 m_buttonWidget
= m_subMenu
->CreateMenu (menuBar
, menu
, topMenu
, m_text
, TRUE
);
246 m_subMenu
->SetButtonWidget(m_buttonWidget
);
247 XtAddCallback ((Widget
) m_buttonWidget
,
248 XmNcascadingCallback
,
249 (XtCallbackProc
) wxMenuItemArmCallback
,
253 XtSetSensitive ((Widget
) m_buttonWidget
, (Boolean
) IsEnabled());
256 void wxMenuItem::DestroyItem(bool full
)
263 else if ((!m_text
.IsNull() && (m_text
!= "")) && !m_subMenu
)
268 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNvalueChangedCallback
,
269 wxMenuItemCallback
, (XtPointer
) this);
271 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNactivateCallback
,
272 wxMenuItemCallback
, (XtPointer
) this);
273 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNarmCallback
,
274 wxMenuItemArmCallback
, (XtPointer
) this);
275 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNdisarmCallback
,
276 wxMenuItemDisarmCallback
, (XtPointer
) this);
279 else if (GetId() == -1)
284 else if (GetSubMenu())
288 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNcascadingCallback
,
289 wxMenuItemArmCallback
, (XtPointer
) this);
291 m_subMenu
->DestroyMenu(full
);
293 m_buttonWidget
= NULL
;
296 if (m_buttonWidget
&& full
)
298 XtDestroyWidget ((Widget
) m_buttonWidget
);
299 m_buttonWidget
= (WXWidget
) 0;
303 void wxMenuItem::SetText(const wxString
& label
)
305 char mnem
= wxFindMnemonic (label
);
306 wxString label2
= wxStripMenuCodes(label
);
312 wxXmString
label_str(label2
);
313 XtVaSetValues ((Widget
) m_buttonWidget
,
314 XmNlabelString
, label_str(),
317 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
318 char *accel
= wxFindAccelerator (label2
);
320 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
322 XmString accel_str
= wxFindAcceleratorText (label2
);
325 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
326 XmStringFree (accel_str
);
331 // ----------------------------------------------------------------------------
333 // ----------------------------------------------------------------------------
335 void wxMenuItemCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
336 XtPointer
WXUNUSED(ptr
))
338 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
341 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
342 event
.SetInt( item
->GetId() );
344 if (item
->IsCheckable())
346 Boolean isChecked
= FALSE
;
347 XtVaGetValues ((Widget
) item
->GetButtonWidget(),
351 // only set the flag, don't actually check anything
352 item
->wxMenuItemBase::Check(isChecked
);
353 event
.SetInt(isChecked
);
356 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
358 event
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
360 item
->GetMenuBar()->GetMenuBarFrame()
361 ->GetEventHandler()->ProcessEvent(event
);
363 // this is the child of a popup menu
364 else if (item
->GetTopMenu())
366 event
.SetEventObject(item
->GetTopMenu());
368 item
->GetTopMenu()->ProcessCommand (event
);
370 // Since PopupMenu under Motif still grab right mouse
371 // button events after it was closed, we need to delete
372 // the associated widgets to allow next PopUpMenu to
373 // appear; this needs to be done there because doing it in
374 // a WorkProc as before may cause crashes if a menu item causes
375 // the parent window of the menu to be destroyed
376 item
->GetTopMenu()->DestroyWidgetAndDetach();
381 void wxMenuItemArmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
382 XtPointer
WXUNUSED(ptr
))
384 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
387 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
389 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, item
->GetId());
390 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
392 item
->GetMenuBar()->GetMenuBarFrame()
393 ->GetEventHandler()->ProcessEvent(menuEvent
);
399 wxMenuItemDisarmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
400 XtPointer
WXUNUSED(ptr
))
402 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
405 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
407 // TODO: not sure this is correct, since -1 means something
408 // special to event system
409 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, -1);
410 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
412 item
->GetMenuBar()->GetMenuBarFrame()
413 ->GetEventHandler()->ProcessEvent(menuEvent
);