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"
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
,
163 wxMenu
* topMenu
, size_t index
)
170 // Id=-3 identifies a Title item.
171 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget
172 (wxStripMenuCodes(m_text
),
173 xmLabelGadgetClass
, (Widget
) menu
, NULL
);
175 else if (!m_text
.empty() && !m_subMenu
)
177 wxString strName
= wxStripMenuCodes(m_text
);
180 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
181 xmToggleButtonGadgetClass
, (Widget
) menu
,
182 #ifdef XmNpositionIndex
183 XmNpositionIndex
, index
,
186 XtVaSetValues ((Widget
) m_buttonWidget
, XmNset
, (Boolean
) IsChecked(), NULL
);
189 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
190 xmPushButtonGadgetClass
, (Widget
) menu
,
191 #ifdef XmNpositionIndex
192 XmNpositionIndex
, index
,
195 char mnem
= wxFindMnemonic (m_text
);
197 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
199 //// TODO: proper accelerator treatment. What does wxFindAccelerator
202 char *accel
= wxFindAccelerator (strName
);
204 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
206 // TODO: What does this do?
207 XmString accel_str
= wxFindAcceleratorText (strName
);
210 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
211 XmStringFree (accel_str
);
215 XtAddCallback ((Widget
) m_buttonWidget
,
216 XmNvalueChangedCallback
,
217 (XtCallbackProc
) wxMenuItemCallback
,
220 XtAddCallback ((Widget
) m_buttonWidget
,
222 (XtCallbackProc
) wxMenuItemCallback
,
224 XtAddCallback ((Widget
) m_buttonWidget
,
226 (XtCallbackProc
) wxMenuItemArmCallback
,
228 XtAddCallback ((Widget
) m_buttonWidget
,
230 (XtCallbackProc
) wxMenuItemDisarmCallback
,
233 else if (GetId() == wxID_SEPARATOR
)
235 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget ("separator",
236 xmSeparatorGadgetClass
, (Widget
) menu
,
237 #ifndef XmNpositionIndex
238 XmNpositionIndex
, index
,
244 m_buttonWidget
= m_subMenu
->CreateMenu (menuBar
, menu
, topMenu
, index
, m_text
, true);
245 m_subMenu
->SetButtonWidget(m_buttonWidget
);
246 XtAddCallback ((Widget
) m_buttonWidget
,
247 XmNcascadingCallback
,
248 (XtCallbackProc
) wxMenuItemArmCallback
,
252 XtSetSensitive ((Widget
) m_buttonWidget
, (Boolean
) IsEnabled());
255 void wxMenuItem::DestroyItem(bool full
)
262 else if (!m_text
.empty() && !m_subMenu
)
267 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNvalueChangedCallback
,
268 wxMenuItemCallback
, (XtPointer
) this);
270 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNactivateCallback
,
271 wxMenuItemCallback
, (XtPointer
) this);
272 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNarmCallback
,
273 wxMenuItemArmCallback
, (XtPointer
) this);
274 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNdisarmCallback
,
275 wxMenuItemDisarmCallback
, (XtPointer
) this);
278 else if (GetId() == wxID_SEPARATOR
)
283 else if (GetSubMenu())
287 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNcascadingCallback
,
288 wxMenuItemArmCallback
, (XtPointer
) this);
290 m_subMenu
->DestroyMenu(full
);
292 m_buttonWidget
= NULL
;
295 if (m_buttonWidget
&& full
)
297 XtDestroyWidget ((Widget
) m_buttonWidget
);
298 m_buttonWidget
= (WXWidget
) 0;
302 void wxMenuItem::SetText(const wxString
& label
)
304 char mnem
= wxFindMnemonic (label
);
305 wxString label2
= wxStripMenuCodes(label
);
311 wxXmString
label_str(label2
);
312 XtVaSetValues ((Widget
) m_buttonWidget
,
313 XmNlabelString
, label_str(),
316 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
317 char *accel
= wxFindAccelerator (label2
);
319 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
321 XmString accel_str
= wxFindAcceleratorText (label2
);
324 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
325 XmStringFree (accel_str
);
330 // ----------------------------------------------------------------------------
332 // ----------------------------------------------------------------------------
334 void wxMenuItemCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
335 XtPointer
WXUNUSED(ptr
))
337 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
340 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
341 event
.SetInt( item
->GetId() );
343 if (item
->IsCheckable())
345 Boolean isChecked
= false;
346 XtVaGetValues ((Widget
) item
->GetButtonWidget(),
350 // only set the flag, don't actually check anything
351 item
->wxMenuItemBase::Check(isChecked
);
352 event
.SetInt(isChecked
);
355 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
357 event
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
359 item
->GetMenuBar()->GetMenuBarFrame()
360 ->GetEventHandler()->ProcessEvent(event
);
362 // this is the child of a popup menu
363 else if (item
->GetTopMenu())
365 event
.SetEventObject(item
->GetTopMenu());
367 item
->GetTopMenu()->ProcessCommand (event
);
369 // Since PopupMenu under Motif still grab right mouse
370 // button events after it was closed, we need to delete
371 // the associated widgets to allow next PopUpMenu to
372 // appear; this needs to be done there because doing it in
373 // a WorkProc as before may cause crashes if a menu item causes
374 // the parent window of the menu to be destroyed
375 item
->GetTopMenu()->DestroyWidgetAndDetach();
380 void wxMenuItemArmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
381 XtPointer
WXUNUSED(ptr
))
383 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
386 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
388 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, item
->GetId());
389 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
391 item
->GetMenuBar()->GetMenuBarFrame()
392 ->GetEventHandler()->ProcessEvent(menuEvent
);
398 wxMenuItemDisarmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
399 XtPointer
WXUNUSED(ptr
))
401 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
404 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
406 // TODO: not sure this is correct, since -1 means something
407 // special to event system
408 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, -1);
409 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
411 item
->GetMenuBar()->GetMenuBarFrame()
412 ->GetEventHandler()->ProcessEvent(menuEvent
);