/////////////////////////////////////////////////////////////////////////////
// Name: menu.cpp
-// Purpose:
-// Author: Robert Roebling
-// Created: 01/02/97
-// Id: $Id$
-// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
-// Licence: wxWindows licence
+// Purpose: wxMenu, wxMenuBar, wxMenuItem
+// Author: AUTHOR
+// Modified by:
+// Created: ??/??/98
+// RCS-ID: $Id$
+// Copyright: (c) AUTHOR
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
+// ============================================================================
+// headers & declarations
+// ============================================================================
+
+// wxWindows headers
+// -----------------
+
#ifdef __GNUG__
#pragma implementation "menu.h"
+#pragma implementation "menuitem.h"
#endif
#include "wx/menu.h"
+#include "wx/menuitem.h"
#include "wx/log.h"
-//-----------------------------------------------------------------------------
-// wxMenuBar
-//-----------------------------------------------------------------------------
+// other standard headers
+// ----------------------
+#include <string.h>
-IMPLEMENT_DYNAMIC_CLASS(wxMenuBar,wxWindow)
+IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
+IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
-wxMenuBar::wxMenuBar()
+// ============================================================================
+// implementation
+// ============================================================================
+
+// Menus
+
+// Construct a menu with optional title (then use append)
+wxMenu::wxMenu(const wxString& title, const wxFunction func)
+{
+ m_title = title;
+ m_parent = NULL;
+ m_eventHandler = this;
+ m_noItems = 0;
+ m_menuBar = NULL;
+ if (m_title != "")
+ {
+ Append(-2, m_title) ;
+ AppendSeparator() ;
+ }
+
+ Callback(func);
+
+ // TODO create menu
+}
+
+// The wxWindow destructor will take care of deleting the submenus.
+wxMenu::~wxMenu()
+{
+ // TODO destroy menu and children
+
+ wxNode *node = m_menuItems.First();
+ while (node)
+ {
+ wxMenuItem *item = (wxMenuItem *)node->Data();
+
+ // Delete child menus.
+ // Beware: they must not be appended to children list!!!
+ // (because order of delete is significant)
+ if (item->GetSubMenu())
+ item->DeleteSubMenu();
+
+ wxNode *next = node->Next();
+ delete item;
+ delete node;
+ node = next;
+ }
+}
+
+void wxMenu::Break()
{
-};
+ // TODO
+}
+
+// function appends a new item or submenu to the menu
+void wxMenu::Append(wxMenuItem *pItem)
+{
+ // TODO
-void wxMenuBar::Append( wxMenu *menu, const wxString &title )
-{
- m_menus.Append( menu );
- menu->m_title = title; // ??????
+ wxCHECK_RET( pItem != NULL, "can't append NULL item to the menu" );
+
+ m_menuItems.Append(pItem);
+
+ m_noItems++;
+}
- int pos;
- do {
- pos = menu->m_title.First( '&' );
- if (pos != -1) menu->m_title.Remove( pos, 1 );
- } while (pos != -1);
+void wxMenu::AppendSeparator()
+{
+ // TODO
+ Append(new wxMenuItem(this, ID_SEPARATOR));
+}
+
+// Pullright item
+void wxMenu::Append(int Id, const wxString& label, wxMenu *SubMenu,
+ const wxString& helpString)
+{
+ Append(new wxMenuItem(this, Id, label, helpString, FALSE, SubMenu));
+}
-};
+// Ordinary menu item
+void wxMenu::Append(int Id, const wxString& label,
+ const wxString& helpString, bool checkable)
+{
+ // 'checkable' parameter is useless for Windows.
+ Append(new wxMenuItem(this, Id, label, helpString, checkable));
+}
-static int FindMenuItemRecursive( const wxMenu *menu, const wxString &menuString, const wxString &itemString )
+void wxMenu::Delete(int id)
{
- if (menu->m_title == menuString)
- {
- int res = menu->FindItem( itemString );
- if (res != -1) return res;
- };
- wxNode *node = menu->m_items.First();
- while (node)
- {
- wxMenuItem *item = (wxMenuItem*)node->Data();
- if (item->IsSubMenu())
- return FindMenuItemRecursive(item->GetSubMenu(), menuString, itemString);
- node = node->Next();
- };
- return -1;
-};
+ wxNode *node;
+ wxMenuItem *item;
+ int pos;
+
+ for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) {
+ item = (wxMenuItem *)node->Data();
+ if (item->GetId() == id)
+ break;
+ }
+
+ if (!node)
+ return;
+
+ m_menuItems.DeleteNode(node);
+ delete item;
-int wxMenuBar::FindMenuItem( const wxString &menuString, const wxString &itemString ) const
+ // TODO
+}
+
+void wxMenu::Enable(int Id, bool Flag)
{
- wxNode *node = m_menus.First();
- while (node)
- {
- wxMenu *menu = (wxMenu*)node->Data();
- int res = FindMenuItemRecursive( menu, menuString, itemString);
- if (res != -1) return res;
- node = node->Next();
- };
- return -1;
-};
+ wxMenuItem *item = FindItemForId(Id);
+ wxCHECK_RET( item != NULL, "can't enable non-existing menu item" );
-// Find a wxMenuItem using its id. Recurses down into sub-menus
-static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id)
+ item->Enable(Flag);
+}
+
+bool wxMenu::Enabled(int Id) const
{
- wxMenuItem* result = menu->FindItem(id);
+ wxMenuItem *item = FindItemForId(Id);
+ wxCHECK( item != NULL, FALSE );
+
+ return item->IsEnabled();
+}
- wxNode *node = menu->m_items.First();
- while ( node && result == NULL ) {
- wxMenuItem *item = (wxMenuItem*)node->Data();
- if ( item->IsSubMenu() )
- result = FindMenuItemByIdRecursive( item->GetSubMenu(), id );
- node = node->Next();
- };
+void wxMenu::Check(int Id, bool Flag)
+{
+ wxMenuItem *item = FindItemForId(Id);
+ wxCHECK_RET( item != NULL, "can't get status of non-existing menu item" );
- return result;
-};
+ item->Check(Flag);
+}
-wxMenuItem* wxMenuBar::FindMenuItemById( int id ) const
+bool wxMenu::Checked(int Id) const
{
- wxMenuItem* result = 0;
- wxNode *node = m_menus.First();
- while (node && result == 0)
- {
- wxMenu *menu = (wxMenu*)node->Data();
- result = FindMenuItemByIdRecursive( menu, id );
- node = node->Next();
- }
- return result;
+ wxMenuItem *item = FindItemForId(Id);
+ wxCHECK( item != NULL, FALSE );
+
+ return item->IsChecked();
}
-void wxMenuBar::Check( int id, bool check )
+void wxMenu::SetTitle(const wxString& label)
{
- wxMenuItem* item = FindMenuItemById( id );
- if (item) item->Check(check);
-};
+ m_title = label ;
+ // TODO
+}
-bool wxMenuBar::Checked( int id ) const
+const wxString& wxMenu::GetTitle() const
{
- wxMenuItem* item = FindMenuItemById( id );
- if (item) return item->IsChecked();
- return FALSE;
-};
+ return m_title;
+}
-void wxMenuBar::Enable( int id, bool enable )
+void wxMenu::SetLabel(int id, const wxString& label)
{
- wxMenuItem* item = FindMenuItemById( id );
- if (item) item->Enable(enable);
-};
+ wxMenuItem *item = FindItemForId(id) ;
+ if (item==NULL)
+ return;
+
+ if (item->GetSubMenu()==NULL)
+ {
+ // TODO
+ }
+ else
+ {
+ // TODO
+ }
+ item->SetName(label);
+}
-bool wxMenuBar::Enabled( int id ) const
+wxString wxMenu::GetLabel(int Id) const
{
- wxMenuItem* item = FindMenuItemById( id );
- if (item) return item->IsEnabled();
- return FALSE;
-};
+ // TODO
+ return wxString("") ;
+}
-//-----------------------------------------------------------------------------
-// wxMenu
-//-----------------------------------------------------------------------------
+// Finds the item id matching the given string, -1 if not found.
+int wxMenu::FindItem (const wxString& itemString) const
+{
+ char buf1[200];
+ char buf2[200];
+ wxStripMenuCodes ((char *)(const char *)itemString, buf1);
+
+ for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
+ {
+ wxMenuItem *item = (wxMenuItem *) node->Data ();
+ if (item->GetSubMenu())
+ {
+ int ans = item->GetSubMenu()->FindItem(itemString);
+ if (ans > -1)
+ return ans;
+ }
+ if ( !item->IsSeparator() )
+ {
+ wxStripMenuCodes((char *)item->GetName().c_str(), buf2);
+ if (strcmp(buf1, buf2) == 0)
+ return item->GetId();
+ }
+ }
+
+ return -1;
+}
+wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const
+{
+ if (itemMenu)
+ *itemMenu = NULL;
+ for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
+ {
+ wxMenuItem *item = (wxMenuItem *) node->Data ();
+
+ if (item->GetId() == itemId)
+ {
+ if (itemMenu)
+ *itemMenu = (wxMenu *) this;
+ return item;
+ }
+
+ if (item->GetSubMenu())
+ {
+ wxMenuItem *ans = item->GetSubMenu()->FindItemForId (itemId, itemMenu);
+ if (ans)
+ return ans;
+ }
+ }
+
+ if (itemMenu)
+ *itemMenu = NULL;
+ return NULL;
+}
-IMPLEMENT_DYNAMIC_CLASS(wxMenuItem,wxObject)
+void wxMenu::SetHelpString(int itemId, const wxString& helpString)
+{
+ wxMenuItem *item = FindItemForId (itemId);
+ if (item)
+ item->SetHelp(helpString);
+}
-wxMenuItem::wxMenuItem()
+wxString wxMenu::GetHelpString (int itemId) const
{
- m_id = ID_SEPARATOR;
- m_isCheckMenu = FALSE;
- m_isChecked = FALSE;
- m_isEnabled = TRUE;
- m_subMenu = NULL;
-};
+ wxMenuItem *item = FindItemForId (itemId);
+ wxString str("");
+ return (item == NULL) ? str : item->GetHelp();
+}
-void wxMenuItem::SetText(const wxString& str)
+void wxMenu::ProcessCommand(wxCommandEvent & event)
{
- for ( const char *pc = str; *pc != '\0'; pc++ ) {
- if ( *pc == '&' )
- pc++; // skip it
+ bool processed = FALSE;
+
+ // Try a callback
+ if (m_callback)
+ {
+ (void) (*(m_callback)) (*this, event);
+ processed = TRUE;
+ }
+
+ // Try the menu's event handler
+ if ( !processed && GetEventHandler())
+ {
+ processed = GetEventHandler()->ProcessEvent(event);
+ }
+
+ // Try the window the menu was popped up from (and up
+ // through the hierarchy)
+ if ( !processed && GetInvokingWindow())
+ processed = GetInvokingWindow()->ProcessEvent(event);
+}
- m_text << *pc;
- }
+bool wxWindow::PopupMenu(wxMenu *menu, int x, int y)
+{
+ // TODO
+ return FALSE;
}
-void wxMenuItem::Check( bool check )
+// Menu Bar
+wxMenuBar::wxMenuBar()
{
- wxCHECK_RET( IsCheckable(), "can't check uncheckable item!" )
+ m_eventHandler = this;
+ m_menuCount = 0;
+ m_menus = NULL;
+ m_titles = NULL;
+ m_menuBarFrame = NULL;
- m_isChecked = check;
+ // TODO
}
-bool wxMenuItem::IsChecked() const
+wxMenuBar::wxMenuBar(int n, wxMenu *Mmnus[], const wxString titles[])
{
- wxCHECK( IsCheckable(), FALSE ); // can't get state of uncheckable item!
+ m_eventHandler = this;
+ m_menuCount = n;
+ m_menus = menus;
+ m_titles = new wxString[n];
+ int i;
+ for ( i = 0; i < n; i++ )
+ m_titles[i] = titles[i];
+ m_menuBarFrame = NULL;
+
+ // TODO
+}
- return FALSE;
+wxMenuBar::~wxMenuBar()
+{
+ int i;
+ for (i = 0; i < m_menuCount; i++)
+ {
+ delete m_menus[i];
+ }
+ delete[] m_menus;
+ delete[] m_titles;
+
+ // TODO
}
-IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler)
+// Must only be used AFTER menu has been attached to frame,
+// otherwise use individual menus to enable/disable items
+void wxMenuBar::Enable(int id, bool flag)
+{
+ wxMenu *itemMenu = NULL;
+ wxMenuItem *item = FindItemForId(id, &itemMenu) ;
+ if (!item)
+ return;
+
+ // TODO
+}
-wxMenu::wxMenu( const wxString &title )
+void wxMenuBar::EnableTop(int pos, bool flag)
{
- m_title = title;
- m_items.DeleteContents( TRUE );
- m_invokingWindow = NULL;
-};
+ // TODO
+}
-void wxMenu::AppendSeparator()
+// Must only be used AFTER menu has been attached to frame,
+// otherwise use individual menus
+void wxMenuBar::Check(int id, bool flag)
{
- wxMenuItem *mitem = new wxMenuItem();
- mitem->SetId(ID_SEPARATOR);
+ wxMenu *itemMenu = NULL;
+ wxMenuItem *item = FindItemForId(id, &itemMenu) ;
+ if (!item)
+ return;
- m_items.Append( mitem );
-};
+ if (!item->IsCheckable())
+ return ;
-void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool checkable )
+ // TODO
+}
+
+bool wxMenuBar::Checked(int id) const
{
- wxMenuItem *mitem = new wxMenuItem();
- mitem->SetId(id);
- mitem->SetText(item);
- mitem->SetHelpString(helpStr);
- mitem->SetCheckable(checkable);
-
- m_items.Append( mitem );
-};
+ wxMenu *itemMenu = NULL;
+ wxMenuItem *item = FindItemForId(id, &itemMenu) ;
+ if (!item)
+ return FALSE;
+
+ // TODO
+ return FALSE;
+}
-void wxMenu::Append( int id, const wxString &text, wxMenu *subMenu, const wxString &helpStr )
+bool wxMenuBar::Enabled(int id) const
{
- wxMenuItem *mitem = new wxMenuItem();
- mitem->SetId(id);
- mitem->SetText(text);
- mitem->SetHelpString(helpStr);
- mitem->SetSubMenu(subMenu);
+ wxMenu *itemMenu = NULL;
+ wxMenuItem *item = FindItemForId(id, &itemMenu) ;
+ if (!item)
+ return FALSE;
+
+ // TODO
+ return FALSE ;
+}
- m_items.Append( mitem );
-};
-int wxMenu::FindItem( const wxString itemString ) const
+void wxMenuBar::SetLabel(int id, const wxString& label)
{
- wxString s( itemString );
+ wxMenu *itemMenu = NULL;
+ wxMenuItem *item = FindItemForId(id, &itemMenu) ;
+
+ if (!item)
+ return;
- int pos;
- do {
- pos = s.First( '&' );
- if (pos != -1) s.Remove( pos, 1 );
- } while (pos != -1);
+ // TODO
+}
- wxNode *node = m_items.First();
- while (node)
- {
- wxMenuItem *item = (wxMenuItem*)node->Data();
- if (item->GetText() == s)
- return item->GetId();
- node = node->Next();
- };
+wxString wxMenuBar::GetLabel(int id) const
+{
+ wxMenu *itemMenu = NULL;
+ wxMenuItem *item = FindItemForId(id, &itemMenu) ;
- return -1;
-};
+ if (!item)
+ return wxString("");
-void wxMenu::Enable( int id, bool enable )
+ // TODO
+ return wxString("") ;
+}
+
+void wxMenuBar::SetLabelTop(int pos, const wxString& label)
{
- wxMenuItem *item = FindItem(id);
- if ( item )
- item->Enable(enable);
-};
+ // TODO
+}
-bool wxMenu::IsEnabled( int id ) const
+wxString wxMenuBar::GetLabelTop(int pos) const
{
- wxMenuItem *item = FindItem(id);
- if ( item )
- return item->IsEnabled();
- else
- return FALSE;
-};
+ // TODO
+ return wxString("");
+}
-void wxMenu::Check( int id, bool enable )
+bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos)
{
- wxMenuItem *item = FindItem(id);
- if ( item )
- item->Check(enable);
-};
+ // TODO
+ return FALSE;
+}
-bool wxMenu::IsChecked( int id ) const
+bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title)
{
- wxMenuItem *item = FindItem(id);
- if ( item )
- return item->IsChecked();
- else
+ // TODO
return FALSE;
-};
+}
-void wxMenu::SetLabel( int id, const wxString &label )
+void wxMenuBar::Append (wxMenu * menu, const wxString& title)
{
- wxMenuItem *item = FindItem(id);
- if ( item )
- item->SetText(label);
-};
+ if (!OnAppend(menu, title))
+ return;
+
+ m_menuCount ++;
+ wxMenu **new_menus = new wxMenu *[m_menuCount];
+ wxString *new_titles = new wxString[m_menuCount];
+ int i;
+
+ for (i = 0; i < m_menuCount - 1; i++)
+ {
+ new_menus[i] = m_menus[i];
+ m_menus[i] = NULL;
+ new_titles[i] = m_titles[i];
+ m_titles[i] = "";
+ }
+ if (m_menus)
+ {
+ delete[]m_menus;
+ delete[]m_titles;
+ }
+ m_menus = new_menus;
+ m_titles = new_titles;
+
+ m_menus[m_menuCount - 1] = (wxMenu *)menu;
+ m_titles[m_menuCount - 1] = title;
+
+ // TODO
+}
-wxMenuItem *wxMenu::FindItem(int id) const
+void wxMenuBar::Delete(wxMenu * menu, int i)
{
- wxNode *node = m_items.First();
- while (node) {
- wxMenuItem *item = (wxMenuItem*)node->Data();
- if ( item->GetId() == id )
- return item;
- node = node->Next();
- };
+ int j;
+ int ii = (int) i;
+
+ if (menu != 0)
+ {
+ for (ii = 0; ii < m_menuCount; ii++)
+ {
+ if (m_menus[ii] == menu)
+ break;
+ }
+ if (ii >= m_menuCount)
+ return;
+ } else
+ {
+ if (ii < 0 || ii >= m_menuCount)
+ return;
+ menu = m_menus[ii];
+ }
+
+ if (!OnDelete(menu, ii))
+ return;
+
+ menu->SetParent(NULL);
+
+ -- m_menuCount;
+ for (j = ii; j < m_menuCount; j++)
+ {
+ m_menus[j] = m_menus[j + 1];
+ m_titles[j] = m_titles[j + 1];
+ }
+}
- wxLogDebug("wxMenu::FindItem: item %d not found.", id);
+// Find the menu menuString, item itemString, and return the item id.
+// Returns -1 if none found.
+int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemString) const
+{
+ char buf1[200];
+ char buf2[200];
+ wxStripMenuCodes ((char *)(const char *)menuString, buf1);
+ int i;
+ for (i = 0; i < m_menuCount; i++)
+ {
+ wxStripMenuCodes ((char *)(const char *)m_titles[i], buf2);
+ if (strcmp (buf1, buf2) == 0)
+ return m_menus[i]->FindItem (itemString);
+ }
+ return -1;
+}
- return NULL;
+wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
+{
+ if (itemMenu)
+ *itemMenu = NULL;
+
+ wxMenuItem *item = NULL;
+ int i;
+ for (i = 0; i < m_menuCount; i++)
+ if ((item = m_menus[i]->FindItemForId (Id, itemMenu)))
+ return item;
+ return NULL;
}
-void wxMenu::SetInvokingWindow( wxWindow *win )
+void wxMenuBar::SetHelpString (int Id, const wxString& helpString)
{
- m_invokingWindow = win;
-};
+ int i;
+ for (i = 0; i < m_menuCount; i++)
+ {
+ if (m_menus[i]->FindItemForId (Id))
+ {
+ m_menus[i]->SetHelpString (Id, helpString);
+ return;
+ }
+ }
+}
-wxWindow *wxMenu::GetInvokingWindow()
+wxString wxMenuBar::GetHelpString (int Id) const
{
- return m_invokingWindow;
-};
+ int i;
+ for (i = 0; i < m_menuCount; i++)
+ {
+ if (m_menus[i]->FindItemForId (Id))
+ eturn wxString(m_menus[i]->GetHelpString (Id));
+ }
+ return wxString("");
+}