Browse Source

multichannel: support groups

pull/18/head
Mike Williams 5 months ago
parent
commit
87c91fea3d
  1. 1
      api/proto/board/board_types.proto
  2. 6
      pcbnew/api/api_pcb_enums.cpp
  3. 78
      pcbnew/dialogs/dialog_multichannel_generate_rule_areas.cpp
  4. 3
      pcbnew/dialogs/dialog_multichannel_generate_rule_areas.h
  5. 2
      pcbnew/dialogs/dialog_multichannel_generate_rule_areas_base.cpp
  6. 1
      pcbnew/dialogs/dialog_multichannel_generate_rule_areas_base.fbp
  7. 1
      pcbnew/dialogs/dialog_multichannel_generate_rule_areas_base.h
  8. 56
      pcbnew/dialogs/dialog_rule_area_properties.cpp
  9. 17
      pcbnew/dialogs/panel_rule_area_properties_placement_base.cpp
  10. 143
      pcbnew/dialogs/panel_rule_area_properties_placement_base.fbp
  11. 4
      pcbnew/dialogs/panel_rule_area_properties_placement_base.h
  12. 4
      pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp
  13. 9
      pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp
  14. 65
      pcbnew/tools/multichannel_tool.cpp
  15. 3
      pcbnew/tools/multichannel_tool.h
  16. 3
      pcbnew/zone.cpp
  17. 5
      pcbnew/zone_settings.h

1
api/proto/board/board_types.proto

@ -609,6 +609,7 @@ enum PlacementRuleSourceType
PRST_UNKNOWN = 0;
PRST_SHEET_NAME = 1;
PRST_COMPONENT_CLASS = 2;
PRST_GROUP = 3;
}
message RuleAreaSettings

6
pcbnew/api/api_pcb_enums.cpp

