// Created: 25.08.00
// RCS-ID: $Id$
// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
{
public:
wxPopupMenuWindow(wxWindow *parent, wxMenu *menu);
+
+ ~wxPopupMenuWindow();
// override the base class version to select the first item initially
virtual void Popup(wxWindow *focus = NULL);
}
else
{
+ // return FALSE;
+
return wxEvtHandler::ProcessEvent(event);
}
}
SetCursor(wxCURSOR_ARROW);
}
+wxPopupMenuWindow::~wxPopupMenuWindow()
+{
+ // When m_popupMenu in wxMenu is deleted because it
+ // is a child of an old menu bar being deleted (note: it does
+ // not get destroyed by the wxMenu destructor, but
+ // by DestroyChildren()), m_popupMenu should be reset to NULL.
+
+ m_menu->m_popupMenu = NULL;
+}
+
// ----------------------------------------------------------------------------
// wxPopupMenuWindow current item/node handling
// ----------------------------------------------------------------------------
wxPopupMenuWindow *win = menu->m_popupMenu;
wxCHECK_MSG( win, FALSE, _T("parent menu not shown?") );
-
+
pos = ClientToScreen(pos);
if ( win->GetMenuItemFromPoint(win->ScreenToClient(pos)) )
{
m_geometry = NULL;
m_popupMenu = NULL;
+
+ m_startRadioGroup = -1;
}
wxMenu::~wxMenu()
}
}
+void wxMenu::EndRadioGroup()
+{
+ // we're not inside a radio group any longer
+ m_startRadioGroup = -1;
+}
+
bool wxMenu::DoAppend(wxMenuItem *item)
{
+ bool check = FALSE;
+
+ if ( item->GetKind() == wxITEM_RADIO )
+ {
+ int count = GetMenuItemCount();
+
+ if ( m_startRadioGroup == -1 )
+ {
+ // start a new radio group
+ m_startRadioGroup = count;
+
+ // for now it has just one element
+ item->SetAsRadioGroupStart();
+ item->SetRadioGroupEnd(m_startRadioGroup);
+
+ // ensure that we have a checked item in the radio group
+ check = TRUE;
+ }
+ else // extend the current radio group
+ {
+ // we need to update its end item
+ item->SetRadioGroupStart(m_startRadioGroup);
+ wxMenuItemList::Node *node = GetMenuItems().Item(m_startRadioGroup);
+
+ if ( node )
+ {
+ node->GetData()->SetRadioGroupEnd(count);
+ }
+ else
+ {
+ wxFAIL_MSG( _T("where is the radio group start item?") );
+ }
+ }
+ }
+ else // not a radio item
+ {
+ EndRadioGroup();
+ }
+
if ( !wxMenuBase::DoAppend(item) )
return FALSE;
wxMenu *menu = GetParent();
while ( menu )
{
+ // We are a submenu of a menu of a menubar
+ if (menu->GetMenuBar())
+ return menu->GetMenuBar();
+
win = menu->GetInvokingWindow();
if ( win )
break;
// we're probably going to crash in the caller anyhow, but try to detect
// this error as soon as possible
wxASSERT_MSG( win, _T("menu without any associated window?") );
-
+
// also remember it in this menu so that we don't have to search for it the
// next time
wxConstCast(this, wxMenu)->m_invokingWindow = win;
wxCHECK_RET( m_invokingWindow, _T("what kind of menu is this?") );
m_invokingWindow->DismissPopupMenu();
- SetInvokingWindow(NULL);
+
+ // Why reset it here? We need it for sending the event to...
+ // SetInvokingWindow(NULL);
}
}
}
{
m_popupMenu->SelectFirst();
}
-
+
// the geometry might have changed since the last time we were shown, so
// always resize
m_popupMenu->SetClientSize(GetGeometryInfo().GetSize());
// not applicabled
isChecked = -1;
}
-
+
return SendEvent(item->GetId(), isChecked);
}
int id,
const wxString& text,
const wxString& help,
- bool isCheckable,
+ wxItemKind kind,
wxMenu *subMenu)
+ : wxMenuItemBase(parentMenu, id, text, help, kind, subMenu)
{
- m_id = id;
- m_parentMenu = parentMenu;
- m_subMenu = subMenu;
-
- m_text = text;
- m_help = help;
-
- m_isCheckable = isCheckable;
- m_isEnabled = TRUE;
- m_isChecked = FALSE;
-
m_posY =
m_height = -1;
+ m_radioGroup.start = -1;
+ m_isRadioGroupStart = FALSE;
+
UpdateAccelInfo();
}
int id,
const wxString& name,
const wxString& help,
- bool isCheckable,
+ wxItemKind kind,
wxMenu *subMenu)
{
- return new wxMenuItem(parentMenu, id, name, help, isCheckable, subMenu);
+ return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
}
/* static */
void wxMenuItem::SetCheckable(bool checkable)
{
- if ( checkable != m_isCheckable )
+ if ( checkable != IsCheckable() )
{
wxMenuItemBase::SetCheckable(checkable);
void wxMenuItem::Check(bool check)
{
- if ( check != m_isChecked )
+ wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
+
+ if ( m_isChecked == check )
+ return;
+
+ if ( GetKind() == wxITEM_RADIO )
{
- wxMenuItemBase::Check(check);
+ // it doesn't make sense to uncheck a radio item - what would this do?
+ if ( !check )
+ return;
- NotifyMenu();
+ // get the index of this item in the menu
+ const wxMenuItemList& items = m_parentMenu->GetMenuItems();
+ int pos = items.IndexOf(this);
+ wxCHECK_RET( pos != wxNOT_FOUND,
+ _T("menuitem not found in the menu items list?") );
+
+ // get the radio group range
+ int start,
+ end;
+
+ if ( m_isRadioGroupStart )
+ {
+ // we already have all information we need
+ start = pos;
+ end = m_radioGroup.end;
+ }
+ else // next radio group item
+ {
+ // get the radio group end from the start item
+ start = m_radioGroup.start;
+ end = items.Item(start)->GetData()->m_radioGroup.end;
+ }
+
+ // also uncheck all the other items in this radio group
+ wxMenuItemList::Node *node = items.Item(start);
+ for ( int n = start; n <= end && node; n++ )
+ {
+ if ( n != pos )
+ {
+ node->GetData()->m_isChecked = FALSE;
+ }
+ node = node->GetNext();
+ }
}
+
+ wxMenuItemBase::Check(check);
+
+ NotifyMenu();
+}
+
+// radio group stuff
+// -----------------
+
+void wxMenuItem::SetAsRadioGroupStart()
+{
+ m_isRadioGroupStart = TRUE;
+}
+
+void wxMenuItem::SetRadioGroupStart(int start)
+{
+ wxASSERT_MSG( !m_isRadioGroupStart,
+ _T("should only be called for the next radio items") );
+
+ m_radioGroup.start = start;
+}
+
+void wxMenuItem::SetRadioGroupEnd(int end)
+{
+ wxASSERT_MSG( m_isRadioGroupStart,
+ _T("should only be called for the first radio item") );
+
+ m_radioGroup.end = end;
}
// ----------------------------------------------------------------------------
m_menuShown = NULL;
m_shouldShowMenu = FALSE;
+
+ m_windowStyle |= wxNO_FULL_REPAINT_ON_RESIZE;
}
void wxMenuBar::Attach(wxFrame *frame)
wxCHECK_RET( m_current != -1, _T("no menu to popup") );
// forgot to call DismissMenu()?
- wxASSERT_MSG( !m_menuShown, _T("shouldn't show two menu at once!") );
+ wxASSERT_MSG( !m_menuShown, _T("shouldn't show two menus at once!") );
// in any case, we should show it - even if we won't
m_shouldShowMenu = TRUE;
#endif // 0
menu->SetInvokingWindow(this);
+
+ // wxLogDebug( "Name of invoking window %s", menu->GetInvokingWindow()->GetName().c_str() );
+
menu->Popup(ClientToScreen(wxPoint(x, y)), wxSize(0, 0));
// this is not very useful if the menu was popped up because of the mouse
void wxWindow::DismissPopupMenu()
{
wxCHECK_RET( ms_evtLoopPopup, _T("no popup menu shown") );
-
+
ms_evtLoopPopup->Exit();
}