Commit 61066fa6 authored by Maciej Suminski's avatar Maciej Suminski

Added functions for handling hotkeys, interface for adding TOOL_ACTIONs to CONTEXT_MENU.

Less objects are allocated dynamically.
CONTEXT_MENU is being run using its copy (it saves a hassle of following the lifetime of object).
parent 7b7a3316
...@@ -22,62 +22,45 @@ ...@@ -22,62 +22,45 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <wx/wx.h>
#include <wx/menu.h>
#include <tool/tool_event.h> #include <tool/tool_event.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tool/tool_interactive.h> #include <tool/tool_interactive.h>
#include <tool/context_menu.h> #include <tool/context_menu.h>
#include <cassert>
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.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ),
m_menu = new wxMenu(); NULL, &m_handler );
m_handler = new CMEventHandler( this ); m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ),
m_menu->Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), NULL, &m_handler );
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) // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, 0, m_menu ); wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, 0, &m_menu );
m_menu->AddPendingEvent( menuEvent ); m_menu.AddPendingEvent( menuEvent );
m_titleSet = false;
} }
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; m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ),
delete m_handler; 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 ) ...@@ -86,23 +69,70 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle )
// Unfortunately wxMenu::SetTitle() does nothing.. // Unfortunately wxMenu::SetTitle() does nothing..
if( m_titleSet ) if( m_titleSet )
{ {
m_menu->Delete( m_menu->FindItemByPosition( 0 ) ); // fixme: this is LAME! m_menu.FindItemByPosition( 0 )->SetItemLabel( aTitle );
m_menu->Delete( m_menu->FindItemByPosition( 0 ) ); }
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, aLabel, wxEmptyString, wxITEM_NORMAL ) );
}
void CONTEXT_MENU::Add( const TOOL_ACTION& aAction, int aId )
{ {
m_menu->Append( new wxMenuItem( m_menu, aId, aItem, wxEmptyString, wxITEM_NORMAL ) ); m_menu.Append( new wxMenuItem( &m_menu, aId,
wxString( aAction.GetDescription() + '\t' + getHotKeyDescription( aAction ) ),
wxEmptyString, wxITEM_NORMAL ) );
} }
void CONTEXT_MENU::Clear() void CONTEXT_MENU::Clear()
{ {
m_titleSet = false; 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 );
} }
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <deque> #include <deque>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
...@@ -380,14 +381,15 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) ...@@ -380,14 +381,15 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
{ {
if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( MB_Right ) ) if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( MB_Right ) )
break; break;
st->pendingWait = true; st->pendingWait = true;
st->waitEvents = TOOL_EVENT( TC_Any, TA_Any ); st->waitEvents = TOOL_EVENT( TC_Any, TA_Any );
if( st->contextMenuTrigger == CMENU_NOW ) if( st->contextMenuTrigger == CMENU_NOW )
st->contextMenuTrigger = CMENU_OFF; st->contextMenuTrigger = CMENU_OFF;
GetEditFrame()->PopupMenu( st->contextMenu->GetMenu() ); boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) );
GetEditFrame()->PopupMenu( menu->GetMenu() );
TOOL_EVENT evt( TC_Command, TA_ContextMenuChoice ); TOOL_EVENT evt( TC_Command, TA_ContextMenuChoice );
dispatchInternal( evt ); dispatchInternal( evt );
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
#ifndef __CONTEXT_MENU_H #ifndef __CONTEXT_MENU_H
#define __CONTEXT_MENU_H #define __CONTEXT_MENU_H
#include <wx/string.h> #include <wx/menu.h>
#include <tool/tool_action.h>
class wxMenu; class wxMenu;
class TOOL_INTERACTIVE; class TOOL_INTERACTIVE;
...@@ -41,23 +42,29 @@ class CONTEXT_MENU ...@@ -41,23 +42,29 @@ class CONTEXT_MENU
public: public:
CONTEXT_MENU(); CONTEXT_MENU();
~CONTEXT_MENU(); CONTEXT_MENU( const CONTEXT_MENU& aMenu );
void SetTitle( const wxString& aTitle ); void SetTitle( const wxString& aTitle );
void Add( const wxString& aItem, int aId ); void Add( const wxString& aLabel, int aId );
void Add( const TOOL_ACTION& aAction, int aId = -1 );
// fixme: unimplemented
// void Add ( const TOOL_ACTION& aAction, int aId = -1 );
void Clear(); void Clear();
wxMenu* GetMenu() const wxMenu* GetMenu() const
{ {
return m_menu; return const_cast<wxMenu*>( &m_menu );
} }
private: 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; friend class TOOL_INTERACTIVE;
...@@ -66,10 +73,19 @@ private: ...@@ -66,10 +73,19 @@ private:
m_tool = aTool; 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; bool m_titleSet;
wxMenu* m_menu; wxMenu m_menu;
CMEventHandler* m_handler; CMEventHandler m_handler;
TOOL_INTERACTIVE* m_tool; TOOL_INTERACTIVE* m_tool;
}; };
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#define __TOOL_ACTION_H #define __TOOL_ACTION_H
#include <string> #include <string>
#include <wx/wx.h> #include <cassert>
#include <tool/tool_base.h> #include <tool/tool_base.h>
#include <tool/action_manager.h> #include <tool/action_manager.h>
...@@ -38,8 +38,9 @@ ...@@ -38,8 +38,9 @@
class TOOL_ACTION class TOOL_ACTION
{ {
public: public:
TOOL_ACTION( const std::string& aName, TOOL_ActionScope aScope = AS_CONTEXT, int aDefaultHotKey = 0, TOOL_ACTION( const std::string& aName, TOOL_ActionScope aScope = AS_CONTEXT,
const wxString& aMenuItem = wxT( "" ), const wxString& aMenuDesc = wxT( "" ) ) : 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_name( aName ), m_scope( aScope ), m_defaultHotKey( aDefaultHotKey ),
m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ), m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ),
m_menuDescription( aMenuDesc ), m_id( -1 ), m_actionMgr( NULL ) m_menuDescription( aMenuDesc ), m_id( -1 ), m_actionMgr( NULL )
...@@ -86,6 +87,15 @@ public: ...@@ -86,6 +87,15 @@ public:
return m_id; return m_id;
} }
/**
* Function GetHotKey()
* Returns the associated hot key.
*/
int GetHotKey() const
{
return m_currentHotKey;
}
/** /**
* Function ChangeHotKey() * Function ChangeHotKey()
* Assigns a new hot key. * Assigns a new hot key.
...@@ -94,8 +104,8 @@ public: ...@@ -94,8 +104,8 @@ public:
*/ */
void ChangeHotKey( int aNewHotKey ) void ChangeHotKey( int aNewHotKey )
{ {
wxASSERT_MSG( false, wxT( "It is not fully implemented yet") ); assert( false );
// I mean it has to be changed in the ACTION_MANAGER, or change the implementation // hotkey has to be changed in the ACTION_MANAGER, or change the implementation
m_currentHotKey = aNewHotKey; m_currentHotKey = aNewHotKey;
} }
...@@ -105,8 +115,8 @@ public: ...@@ -105,8 +115,8 @@ public:
*/ */
void RestoreHotKey() void RestoreHotKey()
{ {
wxASSERT_MSG( false, wxT( "It is not fully implemented yet") ); assert( false );
// I mean it has to be changed in the ACTION_MANAGER, or change the implementation // hotkey has to be changed in the ACTION_MANAGER, or change the implementation
m_currentHotKey = m_defaultHotKey; m_currentHotKey = m_defaultHotKey;
} }
...@@ -134,6 +144,26 @@ public: ...@@ -134,6 +144,26 @@ public:
return TOOL_EVENT( TC_Command, TA_Action, m_name, m_scope ); 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: private:
friend class ACTION_MANAGER; friend class ACTION_MANAGER;
...@@ -162,10 +192,10 @@ private: ...@@ -162,10 +192,10 @@ private:
int m_currentHotKey; int m_currentHotKey;
/// Menu entry text /// Menu entry text
wxString m_menuItem; std::string m_menuItem;
/// Pop-up help /// Pop-up help
wxString m_menuDescription; std::string m_menuDescription;
// Icon for menu entry // Icon for menu entry
//KiBitmap m_bitmap; //KiBitmap m_bitmap;
...@@ -182,4 +212,5 @@ private: ...@@ -182,4 +212,5 @@ private:
/// Originating UI object /// Originating UI object
// wxWindow* m_uiOrigin; // wxWindow* m_uiOrigin;
}; };
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment