// Modified by:
// Created: 25.08.00
// RCS-ID: $Id$
-// Copyright: (c) 2000 Vadim Zeitlin
+// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#include "wx/popupwin.h"
#include "wx/evtloop.h"
+#include "wx/dcclient.h"
+#include "wx/frame.h"
#include "wx/univ/renderer.h"
{
wxSize size;
wxClientDC dc(menubar);
- dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+ dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
dc.GetTextExtent(m_label, &size.x, &size.y);
// adjust for the renderer we use and store the width
{
if ( node != m_nodeCurrent )
{
- if ( m_nodeCurrent )
+ wxMenuItemList::Node *nodeOldCurrent = m_nodeCurrent;
+
+ m_nodeCurrent = node;
+
+ if ( nodeOldCurrent )
{
- wxMenuItem *item = m_nodeCurrent->GetData();
+ wxMenuItem *item = nodeOldCurrent->GetData();
wxCHECK_RET( item, _T("no current item?") );
// if it was the currently opened menu, close it
RefreshItem(item);
}
- m_nodeCurrent = node;
-
if ( m_nodeCurrent )
RefreshItem(m_nodeCurrent->GetData());
}
// never partially covered as it is always on top of everything
wxDC& dc = renderer->GetDC();
- dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+ dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
// FIXME: this should be done in the renderer, however when it is fixed
// wxPopupMenuWindow::RefreshItem() should be changed too!
wxASSERT_MSG( !item->IsSeparator() && !item->IsSubMenu(),
_T("can't click this item") );
- m_menu->ClickItem(item);
+ wxMenu* menu = m_menu;
// close all menus
DismissAndNotify();
+
+ menu->ClickItem(item);
}
void wxPopupMenuWindow::OpenSubmenu(wxMenuItem *item, InputMethod how)
SetCursor(wxCURSOR_ARROW);
- SetFont(wxSystemSettings::GetSystemFont(wxSYS_SYSTEM_FONT));
+ SetFont(wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT));
+
+ // calculate and set our height (it won't be changed any more)
+ SetSize(-1, GetBestSize().y);
}
// remember the last frame which had us to avoid unnecessarily reparenting
void wxMenuBar::RefreshAllItemsAfter(size_t pos)
{
+ if ( !IsCreated() )
+ {
+ // no need to refresh if nothing is shown yet
+ return;
+ }
+
wxRect rect = GetItemRect(pos);
rect.width = GetClientSize().x - rect.x;
RefreshRect(rect);
wxCHECK_RET( pos != (size_t)-1,
_T("invalid item in wxMenuBar::RefreshItem") );
+ if ( !IsCreated() )
+ {
+ // no need to refresh if nothing is shown yet
+ return;
+ }
+
RefreshRect(GetItemRect(pos));
}
void wxMenuBar::DoDraw(wxControlRenderer *renderer)
{
wxDC& dc = renderer->GetDC();
- dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+ dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
// redraw only the items which must be redrawn
wxRect wxMenuBar::GetItemRect(size_t pos) const
{
wxASSERT_MSG( pos < GetCount(), _T("invalid menu bar item index") );
+ wxASSERT_MSG( IsCreated(), _T("can't call this method yet") );
wxRect rect;
rect.x =
if ( GetMenuCount() > 0 )
{
wxClientDC dc(wxConstCast(this, wxMenuBar));
- dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+ dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
dc.GetTextExtent(GetLabelTop(0), &size.x, &size.y);
// adjust for the renderer we use
{
wxCHECK_RET( pos < GetCount(), _T("invalid menu index in DoSelectMenu") );
- if ( m_current != -1 )
+ int posOld = m_current;
+
+ m_current = pos;
+
+ if ( posOld != -1 )
{
// close the previous menu
if ( IsShowingMenu() )
m_shouldShowMenu = old;
}
- RefreshItem((size_t)m_current);
+ RefreshItem((size_t)posOld);
}
- m_current = pos;
-
RefreshItem(pos);
}
// show the menu if we know that we should, even if we hadn't been showing
// it before (this may happen if the previous menu was disabled)
- if ( m_shouldShowMenu )
+ if ( m_shouldShowMenu && !m_menuShown)
{
// open the new menu if the old one we closed had been opened
PopupCurrentMenu(FALSE /* don't select first item - as Windows does */);
void wxMenuBar::OnKeyDown(wxKeyEvent& event)
{
- // the current item must have been set before
- wxCHECK_RET( m_current != -1, _T("where is current item?") );
+ // ensure that we have a current item - we might not have it if we're
+ // given the focus with Alt or F10 press (and under GTK+ the menubar
+ // somehow gets the keyboard events even when it doesn't have focus...)
+ if ( m_current == -1 )
+ {
+ if ( !HasCapture() )
+ {
+ SelectMenu(0);
+ }
+ else // we do have capture
+ {
+ // we always maintain a valid current item while we're in modal
+ // state (i.e. have the capture)
+ wxFAIL_MSG( _T("how did we manage to lose current item?") );
+
+ return;
+ }
+ }
int key = event.GetKeyCode();
}
else // right
{
- if ( ++currentNew == (int)count )
+ if ( ++currentNew == count )
currentNew = 0;
}
// that we pass 0 as width to position the menu exactly below the
// item, not to the right of it
wxRect rectItem = GetItemRect(m_current);
+
m_menuShown->Popup(ClientToScreen(rectItem.GetPosition()),
wxSize(0, rectItem.GetHeight()),
selectFirst);
void wxMenuBar::OnDismiss()
{
- ReleaseCapture();
+ if ( GetCapture() )
+ GetCapture()->ReleaseMouse();
if ( m_current != -1 )
{
- RefreshItem((size_t)m_current);
-
+ size_t current = m_current;
m_current = -1;
+
+ RefreshItem(current);
}
GiveAwayFocus();