Support synchronous move in symbol editor.

Also removes duplicate-during-move.  It's not really compatibile with
a passed-in SCH_COMMIT, and it was never clear it was worth the code.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14274
This commit is contained in:
Jeff Young 2023-07-01 22:35:39 +01:00
parent 632e94ef81
commit 4cbf512461
5 changed files with 57 additions and 88 deletions

View File

@ -407,6 +407,7 @@ void SCH_COMMIT::revertLibEdit()
// Symbol editor just saves copies of the whole symbol, so grab the first and discard the rest // Symbol editor just saves copies of the whole symbol, so grab the first and discard the rest
SYMBOL_EDIT_FRAME* frame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() ); SYMBOL_EDIT_FRAME* frame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
LIB_SYMBOL* copy = dynamic_cast<LIB_SYMBOL*>( m_changes.front().m_copy ); LIB_SYMBOL* copy = dynamic_cast<LIB_SYMBOL*>( m_changes.front().m_copy );
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
if( frame && copy ) if( frame && copy )
{ {
@ -417,6 +418,9 @@ void SCH_COMMIT::revertLibEdit()
for( size_t ii = 1; ii < m_changes.size(); ++ii ) for( size_t ii = 1; ii < m_changes.size(); ++ii )
delete m_changes[ii].m_copy; delete m_changes[ii].m_copy;
if( selTool )
selTool->RebuildSelection();
clear(); clear();
} }

View File

@ -471,7 +471,6 @@ bool SCH_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COMMIT* aComm
} }
bool restore_state = false; bool restore_state = false;
bool chain_commands = false;
TOOL_EVENT copy = aEvent; TOOL_EVENT copy = aEvent;
TOOL_EVENT* evt = &copy; TOOL_EVENT* evt = &copy;
VECTOR2I prevPos; VECTOR2I prevPos;
@ -842,19 +841,7 @@ bool SCH_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COMMIT* aComm
} }
else if( evt->IsAction( &ACTIONS::duplicate ) ) else if( evt->IsAction( &ACTIONS::duplicate ) )
{ {
if( selection.Front()->IsNew() ) wxBell();
{
// This doesn't really make sense; we'll just end up dragging a stack of
// objects so we ignore the duplicate and just carry on.
wxBell();
continue;
}
// Move original back and exit. The duplicate will run in its own loop.
restore_state = true;
unselect = false;
chain_commands = true;
break;
} }
else if( evt->IsAction( &EE_ACTIONS::rotateCW ) ) else if( evt->IsAction( &EE_ACTIONS::rotateCW ) )
{ {
@ -939,9 +926,7 @@ bool SCH_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COMMIT* aComm
controls->ShowCursor( false ); controls->ShowCursor( false );
controls->SetAutoPan( false ); controls->SetAutoPan( false );
if( !chain_commands ) m_moveOffset = { 0, 0 };
m_moveOffset = { 0, 0 };
m_anchorPos.reset(); m_anchorPos.reset();
if( restore_state ) if( restore_state )

View File

@ -103,7 +103,6 @@ private:
///< Lines changed by drag algorithm that weren't selected ///< Lines changed by drag algorithm that weren't selected
std::unordered_set<SCH_LINE*> m_changedDragLines; std::unordered_set<SCH_LINE*> m_changedDragLines;
///< Used for chaining commands
VECTOR2I m_moveOffset; VECTOR2I m_moveOffset;
///< Last cursor position (needed for getModificationPoint() to avoid changes ///< Last cursor position (needed for getModificationPoint() to avoid changes

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 CERN * Copyright (C) 2019 CERN
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* 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
@ -34,8 +34,7 @@
SYMBOL_EDITOR_MOVE_TOOL::SYMBOL_EDITOR_MOVE_TOOL() : SYMBOL_EDITOR_MOVE_TOOL::SYMBOL_EDITOR_MOVE_TOOL() :
EE_TOOL_BASE( "eeschema.SymbolMoveTool" ), EE_TOOL_BASE( "eeschema.SymbolMoveTool" ),
m_moveInProgress( false ), m_moveInProgress( false )
m_moveOffset( 0, 0 )
{ {
} }
@ -81,21 +80,39 @@ void SYMBOL_EDITOR_MOVE_TOOL::Reset( RESET_REASON aReason )
EE_TOOL_BASE::Reset( aReason ); EE_TOOL_BASE::Reset( aReason );
if( aReason == MODEL_RELOAD ) if( aReason == MODEL_RELOAD )
{
m_moveInProgress = false; m_moveInProgress = false;
m_moveOffset = { 0, 0 };
}
} }
int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent ) int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
{ {
KIGFX::VIEW_CONTROLS* controls = getViewControls(); if( SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() ) )
SCH_COMMIT localCommit( m_toolMgr ); {
SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() ); wxCHECK( aEvent.SynchronousState(), 0 );
aEvent.SynchronousState()->store( STS_RUNNING );
if( !commit ) if( doMoveSelection( aEvent, commit ) )
commit = &localCommit; aEvent.SynchronousState()->store( STS_FINISHED );
else
aEvent.SynchronousState()->store( STS_CANCELLED );
}
else
{
SCH_COMMIT localCommit( m_toolMgr );
if( doMoveSelection( aEvent, &localCommit ) )
localCommit.Push( _( "Move" ) );
else
localCommit.Revert();
}
return 0;
}
bool SYMBOL_EDITOR_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COMMIT* aCommit )
{
KIGFX::VIEW_CONTROLS* controls = getViewControls();
m_anchorPos = { 0, 0 }; m_anchorPos = { 0, 0 };
@ -107,13 +124,13 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
bool unselect = selection.IsHover(); bool unselect = selection.IsHover();
if( !m_frame->IsSymbolEditable() || selection.Empty() ) if( !m_frame->IsSymbolEditable() || selection.Empty() )
return 0; return false;
if( m_moveInProgress ) if( m_moveInProgress )
{ {
// The tool hotkey is interpreted as a click when already moving // The tool hotkey is interpreted as a click when already moving
m_toolMgr->RunAction( ACTIONS::cursorClick ); m_toolMgr->RunAction( ACTIONS::cursorClick );
return 0; return true;
} }
m_frame->PushTool( aEvent ); m_frame->PushTool( aEvent );
@ -124,13 +141,13 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
controls->SetAutoPan( true ); controls->SetAutoPan( true );
bool restore_state = false; bool restore_state = false;
bool chain_commands = false;
TOOL_EVENT copy = aEvent; TOOL_EVENT copy = aEvent;
TOOL_EVENT* evt = &copy; TOOL_EVENT* evt = &copy;
VECTOR2I prevPos; VECTOR2I prevPos;
VECTOR2I moveOffset;
if( !selection.Front()->IsNew() ) if( !selection.Front()->IsNew() )
commit->Modify( m_frame->GetCurSymbol(), m_frame->GetScreen() ); aCommit->Modify( m_frame->GetCurSymbol(), m_frame->GetScreen() );
m_cursor = controls->GetCursorPosition( !aEvent.DisableGridSnapping() ); m_cursor = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
@ -195,7 +212,7 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
// Apply any initial offset in case we're coming from a previous command. // Apply any initial offset in case we're coming from a previous command.
// //
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
moveItem( item, m_moveOffset ); moveItem( item, moveOffset );
// Set up the starting position and move/drag offset // Set up the starting position and move/drag offset
// //
@ -243,7 +260,7 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
VECTOR2I delta( m_cursor - prevPos ); VECTOR2I delta( m_cursor - prevPos );
m_anchorPos = m_cursor; m_anchorPos = m_cursor;
m_moveOffset += delta; moveOffset += delta;
prevPos = m_cursor; prevPos = m_cursor;
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
@ -275,32 +292,14 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
unselect = true; unselect = true;
break; break;
} }
else if( evt->Category() == TC_COMMAND ) else if( evt->IsAction( &ACTIONS::doDelete ) )
{ {
if( evt->IsAction( &ACTIONS::doDelete ) ) // Exit on a remove operation; there is no further processing for removed items.
{ break;
// Exit on a remove operation; there is no further processing for removed items. }
break; else if( evt->IsAction( &ACTIONS::duplicate ) )
} {
else if( evt->IsAction( &ACTIONS::duplicate ) ) wxBell();
{
if( selection.Front()->IsNew() )
{
// This doesn't really make sense; we'll just end up dragging a stack of
// objects so Duplicate() is going to ignore this and we'll just carry on.
continue;
}
// Move original back and exit. The duplicate will run in its own loop.
restore_state = true;
unselect = false;
chain_commands = true;
break;
}
else
{
evt->SetPassEvent();
}
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Handle context menu // Handle context menu
@ -350,39 +349,22 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
controls->ShowCursor( false ); controls->ShowCursor( false );
controls->SetAutoPan( false ); controls->SetAutoPan( false );
if( !chain_commands )
m_moveOffset = { 0, 0 };
m_anchorPos = { 0, 0 }; m_anchorPos = { 0, 0 };
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
item->ClearEditFlags(); item->ClearEditFlags();
if( restore_state ) if( unselect )
{ m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
commit->Revert();
if( unselect )
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
else
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
else
{
if( unselect )
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
if( !localCommit.Empty() )
localCommit.Push( _( "Move" ) );
}
m_moveInProgress = false; m_moveInProgress = false;
m_frame->PopTool( aEvent ); m_frame->PopTool( aEvent );
return 0;
return !restore_state;
} }
void SYMBOL_EDITOR_MOVE_TOOL::moveItem( EDA_ITEM* aItem, VECTOR2I aDelta ) void SYMBOL_EDITOR_MOVE_TOOL::moveItem( EDA_ITEM* aItem, const VECTOR2I& aDelta )
{ {
static_cast<LIB_ITEM*>( aItem )->Offset( mapCoords( aDelta ) ); static_cast<LIB_ITEM*>( aItem )->Offset( mapCoords( aDelta ) );
aItem->SetFlags( IS_MOVING ); aItem->SetFlags( IS_MOVING );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 CERN * Copyright (C) 2019 CERN
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* 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
@ -50,17 +50,16 @@ public:
int Main( const TOOL_EVENT& aEvent ); int Main( const TOOL_EVENT& aEvent );
private: private:
void moveItem( EDA_ITEM* aItem, VECTOR2I aDelta ); bool doMoveSelection( const TOOL_EVENT& aEvent, SCH_COMMIT* aCommit );
void moveItem( EDA_ITEM* aItem, const VECTOR2I& aDelta );
///< Set up handlers for various events. ///< Set up handlers for various events.
void setTransitions() override; void setTransitions() override;
///< Flag determining if anything is being dragged right now private:
bool m_moveInProgress; bool m_moveInProgress;
///< Used for chaining commands
VECTOR2I m_moveOffset;
///< Last cursor position (needed for getModificationPoint() to avoid changes ///< Last cursor position (needed for getModificationPoint() to avoid changes
///< of edit reference point). ///< of edit reference point).
VECTOR2I m_cursor; VECTOR2I m_cursor;