diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index 951351017a..281a083df0 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -22,62 +22,45 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include - #include #include #include - #include +#include -class CONTEXT_MENU::CMEventHandler : public wxEvtHandler +CONTEXT_MENU::CONTEXT_MENU() : + m_titleSet( false ), m_handler( this ), m_tool( NULL ) { -public: - CMEventHandler( CONTEXT_MENU* aMenu ): - m_menu( aMenu ) {}; - - void onEvent( wxEvent& aEvent ) - { - TOOL_EVENT evt; - wxEventType type = aEvent.GetEventType(); - - if( type == wxEVT_MENU_HIGHLIGHT ) - evt = TOOL_EVENT( TC_Command, TA_ContextMenuUpdate, aEvent.GetId() ); - else if( type == wxEVT_COMMAND_MENU_SELECTED ) - evt = TOOL_EVENT( TC_Command, TA_ContextMenuChoice, aEvent.GetId() ); - - if( m_menu->m_tool ) - m_menu->m_tool->GetManager()->ProcessEvent( evt ); - } - -private: - CONTEXT_MENU* m_menu; -}; - - -CONTEXT_MENU::CONTEXT_MENU() -{ - m_tool = NULL; - m_menu = new wxMenu(); - m_handler = new CMEventHandler( this ); - m_menu->Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), - NULL, m_handler ); - m_menu->Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ), - NULL, m_handler ); + m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), + NULL, &m_handler ); + m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ), + NULL, &m_handler ); // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu) - wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, 0, m_menu ); - m_menu->AddPendingEvent( menuEvent ); - - m_titleSet = false; + wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, 0, &m_menu ); + m_menu.AddPendingEvent( menuEvent ); } -CONTEXT_MENU::~CONTEXT_MENU() +CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) : + m_titleSet( aMenu.m_titleSet ), m_handler( this ), m_tool( aMenu.m_tool ) { - delete m_menu; - delete m_handler; + m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), + NULL, &m_handler ); + m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ), + NULL, &m_handler ); + + // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu) + wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, 0, &m_menu ); + m_menu.AddPendingEvent( menuEvent ); + + // Copy all the menu entries + for( unsigned i = 0; i < aMenu.m_menu.GetMenuItemCount(); ++i ) + { + wxMenuItem* item = aMenu.m_menu.FindItemByPosition( i ); + m_menu.Append( new wxMenuItem( &m_menu, item->GetId(), item->GetItemLabel(), + wxEmptyString, wxITEM_NORMAL ) ); + } } @@ -86,23 +69,70 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle ) // Unfortunately wxMenu::SetTitle() does nothing.. if( m_titleSet ) { - m_menu->Delete( m_menu->FindItemByPosition( 0 ) ); // fixme: this is LAME! - m_menu->Delete( m_menu->FindItemByPosition( 0 ) ); + m_menu.FindItemByPosition( 0 )->SetItemLabel( aTitle ); + } + else + { + m_menu.InsertSeparator( 0 ); + m_menu.Insert( 0, new wxMenuItem( &m_menu, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) ); + m_titleSet = true; } - - m_menu->InsertSeparator( 0 ); - m_menu->Insert( 0, new wxMenuItem( m_menu, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) ); - m_titleSet = true; } -void CONTEXT_MENU::Add( const wxString& aItem, int aId ) +void CONTEXT_MENU::Add( const wxString& aLabel, int aId ) { - m_menu->Append( new wxMenuItem( m_menu, aId, aItem, wxEmptyString, wxITEM_NORMAL ) ); + m_menu.Append( new wxMenuItem( &m_menu, aId, aLabel, wxEmptyString, wxITEM_NORMAL ) ); +} + + +void CONTEXT_MENU::Add( const TOOL_ACTION& aAction, int aId ) +{ + m_menu.Append( new wxMenuItem( &m_menu, aId, + wxString( aAction.GetDescription() + '\t' + getHotKeyDescription( aAction ) ), + wxEmptyString, wxITEM_NORMAL ) ); } void CONTEXT_MENU::Clear() { m_titleSet = false; + + for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i ) + m_menu.Destroy( m_menu.FindItemByPosition( 0 ) ); +} + + +std::string CONTEXT_MENU::getHotKeyDescription( const TOOL_ACTION& aAction ) const +{ + int hotkey = aAction.GetHotKey(); + + std::string description = ""; + + if( hotkey & MD_ModAlt ) + description += "ALT+"; + if( hotkey & MD_ModCtrl ) + description += "CTRL+"; + if( hotkey & MD_ModShift ) + description += "SHIFT+"; + + // TODO dispatch keys such as Fx, TAB, PG_UP/DN, HOME, END, etc. + description += char( hotkey & ~MD_ModifierMask ); + + return description; +} + + +void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent ) +{ + TOOL_EVENT evt; + wxEventType type = aEvent.GetEventType(); + + if( type == wxEVT_MENU_HIGHLIGHT ) + evt = TOOL_EVENT( TC_Command, TA_ContextMenuUpdate, aEvent.GetId() ); + else if( type == wxEVT_COMMAND_MENU_SELECTED ) + evt = TOOL_EVENT( TC_Command, TA_ContextMenuChoice, aEvent.GetId() ); + + if( m_menu->m_tool ) + m_menu->m_tool->GetManager()->ProcessEvent( evt ); } diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index e5dee7dea2..20333af66d 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -380,14 +381,15 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) { if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( MB_Right ) ) break; - + st->pendingWait = true; st->waitEvents = TOOL_EVENT( TC_Any, TA_Any ); - + if( st->contextMenuTrigger == CMENU_NOW ) st->contextMenuTrigger = CMENU_OFF; - - GetEditFrame()->PopupMenu( st->contextMenu->GetMenu() ); + + boost::scoped_ptr menu( new CONTEXT_MENU( *st->contextMenu ) ); + GetEditFrame()->PopupMenu( menu->GetMenu() ); TOOL_EVENT evt( TC_Command, TA_ContextMenuChoice ); dispatchInternal( evt ); diff --git a/include/tool/context_menu.h b/include/tool/context_menu.h index b62a55a041..cb518feb69 100644 --- a/include/tool/context_menu.h +++ b/include/tool/context_menu.h @@ -25,7 +25,8 @@ #ifndef __CONTEXT_MENU_H #define __CONTEXT_MENU_H -#include +#include +#include class wxMenu; class TOOL_INTERACTIVE; @@ -41,23 +42,29 @@ class CONTEXT_MENU public: CONTEXT_MENU(); - ~CONTEXT_MENU(); + CONTEXT_MENU( const CONTEXT_MENU& aMenu ); void SetTitle( const wxString& aTitle ); - void Add( const wxString& aItem, int aId ); - - // fixme: unimplemented - // void Add ( const TOOL_ACTION& aAction, int aId = -1 ); - + void Add( const wxString& aLabel, int aId ); + void Add( const TOOL_ACTION& aAction, int aId = -1 ); void Clear(); wxMenu* GetMenu() const { - return m_menu; + return const_cast( &m_menu ); } private: - class CMEventHandler; + class CMEventHandler : public wxEvtHandler + { + public: + CMEventHandler( CONTEXT_MENU* aMenu ) : m_menu( aMenu ) {}; + + void onEvent( wxEvent& aEvent ); + + private: + CONTEXT_MENU* m_menu; + }; friend class TOOL_INTERACTIVE; @@ -66,10 +73,19 @@ private: m_tool = aTool; } + /** + * Returns a hot key in the string format accepted by wxMenu. + * + * @param aAction is the action with hot key to be converted. + * @return Hot key in the string format compatible with wxMenu. + */ + std::string getHotKeyDescription( const TOOL_ACTION& aAction ) const; + + /// Flag indicating that the menu title was set up bool m_titleSet; - wxMenu* m_menu; - CMEventHandler* m_handler; + wxMenu m_menu; + CMEventHandler m_handler; TOOL_INTERACTIVE* m_tool; }; diff --git a/include/tool/tool_action.h b/include/tool/tool_action.h index 61ef7ad886..cc1559983d 100644 --- a/include/tool/tool_action.h +++ b/include/tool/tool_action.h @@ -26,7 +26,7 @@ #define __TOOL_ACTION_H #include -#include +#include #include #include @@ -38,8 +38,9 @@ class TOOL_ACTION { public: - TOOL_ACTION( const std::string& aName, TOOL_ActionScope aScope = AS_CONTEXT, int aDefaultHotKey = 0, - const wxString& aMenuItem = wxT( "" ), const wxString& aMenuDesc = wxT( "" ) ) : + TOOL_ACTION( const std::string& aName, TOOL_ActionScope aScope = AS_CONTEXT, + int aDefaultHotKey = 0, const std::string& aMenuItem = std::string( "" ), + const std::string& aMenuDesc = std::string( "" ) ) : m_name( aName ), m_scope( aScope ), m_defaultHotKey( aDefaultHotKey ), m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ), m_menuDescription( aMenuDesc ), m_id( -1 ), m_actionMgr( NULL ) @@ -86,6 +87,15 @@ public: return m_id; } + /** + * Function GetHotKey() + * Returns the associated hot key. + */ + int GetHotKey() const + { + return m_currentHotKey; + } + /** * Function ChangeHotKey() * Assigns a new hot key. @@ -94,8 +104,8 @@ public: */ void ChangeHotKey( int aNewHotKey ) { - wxASSERT_MSG( false, wxT( "It is not fully implemented yet") ); - // I mean it has to be changed in the ACTION_MANAGER, or change the implementation + assert( false ); + // hotkey has to be changed in the ACTION_MANAGER, or change the implementation m_currentHotKey = aNewHotKey; } @@ -105,8 +115,8 @@ public: */ void RestoreHotKey() { - wxASSERT_MSG( false, wxT( "It is not fully implemented yet") ); - // I mean it has to be changed in the ACTION_MANAGER, or change the implementation + assert( false ); + // hotkey has to be changed in the ACTION_MANAGER, or change the implementation m_currentHotKey = m_defaultHotKey; } @@ -134,6 +144,26 @@ public: return TOOL_EVENT( TC_Command, TA_Action, m_name, m_scope ); } + const std::string& GetMenuItem() const + { + return m_menuItem; + } + + void SetMenuItem( const std::string& aItem ) + { + m_menuItem = aItem; + } + + const std::string& GetDescription() const + { + return m_menuDescription; + } + + void SetDescription( const std::string& aDescription ) + { + m_menuDescription = aDescription; + } + private: friend class ACTION_MANAGER; @@ -162,10 +192,10 @@ private: int m_currentHotKey; /// Menu entry text - wxString m_menuItem; + std::string m_menuItem; /// Pop-up help - wxString m_menuDescription; + std::string m_menuDescription; // Icon for menu entry //KiBitmap m_bitmap; @@ -182,4 +212,5 @@ private: /// Originating UI object // wxWindow* m_uiOrigin; }; + #endif