Commit 87b3f2e4 authored by Maciej Suminski's avatar Maciej Suminski

Added Init() to TOOL_INTERACTIVE, allowing to set up things that are needed to...

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.
parent e6c20adc
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tool/tool_event.h> #include <tool/tool_event.h>
#include <tool/tool_action.h> #include <tool/tool_action.h>
#include <cassert>
ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) : ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) :
m_toolMgr( aToolManager ) m_toolMgr( aToolManager )
...@@ -33,15 +34,11 @@ ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) : ...@@ -33,15 +34,11 @@ ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) :
} }
ACTION_MANAGER::~ACTION_MANAGER()
{
}
void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
{ {
int aId = MakeActionId( aAction->m_name ); assert( aAction->GetId() == -1 ); // Check if the TOOL_ACTION was not registered before
aAction->setId( aId );
aAction->setId( MakeActionId( aAction->m_name ) );
m_actionNameIndex[aAction->m_name] = aAction; m_actionNameIndex[aAction->m_name] = aAction;
m_actionIdIndex[aAction->m_id] = aAction; m_actionIdIndex[aAction->m_id] = aAction;
......
...@@ -61,6 +61,9 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) : ...@@ -61,6 +61,9 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) :
m_menu.Append( new wxMenuItem( &m_menu, item->GetId(), item->GetItemLabel(), m_menu.Append( new wxMenuItem( &m_menu, item->GetId(), item->GetItemLabel(),
wxEmptyString, wxITEM_NORMAL ) ); 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 ) ...@@ -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, int id = m_actionId + aAction.GetId();
wxString( aAction.GetDescription() + '\t' + getHotKeyDescription( aAction ) ), wxString menuEntry;
wxEmptyString, wxITEM_NORMAL ) );
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() ...@@ -100,6 +112,8 @@ void CONTEXT_MENU::Clear()
for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i ) for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i )
m_menu.Destroy( m_menu.FindItemByPosition( 0 ) ); m_menu.Destroy( m_menu.FindItemByPosition( 0 ) );
m_toolActions.clear();
} }
...@@ -131,7 +145,17 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent ) ...@@ -131,7 +145,17 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent )
if( type == wxEVT_MENU_HIGHLIGHT ) if( type == wxEVT_MENU_HIGHLIGHT )
evt = TOOL_EVENT( TC_Command, TA_ContextMenuUpdate, aEvent.GetId() ); evt = TOOL_EVENT( TC_Command, TA_ContextMenuUpdate, aEvent.GetId() );
else if( type == wxEVT_COMMAND_MENU_SELECTED ) else if( type == wxEVT_COMMAND_MENU_SELECTED )
{
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() ); evt = TOOL_EVENT( TC_Command, TA_ContextMenuChoice, aEvent.GetId() );
}
}
if( m_menu->m_tool ) if( m_menu->m_tool )
m_menu->m_tool->GetManager()->ProcessEvent( evt ); m_menu->m_tool->GetManager()->ProcessEvent( evt );
......
...@@ -129,7 +129,21 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) ...@@ -129,7 +129,21 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool )
aTool->m_toolMgr = this; aTool->m_toolMgr = this;
if( aTool->GetType() == TOOL_Interactive ) 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: ...@@ -40,7 +40,6 @@ public:
* @param aToolManager is a tool manager instance that is used to pass events to tools. * @param aToolManager is a tool manager instance that is used to pass events to tools.
*/ */
ACTION_MANAGER( TOOL_MANAGER* aToolManager ); ACTION_MANAGER( TOOL_MANAGER* aToolManager );
~ACTION_MANAGER();
/** /**
* Function RegisterAction() * Function RegisterAction()
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <wx/menu.h> #include <wx/menu.h>
#include <tool/tool_action.h> #include <tool/tool_action.h>
#include <map>
class wxMenu; class wxMenu;
class TOOL_INTERACTIVE; class TOOL_INTERACTIVE;
...@@ -46,7 +47,7 @@ public: ...@@ -46,7 +47,7 @@ public:
void SetTitle( const wxString& aTitle ); void SetTitle( const wxString& aTitle );
void Add( const wxString& aLabel, int aId ); void Add( const wxString& aLabel, int aId );
void Add( const TOOL_ACTION& aAction, int aId = -1 ); void Add( const TOOL_ACTION& aAction );
void Clear(); void Clear();
wxMenu* GetMenu() const wxMenu* GetMenu() const
...@@ -87,6 +88,12 @@ private: ...@@ -87,6 +88,12 @@ private:
wxMenu m_menu; wxMenu m_menu;
CMEventHandler m_handler; CMEventHandler m_handler;
TOOL_INTERACTIVE* m_tool; 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 #endif
...@@ -51,6 +51,17 @@ public: ...@@ -51,6 +51,17 @@ public:
*/ */
virtual void Reset() = 0; 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() * Function SetContextMenu()
* *
......
...@@ -49,27 +49,38 @@ MOVE_TOOL::~MOVE_TOOL() ...@@ -49,27 +49,38 @@ MOVE_TOOL::~MOVE_TOOL()
void MOVE_TOOL::Reset() 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 // 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 ) if( selectionTool )
{ {
m_selectionTool = static_cast<SELECTION_TOOL*>( 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 else
{ {
wxLogError( "pcbnew.InteractiveSelection tool is not available" ); wxLogError( "pcbnew.InteractiveSelection tool is not available" );
return; return false;
} }
// Activate hotkeys return true;
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() );
} }
......
...@@ -51,13 +51,12 @@ public: ...@@ -51,13 +51,12 @@ public:
MOVE_TOOL(); MOVE_TOOL();
~MOVE_TOOL(); ~MOVE_TOOL();
/** /// @copydoc TOOL_INTERACTIVE::Reset()
* Function Reset()
*
* Resets the tool and initializes it.
*/
void Reset(); void Reset();
/// @copydoc TOOL_INTERACTIVE::Init()
bool Init();
/** /**
* Function Main() * Function Main()
* *
......
...@@ -45,7 +45,7 @@ void PCB_EDIT_FRAME::setupTools() ...@@ -45,7 +45,7 @@ void PCB_EDIT_FRAME::setupTools()
m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, this ); m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, this );
m_galCanvas->SetEventDispatcher( m_toolDispatcher ); m_galCanvas->SetEventDispatcher( m_toolDispatcher );
// Register tools. // Register tools
m_toolManager->RegisterTool( new SELECTION_TOOL ); m_toolManager->RegisterTool( new SELECTION_TOOL );
m_toolManager->RegisterTool( new ROUTER_TOOL ); m_toolManager->RegisterTool( new ROUTER_TOOL );
m_toolManager->RegisterTool( new MOVE_TOOL ); m_toolManager->RegisterTool( new MOVE_TOOL );
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <cassert>
#include <class_drawpanel_gal.h> #include <class_drawpanel_gal.h>
#include <class_board.h> #include <class_board.h>
...@@ -37,7 +38,6 @@ ...@@ -37,7 +38,6 @@
#include <view/view_controls.h> #include <view/view_controls.h>
#include <painter.h> #include <painter.h>
#include <tool/context_menu.h>
#include <tool/tool_event.h> #include <tool/tool_event.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
...@@ -65,7 +65,6 @@ SELECTION_TOOL::~SELECTION_TOOL() ...@@ -65,7 +65,6 @@ SELECTION_TOOL::~SELECTION_TOOL()
void SELECTION_TOOL::Reset() void SELECTION_TOOL::Reset()
{ {
m_toolMgr->RegisterAction( &m_activate );
m_selectedItems.clear(); m_selectedItems.clear();
// The tool launches upon reception of action event ("pcbnew.InteractiveSelection") // The tool launches upon reception of action event ("pcbnew.InteractiveSelection")
...@@ -73,11 +72,19 @@ void SELECTION_TOOL::Reset() ...@@ -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 ) int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
{ {
BOARD* board = getModel<BOARD>( PCB_T ); BOARD* board = getModel<BOARD>( PCB_T );
wxASSERT( board != NULL ); assert( board != NULL );
// Main loop: keep receiving events // Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
...@@ -91,7 +98,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -91,7 +98,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
if( !m_selectedItems.empty() ) // Cancel event deselects items... if( !m_selectedItems.empty() ) // Cancel event deselects items...
clearSelection(); clearSelection();
else // ...unless there is nothing selected else // ...unless there is nothing selected
break; break; // then exit the tool
} }
// single click? Select single object // single click? Select single object
...@@ -126,12 +133,19 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -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 ) void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem )
{ {
if( m_selectedItems.find( aItem ) != m_selectedItems.end() ) if( m_selectedItems.find( aItem ) != m_selectedItems.end() )
{ {
aItem->ClearSelected(); deselectItem( aItem );
m_selectedItems.erase( aItem );
} }
else else
{ {
...@@ -140,10 +154,7 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) ...@@ -140,10 +154,7 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem )
// Prevent selection of invisible or inactive items // Prevent selection of invisible or inactive items
if( selectable( aItem ) ) if( selectable( aItem ) )
{ selectItem( aItem );
aItem->SetSelected();
m_selectedItems.insert( aItem );
}
} }
} }
...@@ -156,6 +167,9 @@ void SELECTION_TOOL::clearSelection() ...@@ -156,6 +167,9 @@ void SELECTION_TOOL::clearSelection()
} }
m_selectedItems.clear(); 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 ) ...@@ -198,6 +212,7 @@ void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere )
else if( collector.GetCount() > 1 ) else if( collector.GetCount() > 1 )
{ {
item = disambiguationMenu( &collector ); item = disambiguationMenu( &collector );
if( item ) if( item )
toggleSelection( item ); toggleSelection( item );
} }
...@@ -296,6 +311,10 @@ bool SELECTION_TOOL::selectMultiple() ...@@ -296,6 +311,10 @@ bool SELECTION_TOOL::selectMultiple()
m_selectedItems.insert( item ); m_selectedItems.insert( item );
} }
} }
// Now the context menu should be enabled
if( !m_selectedItems.empty() )
SetContextMenu( &m_menu, CMENU_BUTTON );
break; break;
} }
} }
...@@ -312,7 +331,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) ...@@ -312,7 +331,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
{ {
BOARD_ITEM* current = NULL; BOARD_ITEM* current = NULL;
boost::shared_ptr<BRIGHT_BOX> brightBox; boost::shared_ptr<BRIGHT_BOX> brightBox;
CONTEXT_MENU m_menu; CONTEXT_MENU menu;
int limit = std::min( 10, aCollector->GetCount() ); int limit = std::min( 10, aCollector->GetCount() );
for( int i = 0; i < limit; ++i ) for( int i = 0; i < limit; ++i )
...@@ -320,11 +339,11 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) ...@@ -320,11 +339,11 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
wxString text; wxString text;
BOARD_ITEM* item = ( *aCollector )[i]; BOARD_ITEM* item = ( *aCollector )[i];
text = item->GetSelectMenuText(); text = item->GetSelectMenuText();
m_menu.Add( text, i ); menu.Add( text, i );
} }
m_menu.SetTitle( _( "Clarify selection" ) ); menu.SetTitle( _( "Clarify selection" ) );
SetContextMenu( &m_menu, CMENU_NOW ); SetContextMenu( &menu, CMENU_NOW );
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
...@@ -364,6 +383,9 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) ...@@ -364,6 +383,9 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
getView()->MarkTargetDirty( TARGET_OVERLAY ); getView()->MarkTargetDirty( TARGET_OVERLAY );
// Restore the original menu
SetContextMenu( &m_menu, CMENU_BUTTON );
return current; return current;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <math/vector2d.h> #include <math/vector2d.h>
#include <tool/tool_interactive.h> #include <tool/tool_interactive.h>
#include <tool/tool_action.h> #include <tool/tool_action.h>
#include <tool/context_menu.h>
class SELECTION_AREA; class SELECTION_AREA;
class BOARD_ITEM; class BOARD_ITEM;
...@@ -54,13 +55,12 @@ public: ...@@ -54,13 +55,12 @@ public:
SELECTION_TOOL(); SELECTION_TOOL();
~SELECTION_TOOL(); ~SELECTION_TOOL();
/** /// @copydoc TOOL_INTERACTIVE::Reset()
* Function Reset()
*
* Initializes the selection tool.
*/
void Reset(); void Reset();
/// @copydoc TOOL_INTERACTIVE::Init()
bool Init();
/** /**
* Function Main() * Function Main()
* *
...@@ -78,6 +78,14 @@ public: ...@@ -78,6 +78,14 @@ public:
return m_selectedItems; 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: private:
/** /**
* Function selectSingle() * Function selectSingle()
...@@ -135,6 +143,37 @@ private: ...@@ -135,6 +143,37 @@ private:
*/ */
bool selectable( const BOARD_ITEM* aItem ) const; 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() * Function containsSelected()
* Checks if the given point is placed within any of selected items' bounding box. * Checks if the given point is placed within any of selected items' bounding box.
...@@ -157,6 +196,9 @@ private: ...@@ -157,6 +196,9 @@ private:
/// Register hotkey fot activation of the selection tool /// Register hotkey fot activation of the selection tool
TOOL_ACTION m_activate; TOOL_ACTION m_activate;
/// Right click popup menu
CONTEXT_MENU m_menu;
}; };
#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