From 20c72504c3281fb697d56275fffc85ccdf508541 Mon Sep 17 00:00:00 2001 From: Dhineshkumar S <dhineshkumar@cgvakindia.com> Date: Wed, 26 Feb 2025 21:24:02 +0000 Subject: [PATCH] Eeschema: Import and auto place all sheet pins https://gitlab.com/kicad/code/kicad/-/issues/6736 --- eeschema/tools/ee_actions.cpp | 6 ++ eeschema/tools/ee_actions.h | 1 + eeschema/tools/ee_selection_tool.cpp | 1 + eeschema/tools/sch_drawing_tools.cpp | 126 +++++++++++++++++++++++++++ eeschema/tools/sch_drawing_tools.h | 3 + 5 files changed, 137 insertions(+) diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index c457920bba..73385ba3a9 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -546,6 +546,12 @@ TOOL_ACTION EE_ACTIONS::placeSheetPin( TOOL_ACTION_ARGS() .Icon( BITMAPS::add_hierar_pin ) .Flags( AF_ACTIVATE ) ); +TOOL_ACTION EE_ACTIONS::autoplaceAllSheetPins( TOOL_ACTION_ARGS() + .Name( "eeschema.InteractiveDrawing.autoplaceAllSheetPins" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Autoplace All Sheet Pins" ) ) + .Tooltip( _( "Imports and auto places all sheet pins" ) ) ); + TOOL_ACTION EE_ACTIONS::syncSheetPins( TOOL_ACTION_ARGS() .Name( "eeschema.InteractiveDrawing.syncSheetPins" ) .Scope( AS_GLOBAL ) diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index 8136bc9d61..490e51ade0 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -94,6 +94,7 @@ public: static TOOL_ACTION drawSheetFromFile; static TOOL_ACTION drawSheetFromDesignBlock; static TOOL_ACTION placeSheetPin; + static TOOL_ACTION autoplaceAllSheetPins; static TOOL_ACTION importSheet; // Sync sheet pins for selected sheet symbol static TOOL_ACTION syncSheetPins; diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp index 298a71ae57..36414dd208 100644 --- a/eeschema/tools/ee_selection_tool.cpp +++ b/eeschema/tools/ee_selection_tool.cpp @@ -325,6 +325,7 @@ bool EE_SELECTION_TOOL::Init() menu.AddItem( EE_ACTIONS::breakWire, linesSelection && EE_CONDITIONS::Idle, 250 ); menu.AddItem( EE_ACTIONS::slice, linesSelection && EE_CONDITIONS::Idle, 250 ); menu.AddItem( EE_ACTIONS::placeSheetPin, sheetSelection && EE_CONDITIONS::Idle, 250 ); + menu.AddItem( EE_ACTIONS::autoplaceAllSheetPins, sheetSelection && EE_CONDITIONS::Idle, 250 ); menu.AddItem( EE_ACTIONS::syncSheetPins, sheetSelection && EE_CONDITIONS::Idle, 250 ); menu.AddItem( EE_ACTIONS::assignNetclass, connectedSelection && EE_CONDITIONS::Idle, 250 ); menu.AddItem( EE_ACTIONS::editPageNumber, schEditSheetPageNumberCondition, 250 ); diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp index 20f5ff600a..e1840d6ca9 100644 --- a/eeschema/tools/sch_drawing_tools.cpp +++ b/eeschema/tools/sch_drawing_tools.cpp @@ -3296,6 +3296,110 @@ int SCH_DRAWING_TOOLS::SyncSheetsPins( const TOOL_EVENT& aEvent ) } +int SCH_DRAWING_TOOLS::AutoPlaceAllSheetPins( const TOOL_EVENT& aEvent ) +{ + if( m_inDrawingTool ) + return 0; + + REENTRANCY_GUARD guard( &m_inDrawingTool ); + + SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() ); + std::vector<SCH_HIERLABEL*> labels = importHierLabels( sheet ); + + if( labels.empty() ) + { + m_frame->PushTool( aEvent ); + m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame ); + m_statusPopup->SetText( _( "No new hierarchical labels found." ) ); + m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) ); + m_statusPopup->PopupFor( 2000 ); + m_frame->PopTool( aEvent ); + m_toolMgr->RunAction( EE_ACTIONS::clearSelection ); + m_view->ClearPreview(); + return 0; + } + + m_toolMgr->RunAction( EE_ACTIONS::clearSelection ); + + SCH_COMMIT commit( m_toolMgr ); + BOX2I boundingBox = sheet->GetBoundingBox(); + VECTOR2I cursorPos = boundingBox.GetPosition(); + SCH_ITEM* lastPlacedLabel = nullptr; + + auto calculatePositionForLabel = [&]( const SCH_ITEM* lastLabel, + const SCH_HIERLABEL* currentLabel ) -> VECTOR2I + { + if( !lastLabel ) + return cursorPos; + + int lastX = lastLabel->GetPosition().x; + int lastY = lastLabel->GetPosition().y; + int lastWidth = lastLabel->GetBoundingBox().GetWidth(); + int lastHeight = lastLabel->GetBoundingBox().GetHeight(); + + int currentWidth = currentLabel->GetBoundingBox().GetWidth(); + int currentHeight = currentLabel->GetBoundingBox().GetHeight(); + + // If there is enough space, place the label to the right of the last placed label + if( ( lastX + lastWidth + currentWidth ) + <= ( boundingBox.GetPosition().x + boundingBox.GetSize().x ) ) + return { lastX + lastWidth, lastY }; + + // If not enough space to the right, move to the next row if vertical space allows + if( ( lastY + lastHeight + currentHeight ) + <= ( boundingBox.GetPosition().y + boundingBox.GetSize().y ) ) + return { boundingBox.GetPosition().x, lastY + lastHeight }; + + return cursorPos; + }; + + for( SCH_HIERLABEL* label : labels ) + { + if( !lastPlacedLabel ) + { + std::vector<SCH_SHEET_PIN*> existingPins = sheet->GetPins(); + + if( !existingPins.empty() ) + { + std::sort( existingPins.begin(), existingPins.end(), + []( const SCH_ITEM* a, const SCH_ITEM* b ) + { + return ( a->GetPosition().x < b->GetPosition().x ) + || ( a->GetPosition().x == b->GetPosition().x + && a->GetPosition().y < b->GetPosition().y ); + } ); + + lastPlacedLabel = existingPins.back(); + } + } + + cursorPos = calculatePositionForLabel( lastPlacedLabel, label ); + SCH_ITEM* item = createNewSheetPinFromLabel( sheet, cursorPos, label ); + + if( item ) + { + item->SetFlags( IS_NEW | IS_MOVING ); + item->AutoplaceFields( nullptr, AUTOPLACE_AUTO ); + item->ClearFlags( IS_MOVING ); + + if( item->IsConnectable() ) + m_frame->AutoRotateItem( m_frame->GetScreen(), item ); + + commit.Modify( sheet, m_frame->GetScreen() ); + + sheet->AddPin( static_cast<SCH_SHEET_PIN*>( item ) ); + item->AutoplaceFields( m_frame->GetScreen(), AUTOPLACE_AUTO ); + + commit.Push( _( "Add Sheet Pin" ) ); + + lastPlacedLabel = item; + } + } + + return 0; +} + + int SCH_DRAWING_TOOLS::SyncAllSheetsPins( const TOOL_EVENT& aEvent ) { static const std::function<void( std::list<SCH_SHEET_PATH>&, SCH_SCREEN*, @@ -3364,6 +3468,27 @@ SCH_HIERLABEL* SCH_DRAWING_TOOLS::importHierLabel( SCH_SHEET* aSheet ) } +std::vector<SCH_HIERLABEL*> SCH_DRAWING_TOOLS::importHierLabels( SCH_SHEET* aSheet ) +{ + if( !aSheet->GetScreen() ) + return {}; + + std::vector<SCH_HIERLABEL*> labels; + + for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) ) + { + SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item ); + + if( !aSheet->HasPin( label->GetText() ) ) + { + labels.push_back( label ); + } + } + + return labels; +} + + void SCH_DRAWING_TOOLS::setTransitions() { // clang-format off @@ -3395,5 +3520,6 @@ void SCH_DRAWING_TOOLS::setTransitions() Go( &SCH_DRAWING_TOOLS::ImportGraphics, EE_ACTIONS::importGraphics.MakeEvent() ); Go( &SCH_DRAWING_TOOLS::SyncSheetsPins, EE_ACTIONS::syncSheetPins.MakeEvent() ); Go( &SCH_DRAWING_TOOLS::SyncAllSheetsPins, EE_ACTIONS::syncAllSheetsPins.MakeEvent() ); + Go( &SCH_DRAWING_TOOLS::AutoPlaceAllSheetPins, EE_ACTIONS::autoplaceAllSheetPins.MakeEvent() ); // clang-format on } diff --git a/eeschema/tools/sch_drawing_tools.h b/eeschema/tools/sch_drawing_tools.h index df3e4d388d..1a9a6f9e62 100644 --- a/eeschema/tools/sch_drawing_tools.h +++ b/eeschema/tools/sch_drawing_tools.h @@ -65,6 +65,7 @@ public: int ImportGraphics( const TOOL_EVENT& aEvent ); int SyncSheetsPins( const TOOL_EVENT& aEvent ); int SyncAllSheetsPins( const TOOL_EVENT& aEvent ); + int AutoPlaceAllSheetPins( const TOOL_EVENT& aEvent ); private: SCH_LINE* findWire( const VECTOR2I& aPosition ); @@ -89,6 +90,8 @@ private: ///< Try finding any hierlabel that does not have a sheet pin associated with it SCH_HIERLABEL* importHierLabel( SCH_SHEET* aSheet ); + std::vector<SCH_HIERLABEL*> importHierLabels( SCH_SHEET* aSheet ); + std::vector<PICKED_SYMBOL> m_symbolHistoryList; std::vector<PICKED_SYMBOL> m_powerHistoryList; std::vector<LIB_ID> m_designBlockHistoryList;