1 ///////////////////////////////////////////////////////////////////////////////
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"
26 #include "wx/menuitem.h"
31 #pragma message disable nosimpint
34 #include <Xm/LabelG.h>
35 #include <Xm/CascadeBG.h>
36 #include <Xm/CascadeB.h>
37 #include <Xm/SeparatoG.h>
38 #include <Xm/PushBG.h>
39 #include <Xm/ToggleB.h>
40 #include <Xm/ToggleBG.h>
41 #include <Xm/RowColumn.h>
43 #pragma message enable nosimpint
46 #include "wx/motif/private.h"
48 // ----------------------------------------------------------------------------
49 // functions prototypes
50 // ----------------------------------------------------------------------------
52 static void wxMenuItemCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
53 static void wxMenuItemArmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
54 static void wxMenuItemDisarmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
56 // ============================================================================
58 // ============================================================================
60 // ----------------------------------------------------------------------------
61 // dynamic classes implementation
62 // ----------------------------------------------------------------------------
64 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
73 wxMenuItem::wxMenuItem(wxMenu
*pParentMenu
,
75 const wxString
& strName
,
76 const wxString
& strHelp
,
79 : wxMenuItemBase(pParentMenu
, id
, strName
, strHelp
, kind
, pSubMenu
)
83 m_buttonWidget
= (WXWidget
) NULL
;
87 wxMenuItem::~wxMenuItem()
94 void wxMenuItem::Enable(bool bDoEnable
)
96 if ( m_isEnabled
!= bDoEnable
)
102 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
106 // Maybe we should apply this to all items in the submenu?
107 // Or perhaps it works anyway.
109 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
112 wxMenuItemBase::Enable(bDoEnable
);
116 void wxMenuItem::Check(bool bDoCheck
)
118 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
120 if ( m_isChecked
!= bDoCheck
)
122 if ( m_buttonWidget
)
124 wxASSERT_MSG( XtIsSubclass((Widget
)m_buttonWidget
,
125 xmToggleButtonGadgetClass
),
126 wxT("checkable menu item must be a toggle button") );
128 XtVaSetValues((Widget
)m_buttonWidget
,
129 XmNset
, (Boolean
)bDoCheck
,
133 wxMenuItemBase::Check(bDoCheck
);
138 wxString
wxMenuItemBase::GetLabelFromText(const wxString
& text
)
140 return wxStripMenuCodes(text
);
143 // ----------------------------------------------------------------------------
145 // ----------------------------------------------------------------------------
147 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
149 const wxString
& name
,
150 const wxString
& help
,
154 return new wxMenuItem(parentMenu
, id
, name
, help
, kind
, subMenu
);
157 // ----------------------------------------------------------------------------
159 // ----------------------------------------------------------------------------
161 void wxMenuItem::CreateItem (WXWidget menu
, wxMenuBar
* menuBar
,
162 wxMenu
* topMenu
, size_t index
)
169 // Id=-3 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
,
181 #ifdef XmNpositionIndex
182 XmNpositionIndex
, index
,
185 XtVaSetValues ((Widget
) m_buttonWidget
, XmNset
, (Boolean
) IsChecked(), NULL
);
188 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
189 xmPushButtonGadgetClass
, (Widget
) menu
,
190 #ifdef XmNpositionIndex
191 XmNpositionIndex
, index
,
194 char mnem
= wxFindMnemonic (m_text
);
196 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
198 //// TODO: proper accelerator treatment. What does wxFindAccelerator
201 char *accel
= wxFindAccelerator (strName
);
203 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
205 // TODO: What does this do?
206 XmString accel_str
= wxFindAcceleratorText (strName
);
209 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
210 XmStringFree (accel_str
);
214 XtAddCallback ((Widget
) m_buttonWidget
,
215 XmNvalueChangedCallback
,
216 (XtCallbackProc
) wxMenuItemCallback
,
219 XtAddCallback ((Widget
) m_buttonWidget
,
221 (XtCallbackProc
) wxMenuItemCallback
,
223 XtAddCallback ((Widget
) m_buttonWidget
,
225 (XtCallbackProc
) wxMenuItemArmCallback
,
227 XtAddCallback ((Widget
) m_buttonWidget
,
229 (XtCallbackProc
) wxMenuItemDisarmCallback
,
232 else if (GetId() == wxID_SEPARATOR
)
234 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget ("separator",
235 xmSeparatorGadgetClass
, (Widget
) menu
,
236 #ifndef XmNpositionIndex
237 XmNpositionIndex
, index
,
243 m_buttonWidget
= m_subMenu
->CreateMenu (menuBar
, menu
, topMenu
, index
, m_text
, true);
244 m_subMenu
->SetButtonWidget(m_buttonWidget
);
245 XtAddCallback ((Widget
) m_buttonWidget
,
246 XmNcascadingCallback
,
247 (XtCallbackProc
) wxMenuItemArmCallback
,
251 XtSetSensitive ((Widget
) m_buttonWidget
, (Boolean
) IsEnabled());
254 void wxMenuItem::DestroyItem(bool full
)
261 else if ((!m_text
.IsNull() && (m_text
!= "")) && !m_subMenu
)
266 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNvalueChangedCallback
,
267 wxMenuItemCallback
, (XtPointer
) this);
269 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNactivateCallback
,
270 wxMenuItemCallback
, (XtPointer
) this);
271 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNarmCallback
,
272 wxMenuItemArmCallback
, (XtPointer
) this);
273 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNdisarmCallback
,
274 wxMenuItemDisarmCallback
, (XtPointer
) this);
277 else if (GetId() == wxID_SEPARATOR
)
282 else if (GetSubMenu())
286 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNcascadingCallback
,
287 wxMenuItemArmCallback
, (XtPointer
) this);
289 m_subMenu
->DestroyMenu(full
);
291 m_buttonWidget
= NULL
;
294 if (m_buttonWidget
&& full
)
296 XtDestroyWidget ((Widget
) m_buttonWidget
);
297 m_buttonWidget
= (WXWidget
) 0;
301 void wxMenuItem::SetText(const wxString
& label
)
303 char mnem
= wxFindMnemonic (label
);
304 wxString label2
= wxStripMenuCodes(label
);
310 wxXmString
label_str(label2
);
311 XtVaSetValues ((Widget
) m_buttonWidget
,
312 XmNlabelString
, label_str(),
315 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
316 char *accel
= wxFindAccelerator (label2
);
318 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
320 XmString accel_str
= wxFindAcceleratorText (label2
);
323 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
324 XmStringFree (accel_str
);
329 // ----------------------------------------------------------------------------
331 // ----------------------------------------------------------------------------
333 void wxMenuItemCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
334 XtPointer
WXUNUSED(ptr
))
336 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
339 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
340 event
.SetInt( item
->GetId() );
342 if (item
->IsCheckable())
344 Boolean isChecked
= false;
345 XtVaGetValues ((Widget
) item
->GetButtonWidget(),
349 // only set the flag, don't actually check anything
350 item
->wxMenuItemBase::Check(isChecked
);
351 event
.SetInt(isChecked
);
354 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
356 event
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
358 item
->GetMenuBar()->GetMenuBarFrame()
359 ->GetEventHandler()->ProcessEvent(event
);
361 // this is the child of a popup menu
362 else if (item
->GetTopMenu())
364 event
.SetEventObject(item
->GetTopMenu());
366 item
->GetTopMenu()->ProcessCommand (event
);
368 // Since PopupMenu under Motif still grab right mouse
369 // button events after it was closed, we need to delete
370 // the associated widgets to allow next PopUpMenu to
371 // appear; this needs to be done there because doing it in
372 // a WorkProc as before may cause crashes if a menu item causes
373 // the parent window of the menu to be destroyed
374 item
->GetTopMenu()->DestroyWidgetAndDetach();
379 void wxMenuItemArmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
380 XtPointer
WXUNUSED(ptr
))
382 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
385 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
387 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, item
->GetId());
388 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
390 item
->GetMenuBar()->GetMenuBarFrame()
391 ->GetEventHandler()->ProcessEvent(menuEvent
);
397 wxMenuItemDisarmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
398 XtPointer
WXUNUSED(ptr
))
400 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
403 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
405 // TODO: not sure this is correct, since -1 means something
406 // special to event system
407 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, -1);
408 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
410 item
->GetMenuBar()->GetMenuBarFrame()
411 ->GetEventHandler()->ProcessEvent(menuEvent
);