@ -396,6 +396,9 @@ types::PlacementRuleSourceType ToProtoEnum( RULE_AREA_PLACEMENT_SOURCE_TYPE aVal
case RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS:
return types::PlacementRuleSourceType::PRST_COMPONENT_CLASS;
case RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP:
return types::PlacementRuleSourceType::PRST_GROUP;
default:
wxCHECK_MSG( false, types::PlacementRuleSourceType::PRST_UNKNOWN,
"Unhandled case in ToProtoEnum<RULE_AREA_PLACEMENT_SOURCE_TYPE>");
@ -415,6 +418,9 @@ RULE_AREA_PLACEMENT_SOURCE_TYPE FromProtoEnum( types::PlacementRuleSourceType aV
case types::PlacementRuleSourceType::PRST_COMPONENT_CLASS:
return RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS;
case types::PlacementRuleSourceType::PRST_GROUP:
return RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP;
default:
wxCHECK_MSG( false, RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME,
"Unhandled case in FromProtoEnum<types::PlacementRuleSourceType>" );

78
pcbnew/dialogs/dialog_multichannel_generate_rule_areas.cpp

@ -89,17 +89,45 @@ DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS
m_componentClassGrid->AutoSizeColumn( 1 );
m_sourceNotebook->AddPage( m_componentClassGrid, _( "Component Classes" ) );
// Generate the group source grid
m_groupGrid = new WX_GRID( m_sourceNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_groupGrid->CreateGrid( 0, 2 );
m_groupGrid->EnableEditing( false );
m_groupGrid->EnableGridLines( true );
m_groupGrid->EnableDragGridSize( false );
m_groupGrid->SetMargins( 0, 0 );
m_groupGrid->SetColSize( 0, 100 );
m_groupGrid->SetColSize( 1, 300 );
m_groupGrid->AutoSizeColumns();
m_groupGrid->EnableDragColMove( true );
m_groupGrid->EnableDragColSize( true );
m_groupGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
m_groupGrid->AutoSizeRows();
m_groupGrid->EnableDragRowSize( true );
m_groupGrid->SetRowLabelSize( wxGRID_AUTOSIZE );
m_groupGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
m_groupGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
m_groupGrid->EnableEditing( true );
m_groupGrid->HideRowLabels();
m_groupGrid->SetColLabelValue( 0, _( "Generate" ) );
m_groupGrid->SetColLabelValue( 1, _( "Name" ) );
m_groupGrid->AutoSizeColumn( 1 );
m_sourceNotebook->AddPage( m_groupGrid, _( "Groups" ) );
RULE_AREAS_DATA* raData = m_parentTool->GetData();
int sheetRowIdx = 0;
int componentClassRowIdx = 0;
int groupIdx = 0;
for( RULE_AREA& ruleArea : raData->m_areas )
{
if( ruleArea.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
sheetRowIdx++;
else
else if( ruleArea.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
componentClassRowIdx++;
else if( ruleArea.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP )
groupIdx++;
}
if( sheetRowIdx > 0 )
@ -108,8 +136,12 @@ DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS
if( componentClassRowIdx > 0 )
m_componentClassGrid->AppendRows( componentClassRowIdx );
if( groupIdx > 0 )
m_groupGrid->AppendRows( groupIdx );
sheetRowIdx = 0;
componentClassRowIdx = 0;
groupIdx = 0;
for( RULE_AREA& ruleArea : raData->m_areas )
{
@ -123,7 +155,7 @@ DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS
ruleArea.m_generateEnabled ? wxT( "1" ) : wxT( "" ) );
sheetRowIdx++;
}
else
else if( ruleArea.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
{
m_componentClassGrid->SetCellValue( componentClassRowIdx, 1,
ruleArea.m_componentClass );
@ -135,19 +167,34 @@ DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS
componentClassRowIdx, 0, ruleArea.m_generateEnabled ? wxT( "1" ) : wxT( "" ) );
componentClassRowIdx++;
}
else
{
m_groupGrid->SetCellValue( groupIdx, 1, ruleArea.m_groupName );
m_groupGrid->SetCellRenderer( groupIdx, 0, new wxGridCellBoolRenderer );
m_groupGrid->SetCellEditor( groupIdx, 0, new wxGridCellBoolEditor );
m_groupGrid->SetCellValue( groupIdx, 0, ruleArea.m_generateEnabled ? wxT( "1" ) : wxT( "" ) );
groupIdx++;
}
}
m_sheetGrid->SetMaxSize( wxSize( -1, 800 ) );
m_sheetGrid->Fit();
m_componentClassGrid->SetMaxSize( wxSize( -1, 800 ) );
m_componentClassGrid->Fit();
m_groupGrid->SetMaxSize( wxSize( -1, 800 ) );
m_groupGrid->Fit();
m_cbGroupItems->SetValue( raData->m_options.m_groupItems );
m_cbReplaceExisting->SetValue( raData->m_replaceExisting );
Layout();
if( m_sheetGrid->GetNumberRows() == 1 && m_componentClassGrid->GetNumberRows() > 0 )
m_sourceNotebook->SetSelection( 1 );
if( m_sheetGrid->GetNumberRows() == 1 )
{
if( m_componentClassGrid->GetNumberRows() > 0 )
m_sourceNotebook->SetSelection( 1 );
else if( m_groupGrid->GetNumberRows() > 0 )
m_sourceNotebook->SetSelection( 2 );
}
SetupStandardButtons();
finishDialogSettings();
@ -166,6 +213,7 @@ bool DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::TransferDataFromWindow()
int sheetRowIdx = 0;
int componentClassRowIdx = 0;
int groupIdx = 0;
for( size_t i = 0; i < raData->m_areas.size(); i++ )
{
@ -176,17 +224,27 @@ bool DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::TransferDataFromWindow()
enabled = m_sheetGrid->GetCellValue( sheetRowIdx, 0 );
sheetRowIdx++;
}
else
else if( raData->m_areas[i].m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
{
enabled = m_componentClassGrid->GetCellValue( componentClassRowIdx, 0 );
componentClassRowIdx++;
}
else
{
enabled = m_groupGrid->GetCellValue( groupIdx, 0 );
groupIdx++;
}
raData->m_areas[i].m_generateEnabled = ( !enabled.CompareTo( wxT( "1" ) ) ) ? true : false;
}
raData->m_replaceExisting = m_cbReplaceExisting->GetValue();
raData->m_options.m_groupItems = m_cbGroupItems->GetValue();
// Don't allow grouping for groups
if( m_sourceNotebook->GetNotebookPage( 2 ) )
raData->m_options.m_groupItems = false;
else
raData->m_options.m_groupItems = m_cbGroupItems->GetValue();
return true;
}
@ -199,3 +257,11 @@ bool DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::TransferDataToWindow()
return true;
}
void DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS::OnNotebookPageChanged( wxNotebookEvent& event )
{
if( event.GetSelection() == 2 )
m_cbGroupItems->Disable();
else
m_cbGroupItems->Enable();
}

3
pcbnew/dialogs/dialog_multichannel_generate_rule_areas.h

@ -45,11 +45,14 @@ public:
bool TransferDataFromWindow() override;
bool TransferDataToWindow() override;
void OnNotebookPageChanged( wxNotebookEvent& event ) override;
private:
MULTICHANNEL_TOOL* m_parentTool;
wxGrid* m_sheetGrid;
wxGrid* m_componentClassGrid;
wxGrid* m_groupGrid;
};
#endif

