From 6dd366f7bfee6f8e68ea1acd12c8a36d5cdf963a Mon Sep 17 00:00:00 2001 From: Alexander Boehm Date: Sat, 19 Apr 2025 16:33:08 +0200 Subject: [PATCH] multi-channel tool: anchor footprints adds a dropdown menu to select an anchor footprint from the reference rule area. The corresponding footprints in the target areas determine displacement and rotation off all the replicated items. If no anchor footprint has been selected the previous behavior is unchanged, i.e. rule area position determines placement. Fixes https://gitlab.com/kicad/code/kicad/-/issues/20603 --- .../dialog_multichannel_repeat_layout.cpp | 29 +- .../dialog_multichannel_repeat_layout.fbp | 1373 +++++++++-------- .../dialog_multichannel_repeat_layout.h | 2 + ...dialog_multichannel_repeat_layout_base.cpp | 41 +- .../dialog_multichannel_repeat_layout_base.h | 6 +- pcbnew/tools/multichannel_tool.cpp | 58 +- pcbnew/tools/multichannel_tool.h | 1 + 7 files changed, 853 insertions(+), 657 deletions(-) diff --git a/pcbnew/dialogs/dialog_multichannel_repeat_layout.cpp b/pcbnew/dialogs/dialog_multichannel_repeat_layout.cpp index faedf5e303..40caf12a02 100644 --- a/pcbnew/dialogs/dialog_multichannel_repeat_layout.cpp +++ b/pcbnew/dialogs/dialog_multichannel_repeat_layout.cpp @@ -27,6 +27,8 @@ #include #include #include +#include + DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT ( PCB_BASE_FRAME* aFrame, @@ -34,6 +36,7 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT ( DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE( aFrame ), m_parentTool( aParentTool ) { + m_board = aFrame->GetBoard(); auto data = m_parentTool->GetData(); m_refRAName->SetLabelText( data->m_refRA->m_area->GetZoneName() ); @@ -69,6 +72,7 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT ( m_raGrid->SetColLabelValue( 0, wxT("Copy") ); m_raGrid->SetColLabelValue( 1, wxT("Target Rule Area") ); m_raGrid->SetColLabelValue( 2, wxT("Status") ); + m_raGrid->SetColLabelValue( 3, wxT( "RefFp" ) ); m_raGrid->AutoSizeColumn( 1 ); m_raGrid->AppendRows( m_targetRAs.size() - 1 ); @@ -82,9 +86,19 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT::DIALOG_MULTICHANNEL_REPEAT_LAYOUT ( i++; } - m_raGrid->SetMaxSize( wxSize( -1, 800 ) ); + m_raGrid->SetMaxSize( wxSize( -1, 400 ) ); m_raGrid->Fit(); + wxArrayString refFpNames; + refFpNames.push_back( "" ); + + for( FOOTPRINT* fp : data->m_refRA->m_raFootprints ) + refFpNames.push_back( fp->GetReference() ); + + refFpNames.Sort(); + m_refAnchorFp->Set( refFpNames ); + m_refAnchorFp->SetSelection( 0 ); + m_cbCopyPlacement->SetValue( data->m_options.m_copyPlacement ); m_cbCopyRouting->SetValue( data->m_options.m_copyRouting ); m_cbGroupItems->SetValue( data->m_options.m_groupItems ); @@ -117,6 +131,19 @@ bool DIALOG_MULTICHANNEL_REPEAT_LAYOUT::TransferDataFromWindow() data->m_options.m_includeLockedItems = m_cbIncludeLockedComponents->GetValue(); data->m_options.m_moveOffRAComponents = m_cbIncludeOffRAComponents->GetValue(); + if( m_refAnchorFp->GetString( m_refAnchorFp->GetSelection() ) == "" ) + { + data->m_options.m_anchorFp = nullptr; + } + else + { + for( FOOTPRINT* fp : m_board->Footprints() ) + { + if( fp->GetReference() == m_refAnchorFp->GetString( m_refAnchorFp->GetSelection() ) ) + data->m_options.m_anchorFp = fp; + } + } + return true; } diff --git a/pcbnew/dialogs/dialog_multichannel_repeat_layout.fbp b/pcbnew/dialogs/dialog_multichannel_repeat_layout.fbp index 73980a7c94..4080f52542 100644 --- a/pcbnew/dialogs/dialog_multichannel_repeat_layout.fbp +++ b/pcbnew/dialogs/dialog_multichannel_repeat_layout.fbp @@ -47,7 +47,7 @@ 0 wxID_ANY - 800,-1 + -1,-1 DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE -1,-1 @@ -61,30 +61,316 @@ OnInitDlg OnUpdateUI - - 800,300 - m_GeneralBoxSizer - wxVERTICAL - private + + 1 + wxBOTH + 0 + 1 + 0 + 600,-1 + fgSizer3 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Target areas: + 0 + + 0 + + + 0 + + 1 + m_staticText4 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 1 + 1 + + + + 1 + + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTER + wxGRID_AUTOSIZE + + wxALIGN_CENTER + 3 + + + 1 + 0 + Dock + 0 + Left + 0 + 0 + 1 + 0 + 1 + 0 + 1 + + 1 + + + 1 + 0 + 0 + wxID_ANY + + + + 0 + 0 + + 0 + -1,-1 + + 0 + -1,-1 + 1 + m_raGrid + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTER + wxGRID_AUTOSIZE + + wxALIGN_CENTER + + 1 + 1 + + ; ; forward_declare + 0 + + + + wxVSCROLL + + 5 wxEXPAND 1 - - 1 - wxBOTH - 0 - 2 - 0 - 800,300 - fgSizer3 - wxFLEX_GROWMODE_SPECIFIED + + + bSizer4 + wxHORIZONTAL + none + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Reference Rule Area: + 0 + + 0 + + + 0 + + 1 + m_staticText1 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + ,90,92,-1,70,0 + 0 + 0 + wxID_ANY + MyLabel + 0 + + 0 + + + 0 + + 1 + m_refRAName + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + + + 5 + wxEXPAND + 1 + + + bSizer41 + wxHORIZONTAL none - 0 - 0 5 - wxALL + wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -115,7 +401,7 @@ 0 0 wxID_ANY - Target areas: + Anchor footprint: 0 0 @@ -124,7 +410,7 @@ 0 1 - m_staticText4 + m_staticText2 1 @@ -144,11 +430,11 @@ -1 - + 5 - wxALL|wxEXPAND - 1 - + wxALL + 0 + 1 1 1 @@ -157,25 +443,13 @@ 0 0 - 1 - 1 1 - - - wxALIGN_LEFT - - wxALIGN_TOP 0 + 1 - wxALIGN_CENTER - - - wxALIGN_CENTER - 3 - 1 0 @@ -183,33 +457,21 @@ 0 Left 0 - 1 - 1 - 0 - 1 - 0 1 1 - - 1 0 0 wxID_ANY - - - - 0 - 0 0 - + -1,400 0 1 - m_raGrid + m_refAnchorFp 1 @@ -217,595 +479,460 @@ 1 Resizable - wxALIGN_CENTER - wxGRID_AUTOSIZE - - wxALIGN_CENTER - - 1 + 0 1 + ; ; forward_declare 0 - + Optional, use for precise and/or rotated placement. Select reference rule area footprint, place corresponding target rule area footprint(s). + + wxFILTER_NONE + wxDefaultValidator + - + + + + 5 + wxEXPAND + 1 + + + bSizer13 + wxVERTICAL + none + 5 - wxEXPAND - 1 - + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Copy footprint placement + + 0 + + + 0 - bSizer4 - wxHORIZONTAL - none - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Reference Rule Area: - 0 - - 0 - - - 0 - - 1 - m_staticText1 - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - ,90,92,-1,70,0 - 0 - 0 - wxID_ANY - MyLabel - 0 - - 0 - - - 0 - - 1 - m_refRAName - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - - - 5 - wxEXPAND - 1 - - - bSizer13 - wxVERTICAL - none - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Copy footprint placement - - 0 - - - 0 - - 1 - m_cbCopyPlacement - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Copy routing - - 0 - - - 0 - - 1 - m_cbCopyRouting - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Copy other items - - 0 - - - 0 - - 1 - m_cbCopyOtherItems - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - Copy text, shapes, zones, and other items inside the source rule area - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 1 - wxID_ANY - Include footprints outside the reference rule area - - 0 - - - 0 - - 1 - m_cbIncludeOffRAComponents - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Group items with their target rule areas - - 0 - - - 0 - - 1 - m_cbGroupItems - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Remove locked items from target rule areas - - 0 - - - 0 - - 1 - m_cbIncludeLockedComponents - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - + 1 + m_cbCopyPlacement + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + 5 - wxEXPAND|wxLEFT + wxALL 0 - + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Copy routing + + 0 + + + 0 - bottomButtonsSizer - wxHORIZONTAL - none - - 5 - - 0 - - 0 - protected - 10 - - - - 5 - wxEXPAND|wxALL - 1 - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - - m_sdbSizerStdButtons - protected - - + 1 + m_cbCopyRouting + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Copy other items + + 0 + + + 0 + + 1 + m_cbCopyOtherItems + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + Copy text, shapes, zones, and other items inside the source rule area + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 1 + wxID_ANY + Include footprints outside the reference rule area + + 0 + + + 0 + + 1 + m_cbIncludeOffRAComponents + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Group items with their target rule areas + + 0 + + + 0 + + 1 + m_cbGroupItems + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Remove locked items from target rule areas + + 0 + + + 0 + + 1 + m_cbIncludeLockedComponents + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + 5 + wxEXPAND|wxLEFT + 0 + + + bottomButtonsSizer + wxHORIZONTAL + none + + 5 + + 0 + + 0 + protected + 10 + + + + 5 + wxEXPAND|wxALL + 1 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizerStdButtons + protected diff --git a/pcbnew/dialogs/dialog_multichannel_repeat_layout.h b/pcbnew/dialogs/dialog_multichannel_repeat_layout.h index 03bd964b17..293d3f9cf0 100644 --- a/pcbnew/dialogs/dialog_multichannel_repeat_layout.h +++ b/pcbnew/dialogs/dialog_multichannel_repeat_layout.h @@ -25,6 +25,7 @@ #define __DIALOG_MULTICHANNEL_REPEAT_LAYOUT__ #include +#include #include #include @@ -54,6 +55,7 @@ private: std::vector m_targetRAs; MULTICHANNEL_TOOL* m_parentTool; + BOARD* m_board; }; #endif diff --git a/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.cpp b/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.cpp index a82324b3b7..3caf6ecb0b 100644 --- a/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.cpp +++ b/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -11,24 +11,21 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( 800,-1 ), wxDefaultSize ); + this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - m_GeneralBoxSizer = new wxBoxSizer( wxVERTICAL ); - - m_GeneralBoxSizer->SetMinSize( wxSize( 800,300 ) ); wxFlexGridSizer* fgSizer3; fgSizer3 = new wxFlexGridSizer( 0, 1, 0, 0 ); fgSizer3->AddGrowableCol( 0 ); - fgSizer3->AddGrowableRow( 2 ); + fgSizer3->AddGrowableRow( 1 ); fgSizer3->SetFlexibleDirection( wxBOTH ); fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - fgSizer3->SetMinSize( wxSize( 800,300 ) ); + fgSizer3->SetMinSize( wxSize( 600,-1 ) ); m_staticText4 = new wxStaticText( this, wxID_ANY, _("Target areas:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText4->Wrap( -1 ); fgSizer3->Add( m_staticText4, 0, wxALL, 5 ); - m_raGrid = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_raGrid = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL ); // Grid m_raGrid->CreateGrid( 1, 3 ); @@ -39,8 +36,9 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE( // Columns m_raGrid->AutoSizeColumns(); - m_raGrid->EnableDragColMove( true ); + m_raGrid->EnableDragColMove( false ); m_raGrid->EnableDragColSize( true ); + m_raGrid->SetColLabelSize( wxGRID_AUTOSIZE ); m_raGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); // Rows @@ -71,6 +69,24 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE( fgSizer3->Add( bSizer4, 1, wxEXPAND, 5 ); + wxBoxSizer* bSizer41; + bSizer41 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText2 = new wxStaticText( this, wxID_ANY, _("Anchor footprint:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText2->Wrap( -1 ); + bSizer41->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + wxArrayString m_refAnchorFpChoices; + m_refAnchorFp = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_refAnchorFpChoices, 0 ); + m_refAnchorFp->SetSelection( 0 ); + m_refAnchorFp->SetToolTip( _("Optional, use for precise and/or rotated placement.\nSelect reference rule area footprint, place corresponding\ntarget rule area footprint(s).") ); + m_refAnchorFp->SetMaxSize( wxSize( -1,400 ) ); + + bSizer41->Add( m_refAnchorFp, 0, wxALL, 5 ); + + + fgSizer3->Add( bSizer41, 1, wxEXPAND, 5 ); + wxBoxSizer* bSizer13; bSizer13 = new wxBoxSizer( wxVERTICAL ); @@ -118,12 +134,9 @@ DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE( fgSizer3->Add( bottomButtonsSizer, 0, wxEXPAND|wxLEFT, 5 ); - m_GeneralBoxSizer->Add( fgSizer3, 1, wxEXPAND, 5 ); - - - this->SetSizer( m_GeneralBoxSizer ); + this->SetSizer( fgSizer3 ); this->Layout(); - m_GeneralBoxSizer->Fit( this ); + fgSizer3->Fit( this ); // Connect Events this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE::OnInitDlg ) ); diff --git a/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.h b/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.h index 4e01168cfd..1e0937748c 100644 --- a/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.h +++ b/pcbnew/dialogs/dialog_multichannel_repeat_layout_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -31,13 +32,14 @@ class DIALOG_MULTICHANNEL_REPEAT_LAYOUT_BASE : public DIALOG_SHIM { private: - wxBoxSizer* m_GeneralBoxSizer; protected: wxStaticText* m_staticText4; wxGrid* m_raGrid; wxStaticText* m_staticText1; wxStaticText* m_refRAName; + wxStaticText* m_staticText2; + wxChoice* m_refAnchorFp; wxCheckBox* m_cbCopyPlacement; wxCheckBox* m_cbCopyRouting; wxCheckBox* m_cbCopyOtherItems; diff --git a/pcbnew/tools/multichannel_tool.cpp b/pcbnew/tools/multichannel_tool.cpp index 703e40cb3f..315127185a 100644 --- a/pcbnew/tools/multichannel_tool.cpp +++ b/pcbnew/tools/multichannel_tool.cpp @@ -528,7 +528,6 @@ int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone ) int totalCopied = 0; BOARD_COMMIT commit( GetManager(), true ); - for( auto& targetArea : m_areas.m_compatMap ) { if( !targetArea.second.m_doCopy ) @@ -541,9 +540,8 @@ int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone ) if( !targetArea.second.m_isOk ) continue; - - if( !copyRuleAreaContents( targetArea.second.m_matchingComponents, &commit, m_areas.m_refRA, - targetArea.first, m_areas.m_options, targetArea.second.m_affectedItems, + if( !copyRuleAreaContents( targetArea.second.m_matchingComponents, &commit, m_areas.m_refRA, targetArea.first, + m_areas.m_options, targetArea.second.m_affectedItems, targetArea.second.m_groupableItems ) ) { auto errMsg = wxString::Format( @@ -561,6 +559,7 @@ int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone ) return -1; } totalCopied++; + wxSafeYield(); } if( m_areas.m_options.m_groupItems ) @@ -707,10 +706,8 @@ int MULTICHANNEL_TOOL::findRoutedConnections( std::set& } -bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatches, - BOARD_COMMIT* aCommit, - RULE_AREA* aRefArea, RULE_AREA* aTargetArea, - REPEAT_LAYOUT_OPTIONS aOpts, +bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatches, BOARD_COMMIT* aCommit, + RULE_AREA* aRefArea, RULE_AREA* aTargetArea, REPEAT_LAYOUT_OPTIONS aOpts, std::unordered_set& aAffectedItems, std::unordered_set& aGroupableItems ) { @@ -718,7 +715,29 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche SHAPE_LINE_CHAIN refOutline = aRefArea->m_area->Outline()->COutline( 0 ); SHAPE_LINE_CHAIN targetOutline = aTargetArea->m_area->Outline()->COutline( 0 ); + FOOTPRINT* targetAnchorFp = nullptr; VECTOR2I disp = aTargetArea->m_center - aRefArea->m_center; + EDA_ANGLE rot = EDA_ANGLE( 0 ); + + if( aOpts.m_anchorFp ) + { + for( auto& fpPair : aMatches ) + { + if( fpPair.first->GetReference() == aOpts.m_anchorFp->GetReference() ) + targetAnchorFp = fpPair.second; + } + + if( targetAnchorFp ) + { + VECTOR2I oldpos = aOpts.m_anchorFp->GetPosition(); + rot = EDA_ANGLE( targetAnchorFp->GetOrientationDegrees() - aOpts.m_anchorFp->GetOrientationDegrees() ); + aOpts.m_anchorFp->Rotate( VECTOR2( 0, 0 ), EDA_ANGLE( rot ) ); + oldpos = aOpts.m_anchorFp->GetPosition(); + VECTOR2I newpos = targetAnchorFp->GetPosition(); + disp = newpos - oldpos; + aOpts.m_anchorFp->Rotate( VECTOR2( 0, 0 ), EDA_ANGLE( -rot ) ); + } + } SHAPE_POLY_SET refPoly; refPoly.AddOutline( refOutline ); @@ -727,6 +746,7 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche SHAPE_POLY_SET targetPoly; SHAPE_LINE_CHAIN newTargetOutline( refOutline ); + newTargetOutline.Rotate( rot, VECTOR2( 0, 0 ) ); newTargetOutline.Move( disp ); targetPoly.AddOutline( newTargetOutline ); targetPoly.CacheTriangulation( false ); @@ -786,6 +806,7 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche fixupNet( static_cast( item ), static_cast( copied ), aMatches ); } + copied->Rotate( VECTOR2( 0, 0 ), rot ); copied->Move( disp ); copied->SetParentGroup( nullptr ); const_cast( copied->m_Uuid ) = KIID(); @@ -900,6 +921,7 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche copied->ClearFlags(); copied->SetParentGroup( nullptr ); const_cast( copied->m_Uuid ) = KIID(); + copied->Rotate( VECTOR2( 0, 0 ), rot ); copied->Move( disp ); aGroupableItems.insert( copied ); aCommit->Add( copied ); @@ -907,11 +929,6 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche } } - aTargetArea->m_area->RemoveAllContours(); - aTargetArea->m_area->AddPolygon( newTargetOutline ); - aTargetArea->m_area->UnHatchBorder(); - aTargetArea->m_area->HatchBorder(); - if( aOpts.m_copyPlacement ) { for( auto& fpPair : aMatches ) @@ -943,9 +960,9 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche targetFP->SetLayerAndFlip( refFP->GetLayer() ); targetFP->SetOrientation( refFP->GetOrientation() ); - VECTOR2I targetPos = refFP->GetPosition() + disp; - targetFP->SetPosition( targetPos ); - + targetFP->SetPosition( refFP->GetPosition() ); + targetFP->Rotate( VECTOR2( 0, 0 ), rot ); + targetFP->Move( disp ); for( PCB_FIELD* refField : refFP->GetFields() ) { if( !refField->IsVisible() ) @@ -955,7 +972,9 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche wxCHECK2( targetField, continue ); targetField->SetAttributes( refField->GetAttributes() ); - targetField->SetPosition( refField->GetPosition() + disp ); + targetField->SetPosition( refField->GetPosition() ); + targetField->Rotate( VECTOR2( 0, 0 ), rot ); + targetField->Move( disp ); targetField->SetIsKnockout( refField->IsKnockout() ); } @@ -964,6 +983,11 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche } } + aTargetArea->m_area->RemoveAllContours(); + aTargetArea->m_area->AddPolygon( newTargetOutline ); + aTargetArea->m_area->UnHatchBorder(); + aTargetArea->m_area->HatchBorder(); + return true; } diff --git a/pcbnew/tools/multichannel_tool.h b/pcbnew/tools/multichannel_tool.h index 24f7494321..316ceeefbe 100644 --- a/pcbnew/tools/multichannel_tool.h +++ b/pcbnew/tools/multichannel_tool.h @@ -55,6 +55,7 @@ struct REPEAT_LAYOUT_OPTIONS bool m_includeLockedItems = true; bool m_keepOldRouting = false; bool m_copyOnlyMatchingRAShapes = false; + FOOTPRINT* m_anchorFp = nullptr; REPEAT_LAYOUT_EDGE_MODE m_edgeMode = REPEAT_LAYOUT_EDGE_MODE::INSIDE; };