From 7578439b0c7a19f22f3b6faeacc3823df239fb7c Mon Sep 17 00:00:00 2001 From: Mike Williams <mike@mikebwilliams.com> Date: Mon, 17 Feb 2025 10:24:01 -0500 Subject: [PATCH] PCB editor: extend create array functionality to arrange existing items Fixes: https://gitlab.com/kicad/code/kicad/-/issues/19919 --- include/array_options.h | 18 + pcbnew/dialogs/dialog_create_array.cpp | 11 + pcbnew/dialogs/dialog_create_array_base.cpp | 45 +- pcbnew/dialogs/dialog_create_array_base.fbp | 610 ++++++++++++++------ pcbnew/dialogs/dialog_create_array_base.h | 4 + pcbnew/tools/array_tool.cpp | 71 +++ 6 files changed, 571 insertions(+), 188 deletions(-) diff --git a/include/array_options.h b/include/array_options.h index e45deefff9..720dcec890 100644 --- a/include/array_options.h +++ b/include/array_options.h @@ -47,6 +47,7 @@ public: ARRAY_OPTIONS( ARRAY_TYPE_T aType ) : m_type( aType ), m_shouldNumber( false ), + m_arrangeSelection( false ), m_reannotateFootprints( false ), m_numberingStartIsSpecified( false ) { @@ -98,6 +99,19 @@ public: m_shouldNumber = aShouldNumber; } + /** + * @return true if arranging selection, false if creating an array of copies + */ + bool ShouldArrangeSelection() const + { + return m_arrangeSelection; + } + + void SetShouldArrangeSelection( bool aShouldArrange ) + { + m_arrangeSelection = aShouldArrange; + } + /** * @return are the footprints in this array reannotated to be unique (true), or do they * keep the original annotation (false)? @@ -134,6 +148,10 @@ protected: /// True if this array numbers the new items bool m_shouldNumber; + /// True if this array should arrange the selected items instead of creating + /// an array of copies of the selection + bool m_arrangeSelection; + /// True if this array will rename any footprints to be unique bool m_reannotateFootprints; diff --git a/pcbnew/dialogs/dialog_create_array.cpp b/pcbnew/dialogs/dialog_create_array.cpp index d5b6a2ed90..73404a9b5c 100644 --- a/pcbnew/dialogs/dialog_create_array.cpp +++ b/pcbnew/dialogs/dialog_create_array.cpp @@ -78,6 +78,8 @@ struct CREATE_ARRAY_DIALOG_ENTRIES long m_CircNumberingStep = 1; bool m_CircRotatationStep = false; long m_ArrayTypeTab = 0; // start on grid view + bool m_SelectionArrange = false; + bool m_SelectionDuplicate = true; // Duplicate by default bool m_FootprintKeepAnnotations = false; bool m_FootprintReannotate = true; // Assign unique by default }; @@ -201,6 +203,9 @@ DIALOG_CREATE_ARRAY::DIALOG_CREATE_ARRAY( PCB_BASE_FRAME* aParen m_cfg_persister.Add( *m_gridTypeNotebook, s_arrayOptions.m_ArrayTypeTab ); + m_cfg_persister.Add( *m_radioBtnArrangeSelection, s_arrayOptions.m_SelectionArrange ); + m_cfg_persister.Add( *m_radioBtnDuplicateSelection, s_arrayOptions.m_SelectionDuplicate ); + m_cfg_persister.Add( *m_radioBtnKeepRefs, s_arrayOptions.m_FootprintKeepAnnotations ); m_cfg_persister.Add( *m_radioBtnUniqueRefs, s_arrayOptions.m_FootprintReannotate ); @@ -511,6 +516,7 @@ bool DIALOG_CREATE_ARRAY::TransferDataFromWindow() // assign pointer and ownership here m_settings = std::move( newSettings ); + m_settings->SetShouldArrangeSelection( m_radioBtnArrangeSelection->GetValue() ); m_settings->SetSShouldReannotateFootprints( m_radioBtnUniqueRefs->GetValue() ); // persist the control state for next time @@ -608,6 +614,11 @@ void DIALOG_CREATE_ARRAY::setControlEnablement() m_footprintReannotatePanel->Show( true ); } + + if( m_radioBtnArrangeSelection->GetValue() ) + { + m_footprintReannotatePanel->Show( false ); + } } diff --git a/pcbnew/dialogs/dialog_create_array_base.cpp b/pcbnew/dialogs/dialog_create_array_base.cpp index 9bec7a79b5..3e0da37176 100644 --- a/pcbnew/dialogs/dialog_create_array_base.cpp +++ b/pcbnew/dialogs/dialog_create_array_base.cpp @@ -287,7 +287,7 @@ DIALOG_CREATE_ARRAY_BASE::DIALOG_CREATE_ARRAY_BASE( wxWindow* parent, wxWindowID m_gridPanel->SetSizer( bSizerGridArray ); m_gridPanel->Layout(); bSizerGridArray->Fit( m_gridPanel ); - m_gridTypeNotebook->AddPage( m_gridPanel, _("Grid Array"), false ); + m_gridTypeNotebook->AddPage( m_gridPanel, _("Grid Array"), true ); m_circularPanel = new wxPanel( m_gridTypeNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer4; bSizer4 = new wxBoxSizer( wxHORIZONTAL ); @@ -459,14 +459,34 @@ DIALOG_CREATE_ARRAY_BASE::DIALOG_CREATE_ARRAY_BASE( wxWindow* parent, wxWindowID m_circularPanel->SetSizer( bSizer4 ); m_circularPanel->Layout(); bSizer4->Fit( m_circularPanel ); - m_gridTypeNotebook->AddPage( m_circularPanel, _("Circular Array"), true ); + m_gridTypeNotebook->AddPage( m_circularPanel, _("Circular Array"), false ); bSizer7->Add( m_gridTypeNotebook, 1, wxALL|wxEXPAND, 10 ); - m_footprintReannotatePanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_optionsPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer8; bSizer8 = new wxBoxSizer( wxVERTICAL ); + m_itemSourcePanel = new wxPanel( m_optionsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxStaticBoxSizer* sbSizerDuplicateOrArrange; + sbSizerDuplicateOrArrange = new wxStaticBoxSizer( new wxStaticBox( m_itemSourcePanel, wxID_ANY, _("Item Source") ), wxVERTICAL ); + + m_radioBtnDuplicateSelection = new wxRadioButton( sbSizerDuplicateOrArrange->GetStaticBox(), wxID_ANY, _("Duplicate selection"), wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnDuplicateSelection->SetValue( true ); + sbSizerDuplicateOrArrange->Add( m_radioBtnDuplicateSelection, 0, wxALL, 5 ); + + m_radioBtnArrangeSelection = new wxRadioButton( sbSizerDuplicateOrArrange->GetStaticBox(), wxID_ANY, _("Arrange selection"), wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnArrangeSelection->SetToolTip( _("This can conflict with reference designators in the schematic that have not yet been synchronized with the board.") ); + + sbSizerDuplicateOrArrange->Add( m_radioBtnArrangeSelection, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); + + + m_itemSourcePanel->SetSizer( sbSizerDuplicateOrArrange ); + m_itemSourcePanel->Layout(); + sbSizerDuplicateOrArrange->Fit( m_itemSourcePanel ); + bSizer8->Add( m_itemSourcePanel, 0, wxEXPAND | wxALL, 5 ); + + m_footprintReannotatePanel = new wxPanel( m_optionsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxStaticBoxSizer* sbSizerFootprintAnnotation; sbSizerFootprintAnnotation = new wxStaticBoxSizer( new wxStaticBox( m_footprintReannotatePanel, wxID_ANY, _("Footprint Annotation") ), wxVERTICAL ); @@ -480,13 +500,16 @@ DIALOG_CREATE_ARRAY_BASE::DIALOG_CREATE_ARRAY_BASE( wxWindow* parent, wxWindowID sbSizerFootprintAnnotation->Add( m_radioBtnUniqueRefs, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); - bSizer8->Add( sbSizerFootprintAnnotation, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 ); - - - m_footprintReannotatePanel->SetSizer( bSizer8 ); + m_footprintReannotatePanel->SetSizer( sbSizerFootprintAnnotation ); m_footprintReannotatePanel->Layout(); - bSizer8->Fit( m_footprintReannotatePanel ); - bSizer7->Add( m_footprintReannotatePanel, 1, wxEXPAND | wxALL, 5 ); + sbSizerFootprintAnnotation->Fit( m_footprintReannotatePanel ); + bSizer8->Add( m_footprintReannotatePanel, 0, wxEXPAND | wxALL, 5 ); + + + m_optionsPanel->SetSizer( bSizer8 ); + m_optionsPanel->Layout(); + bSizer8->Fit( m_optionsPanel ); + bSizer7->Add( m_optionsPanel, 1, wxEXPAND | wxALL, 5 ); bMainSizer->Add( bSizer7, 1, wxEXPAND, 5 ); @@ -527,6 +550,8 @@ DIALOG_CREATE_ARRAY_BASE::DIALOG_CREATE_ARRAY_BASE( wxWindow* parent, wxWindowID m_entryCircCount->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_rbCircStartNumberingOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_choiceCircNumbering->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnAxisNumberingChange ), NULL, this ); + m_radioBtnDuplicateSelection->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); + m_radioBtnArrangeSelection->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); } DIALOG_CREATE_ARRAY_BASE::~DIALOG_CREATE_ARRAY_BASE() @@ -553,5 +578,7 @@ DIALOG_CREATE_ARRAY_BASE::~DIALOG_CREATE_ARRAY_BASE() m_entryCircCount->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_rbCircStartNumberingOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_choiceCircNumbering->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnAxisNumberingChange ), NULL, this ); + m_radioBtnDuplicateSelection->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); + m_radioBtnArrangeSelection->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); } diff --git a/pcbnew/dialogs/dialog_create_array_base.fbp b/pcbnew/dialogs/dialog_create_array_base.fbp index 8200386787..ac806d6a11 100644 --- a/pcbnew/dialogs/dialog_create_array_base.fbp +++ b/pcbnew/dialogs/dialog_create_array_base.fbp @@ -135,8 +135,8 @@ <object class="notebookpage" expanded="true"> <property name="bitmap">Load From File; </property> <property name="label">Grid Array</property> - <property name="select">0</property> - <object class="wxPanel" expanded="true"> + <property name="select">1</property> + <object class="wxPanel" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -188,16 +188,16 @@ <property name="window_extra_style"></property> <property name="window_name"></property> <property name="window_style">wxTAB_TRAVERSAL</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">bSizerGridArray</property> <property name="orient">wxHORIZONTAL</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxEXPAND</property> <property name="proportion">1</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">bSizerGridLeft</property> <property name="orient">wxVERTICAL</property> @@ -1312,11 +1312,11 @@ </object> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">10</property> <property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property> <property name="proportion">0</property> - <object class="wxStaticBoxSizer" expanded="true"> + <object class="wxStaticBoxSizer" expanded="false"> <property name="id">wxID_ANY</property> <property name="label">Stagger Settings</property> <property name="minimum_size"></property> @@ -1324,7 +1324,7 @@ <property name="orient">wxVERTICAL</property> <property name="parent">1</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxEXPAND</property> <property name="proportion">1</property> @@ -1595,11 +1595,11 @@ </object> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">10</property> <property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property> <property name="proportion">0</property> - <object class="wxStaticBoxSizer" expanded="true"> + <object class="wxStaticBoxSizer" expanded="false"> <property name="id">wxID_ANY</property> <property name="label">Grid Position</property> <property name="minimum_size"></property> @@ -1607,11 +1607,11 @@ <property name="orient">wxVERTICAL</property> <property name="parent">1</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property> <property name="proportion">0</property> - <object class="wxRadioButton" expanded="true"> + <object class="wxRadioButton" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -1672,11 +1672,11 @@ <property name="window_style"></property> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property> <property name="proportion">0</property> - <object class="wxRadioButton" expanded="true"> + <object class="wxRadioButton" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -1741,11 +1741,11 @@ </object> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxEXPAND</property> <property name="proportion">1</property> - <object class="wxPanel" expanded="true"> + <object class="wxPanel" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -1797,16 +1797,16 @@ <property name="window_extra_style"></property> <property name="window_name"></property> <property name="window_style">wxTAB_TRAVERSAL</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">bSizer15</property> <property name="orient">wxVERTICAL</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">10</property> <property name="flag">wxEXPAND|wxLEFT</property> <property name="proportion">1</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">m_gridPadNumberingSizer</property> <property name="orient">wxVERTICAL</property> @@ -2748,8 +2748,8 @@ <object class="notebookpage" expanded="true"> <property name="bitmap"></property> <property name="label">Circular Array</property> - <property name="select">1</property> - <object class="wxPanel" expanded="true"> + <property name="select">0</property> + <object class="wxPanel" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -2801,25 +2801,25 @@ <property name="window_extra_style"></property> <property name="window_name"></property> <property name="window_style">wxTAB_TRAVERSAL</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">bSizer4</property> <property name="orient">wxHORIZONTAL</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxEXPAND</property> <property name="proportion">1</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">bSizerCircLeft</property> <property name="orient">wxVERTICAL</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">10</property> <property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property> <property name="proportion">0</property> - <object class="wxStaticBoxSizer" expanded="true"> + <object class="wxStaticBoxSizer" expanded="false"> <property name="id">wxID_ANY</property> <property name="label">Center position</property> <property name="minimum_size"></property> @@ -2827,11 +2827,11 @@ <property name="orient">wxVERTICAL</property> <property name="parent">1</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">25</property> <property name="flag">wxEXPAND|wxLEFT</property> <property name="proportion">0</property> - <object class="wxFlexGridSizer" expanded="true"> + <object class="wxFlexGridSizer" expanded="false"> <property name="cols">3</property> <property name="flexible_direction">wxBOTH</property> <property name="growablecols">1</property> @@ -3235,20 +3235,20 @@ </object> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxEXPAND</property> <property name="proportion">1</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">bSizer12</property> <property name="orient">wxHORIZONTAL</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxALL</property> <property name="proportion">1</property> - <object class="wxButton" expanded="true"> + <object class="wxButton" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -3319,11 +3319,11 @@ <event name="OnButtonClick">OnSelectCenterButton</event> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxALL</property> <property name="proportion">1</property> - <object class="wxButton" expanded="true"> + <object class="wxButton" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -3398,11 +3398,11 @@ </object> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">10</property> <property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property> <property name="proportion">0</property> - <object class="wxStaticBoxSizer" expanded="true"> + <object class="wxStaticBoxSizer" expanded="false"> <property name="id">wxID_ANY</property> <property name="label">Duplication Settings</property> <property name="minimum_size"></property> @@ -3410,11 +3410,11 @@ <property name="orient">wxVERTICAL</property> <property name="parent">1</property> <property name="permission">none</property> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxALL</property> <property name="proportion">0</property> - <object class="wxCheckBox" expanded="true"> + <object class="wxCheckBox" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -3476,11 +3476,11 @@ <event name="OnCheckBox">OnParameterChanged</event> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxBOTTOM|wxEXPAND</property> <property name="proportion">0</property> - <object class="wxFlexGridSizer" expanded="true"> + <object class="wxFlexGridSizer" expanded="false"> <property name="cols">3</property> <property name="flexible_direction">wxBOTH</property> <property name="growablecols">1</property> @@ -3881,11 +3881,11 @@ </object> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxEXPAND | wxALL</property> <property name="proportion">0</property> - <object class="wxPanel" expanded="true"> + <object class="wxPanel" expanded="false"> <property name="BottomDockable">1</property> <property name="LeftDockable">1</property> <property name="RightDockable">1</property> @@ -3937,7 +3937,7 @@ <property name="window_extra_style"></property> <property name="window_name"></property> <property name="window_style">wxTAB_TRAVERSAL</property> - <object class="wxBoxSizer" expanded="true"> + <object class="wxBoxSizer" expanded="false"> <property name="minimum_size"></property> <property name="name">bSizer13</property> <property name="orient">wxHORIZONTAL</property> @@ -3952,11 +3952,11 @@ <property name="width">10</property> </object> </object> - <object class="sizeritem" expanded="true"> + <object class="sizeritem" expanded="false"> <property name="border">5</property> <property name="flag">wxEXPAND</property> <property name="proportion">1</property> - <object class="wxStaticBoxSizer" expanded="true"> + <object class="wxStaticBoxSizer" expanded="false"> <property name="id">wxID_ANY</property> <property name="label">Numbering Options</property> <property name="minimum_size"></property> @@ -4482,7 +4482,7 @@ <property name="minimize_button">0</property> <property name="minimum_size"></property> <property name="moveable">1</property> - <property name="name">m_footprintReannotatePanel</property> + <property name="name">m_optionsPanel</property> <property name="pane_border">1</property> <property name="pane_position"></property> <property name="pane_size"></property> @@ -4505,144 +4505,396 @@ <property name="permission">none</property> <object class="sizeritem" expanded="true"> <property name="border">5</property> - <property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property> + <property name="flag">wxEXPAND | wxALL</property> <property name="proportion">0</property> - <object class="wxStaticBoxSizer" expanded="true"> + <object class="wxPanel" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer">0</property> + <property name="aui_name"></property> + <property name="aui_position">0</property> + <property name="aui_row">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> <property name="id">wxID_ANY</property> - <property name="label">Footprint Annotation</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> <property name="minimum_size"></property> - <property name="name">sbSizerFootprintAnnotation</property> - <property name="orient">wxVERTICAL</property> - <property name="parent">1</property> - <property name="permission">none</property> - <object class="sizeritem" expanded="false"> - <property name="border">5</property> - <property name="flag">wxALL</property> - <property name="proportion">0</property> - <object class="wxRadioButton" expanded="false"> - <property name="BottomDockable">1</property> - <property name="LeftDockable">1</property> - <property name="RightDockable">1</property> - <property name="TopDockable">1</property> - <property name="aui_layer">0</property> - <property name="aui_name"></property> - <property name="aui_position">0</property> - <property name="aui_row">0</property> - <property name="best_size"></property> - <property name="bg"></property> - <property name="caption"></property> - <property name="caption_visible">1</property> - <property name="center_pane">0</property> - <property name="close_button">1</property> - <property name="context_help"></property> - <property name="context_menu">1</property> - <property name="default_pane">0</property> - <property name="dock">Dock</property> - <property name="dock_fixed">0</property> - <property name="docking">Left</property> - <property name="drag_accept_files">0</property> - <property name="enabled">1</property> - <property name="fg"></property> - <property name="floatable">1</property> - <property name="font"></property> - <property name="gripper">0</property> - <property name="hidden">0</property> - <property name="id">wxID_ANY</property> - <property name="label">Keep existing reference designators</property> - <property name="max_size"></property> - <property name="maximize_button">0</property> - <property name="maximum_size"></property> - <property name="min_size"></property> - <property name="minimize_button">0</property> - <property name="minimum_size"></property> - <property name="moveable">1</property> - <property name="name">m_radioBtnKeepRefs</property> - <property name="pane_border">1</property> - <property name="pane_position"></property> - <property name="pane_size"></property> - <property name="permission">protected</property> - <property name="pin_button">1</property> - <property name="pos"></property> - <property name="resize">Resizable</property> - <property name="show">1</property> - <property name="size"></property> - <property name="style"></property> - <property name="subclass">; ; forward_declare</property> - <property name="toolbar_pane">0</property> - <property name="tooltip"></property> - <property name="validator_data_type"></property> - <property name="validator_style">wxFILTER_NONE</property> - <property name="validator_type">wxDefaultValidator</property> - <property name="validator_variable"></property> - <property name="value">0</property> - <property name="window_extra_style"></property> - <property name="window_name"></property> - <property name="window_style"></property> + <property name="moveable">1</property> + <property name="name">m_itemSourcePanel</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxTAB_TRAVERSAL</property> + <object class="wxStaticBoxSizer" expanded="true"> + <property name="id">wxID_ANY</property> + <property name="label">Item Source</property> + <property name="minimum_size"></property> + <property name="name">sbSizerDuplicateOrArrange</property> + <property name="orient">wxVERTICAL</property> + <property name="parent">1</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxRadioButton" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer">0</property> + <property name="aui_name"></property> + <property name="aui_position">0</property> + <property name="aui_row">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Duplicate selection</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_radioBtnDuplicateSelection</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value">1</property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnRadioButton">OnParameterChanged</event> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxRadioButton" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer">0</property> + <property name="aui_name"></property> + <property name="aui_position">0</property> + <property name="aui_row">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Arrange selection</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_radioBtnArrangeSelection</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip">This can conflict with reference designators in the schematic that have not yet been synchronized with the board.</property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value">0</property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnRadioButton">OnParameterChanged</event> + </object> </object> </object> - <object class="sizeritem" expanded="false"> - <property name="border">5</property> - <property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property> - <property name="proportion">0</property> - <object class="wxRadioButton" expanded="false"> - <property name="BottomDockable">1</property> - <property name="LeftDockable">1</property> - <property name="RightDockable">1</property> - <property name="TopDockable">1</property> - <property name="aui_layer">0</property> - <property name="aui_name"></property> - <property name="aui_position">0</property> - <property name="aui_row">0</property> - <property name="best_size"></property> - <property name="bg"></property> - <property name="caption"></property> - <property name="caption_visible">1</property> - <property name="center_pane">0</property> - <property name="close_button">1</property> - <property name="context_help"></property> - <property name="context_menu">1</property> - <property name="default_pane">0</property> - <property name="dock">Dock</property> - <property name="dock_fixed">0</property> - <property name="docking">Left</property> - <property name="drag_accept_files">0</property> - <property name="enabled">1</property> - <property name="fg"></property> - <property name="floatable">1</property> - <property name="font"></property> - <property name="gripper">0</property> - <property name="hidden">0</property> - <property name="id">wxID_ANY</property> - <property name="label">Assign unique reference designators</property> - <property name="max_size"></property> - <property name="maximize_button">0</property> - <property name="maximum_size"></property> - <property name="min_size"></property> - <property name="minimize_button">0</property> - <property name="minimum_size"></property> - <property name="moveable">1</property> - <property name="name">m_radioBtnUniqueRefs</property> - <property name="pane_border">1</property> - <property name="pane_position"></property> - <property name="pane_size"></property> - <property name="permission">protected</property> - <property name="pin_button">1</property> - <property name="pos"></property> - <property name="resize">Resizable</property> - <property name="show">1</property> - <property name="size"></property> - <property name="style"></property> - <property name="subclass">; ; forward_declare</property> - <property name="toolbar_pane">0</property> - <property name="tooltip">This can conflict with reference designators in the schematic that have not yet been synchronized with the board.</property> - <property name="validator_data_type"></property> - <property name="validator_style">wxFILTER_NONE</property> - <property name="validator_type">wxDefaultValidator</property> - <property name="validator_variable"></property> - <property name="value">1</property> - <property name="window_extra_style"></property> - <property name="window_name"></property> - <property name="window_style"></property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxEXPAND | wxALL</property> + <property name="proportion">0</property> + <object class="wxPanel" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer">0</property> + <property name="aui_name"></property> + <property name="aui_position">0</property> + <property name="aui_row">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_footprintReannotatePanel</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxTAB_TRAVERSAL</property> + <object class="wxStaticBoxSizer" expanded="true"> + <property name="id">wxID_ANY</property> + <property name="label">Footprint Annotation</property> + <property name="minimum_size"></property> + <property name="name">sbSizerFootprintAnnotation</property> + <property name="orient">wxVERTICAL</property> + <property name="parent">1</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="false"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxRadioButton" expanded="false"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer">0</property> + <property name="aui_name"></property> + <property name="aui_position">0</property> + <property name="aui_row">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Keep existing reference designators</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_radioBtnKeepRefs</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value">0</property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> + </object> + <object class="sizeritem" expanded="false"> + <property name="border">5</property> + <property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxRadioButton" expanded="false"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer">0</property> + <property name="aui_name"></property> + <property name="aui_position">0</property> + <property name="aui_row">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Assign unique reference designators</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_radioBtnUniqueRefs</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip">This can conflict with reference designators in the schematic that have not yet been synchronized with the board.</property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value">1</property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> </object> </object> </object> diff --git a/pcbnew/dialogs/dialog_create_array_base.h b/pcbnew/dialogs/dialog_create_array_base.h index d107574dfb..56cf3808d8 100644 --- a/pcbnew/dialogs/dialog_create_array_base.h +++ b/pcbnew/dialogs/dialog_create_array_base.h @@ -111,6 +111,10 @@ class DIALOG_CREATE_ARRAY_BASE : public DIALOG_SHIM wxTextCtrl* m_entryCircNumberingStart; wxStaticText* m_labelCircNumStep; wxTextCtrl* m_entryCircNumberingStep; + wxPanel* m_optionsPanel; + wxPanel* m_itemSourcePanel; + wxRadioButton* m_radioBtnDuplicateSelection; + wxRadioButton* m_radioBtnArrangeSelection; wxPanel* m_footprintReannotatePanel; wxRadioButton* m_radioBtnKeepRefs; wxRadioButton* m_radioBtnUniqueRefs; diff --git a/pcbnew/tools/array_tool.cpp b/pcbnew/tools/array_tool.cpp index 433faa4cbb..6c1c19ddba 100644 --- a/pcbnew/tools/array_tool.cpp +++ b/pcbnew/tools/array_tool.cpp @@ -135,6 +135,77 @@ void ARRAY_TOOL::onDialogClosed( wxCloseEvent& aEvent ) EDA_ITEMS all_added_items; int arraySize = m_array_opts->GetArraySize(); + + if( m_array_opts->ShouldArrangeSelection() ) + { + std::set<FOOTPRINT*> fpDeDupe; + + EDA_ITEMS sortedSelection = selection.GetItemsSortedBySelectionOrder(); + int selectionIndex = 0; + + BOARD_ITEM* firstItem = nullptr; + + for( int arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex ) + { + BOARD_ITEM* item = nullptr; + + // Get the next valid item to arrange + for( ; selectionIndex < (int) sortedSelection.size(); selectionIndex++ ) + { + item = nullptr; + + if( !sortedSelection[selectionIndex]->IsBOARD_ITEM() ) + continue; + + item = static_cast<BOARD_ITEM*>( sortedSelection[selectionIndex] ); + + FOOTPRINT* parentFootprint = item->GetParentFootprint(); + + // If it is not the footprint editor, then move the parent footprint instead. + if( !m_isFootprintEditor && parentFootprint ) + { + // It is possible to select multiple footprint child objects in the board editor. + // Do not create multiple copies of the same footprint when this occurs. + if( fpDeDupe.count( parentFootprint ) == 0 ) + { + fpDeDupe.emplace( parentFootprint ); + item = parentFootprint; + } + else + { + item = nullptr; + continue; + } + } + + // Found a valid item + selectionIndex++; + break; + } + + // Must be out of items to arrange, we're done + if( item == nullptr ) + break; + + commit.Modify( item ); + + // Transform is a relative move, so when arranging the transform needs to start from + // the same point for each item, e.g. the first item's position + if( firstItem == nullptr ) + firstItem = item; + else + item->SetPosition( firstItem->GetPosition() ); + + TransformItem( *m_array_opts, arrayIndex, *item ); + } + + // Make sure we did something... + if( firstItem != nullptr ) + commit.Push( _( "Arrange selection" ) ); + + return; + } + // Iterate in reverse so the original items go last, and we can // use them for the positions of the clones. for( int ptN = arraySize - 1; ptN >= 0; --ptN )