1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/menuitem.cpp
3 // Purpose: wxMenuItem implementation
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #include "wx/menuitem.h"
24 #include "wx/stockitem.h"
33 #pragma message disable nosimpint
36 #include <Xm/LabelG.h>
37 #include <Xm/CascadeBG.h>
38 #include <Xm/CascadeB.h>
39 #include <Xm/SeparatoG.h>
40 #include <Xm/PushBG.h>
41 #include <Xm/ToggleB.h>
42 #include <Xm/ToggleBG.h>
43 #include <Xm/RowColumn.h>
45 #pragma message enable nosimpint
48 #include "wx/motif/private.h"
50 // ----------------------------------------------------------------------------
51 // functions prototypes
52 // ----------------------------------------------------------------------------
54 static void wxMenuItemCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
55 static void wxMenuItemArmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
56 static void wxMenuItemDisarmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
58 // ============================================================================
60 // ============================================================================
62 // ----------------------------------------------------------------------------
63 // dynamic classes implementation
64 // ----------------------------------------------------------------------------
66 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
75 wxMenuItem::wxMenuItem(wxMenu
*pParentMenu
,
77 const wxString
& strName
,
78 const wxString
& strHelp
,
81 : wxMenuItemBase(pParentMenu
, id
, strName
, strHelp
, kind
, pSubMenu
)
85 m_buttonWidget
= (WXWidget
) NULL
;
89 wxMenuItem::~wxMenuItem()
96 void wxMenuItem::Enable(bool bDoEnable
)
98 if ( m_isEnabled
!= bDoEnable
)
104 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
108 // Maybe we should apply this to all items in the submenu?
109 // Or perhaps it works anyway.
111 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
114 wxMenuItemBase::Enable(bDoEnable
);
118 void wxMenuItem::Check(bool bDoCheck
)
120 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
122 if ( m_isChecked
!= bDoCheck
)
124 if ( m_buttonWidget
)
126 wxASSERT_MSG( XtIsSubclass((Widget
)m_buttonWidget
,
127 xmToggleButtonGadgetClass
),
128 wxT("checkable menu item must be a toggle button") );
130 XtVaSetValues((Widget
)m_buttonWidget
,
131 XmNset
, (Boolean
)bDoCheck
,
135 wxMenuItemBase::Check(bDoCheck
);
140 wxString
wxMenuItemBase::GetLabelText(const wxString
& text
)
142 return wxStripMenuCodes(text
);
145 // ----------------------------------------------------------------------------
147 // ----------------------------------------------------------------------------
149 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
151 const wxString
& name
,
152 const wxString
& help
,
156 return new wxMenuItem(parentMenu
, id
, name
, help
, kind
, subMenu
);
159 // ----------------------------------------------------------------------------
161 // ----------------------------------------------------------------------------
163 void wxMenuItem::CreateItem (WXWidget menu
, wxMenuBar
* menuBar
,
164 wxMenu
* topMenu
, size_t index
)
171 // Id=-3 identifies a Title item.
172 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget
173 (wxStripMenuCodes(m_text
),
174 xmLabelGadgetClass
, (Widget
) menu
, NULL
);
176 else if (!IsSeparator() && !m_subMenu
)
178 wxString txt
= m_text
;
180 if (m_text
.IsEmpty())
182 wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
183 txt
= wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR
|wxSTOCK_WITH_MNEMONIC
);
186 wxString strName
= wxStripMenuCodes(txt
);
189 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
190 xmToggleButtonGadgetClass
, (Widget
) menu
,
191 #ifdef XmNpositionIndex
192 XmNpositionIndex
, index
,
195 XtVaSetValues ((Widget
) m_buttonWidget
, XmNset
, (Boolean
) IsChecked(), NULL
);
198 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
199 xmPushButtonGadgetClass
, (Widget
) menu
,
200 #ifdef XmNpositionIndex
201 XmNpositionIndex
, index
,
204 char mnem
= wxFindMnemonic (m_text
);
206 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
208 //// TODO: proper accelerator treatment. What does wxFindAccelerator
211 char *accel
= wxFindAccelerator (strName
);
213 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
215 // TODO: What does this do?
216 XmString accel_str
= wxFindAcceleratorText (strName
);
219 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
220 XmStringFree (accel_str
);
224 XtAddCallback ((Widget
) m_buttonWidget
,
225 XmNvalueChangedCallback
,
226 (XtCallbackProc
) wxMenuItemCallback
,
229 XtAddCallback ((Widget
) m_buttonWidget
,
231 (XtCallbackProc
) wxMenuItemCallback
,
233 XtAddCallback ((Widget
) m_buttonWidget
,
235 (XtCallbackProc
) wxMenuItemArmCallback
,
237 XtAddCallback ((Widget
) m_buttonWidget
,
239 (XtCallbackProc
) wxMenuItemDisarmCallback
,
242 else if (IsSeparator())
244 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget ("separator",
245 xmSeparatorGadgetClass
, (Widget
) menu
,
246 #ifndef XmNpositionIndex
247 XmNpositionIndex
, index
,
253 m_buttonWidget
= m_subMenu
->CreateMenu (menuBar
, menu
, topMenu
, index
, m_text
, true);
254 m_subMenu
->SetButtonWidget(m_buttonWidget
);
255 XtAddCallback ((Widget
) m_buttonWidget
,
256 XmNcascadingCallback
,
257 (XtCallbackProc
) wxMenuItemArmCallback
,
261 XtSetSensitive ((Widget
) m_buttonWidget
, (Boolean
) IsEnabled());
264 void wxMenuItem::DestroyItem(bool full
)
271 else if (!m_text
.empty() && !m_subMenu
)
276 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNvalueChangedCallback
,
277 wxMenuItemCallback
, (XtPointer
) this);
279 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNactivateCallback
,
280 wxMenuItemCallback
, (XtPointer
) this);
281 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNarmCallback
,
282 wxMenuItemArmCallback
, (XtPointer
) this);
283 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNdisarmCallback
,
284 wxMenuItemDisarmCallback
, (XtPointer
) this);
287 else if (IsSeparator())
292 else if (GetSubMenu())
296 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNcascadingCallback
,
297 wxMenuItemArmCallback
, (XtPointer
) this);
299 m_subMenu
->DestroyMenu(full
);
301 m_buttonWidget
= NULL
;
304 if (m_buttonWidget
&& full
)
306 XtDestroyWidget ((Widget
) m_buttonWidget
);
307 m_buttonWidget
= (WXWidget
) 0;
311 void wxMenuItem::SetItemLabel(const wxString
& label
)
313 char mnem
= wxFindMnemonic (label
);
314 wxString label2
= wxStripMenuCodes(label
);
320 wxXmString
label_str(label2
);
321 XtVaSetValues ((Widget
) m_buttonWidget
,
322 XmNlabelString
, label_str(),
325 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
326 char *accel
= wxFindAccelerator (label2
);
328 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
330 XmString accel_str
= wxFindAcceleratorText (label2
);
333 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
334 XmStringFree (accel_str
);
339 // ----------------------------------------------------------------------------
341 // ----------------------------------------------------------------------------
343 void wxMenuItemCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
344 XtPointer
WXUNUSED(ptr
))
346 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
349 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
350 event
.SetInt( item
->GetId() );
352 if (item
->IsCheckable())
354 Boolean isChecked
= false;
355 XtVaGetValues ((Widget
) item
->GetButtonWidget(),
359 // only set the flag, don't actually check anything
360 item
->wxMenuItemBase::Check(isChecked
);
361 event
.SetInt(isChecked
);
364 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
366 event
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
368 item
->GetMenuBar()->GetMenuBarFrame()
369 ->HandleWindowEvent(event
);
371 // this is the child of a popup menu
372 else if (item
->GetTopMenu())
374 event
.SetEventObject(item
->GetTopMenu());
376 item
->GetTopMenu()->ProcessCommand (event
);
378 // Since PopupMenu under Motif still grab right mouse
379 // button events after it was closed, we need to delete
380 // the associated widgets to allow next PopUpMenu to
381 // appear; this needs to be done there because doing it in
382 // a WorkProc as before may cause crashes if a menu item causes
383 // the parent window of the menu to be destroyed
384 item
->GetTopMenu()->DestroyWidgetAndDetach();
389 void wxMenuItemArmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
390 XtPointer
WXUNUSED(ptr
))
392 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
395 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
397 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, item
->GetId());
398 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
400 item
->GetMenuBar()->GetMenuBarFrame()
401 ->HandleWindowEvent(menuEvent
);
407 wxMenuItemDisarmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
408 XtPointer
WXUNUSED(ptr
))
410 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
413 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
415 // TODO: not sure this is correct, since -1 means something
416 // special to event system
417 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, -1);
418 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
420 item
->GetMenuBar()->GetMenuBarFrame()
421 ->HandleWindowEvent(menuEvent
);