diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index dbeaf6bf1d..24f5233461 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -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( 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( 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( 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( item ); - if ( otherLabel != label && otherLabel->GetText() == label->GetText() ) - { - otherLabel->AutoplaceFields( aScreen, false ); - } - } - } - } - } + AutoRotateItem( aScreen, aItem ); } TestDanglingEnds(); diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index 788cda3058..03a0dda673 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -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. diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index 2cc44b5f95..855cbada44 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -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" ), diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index 795a944a43..779832d27a 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -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; diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp index aca6fb5a89..4268e4a5c2 100644 --- a/eeschema/tools/sch_edit_tool.cpp +++ b/eeschema/tools/sch_edit_tool.cpp @@ -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 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 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( sorted[i] ); + SCH_ITEM* b = static_cast( 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( a ); + SCH_SYMBOL* bSymbol = static_cast( 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>& 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() ); diff --git a/eeschema/tools/sch_edit_tool.h b/eeschema/tools/sch_edit_tool.h index d4dc200cd2..85f3691323 100644 --- a/eeschema/tools/sch_edit_tool.h +++ b/eeschema/tools/sch_edit_tool.h @@ -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 );