Schematic: Add swap action

This commit is contained in:
Mike Williams 2022-08-30 09:01:48 -04:00
parent de6e368ac6
commit 926f979ebc
6 changed files with 147 additions and 21 deletions

View File

@ -1287,6 +1287,32 @@ bool SCH_EDIT_FRAME::isAutoSaveRequired() const
}
void SCH_EDIT_FRAME::AutoRotateItem( SCH_SCREEN* aScreen, SCH_ITEM* aItem )
{
if( aItem->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T } ) )
{
auto label = static_cast<SCH_LABEL_BASE*>( aItem );
if( label->AutoRotateOnPlacement() )
{
auto textSpin = aScreen->GetLabelOrientationForPoint(
label->GetPosition(), label->GetTextSpinStyle(), &GetCurrentSheet() );
if( textSpin != label->GetTextSpinStyle() )
{
label->SetTextSpinStyle( textSpin );
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_GLOBAL_LABEL_T ) )
{
SCH_LABEL_BASE* otherLabel = static_cast<SCH_LABEL_BASE*>( item );
if( otherLabel != label && otherLabel->GetText() == label->GetText() )
{
otherLabel->AutoplaceFields( aScreen, false );
}
}
}
}
}
}
void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM* aItem,
bool aUndoAppend )
{
@ -1369,27 +1395,7 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM*
if( connected )
{
if( aItem->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T } ) )
{
auto label = static_cast<SCH_LABEL_BASE*>( aItem );
if( label->AutoRotateOnPlacement() )
{
auto textSpin = aScreen->GetLabelOrientationForPoint(
label->GetPosition(), label->GetTextSpinStyle(), &GetCurrentSheet() );
if( textSpin != label->GetTextSpinStyle() )
{
label->SetTextSpinStyle( textSpin );
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_GLOBAL_LABEL_T ) )
{
SCH_LABEL_BASE *otherLabel = static_cast<SCH_LABEL_BASE *>( item );
if ( otherLabel != label && otherLabel->GetText() == label->GetText() )
{
otherLabel->AutoplaceFields( aScreen, false );
}
}
}
}
}
AutoRotateItem( aScreen, aItem );
}
TestDanglingEnds();

View File

@ -188,6 +188,11 @@ public:
void KiwayMailIn( KIWAY_EXPRESS& aEvent ) override;
/**
* Automatically set the rotation of an item (if the item supports it)
*/
void AutoRotateItem( SCH_SCREEN* aScreen, SCH_ITEM* aItem );
/**
* Add an item to the schematic and adds the changes to the undo/redo container.
* @param aUndoAppend True if the action should be appended to the current undo record.

View File

@ -419,6 +419,11 @@ TOOL_ACTION EE_ACTIONS::mirrorH( "eeschema.InteractiveEdit.mirrorH",
_( "Mirror Horizontally" ), _( "Flips selected item(s) from left to right" ),
BITMAPS::mirror_h );
TOOL_ACTION EE_ACTIONS::swap( "eeschema.InteractiveEdit.swap",
AS_GLOBAL, 0, "",
_( "Swap" ), _( "Swaps selected items' positions" ),
BITMAPS::swap_layer );
TOOL_ACTION EE_ACTIONS::properties( "eeschema.InteractiveEdit.properties",
AS_GLOBAL,
'E', LEGACY_HK_NAME( "Edit Item" ),

View File

@ -127,6 +127,7 @@ public:
static TOOL_ACTION rotateCCW;
static TOOL_ACTION mirrorV;
static TOOL_ACTION mirrorH;
static TOOL_ACTION swap;
static TOOL_ACTION properties;
static TOOL_ACTION editReference;
static TOOL_ACTION editValue;

View File

@ -386,6 +386,7 @@ bool SCH_EDIT_TOOL::Init()
moveMenu.AddItem( EE_ACTIONS::rotateCW, orientCondition );
moveMenu.AddItem( EE_ACTIONS::mirrorV, orientCondition );
moveMenu.AddItem( EE_ACTIONS::mirrorH, orientCondition );
moveMenu.AddItem( EE_ACTIONS::swap, SELECTION_CONDITIONS::MoreThan( 1 ) );
moveMenu.AddItem( EE_ACTIONS::properties, propertiesCondition );
@ -465,6 +466,7 @@ bool SCH_EDIT_TOOL::Init()
selToolMenu.AddItem( EE_ACTIONS::rotateCW, orientCondition, 200 );
selToolMenu.AddItem( EE_ACTIONS::mirrorV, orientCondition, 200 );
selToolMenu.AddItem( EE_ACTIONS::mirrorH, orientCondition, 200 );
selToolMenu.AddItem( EE_ACTIONS::swap, SELECTION_CONDITIONS::MoreThan( 1 ) );
selToolMenu.AddItem( EE_ACTIONS::properties, propertiesCondition, 200 );
@ -977,6 +979,111 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
}
const std::vector<KICAD_T> swappableItems = {
SCH_SHAPE_T,
SCH_TEXT_T,
SCH_TEXTBOX_T,
SCH_LABEL_T,
SCH_GLOBAL_LABEL_T,
SCH_HIER_LABEL_T,
SCH_DIRECTIVE_LABEL_T,
SCH_FIELD_T,
SCH_SYMBOL_T,
SCH_SHEET_T,
SCH_BITMAP_T,
SCH_BUS_BUS_ENTRY_T,
SCH_BUS_WIRE_ENTRY_T,
SCH_LINE_T,
SCH_JUNCTION_T,
SCH_NO_CONNECT_T
};
int SCH_EDIT_TOOL::Swap( const TOOL_EVENT& aEvent )
{
EE_SELECTION& selection = m_selectionTool->RequestSelection( swappableItems );
std::vector<EDA_ITEM*> sorted = selection.GetItemsSortedBySelectionOrder();
if( selection.Size() < 2 )
return 0;
bool isMoving = selection.Front()->IsMoving();
bool appendUndo = isMoving;
bool connections = false;
SCH_SCREEN* screen = this->m_frame->GetScreen();
for( size_t i = 0; i < sorted.size() - 1; i++ )
{
SCH_ITEM* a = static_cast<SCH_ITEM*>( sorted[i] );
SCH_ITEM* b = static_cast<SCH_ITEM*>( sorted[( i + 1 ) % sorted.size()] );
VECTOR2I aPos = a->GetPosition(), bPos = b->GetPosition();
std::swap( aPos, bPos );
saveCopyInUndoList( a, UNDO_REDO::CHANGED, appendUndo );
appendUndo = true;
saveCopyInUndoList( b, UNDO_REDO::CHANGED, appendUndo );
a->SetPosition( aPos );
b->SetPosition( bPos );
if( a->Type() == b->Type() )
{
switch( a->Type() )
{
case SCH_LABEL_T:
case SCH_GLOBAL_LABEL_T:
case SCH_HIER_LABEL_T:
case SCH_DIRECTIVE_LABEL_T:
m_frame->AutoRotateItem( screen, a );
m_frame->AutoRotateItem( screen, b );
break;
case SCH_SYMBOL_T:
{
SCH_SYMBOL* aSymbol = static_cast<SCH_SYMBOL*>( a );
SCH_SYMBOL* bSymbol = static_cast<SCH_SYMBOL*>( b );
int aOrient = aSymbol->GetOrientation(), bOrient = bSymbol->GetOrientation();
std::swap( aOrient, bOrient );
aSymbol->SetOrientation( aOrient );
bSymbol->SetOrientation( bOrient );
break;
}
default: break;
}
}
connections |= a->IsConnectable();
connections |= b->IsConnectable();
m_frame->UpdateItem( a, false, true );
m_frame->UpdateItem( b, false, true );
}
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
// Update R-Tree for modified items
for( EDA_ITEM* selected : selection )
updateItem( selected, true );
if( isMoving )
{
m_toolMgr->RunAction( ACTIONS::refreshPreview );
}
else
{
if( selection.IsHover() )
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
if( connections )
m_frame->TestDanglingEnds();
m_frame->OnModify();
}
return 0;
}
int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
{
const std::vector<std::unique_ptr<SCH_ITEM>>& sourceItems = m_frame->GetRepeatItems();
@ -2185,6 +2292,7 @@ void SCH_EDIT_TOOL::setTransitions()
Go( &SCH_EDIT_TOOL::Rotate, EE_ACTIONS::rotateCCW.MakeEvent() );
Go( &SCH_EDIT_TOOL::Mirror, EE_ACTIONS::mirrorV.MakeEvent() );
Go( &SCH_EDIT_TOOL::Mirror, EE_ACTIONS::mirrorH.MakeEvent() );
Go( &SCH_EDIT_TOOL::Swap, EE_ACTIONS::swap.MakeEvent() );
Go( &SCH_EDIT_TOOL::DoDelete, ACTIONS::doDelete.MakeEvent() );
Go( &SCH_EDIT_TOOL::DeleteItemCursor, ACTIONS::deleteTool.MakeEvent() );

View File

@ -44,6 +44,7 @@ public:
int Rotate( const TOOL_EVENT& aEvent );
int Mirror( const TOOL_EVENT& aEvent );
int Swap( const TOOL_EVENT& aEvent );
int RepeatDrawItem( const TOOL_EVENT& aEvent );