Added Init() to TOOL_INTERACTIVE, allowing to set up things that are needed to be initialized only once.
TOOL_ACTIONs can be run from CONTEXT_MENU after adding them. Move tool actions are available to be run from CONTEXT_MENU displayed after right mouse button click on selected items. Added some asserts to check the code.
This commit is contained in:
parent
e6c20adc5a
commit
87b3f2e499
|
@ -26,6 +26,7 @@
|
|||
#include <tool/tool_manager.h>
|
||||
#include <tool/tool_event.h>
|
||||
#include <tool/tool_action.h>
|
||||
#include <cassert>
|
||||
|
||||
ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) :
|
||||
m_toolMgr( aToolManager )
|
||||
|
@ -33,15 +34,11 @@ ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) :
|
|||
}
|
||||
|
||||
|
||||
ACTION_MANAGER::~ACTION_MANAGER()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
|
||||
{
|
||||
int aId = MakeActionId( aAction->m_name );
|
||||
aAction->setId( aId );
|
||||
assert( aAction->GetId() == -1 ); // Check if the TOOL_ACTION was not registered before
|
||||
|
||||
aAction->setId( MakeActionId( aAction->m_name ) );
|
||||
|
||||
m_actionNameIndex[aAction->m_name] = aAction;
|
||||
m_actionIdIndex[aAction->m_id] = aAction;
|
||||
|
|
|
@ -61,6 +61,9 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) :
|
|||
m_menu.Append( new wxMenuItem( &m_menu, item->GetId(), item->GetItemLabel(),
|
||||
wxEmptyString, wxITEM_NORMAL ) );
|
||||
}
|
||||
|
||||
// Copy tool actions that are available to choose from menu
|
||||
m_toolActions = aMenu.m_toolActions;
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,11 +89,20 @@ void CONTEXT_MENU::Add( const wxString& aLabel, int aId )
|
|||
}
|
||||
|
||||
|
||||
void CONTEXT_MENU::Add( const TOOL_ACTION& aAction, int aId )
|
||||
void CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
|
||||
{
|
||||
m_menu.Append( new wxMenuItem( &m_menu, aId,
|
||||
wxString( aAction.GetDescription() + '\t' + getHotKeyDescription( aAction ) ),
|
||||
wxEmptyString, wxITEM_NORMAL ) );
|
||||
int id = m_actionId + aAction.GetId();
|
||||
wxString menuEntry;
|
||||
|
||||
if( aAction.HasHotKey() )
|
||||
menuEntry = wxString( aAction.GetMenuItem() + '\t' + getHotKeyDescription( aAction ) );
|
||||
else
|
||||
menuEntry = wxString( aAction.GetMenuItem() );
|
||||
|
||||
m_menu.Append( new wxMenuItem( &m_menu, id, menuEntry,
|
||||
wxString( aAction.GetDescription() ), wxITEM_NORMAL ) );
|
||||
|
||||
m_toolActions[id] = &aAction;
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,6 +112,8 @@ void CONTEXT_MENU::Clear()
|
|||
|
||||
for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i )
|
||||
m_menu.Destroy( m_menu.FindItemByPosition( 0 ) );
|
||||
|
||||
m_toolActions.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,7 +145,17 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent )
|
|||
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( aEvent.GetId() > m_actionId )
|
||||
{
|
||||
if( m_menu->m_toolActions.count( aEvent.GetId() ) == 1 )
|
||||
evt = m_menu->m_toolActions[aEvent.GetId()]->GetEvent();
|
||||
}
|
||||
else
|
||||
{
|
||||
evt = TOOL_EVENT( TC_Command, TA_ContextMenuChoice, aEvent.GetId() );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_menu->m_tool )
|
||||
m_menu->m_tool->GetManager()->ProcessEvent( evt );
|
||||
|
|
|
@ -129,7 +129,21 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool )
|
|||
aTool->m_toolMgr = this;
|
||||
|
||||
if( aTool->GetType() == TOOL_Interactive )
|
||||
static_cast<TOOL_INTERACTIVE*>( aTool )->Reset();
|
||||
{
|
||||
bool initState = static_cast<TOOL_INTERACTIVE*>( aTool )->Init();
|
||||
if( !initState )
|
||||
{
|
||||
wxLogError( wxT( "Initialization of the %s tool failed" ), aTool->GetName() );
|
||||
|
||||
// Unregister the tool
|
||||
m_toolState.erase( aTool );
|
||||
m_toolNameIndex.erase( aTool->GetName() );
|
||||
m_toolIdIndex.erase( aTool->GetId() );
|
||||
|
||||
delete st;
|
||||
delete aTool;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ public:
|
|||
* @param aToolManager is a tool manager instance that is used to pass events to tools.
|
||||
*/
|
||||
ACTION_MANAGER( TOOL_MANAGER* aToolManager );
|
||||
~ACTION_MANAGER();
|
||||
|
||||
/**
|
||||
* Function RegisterAction()
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <wx/menu.h>
|
||||
#include <tool/tool_action.h>
|
||||
#include <map>
|
||||
|
||||
class wxMenu;
|
||||
class TOOL_INTERACTIVE;
|
||||
|
@ -46,7 +47,7 @@ public:
|
|||
|
||||
void SetTitle( const wxString& aTitle );
|
||||
void Add( const wxString& aLabel, int aId );
|
||||
void Add( const TOOL_ACTION& aAction, int aId = -1 );
|
||||
void Add( const TOOL_ACTION& aAction );
|
||||
void Clear();
|
||||
|
||||
wxMenu* GetMenu() const
|
||||
|
@ -87,6 +88,12 @@ private:
|
|||
wxMenu m_menu;
|
||||
CMEventHandler m_handler;
|
||||
TOOL_INTERACTIVE* m_tool;
|
||||
|
||||
/// Menu items with ID higher than that are considered TOOL_ACTIONs
|
||||
static const int m_actionId = 10000;
|
||||
|
||||
/// Stores tool actions that are choosable from the menu. Does not take the ownership.
|
||||
std::map<int, const TOOL_ACTION*> m_toolActions;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,17 @@ public:
|
|||
*/
|
||||
virtual void Reset() = 0;
|
||||
|
||||
/**
|
||||
* Function Init()
|
||||
* Init() is called once upon a registration of the tool.
|
||||
*
|
||||
* @return True if the initialization went fine, false - otherwise.
|
||||
*/
|
||||
virtual bool Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function SetContextMenu()
|
||||
*
|
||||
|
|
|
@ -49,27 +49,38 @@ MOVE_TOOL::~MOVE_TOOL()
|
|||
|
||||
|
||||
void MOVE_TOOL::Reset()
|
||||
{
|
||||
// The tool launches upon reception of action event ("pcbnew.InteractiveMove")
|
||||
Go( &MOVE_TOOL::Main, m_activate.GetEvent() );
|
||||
}
|
||||
|
||||
|
||||
bool MOVE_TOOL::Init()
|
||||
{
|
||||
// Find the selection tool, so they can cooperate
|
||||
TOOL_BASE* selectionTool = m_toolMgr->FindTool( std::string( "pcbnew.InteractiveSelection" ) );
|
||||
TOOL_BASE* selectionTool = m_toolMgr->FindTool( "pcbnew.InteractiveSelection" );
|
||||
|
||||
if( selectionTool )
|
||||
{
|
||||
m_selectionTool = static_cast<SELECTION_TOOL*>( selectionTool );
|
||||
|
||||
// Activate hot keys
|
||||
m_toolMgr->RegisterAction( &m_activate );
|
||||
m_toolMgr->RegisterAction( &m_rotate );
|
||||
m_toolMgr->RegisterAction( &m_flip );
|
||||
|
||||
// Add context menu entries for the selection tool
|
||||
m_selectionTool->AddMenuItem( m_activate );
|
||||
m_selectionTool->AddMenuItem( m_rotate );
|
||||
m_selectionTool->AddMenuItem( m_flip );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogError( "pcbnew.InteractiveSelection tool is not available" );
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Activate hotkeys
|
||||
m_toolMgr->RegisterAction( &m_activate );
|
||||
m_toolMgr->RegisterAction( &m_rotate );
|
||||
m_toolMgr->RegisterAction( &m_flip );
|
||||
|
||||
// the tool launches upon reception of action event ("pcbnew.InteractiveMove")
|
||||
Go( &MOVE_TOOL::Main, m_activate.GetEvent() );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -51,13 +51,12 @@ public:
|
|||
MOVE_TOOL();
|
||||
~MOVE_TOOL();
|
||||
|
||||
/**
|
||||
* Function Reset()
|
||||
*
|
||||
* Resets the tool and initializes it.
|
||||
*/
|
||||
/// @copydoc TOOL_INTERACTIVE::Reset()
|
||||
void Reset();
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Init()
|
||||
bool Init();
|
||||
|
||||
/**
|
||||
* Function Main()
|
||||
*
|
||||
|
|
|
@ -45,7 +45,7 @@ void PCB_EDIT_FRAME::setupTools()
|
|||
m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, this );
|
||||
m_galCanvas->SetEventDispatcher( m_toolDispatcher );
|
||||
|
||||
// Register tools.
|
||||
// Register tools
|
||||
m_toolManager->RegisterTool( new SELECTION_TOOL );
|
||||
m_toolManager->RegisterTool( new ROUTER_TOOL );
|
||||
m_toolManager->RegisterTool( new MOVE_TOOL );
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <cassert>
|
||||
|
||||
#include <class_drawpanel_gal.h>
|
||||
#include <class_board.h>
|
||||
|
@ -37,7 +38,6 @@
|
|||
#include <view/view_controls.h>
|
||||
#include <painter.h>
|
||||
|
||||
#include <tool/context_menu.h>
|
||||
#include <tool/tool_event.h>
|
||||
#include <tool/tool_manager.h>
|
||||
|
||||
|
@ -65,7 +65,6 @@ SELECTION_TOOL::~SELECTION_TOOL()
|
|||
|
||||
void SELECTION_TOOL::Reset()
|
||||
{
|
||||
m_toolMgr->RegisterAction( &m_activate );
|
||||
m_selectedItems.clear();
|
||||
|
||||
// The tool launches upon reception of action event ("pcbnew.InteractiveSelection")
|
||||
|
@ -73,11 +72,19 @@ void SELECTION_TOOL::Reset()
|
|||
}
|
||||
|
||||
|
||||
bool SELECTION_TOOL::Init()
|
||||
{
|
||||
m_toolMgr->RegisterAction( &m_activate );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
|
||||
{
|
||||
BOARD* board = getModel<BOARD>( PCB_T );
|
||||
|
||||
wxASSERT( board != NULL );
|
||||
assert( board != NULL );
|
||||
|
||||
// Main loop: keep receiving events
|
||||
while( OPT_TOOL_EVENT evt = Wait() )
|
||||
|
@ -91,7 +98,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
if( !m_selectedItems.empty() ) // Cancel event deselects items...
|
||||
clearSelection();
|
||||
else // ...unless there is nothing selected
|
||||
break;
|
||||
break; // then exit the tool
|
||||
}
|
||||
|
||||
// single click? Select single object
|
||||
|
@ -126,12 +133,19 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction )
|
||||
{
|
||||
assert( aAction.GetId() > 0 ); // Check if the action was registered before
|
||||
|
||||
m_menu.Add( aAction );
|
||||
}
|
||||
|
||||
|
||||
void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem )
|
||||
{
|
||||
if( m_selectedItems.find( aItem ) != m_selectedItems.end() )
|
||||
{
|
||||
aItem->ClearSelected();
|
||||
m_selectedItems.erase( aItem );
|
||||
deselectItem( aItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -140,10 +154,7 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem )
|
|||
|
||||
// Prevent selection of invisible or inactive items
|
||||
if( selectable( aItem ) )
|
||||
{
|
||||
aItem->SetSelected();
|
||||
m_selectedItems.insert( aItem );
|
||||
}
|
||||
selectItem( aItem );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,6 +167,9 @@ void SELECTION_TOOL::clearSelection()
|
|||
}
|
||||
|
||||
m_selectedItems.clear();
|
||||
|
||||
// Do not show the context menu when there is nothing selected
|
||||
SetContextMenu( &m_menu, CMENU_OFF );
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,6 +212,7 @@ void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere )
|
|||
else if( collector.GetCount() > 1 )
|
||||
{
|
||||
item = disambiguationMenu( &collector );
|
||||
|
||||
if( item )
|
||||
toggleSelection( item );
|
||||
}
|
||||
|
@ -296,6 +311,10 @@ bool SELECTION_TOOL::selectMultiple()
|
|||
m_selectedItems.insert( item );
|
||||
}
|
||||
}
|
||||
|
||||
// Now the context menu should be enabled
|
||||
if( !m_selectedItems.empty() )
|
||||
SetContextMenu( &m_menu, CMENU_BUTTON );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +331,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
|
|||
{
|
||||
BOARD_ITEM* current = NULL;
|
||||
boost::shared_ptr<BRIGHT_BOX> brightBox;
|
||||
CONTEXT_MENU m_menu;
|
||||
CONTEXT_MENU menu;
|
||||
|
||||
int limit = std::min( 10, aCollector->GetCount() );
|
||||
for( int i = 0; i < limit; ++i )
|
||||
|
@ -320,11 +339,11 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
|
|||
wxString text;
|
||||
BOARD_ITEM* item = ( *aCollector )[i];
|
||||
text = item->GetSelectMenuText();
|
||||
m_menu.Add( text, i );
|
||||
menu.Add( text, i );
|
||||
}
|
||||
|
||||
m_menu.SetTitle( _( "Clarify selection" ) );
|
||||
SetContextMenu( &m_menu, CMENU_NOW );
|
||||
menu.SetTitle( _( "Clarify selection" ) );
|
||||
SetContextMenu( &menu, CMENU_NOW );
|
||||
|
||||
while( OPT_TOOL_EVENT evt = Wait() )
|
||||
{
|
||||
|
@ -364,6 +383,9 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
|
|||
|
||||
getView()->MarkTargetDirty( TARGET_OVERLAY );
|
||||
|
||||
// Restore the original menu
|
||||
SetContextMenu( &m_menu, CMENU_BUTTON );
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <math/vector2d.h>
|
||||
#include <tool/tool_interactive.h>
|
||||
#include <tool/tool_action.h>
|
||||
#include <tool/context_menu.h>
|
||||
|
||||
class SELECTION_AREA;
|
||||
class BOARD_ITEM;
|
||||
|
@ -54,13 +55,12 @@ public:
|
|||
SELECTION_TOOL();
|
||||
~SELECTION_TOOL();
|
||||
|
||||
/**
|
||||
* Function Reset()
|
||||
*
|
||||
* Initializes the selection tool.
|
||||
*/
|
||||
/// @copydoc TOOL_INTERACTIVE::Reset()
|
||||
void Reset();
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Init()
|
||||
bool Init();
|
||||
|
||||
/**
|
||||
* Function Main()
|
||||
*
|
||||
|
@ -78,6 +78,14 @@ public:
|
|||
return m_selectedItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function AddAction()
|
||||
*
|
||||
* Adds a menu entry to run a TOOL_ACTION on selected items.
|
||||
* @param aAction is a menu entry to be added.
|
||||
*/
|
||||
void AddMenuItem( const TOOL_ACTION& aAction );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function selectSingle()
|
||||
|
@ -135,6 +143,37 @@ private:
|
|||
*/
|
||||
bool selectable( const BOARD_ITEM* aItem ) const;
|
||||
|
||||
/**
|
||||
* Function selectItem()
|
||||
* Takes necessary action mark an item as selected.
|
||||
*
|
||||
* @param aItem is an item to be selected.
|
||||
*/
|
||||
void selectItem( BOARD_ITEM* aItem )
|
||||
{
|
||||
aItem->SetSelected();
|
||||
m_selectedItems.insert( aItem );
|
||||
|
||||
// Now the context menu should be enabled
|
||||
SetContextMenu( &m_menu, CMENU_BUTTON );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function deselectItem()
|
||||
* Takes necessary action mark an item as deselected.
|
||||
*
|
||||
* @param aItem is an item to be deselected.
|
||||
*/
|
||||
void deselectItem( BOARD_ITEM* aItem )
|
||||
{
|
||||
aItem->ClearSelected();
|
||||
m_selectedItems.erase( aItem );
|
||||
|
||||
if( m_selectedItems.empty() )
|
||||
// If there is nothing selected, disable the context menu
|
||||
SetContextMenu( &m_menu, CMENU_OFF );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function containsSelected()
|
||||
* Checks if the given point is placed within any of selected items' bounding box.
|
||||
|
@ -157,6 +196,9 @@ private:
|
|||
|
||||
/// Register hotkey fot activation of the selection tool
|
||||
TOOL_ACTION m_activate;
|
||||
|
||||
/// Right click popup menu
|
||||
CONTEXT_MENU m_menu;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue