Removed TA_ActivateTool (now tools are invoked by sending TA_Action event, with the tool name as string parameter).
Developed TOOL_Action class & added ActionManager. Hot keys registered by tools are processed. Selection & move tool can be invoked by a hot key.
This commit is contained in:
parent
eb784536af
commit
2c03bf4109
|
@ -162,6 +162,7 @@ set(COMMON_SRCS
|
||||||
tool/tool_dispatcher.cpp
|
tool/tool_dispatcher.cpp
|
||||||
tool/tool_event.cpp
|
tool/tool_event.cpp
|
||||||
tool/tool_interactive.cpp
|
tool/tool_interactive.cpp
|
||||||
|
tool/action_manager.cpp
|
||||||
tool/context_menu.cpp
|
tool/context_menu.cpp
|
||||||
|
|
||||||
geometry/seg.cpp
|
geometry/seg.cpp
|
||||||
|
|
|
@ -83,9 +83,9 @@ const std::string TOOL_EVENT::Format() const
|
||||||
{ TA_ViewDirty, "view-dirty" },
|
{ TA_ViewDirty, "view-dirty" },
|
||||||
{ TA_ChangeLayer, "change-layer" },
|
{ TA_ChangeLayer, "change-layer" },
|
||||||
{ TA_CancelTool, "cancel-tool" },
|
{ TA_CancelTool, "cancel-tool" },
|
||||||
{ TA_ActivateTool, "activate-tool" },
|
|
||||||
{ TA_ContextMenuUpdate, "context-menu-update" },
|
{ TA_ContextMenuUpdate, "context-menu-update" },
|
||||||
{ TA_ContextMenuChoice, "context-menu-choice" },
|
{ TA_ContextMenuChoice, "context-menu-choice" },
|
||||||
|
{ TA_Action, "action" },
|
||||||
{ 0, "" }
|
{ 0, "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -82,9 +82,8 @@ struct TOOL_MANAGER::TOOL_STATE
|
||||||
|
|
||||||
|
|
||||||
TOOL_MANAGER::TOOL_MANAGER() :
|
TOOL_MANAGER::TOOL_MANAGER() :
|
||||||
m_model( NULL ), m_view( NULL )
|
m_actionMgr( this ), m_model( NULL ), m_view( NULL )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,38 +127,79 @@ bool TOOL_MANAGER::InvokeTool( TOOL_ID aToolId )
|
||||||
TOOL_BASE* tool = FindTool( aToolId );
|
TOOL_BASE* tool = FindTool( aToolId );
|
||||||
|
|
||||||
if( tool && tool->GetType() == TOOL_Interactive )
|
if( tool && tool->GetType() == TOOL_Interactive )
|
||||||
{
|
return invokeTool( tool );
|
||||||
// If the tool is already active, do not invoke it again
|
|
||||||
if( m_toolIdIndex[aToolId]->idle == false )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_toolIdIndex[aToolId]->idle = false;
|
|
||||||
static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
|
|
||||||
|
|
||||||
TOOL_EVENT evt( TC_Command, TA_ActivateTool, tool->GetName() );
|
|
||||||
ProcessEvent( evt );
|
|
||||||
|
|
||||||
// Save the tool on the front of the processing queue
|
|
||||||
m_activeTools.push_front( aToolId );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TOOL_MANAGER::InvokeTool( const std::string& aName )
|
bool TOOL_MANAGER::InvokeTool( const std::string& aToolName )
|
||||||
{
|
{
|
||||||
TOOL_BASE* tool = FindTool( aName );
|
TOOL_BASE* tool = FindTool( aToolName );
|
||||||
|
|
||||||
if( tool )
|
if( tool && tool->GetType() == TOOL_Interactive )
|
||||||
return InvokeTool( tool->GetId() );
|
return invokeTool( tool );
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::invokeTool( TOOL_BASE* aTool )
|
||||||
|
{
|
||||||
|
wxASSERT( aTool != NULL );
|
||||||
|
|
||||||
|
TOOL_EVENT evt( TC_Command, TA_Action, aTool->GetName() );
|
||||||
|
ProcessEvent( evt );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::runTool( TOOL_ID aToolId )
|
||||||
|
{
|
||||||
|
TOOL_BASE* tool = FindTool( aToolId );
|
||||||
|
|
||||||
|
if( tool && tool->GetType() == TOOL_Interactive )
|
||||||
|
return runTool( tool );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::runTool( const std::string& aToolName )
|
||||||
|
{
|
||||||
|
TOOL_BASE* tool = FindTool( aToolName );
|
||||||
|
|
||||||
|
if( tool && tool->GetType() == TOOL_Interactive )
|
||||||
|
return runTool( tool );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::runTool( TOOL_BASE* aTool )
|
||||||
|
{
|
||||||
|
wxASSERT( aTool != NULL );
|
||||||
|
|
||||||
|
if( !isRegistered( aTool ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TOOL_STATE* state = m_toolState[aTool];
|
||||||
|
|
||||||
|
// If the tool is already active, do not invoke it again
|
||||||
|
if( state->idle == false )
|
||||||
|
return false;
|
||||||
|
state->idle = false;
|
||||||
|
|
||||||
|
static_cast<TOOL_INTERACTIVE*>( aTool )->Reset();
|
||||||
|
|
||||||
|
// Add the tool on the front of the processing queue (it gets events first)
|
||||||
|
m_activeTools.push_front( aTool->GetId() );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TOOL_BASE* TOOL_MANAGER::FindTool( int aId ) const
|
TOOL_BASE* TOOL_MANAGER::FindTool( int aId ) const
|
||||||
{
|
{
|
||||||
std::map<TOOL_ID, TOOL_STATE*>::const_iterator it = m_toolIdIndex.find( aId );
|
std::map<TOOL_ID, TOOL_STATE*>::const_iterator it = m_toolIdIndex.find( aId );
|
||||||
|
@ -228,7 +268,8 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
|
||||||
finishTool( st );
|
finishTool( st );
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tool requested to stop propagating event to other tools
|
// If the tool did not request to propagate
|
||||||
|
// the event to other tools, we should stop it now
|
||||||
if( !m_passEvent )
|
if( !m_passEvent )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +310,21 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values )
|
||||||
|
{
|
||||||
|
if( st->theTool->GetName() == aEvent.m_commandStr )
|
||||||
|
{
|
||||||
|
runTool( st->theTool );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TOOL_MANAGER::finishTool( TOOL_STATE* aState )
|
void TOOL_MANAGER::finishTool( TOOL_STATE* aState )
|
||||||
{
|
{
|
||||||
wxASSERT( m_activeTools.front() == aState->theTool->GetId() );
|
wxASSERT( m_activeTools.front() == aState->theTool->GetId() );
|
||||||
|
@ -286,6 +342,16 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
// wxLogDebug( "event: %s", aEvent.Format().c_str() );
|
// wxLogDebug( "event: %s", aEvent.Format().c_str() );
|
||||||
|
|
||||||
|
if( aEvent.Action() == TA_KeyUp )
|
||||||
|
{
|
||||||
|
// Check if there is a hotkey associated
|
||||||
|
if( m_actionMgr.RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) )
|
||||||
|
return false; // hotkey event was handled so it does not go any further
|
||||||
|
} else if( aEvent.Category() == TC_Command ) // it may be a tool activation event
|
||||||
|
{
|
||||||
|
dispatchActivation( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
dispatchInternal( aEvent );
|
dispatchInternal( aEvent );
|
||||||
|
|
||||||
BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
|
BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
|
||||||
|
@ -359,3 +425,12 @@ void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KiGfx::VIEW* aView,
|
||||||
static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
|
static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::isActive( TOOL_BASE* aTool )
|
||||||
|
{
|
||||||
|
if( !isRegistered( aTool ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !m_toolState[aTool]->idle;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef __TOOL_ACTION_H
|
#ifndef __TOOL_ACTION_H
|
||||||
#define __TOOL_ACTION_H
|
#define __TOOL_ACTION_H
|
||||||
|
|
||||||
|
@ -5,12 +29,7 @@
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
|
|
||||||
#include <tool/tool_base.h>
|
#include <tool/tool_base.h>
|
||||||
|
#include <tool/action_manager.h>
|
||||||
///> Scope of tool actions
|
|
||||||
enum TOOL_ActionScope {
|
|
||||||
SCOPE_CONTEXT = 1, ///> Action belongs to a particular tool (i.e. a part of a pop-up menu)
|
|
||||||
SCOPE_GLOBAL ///> Global action (toolbar/main menu event, global shortcut)
|
|
||||||
};
|
|
||||||
|
|
||||||
// TOOL_ACTION - represents a single action. For instance:
|
// TOOL_ACTION - represents a single action. For instance:
|
||||||
// - changing layer to top by pressing PgUp
|
// - changing layer to top by pressing PgUp
|
||||||
|
@ -18,69 +37,149 @@ enum TOOL_ActionScope {
|
||||||
// and so on, and so forth....
|
// and so on, and so forth....
|
||||||
class TOOL_ACTION
|
class TOOL_ACTION
|
||||||
{
|
{
|
||||||
public:
|
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
|
m_name( aName ), m_scope( aScope ), m_defaultHotKey( aDefaultHotKey ),
|
||||||
(
|
m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ),
|
||||||
const std::string& name,
|
m_menuDescription( aMenuDesc ), m_id( -1 ), m_actionMgr( NULL )
|
||||||
TOOL_ActionScope scope = SCOPE_GLOBAL,
|
|
||||||
int aDefaultHotKey = 0,
|
|
||||||
const wxString& menuItem = wxT(""),
|
|
||||||
const wxString& menuDesc = wxT("")
|
|
||||||
) :
|
|
||||||
m_name(name),
|
|
||||||
m_scope(scope),
|
|
||||||
m_defaultHotKey(aDefaultHotKey),
|
|
||||||
m_currentHotKey(aDefaultHotKey),
|
|
||||||
m_menuItem(menuItem),
|
|
||||||
m_menuDescription(menuDesc) {}
|
|
||||||
|
|
||||||
bool operator == ( const TOOL_ACTION& rhs ) const
|
|
||||||
{
|
{
|
||||||
return m_id == rhs.m_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator != ( const TOOL_ACTION& rhs ) const
|
~TOOL_ACTION()
|
||||||
{
|
{
|
||||||
return m_id != rhs.m_id;
|
if( m_actionMgr )
|
||||||
|
m_actionMgr->UnregisterAction( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasHotKey() const
|
bool operator==( const TOOL_ACTION& aRhs ) const
|
||||||
|
{
|
||||||
|
return m_id == aRhs.m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=( const TOOL_ACTION& aRhs ) const
|
||||||
|
{
|
||||||
|
return m_id != aRhs.m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetName()
|
||||||
|
* Returns name of the action. It is the same one that is contained in TOOL_EVENT that is
|
||||||
|
* sent by activating the TOOL_ACTION.
|
||||||
|
*
|
||||||
|
* @return Name of the action.
|
||||||
|
*/
|
||||||
|
const std::string& GetName() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetId()
|
||||||
|
* Returns the unique id of the TOOL_ACTION object. It is valid only after registering the
|
||||||
|
* TOOL_ACTION by ACTION_MANAGER.
|
||||||
|
*
|
||||||
|
* @return The unique identification number. If the number is negative, then it is not valid.
|
||||||
|
*/
|
||||||
|
int GetId() const
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ChangeHotKey()
|
||||||
|
* Assigns a new hot key.
|
||||||
|
*
|
||||||
|
* @param aNewHotKey is the new hot key.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
m_currentHotKey = aNewHotKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function RestoreHotKey()
|
||||||
|
* Changes the assigned hot key to the default one.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
m_currentHotKey = m_defaultHotKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function HasHotKey()
|
||||||
|
* Checks if the action has a hot key assigned.
|
||||||
|
*
|
||||||
|
* @return True if there is a hot key assigned, false otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool HasHotKey() const
|
||||||
{
|
{
|
||||||
return m_currentHotKey > 0;
|
return m_currentHotKey > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
/**
|
||||||
friend class TOOL_MANAGER;
|
* Function GetEvent()
|
||||||
|
* Returns the event associated with the action (ie. the event that will be sent after
|
||||||
|
* activating the action).
|
||||||
|
*
|
||||||
|
* @return The event associated with the action.
|
||||||
|
*/
|
||||||
|
TOOL_EVENT GetEvent() const
|
||||||
|
{
|
||||||
|
return TOOL_EVENT( TC_Command, TA_Action, m_name, m_scope );
|
||||||
|
}
|
||||||
|
|
||||||
void setId ( int aId )
|
private:
|
||||||
|
friend class ACTION_MANAGER;
|
||||||
|
|
||||||
|
/// Assigns an unique identifier. It is given by an instance of ACTION_MANAGER.
|
||||||
|
void setId( int aId )
|
||||||
{
|
{
|
||||||
m_id = aId;
|
m_id = aId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assigns ACTION_MANAGER object that handles the TOOL_ACTION.
|
||||||
|
void setActionMgr( ACTION_MANAGER* aManager )
|
||||||
|
{
|
||||||
|
m_actionMgr = aManager;
|
||||||
|
}
|
||||||
|
|
||||||
// name of the action (convention is: app.[tool.]action.name)
|
/// Name of the action (convention is: app.[tool.]action.name)
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
|
/// Scope of the action (ie. the event that is issued after activation).
|
||||||
TOOL_ActionScope m_scope;
|
TOOL_ActionScope m_scope;
|
||||||
int m_defaultHotKey;
|
|
||||||
|
/// Default hot key that activates the action.
|
||||||
|
const int m_defaultHotKey;
|
||||||
|
|
||||||
|
/// Custom assigned hot key that activates the action.
|
||||||
int m_currentHotKey;
|
int m_currentHotKey;
|
||||||
|
|
||||||
// Menu item text
|
/// Menu entry text
|
||||||
wxString m_menuItem;
|
wxString m_menuItem;
|
||||||
// Pop-up help
|
|
||||||
|
/// Pop-up help
|
||||||
wxString m_menuDescription;
|
wxString m_menuDescription;
|
||||||
|
|
||||||
|
// Icon for menu entry
|
||||||
//KiBitmap m_bitmap;
|
//KiBitmap m_bitmap;
|
||||||
|
|
||||||
// Unique ID for fast matching. Assigned by TOOL_MANAGER
|
/// Unique ID for fast matching. Assigned by ACTION_MANAGER.
|
||||||
int m_id;
|
int m_id;
|
||||||
|
|
||||||
// Origin of the action
|
/// Action manager that handles this TOOL_ACTION.
|
||||||
TOOL_BASE *m_origin;
|
ACTION_MANAGER* m_actionMgr;
|
||||||
|
|
||||||
// Originating UI object
|
/// Origin of the action
|
||||||
wxWindow *m_uiOrigin;
|
// const TOOL_BASE* m_origin;
|
||||||
|
|
||||||
|
/// Originating UI object
|
||||||
|
// wxWindow* m_uiOrigin;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -74,15 +74,16 @@ enum TOOL_Actions
|
||||||
// Tool cancel event. Issued automagically when the user hits escape or selects End Tool from the context menu.
|
// Tool cancel event. Issued automagically when the user hits escape or selects End Tool from the context menu.
|
||||||
TA_CancelTool = 0x2000,
|
TA_CancelTool = 0x2000,
|
||||||
|
|
||||||
// Tool activation event. Issued by the GUI upon pressing a button/menu selection.
|
|
||||||
TA_ActivateTool = 0x4000,
|
|
||||||
|
|
||||||
// Context menu update. Issued whenever context menu is open and the user hovers the mouse over one of choices.
|
// Context menu update. Issued whenever context menu is open and the user hovers the mouse over one of choices.
|
||||||
// Used in dynamic highligting in disambiguation menu
|
// Used in dynamic highligting in disambiguation menu
|
||||||
TA_ContextMenuUpdate = 0x8000,
|
TA_ContextMenuUpdate = 0x4000,
|
||||||
|
|
||||||
// Context menu choice. Sent if the user picked something from the context menu or closed it without selecting anything.
|
// Context menu choice. Sent if the user picked something from the context menu or closed it without selecting anything.
|
||||||
TA_ContextMenuChoice = 0x10000,
|
TA_ContextMenuChoice = 0x8000,
|
||||||
|
|
||||||
|
// Tool action
|
||||||
|
TA_Action = 0x10000,
|
||||||
|
|
||||||
TA_Any = 0xffffffff
|
TA_Any = 0xffffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,7 +105,15 @@ enum TOOL_Modifiers
|
||||||
MD_ModifierMask = MD_ModShift | MD_ModCtrl | MD_ModAlt,
|
MD_ModifierMask = MD_ModShift | MD_ModCtrl | MD_ModAlt,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Defines when a context menu is opened.
|
/// Scope of tool actions
|
||||||
|
enum TOOL_ActionScope
|
||||||
|
{
|
||||||
|
AS_CONTEXT = 1, ///> Action belongs to a particular tool (i.e. a part of a pop-up menu)
|
||||||
|
AS_ACTIVE, ///> All active tools
|
||||||
|
AS_GLOBAL ///> Global action (toolbar/main menu event, global shortcut)
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Defines when a context menu is opened.
|
||||||
enum CONTEXT_MENU_TRIGGER
|
enum CONTEXT_MENU_TRIGGER
|
||||||
{
|
{
|
||||||
CMENU_BUTTON = 0, // On the right button
|
CMENU_BUTTON = 0, // On the right button
|
||||||
|
@ -122,16 +131,19 @@ class TOOL_EVENT
|
||||||
public:
|
public:
|
||||||
const std::string Format() const;
|
const std::string Format() const;
|
||||||
|
|
||||||
TOOL_EVENT( TOOL_EventCategory aCategory = TC_None, TOOL_Actions aAction = TA_None ) :
|
TOOL_EVENT( TOOL_EventCategory aCategory = TC_None, TOOL_Actions aAction = TA_None,
|
||||||
|
TOOL_ActionScope aScope = AS_GLOBAL ) :
|
||||||
m_category( aCategory ),
|
m_category( aCategory ),
|
||||||
m_actions( aAction ),
|
m_actions( aAction ),
|
||||||
|
m_scope( aScope ),
|
||||||
m_mouseButtons( 0 ),
|
m_mouseButtons( 0 ),
|
||||||
m_keyCode( 0 ),
|
m_keyCode( 0 ),
|
||||||
m_modifiers( 0 ) {}
|
m_modifiers( 0 ) {}
|
||||||
|
|
||||||
TOOL_EVENT( TOOL_EventCategory aCategory, TOOL_Actions aAction, int aExtraParam ) :
|
TOOL_EVENT( TOOL_EventCategory aCategory, TOOL_Actions aAction, int aExtraParam, TOOL_ActionScope aScope = AS_GLOBAL ) :
|
||||||
m_category( aCategory ),
|
m_category( aCategory ),
|
||||||
m_actions( aAction )
|
m_actions( aAction ),
|
||||||
|
m_scope( aScope )
|
||||||
{
|
{
|
||||||
if( aCategory == TC_Mouse )
|
if( aCategory == TC_Mouse )
|
||||||
{
|
{
|
||||||
|
@ -153,16 +165,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
TOOL_EVENT( TOOL_EventCategory aCategory, TOOL_Actions aAction,
|
TOOL_EVENT( TOOL_EventCategory aCategory, TOOL_Actions aAction,
|
||||||
const std::string& aExtraParam ) :
|
const std::string& aExtraParam, TOOL_ActionScope aScope = AS_GLOBAL ) :
|
||||||
m_category( aCategory ),
|
m_category( aCategory ),
|
||||||
m_actions( aAction ),
|
m_actions( aAction ),
|
||||||
|
m_scope( aScope ),
|
||||||
m_mouseButtons( 0 )
|
m_mouseButtons( 0 )
|
||||||
{
|
{
|
||||||
if( aCategory == TC_Command )
|
if( aCategory == TC_Command )
|
||||||
m_commandStr = aExtraParam;
|
m_commandStr = aExtraParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TOOL_EventCategory Category() const
|
TOOL_EventCategory Category() const
|
||||||
{
|
{
|
||||||
return m_category;
|
return m_category;
|
||||||
|
@ -285,6 +297,7 @@ private:
|
||||||
|
|
||||||
TOOL_EventCategory m_category;
|
TOOL_EventCategory m_category;
|
||||||
TOOL_Actions m_actions;
|
TOOL_Actions m_actions;
|
||||||
|
TOOL_ActionScope m_scope;
|
||||||
|
|
||||||
VECTOR2D m_mouseDelta;
|
VECTOR2D m_mouseDelta;
|
||||||
VECTOR2D m_mousePos;
|
VECTOR2D m_mousePos;
|
||||||
|
@ -314,9 +327,15 @@ public:
|
||||||
TOOL_EVENT_LIST() {};
|
TOOL_EVENT_LIST() {};
|
||||||
TOOL_EVENT_LIST( const TOOL_EVENT& aSingleEvent )
|
TOOL_EVENT_LIST( const TOOL_EVENT& aSingleEvent )
|
||||||
{
|
{
|
||||||
m_events.push_back(aSingleEvent);
|
m_events.push_back( aSingleEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Format()
|
||||||
|
* Returns information about event in form of a human-readable string.
|
||||||
|
*
|
||||||
|
* @return Event information.
|
||||||
|
*/
|
||||||
const std::string Format() const;
|
const std::string Format() const;
|
||||||
|
|
||||||
boost::optional<const TOOL_EVENT&> Matches( const TOOL_EVENT &b ) const
|
boost::optional<const TOOL_EVENT&> Matches( const TOOL_EVENT &b ) const
|
||||||
|
|
|
@ -25,17 +25,14 @@
|
||||||
#ifndef __TOOL_MANAGER_H
|
#ifndef __TOOL_MANAGER_H
|
||||||
#define __TOOL_MANAGER_H
|
#define __TOOL_MANAGER_H
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include <math/vector2d.h>
|
#include <math/vector2d.h>
|
||||||
|
|
||||||
#include <tool/tool_event.h>
|
#include <tool/tool_event.h>
|
||||||
#include <tool/tool_base.h>
|
#include <tool/tool_base.h>
|
||||||
|
#include <tool/action_manager.h>
|
||||||
|
|
||||||
class TOOL_BASE;
|
class TOOL_BASE;
|
||||||
class CONTEXT_MENU;
|
class CONTEXT_MENU;
|
||||||
|
@ -69,24 +66,61 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function InvokeTool()
|
* Function InvokeTool()
|
||||||
* Calls a tool by sending a tool activation event to tool of given ID or name.
|
* Calls a tool by sending a tool activation event to tool of given ID.
|
||||||
* An user-defined parameter object can be also passed
|
|
||||||
*
|
*
|
||||||
|
* @param aToolId is the ID number of the requested tool.
|
||||||
* @return True if the requested tool was invoked successfully.
|
* @return True if the requested tool was invoked successfully.
|
||||||
*/
|
*/
|
||||||
bool InvokeTool( TOOL_ID aToolId );
|
bool InvokeTool( TOOL_ID aToolId );
|
||||||
bool InvokeTool( const std::string& aName );
|
|
||||||
|
|
||||||
template <class Parameters>
|
/**
|
||||||
void InvokeTool( const std::string& aName, const Parameters& aToolParams );
|
* Function InvokeTool()
|
||||||
|
* Calls a tool by sending a tool activation event to tool of given name.
|
||||||
|
*
|
||||||
|
* @param aToolName is the name of the requested tool.
|
||||||
|
* @return True if the requested tool was invoked successfully.
|
||||||
|
*/
|
||||||
|
bool InvokeTool( const std::string& aToolName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function RegisterAction()
|
||||||
|
* Registers an action that can be used to control tools (eg. invoke, trigger specific
|
||||||
|
* behaviours).
|
||||||
|
*
|
||||||
|
* @param aAction is the action to be registered.
|
||||||
|
*/
|
||||||
|
void RegisterAction( TOOL_ACTION* aAction )
|
||||||
|
{
|
||||||
|
m_actionMgr.RegisterAction( aAction );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function UnregisterAction()
|
||||||
|
* Unregisters an action, so it is no longer active.
|
||||||
|
*
|
||||||
|
* @param aAction is the action to be unregistered.
|
||||||
|
*/
|
||||||
|
void UnregisterAction( TOOL_ACTION* aAction )
|
||||||
|
{
|
||||||
|
m_actionMgr.UnregisterAction( aAction );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function FindTool()
|
* Function FindTool()
|
||||||
* Searches for a tool with given name or ID
|
* Searches for a tool with given ID.
|
||||||
*
|
*
|
||||||
* @return Pointer to the request tool of NULL in case of failure.
|
* @param aId is the ID number of the requested tool.
|
||||||
|
* @return Pointer to the requested tool or NULL in case of failure.
|
||||||
*/
|
*/
|
||||||
TOOL_BASE* FindTool( int aId ) const;
|
TOOL_BASE* FindTool( int aId ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindTool()
|
||||||
|
* Searches for a tool with given name.
|
||||||
|
*
|
||||||
|
* @param aName is the name of the requested tool.
|
||||||
|
* @return Pointer to the requested tool or NULL in case of failure.
|
||||||
|
*/
|
||||||
TOOL_BASE* FindTool( const std::string& aName ) const;
|
TOOL_BASE* FindTool( const std::string& aName ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -170,19 +204,103 @@ private:
|
||||||
typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> TRANSITION;
|
typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> TRANSITION;
|
||||||
|
|
||||||
void dispatchInternal( TOOL_EVENT& aEvent );
|
void dispatchInternal( TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function dispatchActivation()
|
||||||
|
* Checks if it is a valid activation event and invokes a proper tool.
|
||||||
|
* @param aEvent is an event to be tested.
|
||||||
|
* @return True if a tool was invoked, false otherwise.
|
||||||
|
*/
|
||||||
|
bool dispatchActivation( TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function invokeTool()
|
||||||
|
* Invokes a tool by sending a proper event.
|
||||||
|
* @param aTool is the tool to be invoked.
|
||||||
|
*/
|
||||||
|
bool invokeTool( TOOL_BASE* aTool );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function runTool()
|
||||||
|
* Makes a tool active, so it can receive events and react to them. Activated tool is pushed
|
||||||
|
* on the active tools stack, so the last activated tool receives events first.
|
||||||
|
*
|
||||||
|
* @param aToolId is the ID number of tool to be run.
|
||||||
|
*/
|
||||||
|
bool runTool( TOOL_ID aToolId );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function runTool()
|
||||||
|
* Makes a tool active, so it can receive events and react to them. Activated tool is pushed
|
||||||
|
* on the active tools stack, so the last activated tool receives events first.
|
||||||
|
*
|
||||||
|
* @param aToolId is the name of tool to be run.
|
||||||
|
*/
|
||||||
|
bool runTool( const std::string& aName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function runTool()
|
||||||
|
* Makes a tool active, so it can receive events and react to them. Activated tool is pushed
|
||||||
|
* on the active tools stack, so the last activated tool receives events first.
|
||||||
|
*
|
||||||
|
* @param aToolId is the tool to be run.
|
||||||
|
*/
|
||||||
|
bool runTool( TOOL_BASE* aTool );
|
||||||
|
|
||||||
|
template <class Parameters>
|
||||||
|
void invokeTool( const std::string& aName, const Parameters& aToolParams );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function finishTool()
|
||||||
|
* Deactivates a tool and does the necessary clean up.
|
||||||
|
*
|
||||||
|
* @param aState is the state variable of the tool to be stopped.
|
||||||
|
*/
|
||||||
void finishTool( TOOL_STATE* aState );
|
void finishTool( TOOL_STATE* aState );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function isRegistered()
|
||||||
|
* Returns information about a tool registration status.
|
||||||
|
*
|
||||||
|
* @param aTool is the tool to be checked.
|
||||||
|
* @return True if the tool is in the registered tools list, false otherwise.
|
||||||
|
*/
|
||||||
|
bool isRegistered( TOOL_BASE* aTool ) const
|
||||||
|
{
|
||||||
|
return ( m_toolState.count( aTool ) > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function isActive()
|
||||||
|
* Returns information about a tool activation status.
|
||||||
|
*
|
||||||
|
* @param aTool is the tool to be checked.
|
||||||
|
* @return True if the tool is on the active tools stack, false otherwise.
|
||||||
|
*/
|
||||||
|
bool isActive( TOOL_BASE* aTool );
|
||||||
|
|
||||||
|
/// Index of registered tools current states, associated by tools' objects.
|
||||||
std::map<TOOL_BASE*, TOOL_STATE*> m_toolState;
|
std::map<TOOL_BASE*, TOOL_STATE*> m_toolState;
|
||||||
|
|
||||||
|
/// Index of the registered tools current states, associated by tools' names.
|
||||||
std::map<std::string, TOOL_STATE*> m_toolNameIndex;
|
std::map<std::string, TOOL_STATE*> m_toolNameIndex;
|
||||||
|
|
||||||
|
/// Index of the registered tools current states, associated by tools' ID numbers.
|
||||||
std::map<TOOL_ID, TOOL_STATE*> m_toolIdIndex;
|
std::map<TOOL_ID, TOOL_STATE*> m_toolIdIndex;
|
||||||
|
|
||||||
|
/// Stack of the active tools
|
||||||
std::deque<TOOL_ID> m_activeTools;
|
std::deque<TOOL_ID> m_activeTools;
|
||||||
|
|
||||||
|
ACTION_MANAGER m_actionMgr;
|
||||||
EDA_ITEM* m_model;
|
EDA_ITEM* m_model;
|
||||||
KiGfx::VIEW* m_view;
|
KiGfx::VIEW* m_view;
|
||||||
KiGfx::VIEW_CONTROLS* m_viewControls;
|
KiGfx::VIEW_CONTROLS* m_viewControls;
|
||||||
wxWindow* m_editFrame;
|
wxWindow* m_editFrame;
|
||||||
|
|
||||||
|
/// Flag saying if the currently processed event should be passed to other tools.
|
||||||
bool m_passEvent;
|
bool m_passEvent;
|
||||||
|
|
||||||
|
/// Pointer to the tool on the top of the active tools stack.
|
||||||
TOOL_STATE* m_currentTool;
|
TOOL_STATE* m_currentTool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace KiGfx
|
||||||
class VIEW_GROUP : public VIEW_ITEM
|
class VIEW_GROUP : public VIEW_ITEM
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VIEW_GROUP( VIEW* aView );
|
VIEW_GROUP( VIEW* aView = NULL );
|
||||||
virtual ~VIEW_GROUP();
|
virtual ~VIEW_GROUP();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -42,11 +42,11 @@ using namespace KiGfx;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
|
|
||||||
static TOOL_ACTION ACT_AutoEndRoute ( "AutoEndRoute", SCOPE_CONTEXT, 'F' );
|
static TOOL_ACTION ACT_AutoEndRoute ( "AutoEndRoute", AS_CONTEXT, 'F' );
|
||||||
static TOOL_ACTION ACT_PlaceVia ( "PlaceVia", SCOPE_CONTEXT, 'V' );
|
static TOOL_ACTION ACT_PlaceVia ( "PlaceVia", AS_CONTEXT, 'V' );
|
||||||
static TOOL_ACTION ACT_OpenRouteOptions ( "OpenRouterOptions", SCOPE_CONTEXT, 'E' );
|
static TOOL_ACTION ACT_OpenRouteOptions ( "OpenRouterOptions", AS_CONTEXT, 'E' );
|
||||||
static TOOL_ACTION ACT_SwitchPosture ( "SwitchPosture", SCOPE_CONTEXT, '/' );
|
static TOOL_ACTION ACT_SwitchPosture ( "SwitchPosture", AS_CONTEXT, '/' );
|
||||||
static TOOL_ACTION ACT_EndTrack ( "SwitchPosture", SCOPE_CONTEXT, WXK_END );
|
static TOOL_ACTION ACT_EndTrack ( "SwitchPosture", AS_CONTEXT, WXK_END );
|
||||||
|
|
||||||
ROUTER_TOOL::ROUTER_TOOL() :
|
ROUTER_TOOL::ROUTER_TOOL() :
|
||||||
TOOL_INTERACTIVE( "pcbnew.InteractiveRouter" )
|
TOOL_INTERACTIVE( "pcbnew.InteractiveRouter" )
|
||||||
|
@ -88,7 +88,7 @@ void ROUTER_TOOL::Reset()
|
||||||
if(getView())
|
if(getView())
|
||||||
m_router->SetView( getView() );
|
m_router->SetView( getView() );
|
||||||
|
|
||||||
Go( &ROUTER_TOOL::Main, TOOL_EVENT( TC_Command, TA_ActivateTool, GetName() ) );
|
Go( &ROUTER_TOOL::Main, TOOL_EVENT( TC_Command, TA_Action, GetName() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int ROUTER_TOOL::getDefaultWidth( int aNetCode )
|
int ROUTER_TOOL::getDefaultWidth( int aNetCode )
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
#include <class_module.h>
|
#include <class_module.h>
|
||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
#include <view/view_group.h>
|
#include <tool/tool_action.h>
|
||||||
#include <view/view_controls.h>
|
#include <view/view_controls.h>
|
||||||
|
|
||||||
#include "selection_tool.h"
|
#include "selection_tool.h"
|
||||||
|
@ -35,7 +35,8 @@ using namespace KiGfx;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
|
|
||||||
MOVE_TOOL::MOVE_TOOL() :
|
MOVE_TOOL::MOVE_TOOL() :
|
||||||
TOOL_INTERACTIVE( "pcbnew.InteractiveMove" ), m_selectionTool( NULL )
|
TOOL_INTERACTIVE( "pcbnew.InteractiveMove" ), m_selectionTool( NULL ),
|
||||||
|
m_activate( m_toolName, AS_GLOBAL, 'M', "Move", "Moves the selected item(s)" )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +48,8 @@ MOVE_TOOL::~MOVE_TOOL()
|
||||||
|
|
||||||
void MOVE_TOOL::Reset()
|
void MOVE_TOOL::Reset()
|
||||||
{
|
{
|
||||||
|
m_toolMgr->RegisterAction( &m_activate );
|
||||||
|
|
||||||
// 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( std::string( "pcbnew.InteractiveSelection" ) );
|
||||||
|
|
||||||
|
@ -60,8 +63,8 @@ void MOVE_TOOL::Reset()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the tool launches upon reception of activate ("pcbnew.InteractiveMove")
|
// the tool launches upon reception of action event ("pcbnew.InteractiveMove")
|
||||||
Go( &MOVE_TOOL::Main, TOOL_EVENT( TC_Command, TA_ActivateTool, GetName() ) );
|
Go( &MOVE_TOOL::Main, m_activate.GetEvent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,13 +72,12 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
VECTOR2D dragPosition;
|
VECTOR2D dragPosition;
|
||||||
bool dragging = false;
|
bool dragging = false;
|
||||||
bool restore = false;
|
bool restore = false; // Should items' state be restored when finishing the tool?
|
||||||
VIEW* view = m_toolMgr->GetView();
|
VIEW* view = m_toolMgr->GetView();
|
||||||
std::set<BOARD_ITEM*> selection;
|
|
||||||
VIEW_GROUP items( view );
|
|
||||||
|
|
||||||
view->Add( &items );
|
view->Add( &m_items );
|
||||||
m_toolMgr->GetViewControls()->SetSnapping( true );
|
getViewControls()->SetSnapping( true );
|
||||||
|
getViewControls()->SetAutoPan( true );
|
||||||
|
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
|
@ -83,73 +85,68 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
|
||||||
if( evt->IsCancel() )
|
if( evt->IsCancel() )
|
||||||
{
|
{
|
||||||
restore = true;
|
restore = true;
|
||||||
m_toolMgr->PassEvent();
|
|
||||||
break; // Finish
|
break; // Finish
|
||||||
}
|
}
|
||||||
|
|
||||||
if( evt->IsDrag( MB_Left ) )
|
if( evt->IsMotion() || evt->IsDrag( MB_Left ) )
|
||||||
{
|
{
|
||||||
if( dragging )
|
if( dragging )
|
||||||
{
|
{
|
||||||
// Dragging is alre
|
// Dragging is already active
|
||||||
VECTOR2D movement = ( evt->Position() - dragPosition );
|
VECTOR2D movement = ( evt->Position() - dragPosition );
|
||||||
|
|
||||||
std::set<BOARD_ITEM*>::iterator it, it_end;
|
std::set<BOARD_ITEM*>::iterator it, it_end;
|
||||||
for( it = selection.begin(), it_end = selection.end(); it != it_end; ++it )
|
|
||||||
{
|
// so move all the selected items
|
||||||
|
for( it = m_selection.begin(), it_end = m_selection.end(); it != it_end; ++it )
|
||||||
(*it)->Move( wxPoint( movement.x, movement.y ) );
|
(*it)->Move( wxPoint( movement.x, movement.y ) );
|
||||||
}
|
}
|
||||||
items.ViewUpdate( VIEW_ITEM::GEOMETRY );
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Begin dragging
|
// Prepare to drag
|
||||||
selection = m_selectionTool->GetSelection();
|
m_selection = m_selectionTool->GetSelection();
|
||||||
|
if( m_selection.empty() )
|
||||||
|
break; // there are no items to operate on
|
||||||
|
|
||||||
std::set<BOARD_ITEM*>::iterator it;
|
std::set<BOARD_ITEM*>::iterator it;
|
||||||
for( it = selection.begin(); it != selection.end(); ++it )
|
for( it = m_selection.begin(); it != m_selection.end(); ++it )
|
||||||
{
|
{
|
||||||
viewGroupAdd( *it, &items );
|
// Gather all selected items into one VIEW_GROUP
|
||||||
|
viewGroupAdd( *it, &m_items );
|
||||||
|
|
||||||
// but if a MODULE was selected, then we need to redraw all of it's parts
|
// Modules are treated in a special way - when they are moved, we have to
|
||||||
|
// move all the parts that make the module, not the module itself
|
||||||
if( (*it)->Type() == PCB_MODULE_T )
|
if( (*it)->Type() == PCB_MODULE_T )
|
||||||
{
|
{
|
||||||
MODULE* module = static_cast<MODULE*>( *it );
|
MODULE* module = static_cast<MODULE*>( *it );
|
||||||
|
|
||||||
// Move everything that belongs to the module
|
// Add everything that belongs to the module (besides the module itself)
|
||||||
for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
|
for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
|
||||||
viewGroupAdd( pad, &items );
|
viewGroupAdd( pad, &m_items );
|
||||||
|
|
||||||
for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing;
|
for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing;
|
||||||
drawing = drawing->Next() )
|
drawing = drawing->Next() )
|
||||||
viewGroupAdd( drawing, &items );
|
viewGroupAdd( drawing, &m_items );
|
||||||
|
|
||||||
viewGroupAdd( &module->Reference(), &items );
|
viewGroupAdd( &module->Reference(), &m_items );
|
||||||
viewGroupAdd( &module->Value(), &items );
|
viewGroupAdd( &module->Value(), &m_items );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
items.ViewUpdate( VIEW_ITEM::GEOMETRY );
|
|
||||||
|
|
||||||
dragging = true;
|
dragging = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY );
|
||||||
dragPosition = evt->Position();
|
dragPosition = evt->Position();
|
||||||
}
|
}
|
||||||
else if( evt->Category() == TC_Mouse ) // Filter out other events
|
else if( evt->IsMouseUp( MB_Left ) || evt->IsClick( MB_Left ) )
|
||||||
{
|
|
||||||
if( dragging )
|
|
||||||
{
|
|
||||||
break; // Finish
|
break; // Finish
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean-up after movement
|
// Clean-up after movement
|
||||||
std::deque<ITEM_STATE>::iterator it, it_end;
|
std::deque<ITEM_STATE>::iterator it, it_end;
|
||||||
if( restore )
|
if( restore )
|
||||||
{
|
{
|
||||||
// Movement has to be rollbacked, so restore previous state of items
|
// Movement has to be rollbacked, so restore the previous state of items
|
||||||
for( it = m_itemsState.begin(), it_end = m_itemsState.end(); it != it_end; ++it )
|
for( it = m_itemsState.begin(), it_end = m_itemsState.end(); it != it_end; ++it )
|
||||||
it->Restore();
|
it->Restore();
|
||||||
}
|
}
|
||||||
|
@ -164,9 +161,10 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
m_itemsState.clear();
|
m_itemsState.clear();
|
||||||
items.Clear();
|
m_items.Clear();
|
||||||
view->Remove( &items );
|
view->Remove( &m_items );
|
||||||
m_toolMgr->GetViewControls()->SetSnapping( false );
|
getViewControls()->SetSnapping( false );
|
||||||
|
getViewControls()->SetAutoPan( false );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <math/vector2d.h>
|
#include <math/vector2d.h>
|
||||||
#include <tool/tool_interactive.h>
|
#include <tool/tool_interactive.h>
|
||||||
|
#include <view/view_group.h>
|
||||||
|
|
||||||
class BOARD_ITEM;
|
class BOARD_ITEM;
|
||||||
class SELECTION_TOOL;
|
class SELECTION_TOOL;
|
||||||
|
@ -38,13 +39,8 @@ class VIEW_GROUP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class MOVE_TOOL
|
* Class MOVE_TOOL
|
||||||
* /// TODO DOCS!!
|
|
||||||
* Our sample move tool: currently supports:
|
|
||||||
* - pick single objects (click LMB)
|
|
||||||
* - add objects to existing move (Shift+LMB)
|
|
||||||
* - draw move box (drag LMB)
|
|
||||||
*
|
*
|
||||||
* WORK IN PROGRESS. CONSIDER AS A DEMO!
|
* Our sample move tool. Allows to move items selected by pcbnew.InteractiveSelection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MOVE_TOOL : public TOOL_INTERACTIVE
|
class MOVE_TOOL : public TOOL_INTERACTIVE
|
||||||
|
@ -68,6 +64,7 @@ public:
|
||||||
int Main( TOOL_EVENT& aEvent );
|
int Main( TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Adds an item to the VIEW_GROUP that holds all moved items and displays them on the overlay
|
||||||
void viewGroupAdd( BOARD_ITEM* aItem, KiGfx::VIEW_GROUP* aGroup );
|
void viewGroupAdd( BOARD_ITEM* aItem, KiGfx::VIEW_GROUP* aGroup );
|
||||||
|
|
||||||
/// Structure for (re)storing BOARD_ITEM state
|
/// Structure for (re)storing BOARD_ITEM state
|
||||||
|
@ -108,7 +105,17 @@ private:
|
||||||
/// Selection tool used for obtaining selected items
|
/// Selection tool used for obtaining selected items
|
||||||
SELECTION_TOOL* m_selectionTool;
|
SELECTION_TOOL* m_selectionTool;
|
||||||
|
|
||||||
|
/// Stores the initial state of moved items (so it is possible to rollback changes)
|
||||||
std::deque<ITEM_STATE> m_itemsState;
|
std::deque<ITEM_STATE> m_itemsState;
|
||||||
|
|
||||||
|
/// Set of selected items (obtained from pcbnew.
|
||||||
|
std::set<BOARD_ITEM*> m_selection;
|
||||||
|
|
||||||
|
/// VIEW_GROUP that helds currently moved items
|
||||||
|
KiGfx::VIEW_GROUP m_items;
|
||||||
|
|
||||||
|
/// Register hotkey fot activation of the move tool
|
||||||
|
TOOL_ACTION m_activate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 CERN
|
* Copyright (C) 2013 CERN
|
||||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -48,7 +49,8 @@ using namespace KiGfx;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
|
|
||||||
SELECTION_TOOL::SELECTION_TOOL() :
|
SELECTION_TOOL::SELECTION_TOOL() :
|
||||||
TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), m_multiple( false )
|
TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), m_multiple( false ),
|
||||||
|
m_activate( m_toolName, AS_GLOBAL, 'S', "Selection tool", "Allows to select items" )
|
||||||
{
|
{
|
||||||
m_selArea = new SELECTION_AREA;
|
m_selArea = new SELECTION_AREA;
|
||||||
}
|
}
|
||||||
|
@ -63,93 +65,63 @@ 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 activate ("pcbnew.InteractiveSelection")
|
// The tool launches upon reception of action event ("pcbnew.InteractiveSelection")
|
||||||
Go( &SELECTION_TOOL::Main, TOOL_EVENT( TC_Command, TA_ActivateTool, GetName() ) );
|
Go( &SELECTION_TOOL::Main, m_activate.GetEvent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
|
int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
bool dragging = false;
|
|
||||||
bool allowMultiple = true;
|
|
||||||
BOARD* board = getModel<BOARD>( PCB_T );
|
BOARD* board = getModel<BOARD>( PCB_T );
|
||||||
|
|
||||||
if( !board )
|
wxASSERT( board != NULL );
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
{
|
{
|
||||||
|
// Should selected items be added to the current selection or
|
||||||
|
// become the new selection (discarding previously selected items)
|
||||||
m_additive = evt->Modifier( MD_ModShift );
|
m_additive = evt->Modifier( MD_ModShift );
|
||||||
|
|
||||||
if( evt->IsCancel() )
|
if( evt->IsCancel() )
|
||||||
{
|
{
|
||||||
if( !m_selectedItems.empty() )
|
if( !m_selectedItems.empty() ) // Cancel event deselects items...
|
||||||
clearSelection();
|
clearSelection();
|
||||||
else
|
else // ...unless there is nothing selected
|
||||||
break; // Finish
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// single click? Select single object
|
// single click? Select single object
|
||||||
if( evt->IsClick( MB_Left ) )
|
if( evt->IsClick( MB_Left ) )
|
||||||
selectSingle( evt->Position() );
|
selectSingle( evt->Position() );
|
||||||
|
|
||||||
// unlock the multiple selection box
|
|
||||||
if( evt->IsMouseUp( MB_Left ) )
|
|
||||||
allowMultiple = true;
|
|
||||||
|
|
||||||
// drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
|
// drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
|
||||||
if( evt->IsDrag( MB_Left ) )
|
if( evt->IsDrag( MB_Left ) )
|
||||||
{
|
{
|
||||||
dragging = true;
|
|
||||||
getViewControls()->SetAutoPan( true );
|
|
||||||
|
|
||||||
if( m_selectedItems.empty() || m_additive )
|
if( m_selectedItems.empty() || m_additive )
|
||||||
{
|
{
|
||||||
// If nothings has been selected or user wants to select more
|
// If nothings has been selected or user wants to select more
|
||||||
// draw the selection box
|
// draw the selection box
|
||||||
if( allowMultiple )
|
selectMultiple();
|
||||||
allowMultiple = !selectMultiple();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool runTool = false;
|
if( containsSelected( evt->Position() ) )
|
||||||
|
|
||||||
// Check if dragging event started within the currently selected items bounding box
|
|
||||||
std::set<BOARD_ITEM*>::iterator it, it_end;
|
|
||||||
for( it = m_selectedItems.begin(), it_end = m_selectedItems.end();
|
|
||||||
it != it_end; ++it )
|
|
||||||
{
|
{
|
||||||
BOX2I itemBox = (*it)->ViewBBox();
|
|
||||||
itemBox.Inflate( 500000 ); // Give some margin for gripping an item
|
|
||||||
|
|
||||||
if( itemBox.Contains( evt->Position() ) )
|
|
||||||
{
|
|
||||||
// Click event occurred within a selected item bounding box
|
|
||||||
// -> user wants to drag selected items
|
|
||||||
runTool = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( runTool )
|
|
||||||
m_toolMgr->InvokeTool( "pcbnew.InteractiveMove" );
|
m_toolMgr->InvokeTool( "pcbnew.InteractiveMove" );
|
||||||
|
Wait();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
clearSelection();
|
clearSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( dragging )
|
|
||||||
{
|
|
||||||
dragging = false;
|
|
||||||
getViewControls()->SetAutoPan( false );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the default settings
|
|
||||||
getViewControls()->SetAutoPan( false );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +138,7 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem )
|
||||||
if( !m_additive )
|
if( !m_additive )
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|
||||||
// Prevent selection of invisible items
|
// Prevent selection of invisible or inactive items
|
||||||
if( selectable( aItem ) )
|
if( selectable( aItem ) )
|
||||||
{
|
{
|
||||||
aItem->SetSelected();
|
aItem->SetSelected();
|
||||||
|
@ -272,17 +244,17 @@ BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector
|
||||||
|
|
||||||
bool SELECTION_TOOL::selectMultiple()
|
bool SELECTION_TOOL::selectMultiple()
|
||||||
{
|
{
|
||||||
OPT_TOOL_EVENT evt;
|
VIEW* view = getView();
|
||||||
VIEW* v = getView();
|
|
||||||
bool cancelled = false;
|
bool cancelled = false;
|
||||||
m_multiple = true;
|
m_multiple = true; // Multiple selection mode is active
|
||||||
|
getViewControls()->SetAutoPan( true );
|
||||||
|
|
||||||
// Those 2 lines remove the blink-in-the-random-place effect
|
// Those 2 lines remove the blink-in-the-random-place effect
|
||||||
m_selArea->SetOrigin( VECTOR2I( 0, 0 ) );
|
m_selArea->SetOrigin( VECTOR2I( 0, 0 ) );
|
||||||
m_selArea->SetEnd( VECTOR2I( 0, 0 ) );
|
m_selArea->SetEnd( VECTOR2I( 0, 0 ) );
|
||||||
v->Add( m_selArea );
|
view->Add( m_selArea );
|
||||||
|
|
||||||
while( evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
{
|
{
|
||||||
if( evt->IsCancel() )
|
if( evt->IsCancel() )
|
||||||
{
|
{
|
||||||
|
@ -307,17 +279,17 @@ bool SELECTION_TOOL::selectMultiple()
|
||||||
// End drawing a selection box
|
// End drawing a selection box
|
||||||
m_selArea->ViewSetVisible( false );
|
m_selArea->ViewSetVisible( false );
|
||||||
|
|
||||||
// Mark items within a box as selected
|
// Mark items within the selection box as selected
|
||||||
std::vector<VIEW::LayerItemPair> selectedItems;
|
std::vector<VIEW::LayerItemPair> selectedItems;
|
||||||
BOX2I selectionBox = m_selArea->ViewBBox();
|
BOX2I selectionBox = m_selArea->ViewBBox();
|
||||||
|
view->Query( selectionBox, selectedItems ); // Get the list of selected items
|
||||||
|
|
||||||
v->Query( selectionBox, selectedItems );
|
|
||||||
std::vector<VIEW::LayerItemPair>::iterator it, it_end;
|
std::vector<VIEW::LayerItemPair>::iterator it, it_end;
|
||||||
for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it )
|
for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it )
|
||||||
{
|
{
|
||||||
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first );
|
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first );
|
||||||
|
|
||||||
// Add only those items which are visible and fully within the selection box
|
// Add only those items that are visible and fully within the selection box
|
||||||
if( selectable( item ) && selectionBox.Contains( item->ViewBBox() ) )
|
if( selectable( item ) && selectionBox.Contains( item->ViewBBox() ) )
|
||||||
{
|
{
|
||||||
item->SetSelected();
|
item->SetSelected();
|
||||||
|
@ -328,8 +300,9 @@ bool SELECTION_TOOL::selectMultiple()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v->Remove( m_selArea );
|
view->Remove( m_selArea );
|
||||||
m_multiple = false;
|
m_multiple = false; // Multiple selection mode is inactive
|
||||||
|
getViewControls()->SetAutoPan( false );
|
||||||
|
|
||||||
return cancelled;
|
return cancelled;
|
||||||
}
|
}
|
||||||
|
@ -359,12 +332,12 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
|
||||||
{
|
{
|
||||||
if( evt->Action() == TA_ContextMenuUpdate )
|
if( evt->Action() == TA_ContextMenuUpdate )
|
||||||
{
|
{
|
||||||
// User has pointed an item, so show it in a different way
|
|
||||||
if( current )
|
if( current )
|
||||||
current->ClearBrightened();
|
current->ClearBrightened();
|
||||||
|
|
||||||
int id = *evt->GetCommandId();
|
int id = *evt->GetCommandId();
|
||||||
|
|
||||||
|
// User has pointed an item, so show it in a different way
|
||||||
if( id >= 0 )
|
if( id >= 0 )
|
||||||
{
|
{
|
||||||
current = ( *aCollector )[id];
|
current = ( *aCollector )[id];
|
||||||
|
@ -389,6 +362,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw a mark to show which item is available to be selected
|
||||||
if( current && current->IsBrightened() )
|
if( current && current->IsBrightened() )
|
||||||
{
|
{
|
||||||
brightBox.reset( new BRIGHT_BOX( current ) );
|
brightBox.reset( new BRIGHT_BOX( current ) );
|
||||||
|
@ -474,3 +448,21 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem )
|
||||||
// All other items are selected only if the layer on which they exist is visible
|
// All other items are selected only if the layer on which they exist is visible
|
||||||
return board->IsLayerVisible( aItem->GetLayer() );
|
return board->IsLayerVisible( aItem->GetLayer() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SELECTION_TOOL::containsSelected( const VECTOR2I& aPoint ) const
|
||||||
|
{
|
||||||
|
// Check if the point is located within any of the currently selected items bounding boxes
|
||||||
|
std::set<BOARD_ITEM*>::iterator it, it_end;
|
||||||
|
for( it = m_selectedItems.begin(), it_end = m_selectedItems.end();
|
||||||
|
it != it_end; ++it )
|
||||||
|
{
|
||||||
|
BOX2I itemBox = (*it)->ViewBBox();
|
||||||
|
itemBox.Inflate( 500000 ); // Give some margin for gripping an item
|
||||||
|
|
||||||
|
if( itemBox.Contains( aPoint ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 CERN
|
* Copyright (C) 2013 CERN
|
||||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -30,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>
|
||||||
|
|
||||||
class SELECTION_AREA;
|
class SELECTION_AREA;
|
||||||
class BOARD_ITEM;
|
class BOARD_ITEM;
|
||||||
|
@ -42,6 +44,9 @@ class GENERAL_COLLECTOR;
|
||||||
* - pick single objects (click LMB)
|
* - pick single objects (click LMB)
|
||||||
* - add objects to existing selection (Shift+LMB)
|
* - add objects to existing selection (Shift+LMB)
|
||||||
* - draw selection box (drag LMB)
|
* - draw selection box (drag LMB)
|
||||||
|
* - handles MODULEs properly (ie. selects either MODULE or its PADs, TEXTs, etc.)
|
||||||
|
* - takes into account high-contrast & layer visibility settings
|
||||||
|
* - invokes InteractiveMove tool when user starts to drag selected items
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SELECTION_TOOL : public TOOL_INTERACTIVE
|
class SELECTION_TOOL : public TOOL_INTERACTIVE
|
||||||
|
@ -131,10 +136,18 @@ private:
|
||||||
*/
|
*/
|
||||||
bool selectable( const BOARD_ITEM* aItem );
|
bool selectable( const BOARD_ITEM* aItem );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function containsSelected()
|
||||||
|
* Checks if the given point is placed within any of selected items' bounding box.
|
||||||
|
*
|
||||||
|
* @return True if the given point is contained in any of selected items' bouding box.
|
||||||
|
*/
|
||||||
|
bool containsSelected( const VECTOR2I& aPoint ) const;
|
||||||
|
|
||||||
/// Container storing currently selected items
|
/// Container storing currently selected items
|
||||||
std::set<BOARD_ITEM*> m_selectedItems;
|
std::set<BOARD_ITEM*> m_selectedItems;
|
||||||
|
|
||||||
/// Visual representation of selection area
|
/// Visual representation of selection box
|
||||||
SELECTION_AREA* m_selArea;
|
SELECTION_AREA* m_selArea;
|
||||||
|
|
||||||
/// Menu shown in case of selection ambiguity
|
/// Menu shown in case of selection ambiguity
|
||||||
|
@ -145,6 +158,9 @@ private:
|
||||||
|
|
||||||
/// Flag saying if multiple selection mode is active
|
/// Flag saying if multiple selection mode is active
|
||||||
bool m_multiple;
|
bool m_multiple;
|
||||||
|
|
||||||
|
/// Register hotkey fot activation of the selection tool
|
||||||
|
TOOL_ACTION m_activate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue