/////////////////////////////////////////////////////////////////////////////
-// Name: univ/menu.cpp
+// Name: src/univ/menu.cpp
// Purpose: wxMenuItem, wxMenu and wxMenuBar implementation
// Author: Vadim Zeitlin
// Modified by:
// headers
// ----------------------------------------------------------------------------
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
- #pragma implementation "univmenuitem.h"
- #pragma implementation "univmenu.h"
-#endif
-
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
+#if wxUSE_MENUS
+
#ifndef WX_PRECOMP
#include "wx/dynarray.h"
#include "wx/control.h" // for FindAccelIndex()
#include "wx/log.h"
#endif // WX_PRECOMP
-#if wxUSE_MENUS
-
#include "wx/popupwin.h"
#include "wx/evtloop.h"
#include "wx/dcclient.h"
// override the base class version to dismiss any open submenus
virtual void Dismiss();
- // notify the menu when the window disappears from screen
- virtual void OnDismiss();
-
// called when a submenu is dismissed
- void OnSubmenuDismiss() { m_hasOpenSubMenu = false; }
+ void OnSubmenuDismiss(bool dismissParent);
+
+ // the default wxMSW wxPopupTransientWindow::OnIdle disables the capture
+ // when the cursor is inside the popup, which dsables the menu tracking
+ // so override it to do nothing
+#ifdef __WXMSW__
+ void OnIdle(wxIdleEvent& WXUNUSED(event)) { }
+#endif
// get the currently selected item (may be NULL)
wxMenuItem *GetCurrentItem() const
// don't dismiss the popup window if the parent menu was clicked
virtual bool ProcessLeftDown(wxMouseEvent& event);
+ virtual bool SetCurrent(bool doit = true) { return wxPopupTransientWindow::SetCurrent(doit); };
+
protected:
// how did we perform this operation?
enum InputMethod
WithMouse
};
+ // notify the menu when the window disappears from screen
+ virtual void OnDismiss();
+
// draw the menu inside this window
virtual void DoDraw(wxControlRenderer *renderer);
// set the current node and item withotu refreshing anything
void SetCurrent(wxMenuItemList::compatibility_iterator node);
- virtual bool SetCurrent(bool doit = true){return wxPopupTransientWindow::SetCurrent(doit);};
// change the current item refreshing the old and new items
void ChangeCurrent(wxMenuItemList::compatibility_iterator node);
EVT_LEFT_UP(wxPopupMenuWindow::OnLeftUp)
EVT_MOTION(wxPopupMenuWindow::OnMouseMove)
EVT_LEAVE_WINDOW(wxPopupMenuWindow::OnMouseLeave)
+#ifdef __WXMSW__
+ EVT_IDLE(wxPopupMenuWindow::OnIdle)
+#endif
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(wxMenuBar, wxMenuBarBase)
if ( item->IsSubMenu() && item->GetSubMenu()->IsShown() )
{
item->GetSubMenu()->Dismiss();
- OnSubmenuDismiss();
+ OnSubmenuDismiss( false );
}
RefreshItem(item);
wxPopupTransientWindow::Popup(focus);
+ // the base class no-longer captures the mouse automatically when Popup
+ // is called, so do it here to allow the menu tracking to work
+ if ( !HasCapture() )
+ CaptureMouse();
+
#ifdef __WXMSW__
// ensure that this window is really on top of everything: without using
// SetWindowPos() it can be covered by its parent menu which is not
wxCHECK_RET( win, _T("opened submenu is not opened?") );
win->Dismiss();
- OnSubmenuDismiss();
+ OnSubmenuDismiss( false );
}
wxPopupTransientWindow::Dismiss();
+
+ ResetCurrent();
}
void wxPopupMenuWindow::OnDismiss()
HandleDismiss(true);
}
-void wxPopupMenuWindow::HandleDismiss(bool dismissParent)
+void wxPopupMenuWindow::OnSubmenuDismiss(bool WXUNUSED(dismissParent))
{
- ResetCurrent();
+ m_hasOpenSubMenu = false;
+}
+void wxPopupMenuWindow::HandleDismiss(bool dismissParent)
+{
m_menu->OnDismiss(dismissParent);
}
void wxPopupMenuWindow::OnKeyDown(wxKeyEvent& event)
{
- if ( !ProcessKeyDown(event.GetKeyCode()) )
+ wxMenuBar *menubar = m_menu->GetMenuBar();
+
+ if ( menubar )
+ {
+ menubar->ProcessEvent(event);
+ }
+ else if ( !ProcessKeyDown(event.GetKeyCode()) )
{
event.Skip();
}
bool notUnique = false;
// translate everything to lower case before comparing
- wxChar chAccel = wxTolower(key);
+ wxChar chAccel = (wxChar)wxTolower(key);
// loop through all items searching for the item with this
// accel
wxPopupMenuWindow *win = m_menuParent->m_popupMenu;
if ( win )
{
- win->OnSubmenuDismiss();
+ win->OnSubmenuDismiss( true );
}
else
{
m_shouldShowMenu = false;
}
+wxMenuBar::wxMenuBar(size_t n, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
+{
+ Init();
+
+ for (size_t i = 0; i < n; ++i )
+ Append(menus[i], titles[i]);
+}
+
void wxMenuBar::Attach(wxFrame *frame)
{
// maybe you really wanted to call Detach()?
wxString wxMenuBar::GetLabelTop(size_t pos) const
{
- wxCHECK_MSG( pos < GetCount(), _T(""), _T("invalid index in GetLabelTop") );
+ wxCHECK_MSG( pos < GetCount(), wxEmptyString, _T("invalid index in GetLabelTop") );
return m_menuInfos[pos].GetLabel();
}
// the menu when up/down one is
switch ( key )
{
- case WXK_MENU:
+ case WXK_ALT:
// Alt must be processed at wxWindow level too
event.Skip();
// fall through
*unique = true;
// translate everything to lower case before comparing
- wxChar chAccel = wxTolower(key);
+ wxChar chAccel = (wxChar)wxTolower(key);
// the index of the item with this accel
int idxFound = -1;
void wxMenuBar::OnDismiss()
{
- if ( GetCapture() )
- {
+ if ( ReleaseMouseCapture() )
wxLogTrace(_T("mousecapture"), _T("Releasing mouse from wxMenuBar::OnDismiss"));
- GetCapture()->ReleaseMouse();
- }
if ( m_current != -1 )
{
GiveAwayFocus();
}
+bool wxMenuBar::ReleaseMouseCapture()
+{
+#ifdef __WXX11__
+ // With wxX11, when a menu is closed by clicking away from it, a control
+ // under the click will still get an event, even though the menu has the
+ // capture (bug?). So that control may already have taken the capture by
+ // this point, preventing us from releasing the menu's capture. So to work
+ // around this, we release both captures, then put back the control's
+ // capture.
+ wxWindow *capture = GetCapture();
+ if ( capture )
+ {
+ capture->ReleaseMouse();
+
+ if ( capture == this )
+ return true;
+
+ bool had = HasCapture();
+
+ if ( had )
+ ReleaseMouse();
+
+ capture->CaptureMouse();
+
+ return had;
+ }
+#else
+ if ( HasCapture() )
+ {
+ ReleaseMouse();
+ return true;
+ }
+#endif
+ return false;
+}
+
void wxMenuBar::GiveAwayFocus()
{
GetFrame()->SetFocus();
// wxLogDebug( "Name of invoking window %s", menu->GetInvokingWindow()->GetName().c_str() );
- menu->Popup(ClientToScreen(wxPoint(x, y)), wxSize(0, 0));
+ menu->Popup(ClientToScreen(wxPoint(x, y)), wxSize(0,0));
// this is not very useful if the menu was popped up because of the mouse
// click but I think it is nice to do when it appears because of a key
}
#endif // wxUSE_MENUS
-