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"
24 #include "wx/menuitem.h"
29 #pragma message disable nosimpint
32 #include <Xm/LabelG.h>
33 #include <Xm/CascadeBG.h>
34 #include <Xm/CascadeB.h>
35 #include <Xm/SeparatoG.h>
36 #include <Xm/PushBG.h>
37 #include <Xm/ToggleB.h>
38 #include <Xm/ToggleBG.h>
39 #include <Xm/RowColumn.h>
41 #pragma message enable nosimpint
44 #include "wx/motif/private.h"
46 // ----------------------------------------------------------------------------
47 // functions prototypes
48 // ----------------------------------------------------------------------------
50 static void wxMenuItemCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
51 static void wxMenuItemArmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
52 static void wxMenuItemDisarmCallback(Widget w
, XtPointer clientData
, XtPointer ptr
);
54 // ============================================================================
56 // ============================================================================
58 // ----------------------------------------------------------------------------
59 // dynamic classes implementation
60 // ----------------------------------------------------------------------------
62 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
71 wxMenuItem::wxMenuItem(wxMenu
*pParentMenu
,
73 const wxString
& strName
,
74 const wxString
& strHelp
,
77 : wxMenuItemBase(pParentMenu
, id
, strName
, strHelp
, kind
, pSubMenu
)
81 m_buttonWidget
= (WXWidget
) NULL
;
85 wxMenuItem::~wxMenuItem()
92 void wxMenuItem::Enable(bool bDoEnable
)
94 if ( m_isEnabled
!= bDoEnable
)
100 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
104 // Maybe we should apply this to all items in the submenu?
105 // Or perhaps it works anyway.
107 XtSetSensitive( (Widget
) m_buttonWidget
, (Boolean
) bDoEnable
);
110 wxMenuItemBase::Enable(bDoEnable
);
114 void wxMenuItem::Check(bool bDoCheck
)
116 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
118 if ( m_isChecked
!= bDoCheck
)
120 if ( m_buttonWidget
)
122 wxASSERT_MSG( XtIsSubclass((Widget
)m_buttonWidget
,
123 xmToggleButtonGadgetClass
),
124 wxT("checkable menu item must be a toggle button") );
126 XtVaSetValues((Widget
)m_buttonWidget
,
127 XmNset
, (Boolean
)bDoCheck
,
131 wxMenuItemBase::Check(bDoCheck
);
136 wxString
wxMenuItemBase::GetLabelFromText(const wxString
& text
)
138 return wxStripMenuCodes(text
);
141 // ----------------------------------------------------------------------------
143 // ----------------------------------------------------------------------------
145 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
147 const wxString
& name
,
148 const wxString
& help
,
152 return new wxMenuItem(parentMenu
, id
, name
, help
, kind
, subMenu
);
155 // ----------------------------------------------------------------------------
157 // ----------------------------------------------------------------------------
159 void wxMenuItem::CreateItem (WXWidget menu
, wxMenuBar
* menuBar
,
160 wxMenu
* topMenu
, size_t index
)
167 // Id=-3 identifies a Title item.
168 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget
169 (wxStripMenuCodes(m_text
),
170 xmLabelGadgetClass
, (Widget
) menu
, NULL
);
172 else if (!m_text
.empty() && !m_subMenu
)
174 wxString strName
= wxStripMenuCodes(m_text
);
177 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
178 xmToggleButtonGadgetClass
, (Widget
) menu
,
179 #ifdef XmNpositionIndex
180 XmNpositionIndex
, index
,
183 XtVaSetValues ((Widget
) m_buttonWidget
, XmNset
, (Boolean
) IsChecked(), NULL
);
186 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget (strName
,
187 xmPushButtonGadgetClass
, (Widget
) menu
,
188 #ifdef XmNpositionIndex
189 XmNpositionIndex
, index
,
192 char mnem
= wxFindMnemonic (m_text
);
194 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
196 //// TODO: proper accelerator treatment. What does wxFindAccelerator
199 char *accel
= wxFindAccelerator (strName
);
201 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
203 // TODO: What does this do?
204 XmString accel_str
= wxFindAcceleratorText (strName
);
207 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
208 XmStringFree (accel_str
);
212 XtAddCallback ((Widget
) m_buttonWidget
,
213 XmNvalueChangedCallback
,
214 (XtCallbackProc
) wxMenuItemCallback
,
217 XtAddCallback ((Widget
) m_buttonWidget
,
219 (XtCallbackProc
) wxMenuItemCallback
,
221 XtAddCallback ((Widget
) m_buttonWidget
,
223 (XtCallbackProc
) wxMenuItemArmCallback
,
225 XtAddCallback ((Widget
) m_buttonWidget
,
227 (XtCallbackProc
) wxMenuItemDisarmCallback
,
230 else if (GetId() == wxID_SEPARATOR
)
232 m_buttonWidget
= (WXWidget
) XtVaCreateManagedWidget ("separator",
233 xmSeparatorGadgetClass
, (Widget
) menu
,
234 #ifndef XmNpositionIndex
235 XmNpositionIndex
, index
,
241 m_buttonWidget
= m_subMenu
->CreateMenu (menuBar
, menu
, topMenu
, index
, m_text
, true);
242 m_subMenu
->SetButtonWidget(m_buttonWidget
);
243 XtAddCallback ((Widget
) m_buttonWidget
,
244 XmNcascadingCallback
,
245 (XtCallbackProc
) wxMenuItemArmCallback
,
249 XtSetSensitive ((Widget
) m_buttonWidget
, (Boolean
) IsEnabled());
252 void wxMenuItem::DestroyItem(bool full
)
259 else if (!m_text
.empty() && !m_subMenu
)
264 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNvalueChangedCallback
,
265 wxMenuItemCallback
, (XtPointer
) this);
267 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNactivateCallback
,
268 wxMenuItemCallback
, (XtPointer
) this);
269 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNarmCallback
,
270 wxMenuItemArmCallback
, (XtPointer
) this);
271 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNdisarmCallback
,
272 wxMenuItemDisarmCallback
, (XtPointer
) this);
275 else if (GetId() == wxID_SEPARATOR
)
280 else if (GetSubMenu())
284 XtRemoveCallback ((Widget
) m_buttonWidget
, XmNcascadingCallback
,
285 wxMenuItemArmCallback
, (XtPointer
) this);
287 m_subMenu
->DestroyMenu(full
);
289 m_buttonWidget
= NULL
;
292 if (m_buttonWidget
&& full
)
294 XtDestroyWidget ((Widget
) m_buttonWidget
);
295 m_buttonWidget
= (WXWidget
) 0;
299 void wxMenuItem::SetText(const wxString
& label
)
301 char mnem
= wxFindMnemonic (label
);
302 wxString label2
= wxStripMenuCodes(label
);
308 wxXmString
label_str(label2
);
309 XtVaSetValues ((Widget
) m_buttonWidget
,
310 XmNlabelString
, label_str(),
313 XtVaSetValues ((Widget
) m_buttonWidget
, XmNmnemonic
, mnem
, NULL
);
314 char *accel
= wxFindAccelerator (label2
);
316 XtVaSetValues ((Widget
) m_buttonWidget
, XmNaccelerator
, accel
, NULL
);
318 XmString accel_str
= wxFindAcceleratorText (label2
);
321 XtVaSetValues ((Widget
) m_buttonWidget
, XmNacceleratorText
, accel_str
, NULL
);
322 XmStringFree (accel_str
);
327 // ----------------------------------------------------------------------------
329 // ----------------------------------------------------------------------------
331 void wxMenuItemCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
332 XtPointer
WXUNUSED(ptr
))
334 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
337 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
338 event
.SetInt( item
->GetId() );
340 if (item
->IsCheckable())
342 Boolean isChecked
= false;
343 XtVaGetValues ((Widget
) item
->GetButtonWidget(),
347 // only set the flag, don't actually check anything
348 item
->wxMenuItemBase::Check(isChecked
);
349 event
.SetInt(isChecked
);
352 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
354 event
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
356 item
->GetMenuBar()->GetMenuBarFrame()
357 ->GetEventHandler()->ProcessEvent(event
);
359 // this is the child of a popup menu
360 else if (item
->GetTopMenu())
362 event
.SetEventObject(item
->GetTopMenu());
364 item
->GetTopMenu()->ProcessCommand (event
);
366 // Since PopupMenu under Motif still grab right mouse
367 // button events after it was closed, we need to delete
368 // the associated widgets to allow next PopUpMenu to
369 // appear; this needs to be done there because doing it in
370 // a WorkProc as before may cause crashes if a menu item causes
371 // the parent window of the menu to be destroyed
372 item
->GetTopMenu()->DestroyWidgetAndDetach();
377 void wxMenuItemArmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
378 XtPointer
WXUNUSED(ptr
))
380 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
383 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
385 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, item
->GetId());
386 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
388 item
->GetMenuBar()->GetMenuBarFrame()
389 ->GetEventHandler()->ProcessEvent(menuEvent
);
395 wxMenuItemDisarmCallback (Widget
WXUNUSED(w
), XtPointer clientData
,
396 XtPointer
WXUNUSED(ptr
))
398 wxMenuItem
*item
= (wxMenuItem
*) clientData
;
401 if (item
->GetMenuBar() && item
->GetMenuBar()->GetMenuBarFrame())
403 // TODO: not sure this is correct, since -1 means something
404 // special to event system
405 wxMenuEvent
menuEvent(wxEVT_MENU_HIGHLIGHT
, -1);
406 menuEvent
.SetEventObject(item
->GetMenuBar()->GetMenuBarFrame());
408 item
->GetMenuBar()->GetMenuBarFrame()
409 ->GetEventHandler()->ProcessEvent(menuEvent
);