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 void wxMenuItem::Enable(bool bDoEnable
)
97 if ( m_isEnabled
!= bDoEnable
)
103 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
107 // Maybe we should apply this to all items in the submenu?
108 // Or perhaps it works anyway.
110 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
113 wxMenuItemBase::Enable(bDoEnable
);
117 void wxMenuItem::Check(bool bDoCheck
)
119 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
121 if ( m_isChecked
!= bDoCheck
)
123 if ( m_buttonWidget
)
125 wxASSERT_MSG( XtIsSubclass((Widget
)m_buttonWidget
,
126 xmToggleButtonGadgetClass
),
127 wxT("checkable menu item must be a toggle button") );
129 XtVaSetValues((Widget
)m_buttonWidget
,
130 XmNset
, (Boolean
)bDoCheck
,
134 wxMenuItemBase::Check(bDoCheck
);
139 wxString
wxMenuItemBase::GetLabelFromText(const wxString
& text
)
141 return wxStripMenuCodes(text
);
144 // ----------------------------------------------------------------------------
146 // ----------------------------------------------------------------------------
148 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
150 const wxString
& name
,
151 const wxString
& help
,
155 return new wxMenuItem(parentMenu
, id
, name
, help
, kind
, subMenu
);
158 // ----------------------------------------------------------------------------
160 // ----------------------------------------------------------------------------
162 void wxMenuItem::CreateItem (WXWidget menu
, wxMenuBar
* menuBar
, wxMenu
* topMenu
)
169 // Id=-2 identifies a Title item.
170 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget
171 (wxStripMenuCodes(m_text
),
172 xmLabelGadgetClass
, (Widget
) menu
, NULL
);
174 else if ((!m_text
.IsNull() && m_text
!= "") && (!m_subMenu
))
176 wxString strName
= wxStripMenuCodes(m_text
);
179 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
180 xmToggleButtonGadgetClass
, (Widget
) menu
,
182 XtVaSetValues ((Widget
) m_buttonWidget
, XmNset
, (Boolean
) IsChecked(), NULL
);
185 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
186 xmPushButtonGadgetClass
, (Widget
) menu
,
188 char mnem
= wxFindMnemonic (m_text
);
190 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
192 //// TODO: proper accelerator treatment. What does wxFindAccelerator
195 char *accel
= wxFindAccelerator (strName
);
197 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
199 // TODO: What does this do?
200 XmString accel_str
= wxFindAcceleratorText (strName
);
203 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
204 XmStringFree (accel_str
);
208 XtAddCallback ((Widget
) m_buttonWidget
,
209 XmNvalueChangedCallback
,
210 (XtCallbackProc
) wxMenuItemCallback
,
213 XtAddCallback ((Widget
) m_buttonWidget
,
215 (XtCallbackProc
) wxMenuItemCallback
,
217 XtAddCallback ((Widget
) m_buttonWidget
,
219 (XtCallbackProc
) wxMenuItemArmCallback
,
221 XtAddCallback ((Widget
) m_buttonWidget
,
223 (XtCallbackProc
) wxMenuItemDisarmCallback
,
226 else if (GetId() == -1)
228 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget ("separator",
229 xmSeparatorGadgetClass
, (Widget
) menu
, NULL
);
233 m_buttonWidget
= m_subMenu
->CreateMenu (menuBar
, menu
, topMenu
, m_text
, TRUE
);
234 m_subMenu
->SetButtonWidget(m_buttonWidget
);
235 XtAddCallback ((Widget
) m_buttonWidget
,
236 XmNcascadingCallback
,
237 (XtCallbackProc
) wxMenuItemArmCallback
,
241 XtSetSensitive ((Widget
) m_buttonWidget
, (Boolean
) IsEnabled());
244 void wxMenuItem::DestroyItem(bool full
)
251 else if ((!m_text
.IsNull() && (m_text
!= "")) && !m_subMenu
)
256 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNvalueChangedCallback
,
257 wxMenuItemCallback
, (XtPointer
) this);
259 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNactivateCallback
,
260 wxMenuItemCallback
, (XtPointer
) this);
261 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNarmCallback
,
262 wxMenuItemArmCallback
, (XtPointer
) this);
263 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNdisarmCallback
,
264 wxMenuItemDisarmCallback
, (XtPointer
) this);
267 else if (GetId() == -1)
272 else if (GetSubMenu())
276 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNcascadingCallback
,
277 wxMenuItemArmCallback
, (XtPointer
) this);
279 m_subMenu
->DestroyMenu(full
);
281 m_buttonWidget
= NULL
;
284 if (m_buttonWidget
&& full
)
286 XtDestroyWidget ((Widget
) m_buttonWidget
);
287 m_buttonWidget
= (WXWidget
) 0;
291 void wxMenuItem::SetText(const wxString
& label
)
293 char mnem
= wxFindMnemonic (label
);
294 wxString label2
= wxStripMenuCodes(label
);
300 wxXmString
label_str(label2
);
301 XtVaSetValues ((Widget
) m_buttonWidget
,
302 XmNlabelString
, label_str(),
305 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
306 char *accel
= wxFindAccelerator (label2
);
308 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
310 XmString accel_str
= wxFindAcceleratorText (label2
);
313 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
314 XmStringFree (accel_str
);
319 // ----------------------------------------------------------------------------
321 // ----------------------------------------------------------------------------
323 void wxMenuItemCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
324 XtPointer
WXUNUSED(ptr
))
326 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
329 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
330 event
.SetInt( item
->GetId() );
332 if (item
->IsCheckable())
334 Boolean isChecked
= FALSE
;
335 XtVaGetValues ((Widget
) item
->GetButtonWidget(),
339 // only set the flag, don't actually check anything
340 item
->wxMenuItemBase::Check(isChecked
);
341 event
.SetInt(isChecked
);
344 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
346 event
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
348 item
->GetMenuBar()->GetMenuBarFrame()
349 ->GetEventHandler()->ProcessEvent(event
);
351 // this is the child of a popup menu
352 else if (item
->GetTopMenu())
354 event
.SetEventObject(item
->GetTopMenu());
356 item
->GetTopMenu()->ProcessCommand (event
);
358 // Since PopupMenu under Motif still grab right mouse
359 // button events after it was closed, we need to delete
360 // the associated widgets to allow next PopUpMenu to
361 // appear; this needs to be done there because doing it in
362 // a WorkProc as before may cause crashes if a menu item causes
363 // the parent window of the menu to be destroyed
364 item
->GetTopMenu()->DestroyWidgetAndDetach();
369 void wxMenuItemArmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
370 XtPointer
WXUNUSED(ptr
))
372 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
375 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
377 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, item
->GetId());
378 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
380 item
->GetMenuBar()->GetMenuBarFrame()
381 ->GetEventHandler()->ProcessEvent(menuEvent
);
387 wxMenuItemDisarmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
388 XtPointer
WXUNUSED(ptr
))
390 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
393 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
395 // TODO: not sure this is correct, since -1 means something
396 // special to event system
397 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, -1);
398 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
400 item
->GetMenuBar()->GetMenuBarFrame()
401 ->GetEventHandler()->ProcessEvent(menuEvent
);