2
pcbnew/dialogs/dialog_multichannel_generate_rule_areas_base.cpp

@ -66,6 +66,7 @@ DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::DIALOG_MULTICHANNEL_GENERATE_RULE_
// Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::OnInitDlg ) );
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::OnUpdateUI ) );
m_sourceNotebook->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::OnNotebookPageChanged ), NULL, this );
}
DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::~DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE()
@ -73,5 +74,6 @@ DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::~DIALOG_MULTICHANNEL_GENERATE_RULE
// Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::OnInitDlg ) );
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::OnUpdateUI ) );
m_sourceNotebook->Disconnect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE::OnNotebookPageChanged ), NULL, this );
}

1
pcbnew/dialogs/dialog_multichannel_generate_rule_areas_base.fbp

@ -140,6 +140,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnNotebookPageChanged">OnNotebookPageChanged</event>
</object>
</object>
<object class="sizeritem" expanded="true">

1
pcbnew/dialogs/dialog_multichannel_generate_rule_areas_base.h

@ -43,6 +43,7 @@ class DIALOG_MULTICHANNEL_GENERATE_RULE_AREAS_BASE : public DIALOG_SHIM
// Virtual event handlers, override them in your derived class
virtual void OnInitDlg( wxInitDialogEvent& event ) { event.Skip(); }
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnNotebookPageChanged( wxNotebookEvent& event ) { event.Skip(); }
public:

56
pcbnew/dialogs/dialog_rule_area_properties.cpp

