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 @@
* 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_manager.h>
#include <tool/tool_interactive.h>
#include <tool/context_menu.h>
#include <cassert>
class CONTEXT_MENU::CMEventHandler : public wxEvtHandler
{
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()
CONTEXT_MENU::CONTEXT_MENU() :
m_titleSet( false ), m_handler( this ), m_tool( NULL )
{
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, 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()
{
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 @@
#include <deque>
#include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/range/adaptor/map.hpp>
......@@ -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<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) );
GetEditFrame()->PopupMenu( menu->GetMenu() );
TOOL_EVENT evt( TC_Command, TA_ContextMenuChoice );
dispatchInternal( evt );
......
......@@ -25,7 +25,8 @@
#ifndef __CONTEXT_MENU_H
#define __CONTEXT_MENU_H
#include <wx/string.h>
#include <wx/menu.h>
#include <tool/tool_action.h>
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<wxMenu*>( &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;
};
......
......@@ -26,7 +26,7 @@
#define __TOOL_ACTION_H
#include <string>
#include <wx/wx.h>
#include <cassert>
#include <tool/tool_base.h>
#include <tool/action_manager.h>
......@@ -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
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