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
This commit is contained in:
committed by
eurofun1
parent
4678000a0e
commit
6dd366f7bf
@@ -27,6 +27,8 @@
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <tools/multichannel_tool.h>
|
||||
#include <zone.h>
|
||||
#include <board.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@
|
||||
#define __DIALOG_MULTICHANNEL_REPEAT_LAYOUT__
|
||||
|
||||
#include <vector>
|
||||
#include <board.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <dialogs/dialog_multichannel_repeat_layout_base.h>
|
||||
@@ -54,6 +55,7 @@ private:
|
||||
|
||||
std::vector<TABLE_ENTRY> m_targetRAs;
|
||||
MULTICHANNEL_TOOL* m_parentTool;
|
||||
BOARD* m_board;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 ) );
|
||||
|
||||
@@ -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 <wx/settings.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
@@ -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;
|
||||
|
||||
@@ -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<BOARD_ITEM*>&
|
||||
}
|
||||
|
||||
|
||||
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<BOARD_ITEM*>& aAffectedItems,
|
||||
std::unordered_set<BOARD_ITEM*>& 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<BOARD_CONNECTED_ITEM*>( item ), static_cast<BOARD_CONNECTED_ITEM*>( copied ),
|
||||
aMatches );
|
||||
}
|
||||
copied->Rotate( VECTOR2( 0, 0 ), rot );
|
||||
copied->Move( disp );
|
||||
copied->SetParentGroup( nullptr );
|
||||
const_cast<KIID&>( copied->m_Uuid ) = KIID();
|
||||
@@ -900,6 +921,7 @@ bool MULTICHANNEL_TOOL::copyRuleAreaContents( TMATCH::COMPONENT_MATCHES& aMatche
|
||||
copied->ClearFlags();
|
||||
copied->SetParentGroup( nullptr );
|
||||
const_cast<KIID&>( 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user