Improved speed of Duplicate action

- Removed repetitive tool calls
This commit is contained in:
Oliver Walters 2017-06-12 11:16:30 +02:00 committed by Maciej Suminski
parent d5e85726ea
commit 18488342a5
5 changed files with 100 additions and 25 deletions

View File

@ -297,8 +297,10 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
// Drag items to the current cursor position
for( auto item : selection )
{
static_cast<BOARD_ITEM*>( item )->Move( movement + m_offset );
}
}
else if( !m_dragging ) // Prepare to start dragging
{
if( !invokeInlineRouter() )
@ -830,8 +832,6 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
{
// Note: original items are no more modified.
bool increment = aEvent.IsAction( &PCB_ACTIONS::duplicateIncrement );
// Be sure that there is at least one item that we can modify
@ -843,28 +843,24 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
// we have a selection to work on now, so start the tool process
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
std::vector<BOARD_ITEM*> old_items;
std::vector<BOARD_ITEM*> new_items;
new_items.reserve( selection.Size() );
BOARD_ITEM* orig_item = nullptr;
BOARD_ITEM* dupe_item = nullptr;
// Each selected item is duplicated and pushed to new_items list
// Old selection is cleared, and new items are then selected.
for( auto item : selection )
{
if( item )
old_items.push_back( static_cast<BOARD_ITEM*>( item ) );
}
if( !item )
continue;
for( unsigned i = 0; i < old_items.size(); ++i )
{
BOARD_ITEM* item = old_items[i];
// Unselect the item, so we won't pick it up again
// Do this first, so a single-item duplicate will correctly call
// SetCurItem and show the item properties
m_toolMgr->RunAction( PCB_ACTIONS::unselectItem, true, item );
BOARD_ITEM* new_item = NULL;
orig_item = static_cast<BOARD_ITEM*>( item );
if( m_editModules )
{
new_item = editFrame->GetBoard()->m_Modules->Duplicate( item, increment );
dupe_item = editFrame->GetBoard()->m_Modules->Duplicate( orig_item, increment );
}
else
{
@ -874,23 +870,31 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
// so zones are not duplicated
if( item->Type() != PCB_ZONE_AREA_T )
#endif
new_item = editFrame->GetBoard()->Duplicate( item );
dupe_item = editFrame->GetBoard()->Duplicate( orig_item );
}
if( new_item )
if( dupe_item )
{
m_commit->Add( new_item );
// Clear the selection flag here, otherwise the SELECTION_TOOL
// will not properly select it later on
dupe_item->ClearSelected();
// Select the new item, so we can pick it up
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, new_item );
new_items.push_back( dupe_item );
m_commit->Add( dupe_item );
}
}
// Clear the old selection first
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
// Select the new items
m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &new_items );
// record the new items as added
if( !selection.Empty() )
{
editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
(int) old_items.size() ) );
(int) new_items.size() ) );
// If items were duplicated, pick them up
// this works well for "dropping" copies around and pushes the commit

View File

@ -97,7 +97,7 @@ public:
/**
* Function Duplicate()
*
* Duplicates a selection and starts a move action
* Duplicates the current selection and starts a move action.
*/
int Duplicate( const TOOL_EVENT& aEvent );

View File

@ -55,9 +55,15 @@ public:
/// Selects an item (specified as the event parameter).
static TOOL_ACTION selectItem;
/// Selects a list of items (specified as the event parameter)
static TOOL_ACTION selectItems;
/// Unselects an item (specified as the event parameter).
static TOOL_ACTION unselectItem;
/// Unselects a list of items (specified as the event parameter)
static TOOL_ACTION unselectItems;
/// Selects a connection between junctions.
static TOOL_ACTION selectConnection;

View File

@ -70,10 +70,18 @@ TOOL_ACTION PCB_ACTIONS::selectItem( "pcbnew.InteractiveSelection.SelectItem",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::selectItems( "pcbnew.InteractiveSelection.SelectItems",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::unselectItem( "pcbnew.InteractiveSelection.UnselectItem",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::unselectItems( "pcbnew.InteractiveSelection.UnselectItems",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
@ -235,7 +243,7 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
// This will be ignored if the SHIFT modifier is pressed
m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
// single click? Select single object
// Single click? Select single object
if( evt->IsClick( BUT_LEFT ) )
{
if( evt->Modifier( MD_CTRL ) && !m_editModules )
@ -244,8 +252,11 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
}
else
{
// If no modifier keys are pressed, clear the selection
if( !m_additive )
{
clearSelection();
}
selectPoint( evt->Position() );
}
@ -585,7 +596,9 @@ void SELECTION_TOOL::SetTransitions()
Go( &SELECTION_TOOL::CursorSelection, PCB_ACTIONS::selectionCursor.MakeEvent() );
Go( &SELECTION_TOOL::ClearSelection, PCB_ACTIONS::selectionClear.MakeEvent() );
Go( &SELECTION_TOOL::SelectItem, PCB_ACTIONS::selectItem.MakeEvent() );
Go( &SELECTION_TOOL::SelectItems, PCB_ACTIONS::selectItems.MakeEvent() );
Go( &SELECTION_TOOL::UnselectItem, PCB_ACTIONS::unselectItem.MakeEvent() );
Go( &SELECTION_TOOL::UnselectItems, PCB_ACTIONS::unselectItems.MakeEvent() );
Go( &SELECTION_TOOL::find, PCB_ACTIONS::find.MakeEvent() );
Go( &SELECTION_TOOL::findMove, PCB_ACTIONS::findMove.MakeEvent() );
Go( &SELECTION_TOOL::filterSelection, PCB_ACTIONS::filterSelection.MakeEvent() );
@ -672,6 +685,27 @@ int SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
return 0;
}
int SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
{
std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
if( items )
{
// Perform individual selection of each item
// before processing the event.
for( auto item : *items )
{
select( item );
}
m_toolMgr->ProcessEvent( SelectedEvent );
}
return 0;
}
int SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
{
// Check if there is an item to be selected
@ -689,6 +723,26 @@ int SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
}
int SELECTION_TOOL::UnselectItems( const TOOL_EVENT& aEvent )
{
std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
if( items )
{
// Perform individual unselection of each item
// before processing the event
for( auto item : *items )
{
unselect( item );
}
m_toolMgr->ProcessEvent( UnselectedEvent );
}
return 0;
}
int SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
{
// Check if there is an item to be selected
@ -1165,10 +1219,14 @@ int SELECTION_TOOL::filterSelection( const TOOL_EVENT& aEvent )
void SELECTION_TOOL::clearSelection()
{
if( m_selection.Empty() )
{
return;
}
for( auto item : m_selection )
{
unselectVisually( static_cast<BOARD_ITEM*>( item ) );
}
m_selection.Clear();
@ -1393,6 +1451,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
return board()->IsLayerVisible( aItem->GetLayer() );
}
void SELECTION_TOOL::select( BOARD_ITEM* aItem )
{
if( aItem->IsSelected() )

View File

@ -114,9 +114,15 @@ public:
///> Item selection event handler.
int SelectItem( const TOOL_EVENT& aEvent );
///> Multiple item selection event handler
int SelectItems( const TOOL_EVENT& aEvent );
///> Item unselection event handler.
int UnselectItem( const TOOL_EVENT& aEvent );
///> Multiple item unselection event handler
int UnselectItems( const TOOL_EVENT& aEvent );
///> Event sent after an item is selected.
static const TOOL_EVENT SelectedEvent;