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 // ----------------------------------------------------------------------------
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
30 #include "wx/menuitem.h"
35 #pragma message disable nosimpint
38 #include <Xm/LabelG.h>
39 #include <Xm/CascadeBG.h>
40 #include <Xm/CascadeB.h>
41 #include <Xm/SeparatoG.h>
42 #include <Xm/PushBG.h>
43 #include <Xm/ToggleB.h>
44 #include <Xm/ToggleBG.h>
45 #include <Xm/RowColumn.h>
47 #pragma message enable nosimpint
50 #include "wx/motif/private.h"
52 // ----------------------------------------------------------------------------
53 // functions prototypes
54 // ----------------------------------------------------------------------------
56 static void wxMenuItemCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
57 static void wxMenuItemArmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
58 static void wxMenuItemDisarmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
60 // ============================================================================
62 // ============================================================================
64 // ----------------------------------------------------------------------------
65 // dynamic classes implementation
66 // ----------------------------------------------------------------------------
68 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
77 wxMenuItem::wxMenuItem(wxMenu
*pParentMenu
,
79 const wxString
& strName
,
80 const wxString
& strHelp
,
83 : wxMenuItemBase(pParentMenu
, id
, strName
, strHelp
, kind
, pSubMenu
)
87 m_buttonWidget
= (WXWidget
) NULL
;
91 wxMenuItem::~wxMenuItem()
98 void wxMenuItem::Enable(bool bDoEnable
)
100 if ( m_isEnabled
!= bDoEnable
)
106 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
110 // Maybe we should apply this to all items in the submenu?
111 // Or perhaps it works anyway.
113 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
116 wxMenuItemBase::Enable(bDoEnable
);
120 void wxMenuItem::Check(bool bDoCheck
)
122 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
124 if ( m_isChecked
!= bDoCheck
)
126 if ( m_buttonWidget
)
128 wxASSERT_MSG( XtIsSubclass((Widget
)m_buttonWidget
,
129 xmToggleButtonGadgetClass
),
130 wxT("checkable menu item must be a toggle button") );
132 XtVaSetValues((Widget
)m_buttonWidget
,
133 XmNset
, (Boolean
)bDoCheck
,
137 wxMenuItemBase::Check(bDoCheck
);
142 wxString
wxMenuItemBase::GetLabelFromText(const wxString
& text
)
144 return wxStripMenuCodes(text
);
147 // ----------------------------------------------------------------------------
149 // ----------------------------------------------------------------------------
151 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
153 const wxString
& name
,
154 const wxString
& help
,
158 return new wxMenuItem(parentMenu
, id
, name
, help
, kind
, subMenu
);
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 void wxMenuItem::CreateItem (WXWidget menu
, wxMenuBar
* menuBar
, wxMenu
* topMenu
)
172 // Id=-3 identifies a Title item.
173 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget
174 (wxStripMenuCodes(m_text
),
175 xmLabelGadgetClass
, (Widget
) menu
, NULL
);
177 else if ((!m_text
.IsNull() && m_text
!= "") && (!m_subMenu
))
179 wxString strName
= wxStripMenuCodes(m_text
);
182 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
183 xmToggleButtonGadgetClass
, (Widget
) menu
,
185 XtVaSetValues ((Widget
) m_buttonWidget
, XmNset
, (Boolean
) IsChecked(), NULL
);
188 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
189 xmPushButtonGadgetClass
, (Widget
) menu
,
191 char mnem
= wxFindMnemonic (m_text
);
193 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
195 //// TODO: proper accelerator treatment. What does wxFindAccelerator
198 char *accel
= wxFindAccelerator (strName
);
200 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
202 // TODO: What does this do?
203 XmString accel_str
= wxFindAcceleratorText (strName
);
206 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
207 XmStringFree (accel_str
);
211 XtAddCallback ((Widget
) m_buttonWidget
,
212 XmNvalueChangedCallback
,
213 (XtCallbackProc
) wxMenuItemCallback
,
216 XtAddCallback ((Widget
) m_buttonWidget
,
218 (XtCallbackProc
) wxMenuItemCallback
,
220 XtAddCallback ((Widget
) m_buttonWidget
,
222 (XtCallbackProc
) wxMenuItemArmCallback
,
224 XtAddCallback ((Widget
) m_buttonWidget
,
226 (XtCallbackProc
) wxMenuItemDisarmCallback
,
229 else if (GetId() == wxID_SEPARATOR
)
231 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget ("separator",
232 xmSeparatorGadgetClass
, (Widget
) menu
, NULL
);
236 m_buttonWidget
= m_subMenu
->CreateMenu (menuBar
, menu
, topMenu
, m_text
, true);
237 m_subMenu
->SetButtonWidget(m_buttonWidget
);
238 XtAddCallback ((Widget
) m_buttonWidget
,
239 XmNcascadingCallback
,
240 (XtCallbackProc
) wxMenuItemArmCallback
,
244 XtSetSensitive ((Widget
) m_buttonWidget
, (Boolean
) IsEnabled());
247 void wxMenuItem::DestroyItem(bool full
)
254 else if ((!m_text
.IsNull() && (m_text
!= "")) && !m_subMenu
)
259 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNvalueChangedCallback
,
260 wxMenuItemCallback
, (XtPointer
) this);
262 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNactivateCallback
,
263 wxMenuItemCallback
, (XtPointer
) this);
264 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNarmCallback
,
265 wxMenuItemArmCallback
, (XtPointer
) this);
266 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNdisarmCallback
,
267 wxMenuItemDisarmCallback
, (XtPointer
) this);
270 else if (GetId() == wxID_SEPARATOR
)
275 else if (GetSubMenu())
279 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNcascadingCallback
,
280 wxMenuItemArmCallback
, (XtPointer
) this);
282 m_subMenu
->DestroyMenu(full
);
284 m_buttonWidget
= NULL
;
287 if (m_buttonWidget
&& full
)
289 XtDestroyWidget ((Widget
) m_buttonWidget
);
290 m_buttonWidget
= (WXWidget
) 0;
294 void wxMenuItem::SetText(const wxString
& label
)
296 char mnem
= wxFindMnemonic (label
);
297 wxString label2
= wxStripMenuCodes(label
);
303 wxXmString
label_str(label2
);
304 XtVaSetValues ((Widget
) m_buttonWidget
,
305 XmNlabelString
, label_str(),
308 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
309 char *accel
= wxFindAccelerator (label2
);
311 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
313 XmString accel_str
= wxFindAcceleratorText (label2
);
316 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
317 XmStringFree (accel_str
);
322 // ----------------------------------------------------------------------------
324 // ----------------------------------------------------------------------------
326 void wxMenuItemCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
327 XtPointer
WXUNUSED(ptr
))
329 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
332 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
333 event
.SetInt( item
->GetId() );
335 if (item
->IsCheckable())
337 Boolean isChecked
= false;
338 XtVaGetValues ((Widget
) item
->GetButtonWidget(),
342 // only set the flag, don't actually check anything
343 item
->wxMenuItemBase::Check(isChecked
);
344 event
.SetInt(isChecked
);
347 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
349 event
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
351 item
->GetMenuBar()->GetMenuBarFrame()
352 ->GetEventHandler()->ProcessEvent(event
);
354 // this is the child of a popup menu
355 else if (item
->GetTopMenu())
357 event
.SetEventObject(item
->GetTopMenu());
359 item
->GetTopMenu()->ProcessCommand (event
);
361 // Since PopupMenu under Motif still grab right mouse
362 // button events after it was closed, we need to delete
363 // the associated widgets to allow next PopUpMenu to
364 // appear; this needs to be done there because doing it in
365 // a WorkProc as before may cause crashes if a menu item causes
366 // the parent window of the menu to be destroyed
367 item
->GetTopMenu()->DestroyWidgetAndDetach();
372 void wxMenuItemArmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
373 XtPointer
WXUNUSED(ptr
))
375 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
378 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
380 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, item
->GetId());
381 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
383 item
->GetMenuBar()->GetMenuBarFrame()
384 ->GetEventHandler()->ProcessEvent(menuEvent
);
390 wxMenuItemDisarmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
391 XtPointer
WXUNUSED(ptr
))
393 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
396 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
398 // TODO: not sure this is correct, since -1 means something
399 // special to event system
400 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, -1);
401 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
403 item
->GetMenuBar()->GetMenuBarFrame()
404 ->GetEventHandler()->ProcessEvent(menuEvent
);