@ -27,6 +27,7 @@
#include <kiface_base.h>
#include <confirm.h>
#include <board.h>
#include <eda_group.h>
#include <footprint.h>
#include <pcb_edit_frame.h>
#include <pcbnew_settings.h>
@ -59,6 +60,7 @@ private:
void OnLayerSelection( wxDataViewEvent& event ) override;
void OnSheetNameClicked( wxCommandEvent& event );
void OnComponentClassClicked( wxCommandEvent& event );
void OnGroupClicked( wxCommandEvent& event );
private:
BOARD* m_board;
@ -136,6 +138,10 @@ DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aPar
wxEVT_CHECKBOX,
wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnComponentClassClicked ), nullptr,
this );
m_placementProperties->m_GroupRb->Connect(
wxEVT_CHECKBOX,
wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnGroupClicked ), nullptr,
this );
if( aConvertSettings )
{
@ -200,6 +206,10 @@ DIALOG_RULE_AREA_PROPERTIES::~DIALOG_RULE_AREA_PROPERTIES()
wxEVT_CHECKBOX,
wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnComponentClassClicked ), nullptr,
this );
m_placementProperties->m_GroupRb->Disconnect(
wxEVT_CHECKBOX,
wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnGroupClicked ), nullptr,
this );
}
@ -215,6 +225,12 @@ void DIALOG_RULE_AREA_PROPERTIES::OnComponentClassClicked( wxCommandEvent& event
}
void DIALOG_RULE_AREA_PROPERTIES::OnGroupClicked( wxCommandEvent& event )
{
m_lastPlacementSourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP;
}
bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
{
if( m_convertSettings )
@ -235,13 +251,16 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
m_keepoutProperties->m_cbCopperPourCtrl->SetValue( m_zonesettings.GetDoNotAllowZoneFills() );
// Init placement parameters:
m_placementProperties->m_DisabedlRb->SetValue( true );
m_placementProperties->m_DisabledRb->SetValue( true );
m_placementProperties->m_SheetRb->SetValue( false );
m_placementProperties->m_sheetCombo->Clear();
m_placementProperties->m_ComponentsRb->SetValue( false );
m_placementProperties->m_componentClassCombo->Clear();
m_placementProperties->m_GroupRb->SetValue( false );
m_placementProperties->m_groupCombo->Clear();
wxString curSourceName = m_zonesettings.GetRuleAreaPlacementSource();
// Load schematic sheet and component class lists
@ -259,17 +278,29 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
if( !classNames.empty() )
m_placementProperties->m_componentClassCombo->Select( 0 );
// Fetch sheet names
// Fetch sheet names and groups
std::set<wxString> sheetNames;
std::set<wxString> groupNames;
for( FOOTPRINT* fp : m_board->Footprints() )
{
sheetNames.insert( fp->GetSheetname() );
if( fp->GetParentGroup() && !fp->GetParentGroup()->GetName().IsEmpty() )
groupNames.insert( fp->GetParentGroup()->GetName() );
}
for( const wxString& sourceName : sheetNames )
m_placementProperties->m_sheetCombo->Append( sourceName );
for( const wxString& groupName : groupNames )
m_placementProperties->m_groupCombo->Append( groupName );
if( !sheetNames.empty() )
m_placementProperties->m_sheetCombo->Select( 0 );
if( !groupNames.empty() )
m_placementProperties->m_groupCombo->Select( 0 );
}
auto setupCurrentSourceSelection = [&]( wxComboBox* cb )
@ -297,7 +328,8 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
m_originalPlacementSourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME;
m_lastPlacementSourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME;
}
else
else if( m_zonesettings.GetRuleAreaPlacementSourceType()
== RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
{
if( m_zonesettings.GetRuleAreaPlacementEnabled() )
m_placementProperties->m_ComponentsRb->SetValue( true );
@ -306,6 +338,15 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
m_originalPlacementSourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS;
m_lastPlacementSourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS;
}
else
{
if( m_zonesettings.GetRuleAreaPlacementEnabled() )
m_placementProperties->m_GroupRb->SetValue( true );
setupCurrentSourceSelection( m_placementProperties->m_groupCombo );
m_originalPlacementSourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP;
m_lastPlacementSourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP;
}
// Handle most-useful notebook page selection
m_areaPropertiesNb->SetSelection( 0 );
@ -400,8 +441,10 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataFromWindow()
if( sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
cb = m_placementProperties->m_sheetCombo;
else
else if( sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
cb = m_placementProperties->m_componentClassCombo;
else
cb = m_placementProperties->m_groupCombo;
int selectedSourceIdx = cb->GetSelection();
@ -429,6 +472,11 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataFromWindow()
m_zonesettings.SetRuleAreaPlacementEnabled( true );
setPlacementSource( RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
}
else if( m_placementProperties->m_GroupRb->GetValue() )
{
m_zonesettings.SetRuleAreaPlacementEnabled( true );
setPlacementSource( RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP );
}
else
{
setPlacementSource( m_lastPlacementSourceType );

17
pcbnew/dialogs/panel_rule_area_properties_placement_base.cpp

@ -17,9 +17,9 @@ PANEL_RULE_AREA_PROPERTIES_PLACEMENT_BASE::PANEL_RULE_AREA_PROPERTIES_PLACEMENT_
wxBoxSizer* bMarginsSizer;
bMarginsSizer = new wxBoxSizer( wxVERTICAL );
m_DisabedlRb = new wxRadioButton( this, wxID_ANY, _("No placement"), wxDefaultPosition, wxDefaultSize, 0 );
m_DisabedlRb->SetValue( true );
bMarginsSizer->Add( m_DisabedlRb, 0, wxALL, 5 );
m_DisabledRb = new wxRadioButton( this, wxID_ANY, _("No placement"), wxDefaultPosition, wxDefaultSize, 0 );
m_DisabledRb->SetValue( true );
bMarginsSizer->Add( m_DisabledRb, 0, wxALL, 5 );
m_SheetRb = new wxRadioButton( this, wxID_ANY, _("Place items from sheet:"), wxDefaultPosition, wxDefaultSize, 0 );
bMarginsSizer->Add( m_SheetRb, 0, wxALL, 5 );
@ -37,7 +37,16 @@ PANEL_RULE_AREA_PROPERTIES_PLACEMENT_BASE::PANEL_RULE_AREA_PROPERTIES_PLACEMENT_
bMarginsSizer->Add( m_componentClassCombo, 0, wxLEFT|wxEXPAND, 25 );
bMarginsSizer->Add( 0, 5, 0, 0, 5 );
bMarginsSizer->Add( 0, 15, 0, 0, 5 );
m_GroupRb = new wxRadioButton( this, wxID_ANY, _("Place items in group:"), wxDefaultPosition, wxDefaultSize, 0 );
bMarginsSizer->Add( m_GroupRb, 0, wxALL, 5 );
m_groupCombo = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY );
bMarginsSizer->Add( m_groupCombo, 0, wxEXPAND|wxLEFT, 25 );
bMarginsSizer->Add( 0, 5, 1, wxEXPAND, 5 );
bMainSizer->Add( bMarginsSizer, 1, wxEXPAND|wxBOTTOM|wxRIGHT, 5 );

143
pcbnew/dialogs/panel_rule_area_properties_placement_base.fbp

@ -110,7 +110,7 @@
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_DisabedlRb</property>
<property name="name">m_DisabledRb</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
@ -410,6 +410,147 @@
<property name="border">5</property>
<property name="flag"></property>
<property name="proportion">0</property>
<object class="spacer" expanded="true">
<property name="height">15</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<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">Place items in group:</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_GroupRb</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">public</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="true">
<property name="border">25</property>
<property name="flag">wxEXPAND|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxComboBox" 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="choices"></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_groupCombo</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">public</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">-1</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxCB_READONLY</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"></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</property>
<property name="proportion">1</property>
<object class="spacer" expanded="true">
<property name="height">5</property>
<property name="permission">protected</property>

4
pcbnew/dialogs/panel_rule_area_properties_placement_base.h

@ -32,11 +32,13 @@ class PANEL_RULE_AREA_PROPERTIES_PLACEMENT_BASE : public wxPanel
protected:
public:
wxRadioButton* m_DisabedlRb;
wxRadioButton* m_DisabledRb;
wxRadioButton* m_SheetRb;
wxComboBox* m_sheetCombo;
wxRadioButton* m_ComponentsRb;
wxComboBox* m_componentClassCombo;
wxRadioButton* m_GroupRb;
wxComboBox* m_groupCombo;
PANEL_RULE_AREA_PROPERTIES_PLACEMENT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );

4
pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp

@ -2627,6 +2627,10 @@ void PCB_IO_KICAD_SEXPR::format( const ZONE* aZone ) const
m_out->Print( "(component_class %s)",
m_out->Quotew( aZone->GetRuleAreaPlacementSource() ).c_str() );
break;
case RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP:
m_out->Print( "(group %s)",
m_out->Quotew( aZone->GetRuleAreaPlacementSource() ).c_str() );
break;
}
m_out->Print( ")" );

9
pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp

@ -7195,6 +7195,13 @@ ZONE* PCB_IO_KICAD_SEXPR_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent )
zone->SetRuleAreaPlacementSource( FromUTF8() );
break;
}
case T_group:
{
zone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP );
NeedSYMBOL();
zone->SetRuleAreaPlacementSource( FromUTF8() );
break;
}
case T_enabled:
{
token = NextTok();
@ -7210,7 +7217,7 @@ ZONE* PCB_IO_KICAD_SEXPR_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent )
}
default:
{
Expecting( "enabled, sheetname or component_class" );
Expecting( "enabled, sheetname, component_class, or group" );
break;
}
}

65
pcbnew/tools/multichannel_tool.cpp

@ -107,6 +107,9 @@ bool MULTICHANNEL_TOOL::identifyComponentsInRuleArea( ZONE* aRul
ruleText = wxT( "A.hasComponentClass('" ) + aRuleArea->GetRuleAreaPlacementSource()
+ wxT( "')" );
break;
case RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP:
ruleText = wxT( "A.memberOfGroup('" ) + aRuleArea->GetRuleAreaPlacementSource() + wxT( "')" );
break;
}
auto ok = compiler.Compile( ruleText, &ucode, &preflightCtx );
@ -256,6 +259,27 @@ MULTICHANNEL_TOOL::queryComponentsInComponentClass( const wxString& aComponentCl
}
std::set<FOOTPRINT*>
MULTICHANNEL_TOOL::queryComponentsInGroup( const wxString& aGroupName ) const
{
std::set<FOOTPRINT*> rv;
for( auto& group : board()->Groups() )
{
if( group->GetName() == aGroupName )
{
for( EDA_ITEM* item : group->GetItems() )
{
if( item->Type() == PCB_FOOTPRINT_T )
rv.insert( static_cast<FOOTPRINT*>( item ) );
}
}
}
return rv;
}
const SHAPE_LINE_CHAIN MULTICHANNEL_TOOL::buildRAOutline( std::set<FOOTPRINT*>& aFootprints,
int aMargin )
{
@ -283,6 +307,7 @@ void MULTICHANNEL_TOOL::QuerySheetsAndComponentClasses()
using PathAndName = std::pair<wxString, wxString>;
std::set<PathAndName> uniqueSheets;
std::set<wxString> uniqueComponentClasses;
std::set<wxString> uniqueGroups;
m_areas.m_areas.clear();
@ -294,6 +319,9 @@ void MULTICHANNEL_TOOL::QuerySheetsAndComponentClasses()
for( const COMPONENT_CLASS* singleClass : compClass->GetConstituentClasses() )
uniqueComponentClasses.insert( singleClass->GetName() );
if( fp->GetParentGroup() && !fp->GetParentGroup()->GetName().IsEmpty() )
uniqueGroups.insert( fp->GetParentGroup()->GetName() );
}
for( const PathAndName& sheet : uniqueSheets )
@ -324,6 +352,20 @@ void MULTICHANNEL_TOOL::QuerySheetsAndComponentClasses()
wxLogTrace( traceMultichannelTool, wxT( "found component class '%s' s %d\n" ),
ent.m_componentClass, static_cast<int>( m_areas.m_areas.size() ) );
}
for( const wxString& groupName : uniqueGroups )
{
RULE_AREA ent;
ent.m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP;
ent.m_generateEnabled = false;
ent.m_groupName = groupName;
ent.m_components = queryComponentsInGroup( ent.m_groupName );
m_areas.m_areas.push_back( ent );
wxLogTrace( traceMultichannelTool, wxT( "found group '%s' s %d\n" ),
ent.m_componentClass, static_cast<int>( m_areas.m_areas.size() ) );
}
}
@ -1094,13 +1136,21 @@ int MULTICHANNEL_TOOL::AutogenerateRuleAreas( const TOOL_EVENT& aEvent )
wxT( "Placement rule area for sheet '%s' already exists as '%s'\n" ),
ra.m_sheetPath, zone->GetZoneName() );
}
else
else if( zone->GetRuleAreaPlacementSourceType()
== RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
{
wxLogTrace( traceMultichannelTool,
wxT( "Placement rule area for component class '%s' already exists "
"as '%s'\n" ),
ra.m_componentClass, zone->GetZoneName() );
}
else
{
wxLogTrace( traceMultichannelTool,
wxT( "Placement rule area for group '%s' already exists "
"as '%s'\n" ),
ra.m_groupName, zone->GetZoneName() );
}
ra.m_oldArea = zone;
ra.m_existsAlready = true;
@ -1130,11 +1180,15 @@ int MULTICHANNEL_TOOL::AutogenerateRuleAreas( const TOOL_EVENT& aEvent )
newZone->SetZoneName(
wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_sheetPath ) );
}
else
else if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
{
newZone->SetZoneName(
wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_componentClass ) );
}
else
{
newZone->SetZoneName( wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_groupName ) );
}
wxLogTrace( traceMultichannelTool, wxT( "Generated rule area '%s' (%d components)\n" ),
newZone->GetZoneName(), (int) ra.m_components.size() );
@ -1153,12 +1207,17 @@ int MULTICHANNEL_TOOL::AutogenerateRuleAreas( const TOOL_EVENT& aEvent )
newZone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
newZone->SetRuleAreaPlacementSource( ra.m_sheetPath );
}
else
else if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
{
newZone->SetRuleAreaPlacementSourceType(
RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
newZone->SetRuleAreaPlacementSource( ra.m_componentClass );
}
else
{
newZone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP );
newZone->SetRuleAreaPlacementSource( ra.m_groupName );
}
newZone->AddPolygon( raOutline );
newZone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );

3
pcbnew/tools/multichannel_tool.h

@ -85,6 +85,8 @@ struct RULE_AREA
wxString m_sheetName;
wxString m_ruleName;
wxString m_componentClass;
KIID m_group;
wxString m_groupName;
VECTOR2I m_center;
};
@ -135,6 +137,7 @@ private:
std::set<FOOTPRINT*> queryComponentsInSheet( wxString aSheetName ) const;
std::set<FOOTPRINT*>
queryComponentsInComponentClass( const wxString& aComponentClassName ) const;
std::set<FOOTPRINT*> queryComponentsInGroup( const wxString& aGroupName ) const;
RULE_AREA* findRAByName( const wxString& aName );
bool resolveConnectionTopology( RULE_AREA* aRefArea, RULE_AREA* aTargetArea,
RULE_AREA_COMPAT_DATA& aMatches );

3
pcbnew/zone.cpp

@ -1856,7 +1856,8 @@ static struct ZONE_DESC
{
rapstMap.Undefined( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
rapstMap.Map( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME, _HKI( "Sheet Name" ) )
.Map( RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS, _HKI( "Component Class" ) );
.Map( RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS, _HKI( "Component Class" ) )
.Map( RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP, _HKI( "Group" ) );
}
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();

5
pcbnew/zone_settings.h

@ -74,7 +74,8 @@ enum class ISLAND_REMOVAL_MODE
enum class RULE_AREA_PLACEMENT_SOURCE_TYPE
{
SHEETNAME = 0,
COMPONENT_CLASS
COMPONENT_CLASS,
GROUP
};
/**
@ -201,7 +202,7 @@ public:
/**
* Function CopyFrom
* copy settings from a different ZONE_SETTINGS object
*
*
* @param aOther the other ZONE_SETTINGS
* @param aCopyFull if false: some parameters are not copied.
* This option is used specifically to copy zone settings from

Loading…
Cancel
Save