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,7 +297,9 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
// Drag items to the current cursor position // Drag items to the current cursor position
for( auto item : selection ) for( auto item : selection )
{
static_cast<BOARD_ITEM*>( item )->Move( movement + m_offset ); static_cast<BOARD_ITEM*>( item )->Move( movement + m_offset );
}
} }
else if( !m_dragging ) // Prepare to start dragging else if( !m_dragging ) // Prepare to start dragging
{ {
@ -830,8 +832,6 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
int EDIT_TOOL::Duplicate( 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 ); bool increment = aEvent.IsAction( &PCB_ACTIONS::duplicateIncrement );
// Be sure that there is at least one item that we can modify // 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 // we have a selection to work on now, so start the tool process
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); 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 ) for( auto item : selection )
{ {
if( item ) if( !item )
old_items.push_back( static_cast<BOARD_ITEM*>( item ) ); continue;
}
for( unsigned i = 0; i < old_items.size(); ++i ) orig_item = static_cast<BOARD_ITEM*>( item );
{
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;
if( m_editModules ) if( m_editModules )
{ {
new_item = editFrame->GetBoard()->m_Modules->Duplicate( item, increment ); dupe_item = editFrame->GetBoard()->m_Modules->Duplicate( orig_item, increment );
} }
else else
{ {
@ -874,23 +870,31 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
// so zones are not duplicated // so zones are not duplicated
if( item->Type() != PCB_ZONE_AREA_T ) if( item->Type() != PCB_ZONE_AREA_T )
#endif #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 new_items.push_back( dupe_item );
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, new_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 // record the new items as added
if( !selection.Empty() ) if( !selection.Empty() )
{ {
editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ), editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
(int) old_items.size() ) ); (int) new_items.size() ) );
// If items were duplicated, pick them up // If items were duplicated, pick them up
// this works well for "dropping" copies around and pushes the commit // this works well for "dropping" copies around and pushes the commit

View File

@ -97,7 +97,7 @@ public:
/** /**
* Function Duplicate() * 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 ); int Duplicate( const TOOL_EVENT& aEvent );

View File

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

View File

@ -70,10 +70,18 @@ TOOL_ACTION PCB_ACTIONS::selectItem( "pcbnew.InteractiveSelection.SelectItem",
AS_GLOBAL, 0, AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere "", "" ); // 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", TOOL_ACTION PCB_ACTIONS::unselectItem( "pcbnew.InteractiveSelection.UnselectItem",
AS_GLOBAL, 0, AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere "", "" ); // 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", TOOL_ACTION PCB_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear",
AS_GLOBAL, 0, AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere "", "" ); // 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 // This will be ignored if the SHIFT modifier is pressed
m_subtractive = !m_additive && evt->Modifier( MD_CTRL ); 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->IsClick( BUT_LEFT ) )
{ {
if( evt->Modifier( MD_CTRL ) && !m_editModules ) if( evt->Modifier( MD_CTRL ) && !m_editModules )
@ -244,8 +252,11 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
} }
else else
{ {
// If no modifier keys are pressed, clear the selection
if( !m_additive ) if( !m_additive )
{
clearSelection(); clearSelection();
}
selectPoint( evt->Position() ); selectPoint( evt->Position() );
} }
@ -585,7 +596,9 @@ void SELECTION_TOOL::SetTransitions()
Go( &SELECTION_TOOL::CursorSelection, PCB_ACTIONS::selectionCursor.MakeEvent() ); Go( &SELECTION_TOOL::CursorSelection, PCB_ACTIONS::selectionCursor.MakeEvent() );
Go( &SELECTION_TOOL::ClearSelection, PCB_ACTIONS::selectionClear.MakeEvent() ); Go( &SELECTION_TOOL::ClearSelection, PCB_ACTIONS::selectionClear.MakeEvent() );
Go( &SELECTION_TOOL::SelectItem, PCB_ACTIONS::selectItem.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::UnselectItem, PCB_ACTIONS::unselectItem.MakeEvent() );
Go( &SELECTION_TOOL::UnselectItems, PCB_ACTIONS::unselectItems.MakeEvent() );
Go( &SELECTION_TOOL::find, PCB_ACTIONS::find.MakeEvent() ); Go( &SELECTION_TOOL::find, PCB_ACTIONS::find.MakeEvent() );
Go( &SELECTION_TOOL::findMove, PCB_ACTIONS::findMove.MakeEvent() ); Go( &SELECTION_TOOL::findMove, PCB_ACTIONS::findMove.MakeEvent() );
Go( &SELECTION_TOOL::filterSelection, PCB_ACTIONS::filterSelection.MakeEvent() ); Go( &SELECTION_TOOL::filterSelection, PCB_ACTIONS::filterSelection.MakeEvent() );
@ -672,6 +685,27 @@ int SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
return 0; 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 ) int SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
{ {
// Check if there is an item to be selected // 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 ) int SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
{ {
// Check if there is an item to be selected // 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() void SELECTION_TOOL::clearSelection()
{ {
if( m_selection.Empty() ) if( m_selection.Empty() )
{
return; return;
}
for( auto item : m_selection ) for( auto item : m_selection )
{
unselectVisually( static_cast<BOARD_ITEM*>( item ) ); unselectVisually( static_cast<BOARD_ITEM*>( item ) );
}
m_selection.Clear(); m_selection.Clear();
@ -1393,6 +1451,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
return board()->IsLayerVisible( aItem->GetLayer() ); return board()->IsLayerVisible( aItem->GetLayer() );
} }
void SELECTION_TOOL::select( BOARD_ITEM* aItem ) void SELECTION_TOOL::select( BOARD_ITEM* aItem )
{ {
if( aItem->IsSelected() ) if( aItem->IsSelected() )

View File

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