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).
This commit is contained in:
parent
7b7a331645
commit
61066fa608
|
@ -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
|
||||
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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue