X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2d120f8391920145647ec10e84629bc21fa9f1bb..02f35bffeb7e26b6163a027b827692ff4851f3b2:/src/motif/menuitem.cpp diff --git a/src/motif/menuitem.cpp b/src/motif/menuitem.cpp index 800ebb8df2..fb12bf8e2e 100644 --- a/src/motif/menuitem.cpp +++ b/src/motif/menuitem.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: menuitem.cpp +// Name: src/motif/menuitem.cpp // Purpose: wxMenuItem implementation // Author: Julian Smart // Modified by: @@ -10,14 +10,28 @@ /////////////////////////////////////////////////////////////////////////////// // ============================================================================ -// headers & declarations +// declarations // ============================================================================ -#include "wx/menu.h" +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + #include "wx/menuitem.h" -#include "wx/utils.h" -#include "wx/frame.h" +#include "wx/stockitem.h" +#ifndef WX_PRECOMP + #include "wx/utils.h" + #include "wx/frame.h" + #include "wx/menu.h" +#endif + +#ifdef __VMS__ +#pragma message disable nosimpint +#endif #include #include #include @@ -27,15 +41,19 @@ #include #include #include +#ifdef __VMS__ +#pragma message enable nosimpint +#endif #include "wx/motif/private.h" -void wxMenuItemCallback (Widget w, XtPointer clientData, - XtPointer ptr); -void wxMenuItemArmCallback (Widget w, XtPointer clientData, - XtPointer ptr); -void wxMenuItemDisarmCallback (Widget w, XtPointer clientData, - XtPointer ptr); +// ---------------------------------------------------------------------------- +// functions prototypes +// ---------------------------------------------------------------------------- + +static void wxMenuItemCallback(Widget w, XtPointer clientData, XtPointer ptr); +static void wxMenuItemArmCallback(Widget w, XtPointer clientData, XtPointer ptr); +static void wxMenuItemDisarmCallback(Widget w, XtPointer clientData, XtPointer ptr); // ============================================================================ // implementation @@ -45,9 +63,7 @@ void wxMenuItemDisarmCallback (Widget w, XtPointer clientData, // dynamic classes implementation // ---------------------------------------------------------------------------- -#if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject) -#endif //USE_SHARED_LIBRARY // ---------------------------------------------------------------------------- // wxMenuItem @@ -56,42 +72,22 @@ IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject) // ctor & dtor // ----------- -wxMenuItem::wxMenuItem(wxMenu *pParentMenu, int id, - const wxString& strName, const wxString& strHelp, - bool bCheckable, - wxMenu *pSubMenu) : -m_strHelp(strHelp), -m_bCheckable(bCheckable), -m_strName(strName) +wxMenuItem::wxMenuItem(wxMenu *pParentMenu, + int id, + const wxString& strName, + const wxString& strHelp, + wxItemKind kind, + wxMenu *pSubMenu) + : wxMenuItemBase(pParentMenu, id, strName, strHelp, kind, pSubMenu) { - wxASSERT( pParentMenu != NULL ); - - m_pParentMenu = pParentMenu; - m_pSubMenu = pSubMenu; - m_idItem = id; - m_bEnabled = TRUE; - m_bChecked = FALSE; - - //// Motif-specific - m_menuBar = NULL; + // Motif-specific + m_menuBar = NULL; m_buttonWidget = (WXWidget) NULL; - m_topMenu = NULL; -} - -wxMenuItem::~wxMenuItem() -{ + m_topMenu = NULL; } -// misc -// ---- - -// delete the sub menu -void wxMenuItem::DeleteSubMenu() +wxMenuItem::~wxMenuItem() { - wxASSERT( m_pSubMenu != NULL ); - - delete m_pSubMenu; - m_pSubMenu = NULL; } // change item state @@ -99,10 +95,11 @@ void wxMenuItem::DeleteSubMenu() void wxMenuItem::Enable(bool bDoEnable) { - if ( m_bEnabled != bDoEnable ) + if ( m_isEnabled != bDoEnable ) { - if ( m_pSubMenu == NULL ) - { // normal menu item + if ( !IsSubMenu() ) + { + // normal menu item if (m_buttonWidget) XtSetSensitive( (Widget) m_buttonWidget, (Boolean) bDoEnable); } @@ -113,73 +110,110 @@ void wxMenuItem::Enable(bool bDoEnable) if (m_buttonWidget) XtSetSensitive( (Widget) m_buttonWidget, (Boolean) bDoEnable); } - - m_bEnabled = bDoEnable; + + wxMenuItemBase::Enable(bDoEnable); } } void wxMenuItem::Check(bool bDoCheck) { wxCHECK_RET( IsCheckable(), "only checkable items may be checked" ); - - if ( m_bChecked != bDoCheck ) + + if ( m_isChecked != bDoCheck ) { - if (m_buttonWidget && XtIsSubclass ((Widget) m_buttonWidget, xmToggleButtonGadgetClass)) + if ( m_buttonWidget ) { - XtVaSetValues ( (Widget) m_buttonWidget, XmNset, (Boolean) bDoCheck, NULL); + wxASSERT_MSG( XtIsSubclass((Widget)m_buttonWidget, + xmToggleButtonGadgetClass), + wxT("checkable menu item must be a toggle button") ); + + XtVaSetValues((Widget)m_buttonWidget, + XmNset, (Boolean)bDoCheck, + NULL); } - m_bChecked = bDoCheck; + + wxMenuItemBase::Check(bDoCheck); } } -//// Motif-specific +// ---------------------------------------------------------------------------- +// wxMenuItemBase +// ---------------------------------------------------------------------------- -void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar, wxMenu * topMenu) +wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu, + int id, + const wxString& name, + const wxString& help, + wxItemKind kind, + wxMenu *subMenu) +{ + return new wxMenuItem(parentMenu, id, name, help, kind, subMenu); +} + +// ---------------------------------------------------------------------------- +// Motif-specific +// ---------------------------------------------------------------------------- + +void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar, + wxMenu * topMenu, size_t index) { m_menuBar = menuBar; m_topMenu = topMenu; - - if (GetId() == -2) + + if (GetId() == -3) { - // Id=-2 identifies a Title item. - wxStripMenuCodes ((char*) (const char*) m_strName, wxBuffer); - m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (wxBuffer, + // Id=-3 identifies a Title item. + m_buttonWidget = (WXWidget) XtVaCreateManagedWidget + (wxStripMenuCodes(m_text), xmLabelGadgetClass, (Widget) menu, NULL); } - else if ((!m_strName.IsNull() && m_strName != "") && (!m_pSubMenu)) + else if (!IsSeparator() && !m_subMenu) { - wxStripMenuCodes ((char*) (const char*) m_strName, wxBuffer); + wxString txt = m_text; + + if (m_text.IsEmpty()) + { + wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?")); + txt = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC); + } + + wxString strName = wxStripMenuCodes(txt); if (IsCheckable()) { - m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (wxBuffer, + m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (strName, xmToggleButtonGadgetClass, (Widget) menu, +#ifdef XmNpositionIndex + XmNpositionIndex, index, +#endif NULL); XtVaSetValues ((Widget) m_buttonWidget, XmNset, (Boolean) IsChecked(), NULL); } else - m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (wxBuffer, + m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (strName, xmPushButtonGadgetClass, (Widget) menu, +#ifdef XmNpositionIndex + XmNpositionIndex, index, +#endif NULL); - char mnem = wxFindMnemonic (m_strName); + char mnem = wxFindMnemonic (m_text); if (mnem != 0) XtVaSetValues ((Widget) m_buttonWidget, XmNmnemonic, mnem, NULL); - + //// TODO: proper accelerator treatment. What does wxFindAccelerator //// look for? - strcpy(wxBuffer, (char*) (const char*) m_strName); - char *accel = wxFindAccelerator (wxBuffer); + strName = m_text; + char *accel = wxFindAccelerator (strName); if (accel) XtVaSetValues ((Widget) m_buttonWidget, XmNaccelerator, accel, NULL); - + // TODO: What does this do? - strcpy(wxBuffer, (char*) (const char*) m_strName); - XmString accel_str = wxFindAcceleratorText (wxBuffer); + XmString accel_str = wxFindAcceleratorText (strName); if (accel_str) { XtVaSetValues ((Widget) m_buttonWidget, XmNacceleratorText, accel_str, NULL); XmStringFree (accel_str); } - + if (IsCheckable()) XtAddCallback ((Widget) m_buttonWidget, XmNvalueChangedCallback, @@ -199,15 +233,19 @@ void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar, wxMenu * topMen (XtCallbackProc) wxMenuItemDisarmCallback, (XtPointer) this); } - else if (GetId() == -1) + else if (IsSeparator()) { m_buttonWidget = (WXWidget) XtVaCreateManagedWidget ("separator", - xmSeparatorGadgetClass, (Widget) menu, NULL); + xmSeparatorGadgetClass, (Widget) menu, +#ifndef XmNpositionIndex + XmNpositionIndex, index, +#endif + NULL); } - else if (m_pSubMenu) + else if (m_subMenu) { - m_buttonWidget = m_pSubMenu->CreateMenu (menuBar, menu, topMenu, m_strName, TRUE); - m_pSubMenu->SetButtonWidget(m_buttonWidget); + m_buttonWidget = m_subMenu->CreateMenu (menuBar, menu, topMenu, index, m_text, true); + m_subMenu->SetButtonWidget(m_buttonWidget); XtAddCallback ((Widget) m_buttonWidget, XmNcascadingCallback, (XtCallbackProc) wxMenuItemArmCallback, @@ -219,12 +257,12 @@ void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar, wxMenu * topMen void wxMenuItem::DestroyItem(bool full) { - if (GetId() == -2) + if (GetId() == -3) { - ; // Nothing - + ; // Nothing + } - else if ((!m_strName.IsNull() && (m_strName != "")) && !m_pSubMenu) + else if (!m_text.empty() && !m_subMenu) { if (m_buttonWidget) { @@ -240,10 +278,10 @@ void wxMenuItem::DestroyItem(bool full) wxMenuItemDisarmCallback, (XtPointer) this); } } - else if (GetId() == -1) + else if (IsSeparator()) { - ; // Nothing - + ; // Nothing + } else if (GetSubMenu()) { @@ -252,11 +290,11 @@ void wxMenuItem::DestroyItem(bool full) XtRemoveCallback ((Widget) m_buttonWidget, XmNcascadingCallback, wxMenuItemArmCallback, (XtPointer) this); } - m_pSubMenu->DestroyMenu(full); + m_subMenu->DestroyMenu(full); if (full) m_buttonWidget = NULL; } - + if (m_buttonWidget && full) { XtDestroyWidget ((Widget) m_buttonWidget); @@ -264,29 +302,26 @@ void wxMenuItem::DestroyItem(bool full) } } -void wxMenuItem::SetLabel(const wxString& label) +void wxMenuItem::SetItemLabel(const wxString& label) { char mnem = wxFindMnemonic (label); - wxStripMenuCodes ((char*) (const char*) label, wxBuffer); - - m_strName = label; - + wxString label2 = wxStripMenuCodes(label); + + m_text = label; + if (m_buttonWidget) { - XmString label_str = XmStringCreateSimple (wxBuffer); + wxXmString label_str(label2); XtVaSetValues ((Widget) m_buttonWidget, - XmNlabelString, label_str, + XmNlabelString, label_str(), NULL); - XmStringFree (label_str); if (mnem != 0) XtVaSetValues ((Widget) m_buttonWidget, XmNmnemonic, mnem, NULL); - strcpy(wxBuffer, (char*) (const char*) label); - char *accel = wxFindAccelerator (wxBuffer); + char *accel = wxFindAccelerator (label2); if (accel) XtVaSetValues ((Widget) m_buttonWidget, XmNaccelerator, accel, NULL); - - strcpy(wxBuffer, (char*) (const char*) label); - XmString accel_str = wxFindAcceleratorText (wxBuffer); + + XmString accel_str = wxFindAcceleratorText (label2); if (accel_str) { XtVaSetValues ((Widget) m_buttonWidget, XmNacceleratorText, accel_str, NULL); @@ -295,39 +330,58 @@ void wxMenuItem::SetLabel(const wxString& label) } } -void wxMenuItemCallback (Widget w, XtPointer clientData, - XtPointer ptr) +// ---------------------------------------------------------------------------- +// Motif callbacks +// ---------------------------------------------------------------------------- + +void wxMenuItemCallback (Widget WXUNUSED(w), XtPointer clientData, + XtPointer WXUNUSED(ptr)) { wxMenuItem *item = (wxMenuItem *) clientData; if (item) { + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, item->GetId()); + event.SetInt( item->GetId() ); + if (item->IsCheckable()) { - Boolean isChecked = FALSE; - XtVaGetValues ((Widget) item->GetButtonWidget(), XmNset, & isChecked, NULL); - item->SetChecked(isChecked); + Boolean isChecked = false; + XtVaGetValues ((Widget) item->GetButtonWidget(), + XmNset, & isChecked, + NULL); + + // only set the flag, don't actually check anything + item->wxMenuItemBase::Check(isChecked); + event.SetInt(isChecked); } + if (item->GetMenuBar() && item->GetMenuBar()->GetMenuBarFrame()) { - wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, item->GetId()); - commandEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame()); - commandEvent.SetInt( item->GetId() ); - - item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(commandEvent); + event.SetEventObject(item->GetMenuBar()->GetMenuBarFrame()); + + item->GetMenuBar()->GetMenuBarFrame() + ->HandleWindowEvent(event); } + // this is the child of a popup menu else if (item->GetTopMenu()) { - wxCommandEvent event (wxEVT_COMMAND_MENU_SELECTED, item->GetId()); event.SetEventObject(item->GetTopMenu()); - event.SetInt( item->GetId() ); - + item->GetTopMenu()->ProcessCommand (event); + + // Since PopupMenu under Motif still grab right mouse + // button events after it was closed, we need to delete + // the associated widgets to allow next PopUpMenu to + // appear; this needs to be done there because doing it in + // a WorkProc as before may cause crashes if a menu item causes + // the parent window of the menu to be destroyed + item->GetTopMenu()->DestroyWidgetAndDetach(); } } } -void wxMenuItemArmCallback (Widget w, XtPointer clientData, - XtPointer ptr) +void wxMenuItemArmCallback (Widget WXUNUSED(w), XtPointer clientData, + XtPointer WXUNUSED(ptr)) { wxMenuItem *item = (wxMenuItem *) clientData; if (item) @@ -336,15 +390,16 @@ void wxMenuItemArmCallback (Widget w, XtPointer clientData, { wxMenuEvent menuEvent(wxEVT_MENU_HIGHLIGHT, item->GetId()); menuEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame()); - - item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(menuEvent); + + item->GetMenuBar()->GetMenuBarFrame() + ->HandleWindowEvent(menuEvent); } } } -void -wxMenuItemDisarmCallback (Widget w, XtPointer clientData, - XtPointer ptr) +void +wxMenuItemDisarmCallback (Widget WXUNUSED(w), XtPointer clientData, + XtPointer WXUNUSED(ptr)) { wxMenuItem *item = (wxMenuItem *) clientData; if (item) @@ -355,9 +410,9 @@ wxMenuItemDisarmCallback (Widget w, XtPointer clientData, // special to event system wxMenuEvent menuEvent(wxEVT_MENU_HIGHLIGHT, -1); menuEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame()); - - item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(menuEvent); + + item->GetMenuBar()->GetMenuBarFrame() + ->HandleWindowEvent(menuEvent); } } } -