diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp index 7c02c862aa..a9c5dfabe5 100644 --- a/common/dsnlexer.cpp +++ b/common/dsnlexer.cpp @@ -348,7 +348,8 @@ void DSNLEXER::Expecting( int aTok ) const void DSNLEXER::Expecting( const char* text ) const { - wxString errText = wxString::Format( _( "Expecting %s" ), wxString::FromUTF8( text ) ); + wxString errText = + wxString::Format( _( "Expecting %s. Got '%s'" ), wxString::FromUTF8( text ), GetTokenString( CurTok() ) ); THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); } diff --git a/common/lset.cpp b/common/lset.cpp index a7765468d9..f9108df9ea 100644 --- a/common/lset.cpp +++ b/common/lset.cpp @@ -723,13 +723,6 @@ const LSET& LSET::SideSpecificMask() } -const LSET& LSET::ForbiddenFootprintLayers() -{ - static LSET saved = LSET( InternalCuMask() ).set( In1_Cu, false ); - return saved; -} - - LSEQ LSET::UIOrder() const { LSEQ order = CuStack(); diff --git a/include/lset.h b/include/lset.h index b0f4d6b4c8..a3c2429ac6 100644 --- a/include/lset.h +++ b/include/lset.h @@ -196,14 +196,6 @@ public: */ static LSET UserDefinedLayersMask( int aUserDefinedLayerCount = MAX_USER_DEFINED_LAYERS ); - /** - * Layers which are not allowed within footprint definitions. - * - * Currently internal copper layers and Margin. - */ - - static const LSET& ForbiddenFootprintLayers(); - /** * Return a sequence of copper layers in starting from the front/top * and extending to the back/bottom. @@ -364,4 +356,3 @@ public: }; #endif // LSET_H - diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index 93c2cddcd3..b0e800d2e0 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -697,7 +697,12 @@ const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName ) { - if( !aLayerName.IsEmpty() ) + if( aLayerName.IsEmpty() ) + { + // If the name is empty, we clear the user name. + m_layers[aLayer].m_userName.clear(); + } + else { // no quote chars in the name allowed if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND ) diff --git a/pcbnew/dialogs/dialog_copper_zones.cpp b/pcbnew/dialogs/dialog_copper_zones.cpp index 76f820e7c5..d9091d3634 100644 --- a/pcbnew/dialogs/dialog_copper_zones.cpp +++ b/pcbnew/dialogs/dialog_copper_zones.cpp @@ -197,9 +197,7 @@ DIALOG_COPPER_ZONE::DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* m_ptr = aSettings; m_settings = *aSettings; - m_settings.SetupLayersList( m_layers, m_Parent, - LSET::AllCuMask( aParent->GetBoard()->GetCopperLayerCount() ), - false ); + m_settings.SetupLayersList( m_layers, m_Parent, LSET::AllCuMask( aParent->GetBoard()->GetCopperLayerCount() ) ); m_isTeardrop = m_settings.m_TeardropType != TEARDROP_TYPE::TD_NONE; switch( m_settings.m_TeardropType ) diff --git a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp index addbb05068..980b9a8cdc 100644 --- a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp +++ b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp @@ -24,13 +24,17 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "dialog_footprint_properties_fp_editor.h" + +#include + #include <3d_rendering/opengl/3d_model.h> #include <3d_viewer/eda_3d_viewer_frame.h> #include #include #include #include -#include + #include #include #include @@ -57,63 +61,86 @@ #include #include -PRIVATE_LAYERS_GRID_TABLE::PRIVATE_LAYERS_GRID_TABLE( PCB_BASE_FRAME* aFrame ) : + +class LAYERS_GRID_TABLE : public WX_GRID_TABLE_BASE, public std::vector +{ +public: + LAYERS_GRID_TABLE( PCB_BASE_FRAME* aFrame, const LSET& aForbiddenLayers ); + ~LAYERS_GRID_TABLE(); + + int GetNumberRows() override { return (int) size(); } + int GetNumberCols() override { return 1; } + + bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override; + bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override; + wxGridCellAttr* GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) override; + + wxString GetValue( int aRow, int aCol ) override; + long GetValueAsLong( int aRow, int aCol ) override; + + void SetValue( int aRow, int aCol, const wxString& aValue ) override; + void SetValueAsLong( int aRow, int aCol, long aValue ) override; + +private: + PCB_BASE_FRAME* m_frame; + wxGridCellAttr* m_layerColAttr; +}; + + +LAYERS_GRID_TABLE::LAYERS_GRID_TABLE( PCB_BASE_FRAME* aFrame, const LSET& aForbiddenLayers ) : m_frame( aFrame ) { m_layerColAttr = new wxGridCellAttr; m_layerColAttr->SetRenderer( new GRID_CELL_LAYER_RENDERER( m_frame ) ); - LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask(); - forbiddenLayers.set( Edge_Cuts ); - forbiddenLayers.set( Margin ); - m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, forbiddenLayers, true ) ); + m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, aForbiddenLayers, true ) ); } -PRIVATE_LAYERS_GRID_TABLE::~PRIVATE_LAYERS_GRID_TABLE() +LAYERS_GRID_TABLE::~LAYERS_GRID_TABLE() { m_layerColAttr->DecRef(); } -bool PRIVATE_LAYERS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) +bool LAYERS_GRID_TABLE::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) { return aTypeName == wxGRID_VALUE_NUMBER; } -bool PRIVATE_LAYERS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) +bool LAYERS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) { return aTypeName == wxGRID_VALUE_NUMBER; } -wxGridCellAttr* PRIVATE_LAYERS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) +wxGridCellAttr* LAYERS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) { m_layerColAttr->IncRef(); return enhanceAttr( m_layerColAttr, aRow, aCol, aKind ); } -wxString PRIVATE_LAYERS_GRID_TABLE::GetValue( int aRow, int aCol ) +wxString LAYERS_GRID_TABLE::GetValue( int aRow, int aCol ) { return m_frame->GetBoard()->GetLayerName( this->at( (size_t) aRow ) ); } -long PRIVATE_LAYERS_GRID_TABLE::GetValueAsLong( int aRow, int aCol ) +long LAYERS_GRID_TABLE::GetValueAsLong( int aRow, int aCol ) { return this->at( (size_t) aRow ); } -void PRIVATE_LAYERS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue ) +void LAYERS_GRID_TABLE::SetValue( int aRow, int aCol, const wxString& aValue ) { wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) ); } -void PRIVATE_LAYERS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue ) +void LAYERS_GRID_TABLE::SetValueAsLong( int aRow, int aCol, long aValue ) { this->at( (size_t) aRow ) = ToLAYER_ID( (int) aValue ); } @@ -147,7 +174,19 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR( FO m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) ); m_fields = new PCB_FIELDS_GRID_TABLE( m_frame, this, { m_embeddedFiles->GetLocalFiles() } ); - m_privateLayers = new PRIVATE_LAYERS_GRID_TABLE( m_frame ); + + { + LSET forbiddenLayers = LSET::AllCuMask() | LSET::AllTechMask(); + forbiddenLayers.set( Edge_Cuts ); + forbiddenLayers.set( Margin ); + + m_privateLayers = new LAYERS_GRID_TABLE( m_frame, forbiddenLayers ); + } + + { + LSET forbiddenLayers = LSET::AllLayersMask() & ~LSET::UserDefinedLayersMask(); + m_customUserLayers = new LAYERS_GRID_TABLE( m_frame, forbiddenLayers ); + } m_delayedErrorMessage = wxEmptyString; m_delayedFocusCtrl = nullptr; @@ -163,6 +202,7 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR( FO m_itemsGrid->SetTable( m_fields ); m_privateLayersGrid->SetTable( m_privateLayers ); + m_customUserLayersGrid->SetTable( m_customUserLayers ); m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) ); m_privateLayersGrid->PushEventHandler( new GRID_TRICKS( m_privateLayersGrid, @@ -180,11 +220,17 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR( FO { OnAddJumperGroup( aEvent ); } ) ); + m_customUserLayersGrid->PushEventHandler( new GRID_TRICKS( m_customUserLayersGrid, + [this]( wxCommandEvent& aEvent ) + { + OnAddCustomLayer( aEvent ); + } ) ); m_itemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); m_privateLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); m_nettieGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); m_jumperGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); + m_customUserLayersGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); // Show/hide columns according to the user's preference m_itemsGrid->ShowHideColumns( m_frame->GetSettings()->m_FootprintTextShownColumns ); @@ -225,6 +271,8 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR( FO m_bpRemoveNettieGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); m_bpAddJumperGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); m_bpRemoveJumperGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); + m_bpAddCustomLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); + m_bpDeleteCustomLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); SetupStandardButtons(); @@ -240,12 +288,14 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::~DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR() // Prevents crash bug in wxGrid's d'tor m_itemsGrid->DestroyTable( m_fields ); m_privateLayersGrid->DestroyTable( m_privateLayers ); + m_customUserLayersGrid->DestroyTable( m_customUserLayers ); // Delete the GRID_TRICKS. m_itemsGrid->PopEventHandler( true ); m_privateLayersGrid->PopEventHandler( true ); m_nettieGroupsGrid->PopEventHandler( true ); m_jumperGroupsGrid->PopEventHandler( true ); + m_customUserLayersGrid->PopEventHandler( true ); m_page = static_cast( m_NoteBook->GetSelection() ); @@ -301,6 +351,41 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataToWindow() m_privateLayers->GetNumberRows() ); m_privateLayersGrid->ProcessTableMessage( gridTableMessagesg ); + switch( m_footprint->GetStackupMode() ) + { + case FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS: + { + m_cbCustomLayers->SetValue( false ); + + m_copperLayerCount->SetSelection( 0 ); + break; + } + case FOOTPRINT_STACKUP::CUSTOM_LAYERS: + { + m_cbCustomLayers->SetValue( true ); + + const LSET& customFpLayers = m_footprint->GetStackupLayers(); + const LSET customUserLayers = customFpLayers & LSET::UserDefinedLayersMask(); + + for( PCB_LAYER_ID customUserLayer : customUserLayers ) + { + m_customUserLayers->push_back( customUserLayer ); + } + + // Set the number of copper layers + m_copperLayerCount->SetSelection( ( customFpLayers & LSET::AllCuMask() ).count() / 2 - 1 ); + break; + } + } + setCustomLayerCtrlEnablement(); + + // Notify the grid + { + wxGridTableMessage gridTableMessagesCustom( m_customUserLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, + m_customUserLayers->GetNumberRows() ); + m_customUserLayersGrid->ProcessTableMessage( gridTableMessagesCustom ); + } + m_boardOnly->SetValue( m_footprint->GetAttributes() & FP_BOARD_ONLY ); m_excludeFromPosFiles->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_POS_FILES ); m_excludeFromBOM->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ); @@ -440,6 +525,70 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::checkFootprintName( const wxString& } +LSET DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::getCustomLayersFromControls() const +{ + LSET userLayers; + if( m_cbCustomLayers->GetValue() ) + { + userLayers |= LSET::AllCuMask( ( m_copperLayerCount->GetSelection() + 1 ) * 2 ); + + for( PCB_LAYER_ID layer : *m_customUserLayers ) + { + userLayers.set( layer ); + } + } + else + { + userLayers |= LSET{ F_Cu, In1_Cu, B_Cu }; + userLayers |= LSET::UserDefinedLayersMask( 4 ); + } + + return userLayers; +} + + +static LSET GetAllUsedFootprintLayers( const FOOTPRINT& aFootprint ) +{ + LSET usedLayers{}; + aFootprint.RunOnChildren( + [&]( BOARD_ITEM* aSubItem ) + { + wxCHECK2( aSubItem, /*void*/ ); + + switch( aSubItem->Type() ) + { + case PCB_ZONE_T: + { + ZONE& zone = static_cast( *aSubItem ); + usedLayers |= zone.GetLayerSet(); + break; + } + default: + { + usedLayers.set( aSubItem->GetLayer() ); + break; + } + } + }, + RECURSE_MODE::RECURSE ); + return usedLayers; +} + + +static wxString GetLayerStringList( const BOARD& aBoard, const LSET& layers ) +{ + std::vector layerNames; + + for( PCB_LAYER_ID layer : layers.UIOrder() ) + { + wxString layerName = aBoard.GetLayerName( layer ); + layerNames.push_back( layerName ); + } + + return AccumulateDescriptions( layerNames ); +} + + bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::Validate() { if( !m_itemsGrid->CommitPendingChanges() ) @@ -532,6 +681,26 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::Validate() m_frame->SyncLibraryTree( true ); } + // See if there is an object in the footprint that uses a layer that is not in that list + LSET usedLayers = GetAllUsedFootprintLayers( *m_footprint ); + + // Check that the user isn't trying to remove a layer that is used by the footprint + usedLayers &= ~getCustomLayersFromControls(); + usedLayers &= ~LSET::AllTechMask(); + + if( usedLayers.any() ) + { + m_delayedErrorMessage = + wxString::Format( _( "You are trying to remove layers that are used by the footprint: %s.\n" + "Please remove the objects that use these layers first." ), + GetLayerStringList( *m_frame->GetBoard(), usedLayers ) ); + m_delayedFocusGrid = m_customUserLayersGrid; + m_delayedFocusColumn = 0; + m_delayedFocusRow = 0; + m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_LAYERS; + return false; + } + return true; } @@ -541,7 +710,8 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataFromWindow() if( !m_itemsGrid->CommitPendingChanges() || !m_privateLayersGrid->CommitPendingChanges() || !m_nettieGroupsGrid->CommitPendingChanges() - || !m_jumperGroupsGrid->CommitPendingChanges() ) + || !m_jumperGroupsGrid->CommitPendingChanges() + || !m_customUserLayersGrid->CommitPendingChanges() ) { return false; } @@ -624,6 +794,19 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataFromWindow() m_footprint->SetPrivateLayers( privateLayers ); + if( m_cbCustomLayers->GetValue() ) + { + const LSET customLayers = getCustomLayersFromControls(); + + m_footprint->SetStackupMode( FOOTPRINT_STACKUP::CUSTOM_LAYERS ); + m_footprint->SetStackupLayers( std::move( customLayers ) ); + } + else + { + // Just use the default stackup mode + m_footprint->SetStackupMode( FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS ); + } + int attributes = 0; switch( m_componentType->GetSelection() ) @@ -777,24 +960,44 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnDeleteField( wxCommandEvent& event } +void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::onLayerGridRowDelete( WX_GRID& aGrid, LAYERS_GRID_TABLE& aLayerTable, + int aRow ) +{ + aLayerTable.erase( aLayerTable.begin() + aRow ); + + // notify the grid + wxGridTableMessage msg( &aLayerTable, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 ); + aGrid.ProcessTableMessage( msg ); + + OnModify(); +} + + +std::pair DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::onLayerGridRowAddUserLayer( WX_GRID& aGrid, + LAYERS_GRID_TABLE& aGridTable ) +{ + PCB_LAYER_ID nextLayer = User_1; + + while( alg::contains( aGridTable, nextLayer ) && nextLayer < User_45 ) + nextLayer = ToLAYER_ID( nextLayer + 2 ); + + aGridTable.push_back( nextLayer ); + + // notify the grid + wxGridTableMessage msg( &aGridTable, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 ); + aGrid.ProcessTableMessage( msg ); + OnModify(); + + return { aGridTable.size() - 1, 0 }; +} + + void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnAddLayer( wxCommandEvent& event ) { m_privateLayersGrid->OnAddRow( - [&]() -> std::pair + [&]() { - PCB_LAYER_ID nextLayer = User_1; - - while( alg::contains( *m_privateLayers, nextLayer ) && nextLayer < User_45 ) - nextLayer = ToLAYER_ID( nextLayer + 1 ); - - m_privateLayers->push_back( nextLayer ); - - // notify the grid - wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 ); - m_privateLayersGrid->ProcessTableMessage( msg ); - OnModify(); - - return { m_privateLayers->size() - 1, 0 }; + return onLayerGridRowAddUserLayer( *m_privateLayersGrid, *m_privateLayers ); } ); } @@ -804,13 +1007,33 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnDeleteLayer( wxCommandEvent& event m_privateLayersGrid->OnDeleteRows( [&]( int row ) { - m_privateLayers->erase( m_privateLayers->begin() + row ); + onLayerGridRowDelete( *m_privateLayersGrid, *m_privateLayers, row ); + } ); +} - // notify the grid - wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); - m_privateLayersGrid->ProcessTableMessage( msg ); - OnModify(); +void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnUseCustomLayers( wxCommandEvent& event ) +{ + setCustomLayerCtrlEnablement(); +} + + +void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnAddCustomLayer( wxCommandEvent& event ) +{ + m_customUserLayersGrid->OnAddRow( + [&]() + { + return onLayerGridRowAddUserLayer( *m_customUserLayersGrid, *m_customUserLayers ); + } ); +} + + +void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnDeleteCustomLayer( wxCommandEvent& event ) +{ + m_customUserLayersGrid->OnDeleteRows( + [&]( int row ) + { + onLayerGridRowDelete( *m_customUserLayersGrid, *m_customUserLayers, row ); } ); } @@ -890,6 +1113,7 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::adjustGridColumns() updateSingleColumnGrid( m_privateLayersGrid ); updateSingleColumnGrid( m_nettieGroupsGrid ); updateSingleColumnGrid( m_jumperGroupsGrid ); + updateSingleColumnGrid( m_customUserLayersGrid ); // Update the width of the 3D panel m_3dPanel->AdjustGridColumnWidths(); @@ -982,6 +1206,17 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnGridSize( wxSizeEvent& aEvent ) } +void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::setCustomLayerCtrlEnablement() +{ + bool enableCustomCtrls = m_cbCustomLayers->GetValue(); + + m_copperLayerCount->Enable( enableCustomCtrls ); + m_customUserLayersGrid->Enable( enableCustomCtrls ); + m_bpAddCustomLayer->Enable( enableCustomCtrls ); + m_bpDeleteCustomLayer->Enable( enableCustomCtrls ); +} + + void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnPageChanging( wxNotebookEvent& aEvent ) { if( !m_itemsGrid->CommitPendingChanges() ) @@ -989,6 +1224,9 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnPageChanging( wxNotebookEvent& aEv if( !m_privateLayersGrid->CommitPendingChanges() ) aEvent.Veto(); + + if( !m_customUserLayersGrid->CommitPendingChanges() ) + aEvent.Veto(); } @@ -1011,5 +1249,3 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnChoice( wxCommandEvent& event ) if( m_initialized ) OnModify(); } - - diff --git a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.h b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.h index 8a346244ff..6fed734221 100644 --- a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.h +++ b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.h @@ -35,39 +35,16 @@ class FOOTPRINT_EDIT_FRAME; class PANEL_FP_PROPERTIES_3D_MODEL; class PANEL_EMBEDDED_FILES; - - -class PRIVATE_LAYERS_GRID_TABLE : public WX_GRID_TABLE_BASE, public std::vector -{ -public: - PRIVATE_LAYERS_GRID_TABLE( PCB_BASE_FRAME* aFrame ); - ~PRIVATE_LAYERS_GRID_TABLE(); - - int GetNumberRows() override { return (int) size(); } - int GetNumberCols() override { return 1; } - - bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override; - bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override; - wxGridCellAttr* GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) override; - - wxString GetValue( int aRow, int aCol ) override; - long GetValueAsLong( int aRow, int aCol ) override; - - void SetValue( int aRow, int aCol, const wxString& aValue ) override; - void SetValueAsLong( int aRow, int aCol, long aValue ) override; - -private: - PCB_BASE_FRAME* m_frame; - wxGridCellAttr* m_layerColAttr; -}; +class LAYERS_GRID_TABLE; enum class NOTEBOOK_PAGES { PAGE_UNKNOWN = -1, PAGE_GENERAL = 0, - PAGE_CLEARANCES = 1, - PAGE_3D_MODELS = 2 + PAGE_LAYERS = 1, + PAGE_CLEARANCES = 2, + PAGE_3D_MODELS = 3 }; class DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR : public DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE @@ -97,14 +74,27 @@ private: void OnText( wxCommandEvent& event ) override; void OnChoice( wxCommandEvent& event ) override; void OnCheckBox( wxCommandEvent& event ) override; + void OnUseCustomLayers( wxCommandEvent& event ) override; + void OnAddCustomLayer( wxCommandEvent& event ) override; + void OnDeleteCustomLayer( wxCommandEvent& event ) override; bool checkFootprintName( const wxString& aFootprintName, LIB_ID* doOverwrite ); + void setCustomLayerCtrlEnablement(); void onAddGroup( WX_GRID* aGrid ); void onRemoveGroup( WX_GRID* aGrid ); void adjustGridColumns(); + // Layer grid helper callbacks + void onLayerGridRowDelete( WX_GRID& aGrid, LAYERS_GRID_TABLE& aLayerTable, int aRow ); + std::pair onLayerGridRowAddUserLayer( WX_GRID& aGrid, LAYERS_GRID_TABLE& aLayerTable ); + + /** + * Get the layers for the footprint from the controls that can be affected by the stackup. + */ + LSET getCustomLayersFromControls() const; + private: FOOTPRINT_EDIT_FRAME* m_frame; FOOTPRINT* m_footprint; @@ -113,7 +103,8 @@ private: static NOTEBOOK_PAGES m_page; // remember the last open page during session PCB_FIELDS_GRID_TABLE* m_fields; - PRIVATE_LAYERS_GRID_TABLE* m_privateLayers; + LAYERS_GRID_TABLE* m_customUserLayers; + LAYERS_GRID_TABLE* m_privateLayers; UNIT_BINDER m_netClearance; UNIT_BINDER m_solderMask; diff --git a/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.cpp b/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.cpp index b7649de1e9..4113086e81 100644 --- a/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.cpp +++ b/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.cpp @@ -160,7 +160,7 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITO // Cell Defaults m_privateLayersGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER ); - bSizerPrivateLayers->Add( m_privateLayersGrid, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizerPrivateLayers->Add( m_privateLayersGrid, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); wxBoxSizer* bButtonSize1; bButtonSize1 = new wxBoxSizer( wxHORIZONTAL ); @@ -221,7 +221,95 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITO m_PanelGeneral->SetSizer( m_PanelPropertiesBoxSizer ); m_PanelGeneral->Layout(); m_PanelPropertiesBoxSizer->Fit( m_PanelGeneral ); - m_NoteBook->AddPage( m_PanelGeneral, _("General"), true ); + m_NoteBook->AddPage( m_PanelGeneral, _("General"), false ); + m_LayersPanel = new wxPanel( m_NoteBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer14; + bSizer14 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer11; + sbSizer11 = new wxStaticBoxSizer( new wxStaticBox( m_LayersPanel, wxID_ANY, _("Custom Layers") ), wxVERTICAL ); + + wxGridBagSizer* gbSizer3; + gbSizer3 = new wxGridBagSizer( 0, 0 ); + gbSizer3->SetFlexibleDirection( wxBOTH ); + gbSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_cbCustomLayers = new wxCheckBox( sbSizer11->GetStaticBox(), wxID_ANY, _("Use custom stackup"), wxDefaultPosition, wxDefaultSize, 0 ); + gbSizer3->Add( m_cbCustomLayers, wxGBPosition( 0, 0 ), wxGBSpan( 1, 2 ), wxALL, 5 ); + + m_copperLayerCountLabel = new wxStaticText( sbSizer11->GetStaticBox(), wxID_ANY, _("Copper layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_copperLayerCountLabel->Wrap( -1 ); + gbSizer3->Add( m_copperLayerCountLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + wxString m_copperLayerCountChoices[] = { _("2"), _("4"), _("6"), _("8"), _("10"), _("12"), _("14"), _("16"), _("18"), _("20"), _("22"), _("24"), _("26"), _("28"), _("30"), _("32"), wxEmptyString }; + int m_copperLayerCountNChoices = sizeof( m_copperLayerCountChoices ) / sizeof( wxString ); + m_copperLayerCount = new wxChoice( sbSizer11->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, m_copperLayerCountNChoices, m_copperLayerCountChoices, 0 ); + m_copperLayerCount->SetSelection( 0 ); + m_copperLayerCount->Enable( false ); + + gbSizer3->Add( m_copperLayerCount, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 ); + + wxStaticBoxSizer* sbUserCustomerLayers; + sbUserCustomerLayers = new wxStaticBoxSizer( new wxStaticBox( sbSizer11->GetStaticBox(), wxID_ANY, _("User Layers") ), wxVERTICAL ); + + m_customUserLayersGrid = new WX_GRID( sbUserCustomerLayers->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 ); + + // Grid + m_customUserLayersGrid->CreateGrid( 2, 1 ); + m_customUserLayersGrid->EnableEditing( true ); + m_customUserLayersGrid->EnableGridLines( true ); + m_customUserLayersGrid->EnableDragGridSize( false ); + m_customUserLayersGrid->SetMargins( 0, 0 ); + + // Columns + m_customUserLayersGrid->SetColSize( 0, 180 ); + m_customUserLayersGrid->EnableDragColMove( false ); + m_customUserLayersGrid->EnableDragColSize( true ); + m_customUserLayersGrid->SetColLabelSize( 0 ); + m_customUserLayersGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Rows + m_customUserLayersGrid->EnableDragRowSize( false ); + m_customUserLayersGrid->SetRowLabelSize( 0 ); + m_customUserLayersGrid->SetRowLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTER ); + + // Label Appearance + + // Cell Defaults + m_customUserLayersGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER ); + sbUserCustomerLayers->Add( m_customUserLayersGrid, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bButtonSize11; + bButtonSize11 = new wxBoxSizer( wxHORIZONTAL ); + + m_bpAddCustomLayer = new STD_BITMAP_BUTTON( sbUserCustomerLayers->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bButtonSize11->Add( m_bpAddCustomLayer, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); + + + bButtonSize11->Add( 20, 0, 0, wxEXPAND, 5 ); + + m_bpDeleteCustomLayer = new STD_BITMAP_BUTTON( sbUserCustomerLayers->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bButtonSize11->Add( m_bpDeleteCustomLayer, 0, wxBOTTOM|wxRIGHT, 5 ); + + + sbUserCustomerLayers->Add( bButtonSize11, 0, wxEXPAND, 5 ); + + + gbSizer3->Add( sbUserCustomerLayers, wxGBPosition( 2, 0 ), wxGBSpan( 1, 2 ), wxALL|wxEXPAND, 5 ); + + + gbSizer3->AddGrowableRow( 2 ); + + sbSizer11->Add( gbSizer3, 1, wxEXPAND, 5 ); + + + bSizer14->Add( sbSizer11, 1, wxEXPAND, 5 ); + + + m_LayersPanel->SetSizer( bSizer14 ); + m_LayersPanel->Layout(); + bSizer14->Fit( m_LayersPanel ); + m_NoteBook->AddPage( m_LayersPanel, _("Layers"), true ); m_PanelClearances = new wxPanel( m_NoteBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizerPanelClearances; bSizerPanelClearances = new wxBoxSizer( wxVERTICAL ); @@ -524,6 +612,10 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITO m_excludeFromPosFiles->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); m_excludeFromBOM->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); m_cbDNP->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); + m_cbCustomLayers->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnUseCustomLayers ), NULL, this ); + m_customUserLayersGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnGridSize ), NULL, this ); + m_bpAddCustomLayer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnAddCustomLayer ), NULL, this ); + m_bpDeleteCustomLayer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnDeleteCustomLayer ), NULL, this ); m_noCourtyards->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); m_nettieGroupsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnGridSize ), NULL, this ); m_bpAddNettieGroup->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnAddNettieGroup ), NULL, this ); @@ -553,6 +645,10 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::~DIALOG_FOOTPRINT_PROPERTIES_FP_EDIT m_excludeFromPosFiles->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); m_excludeFromBOM->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); m_cbDNP->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); + m_cbCustomLayers->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnUseCustomLayers ), NULL, this ); + m_customUserLayersGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnGridSize ), NULL, this ); + m_bpAddCustomLayer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnAddCustomLayer ), NULL, this ); + m_bpDeleteCustomLayer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnDeleteCustomLayer ), NULL, this ); m_noCourtyards->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnCheckBox ), NULL, this ); m_nettieGroupsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnGridSize ), NULL, this ); m_bpAddNettieGroup->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::OnAddNettieGroup ), NULL, this ); diff --git a/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.fbp b/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.fbp index bc996b58a2..ab0bb20cc8 100644 --- a/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.fbp +++ b/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.fbp @@ -128,7 +128,7 @@ General - 1 + 0 1 1 @@ -886,7 +886,7 @@ none 5 - wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT 1 1 @@ -1163,16 +1163,16 @@ 5 wxEXPAND|wxBOTTOM|wxRIGHT 0 - + bPartTypeSizer wxHORIZONTAL none - + 5 wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL 0 - + 1 1 1 @@ -1230,11 +1230,11 @@ -1 - + 5 wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT 0 - + 1 1 1 @@ -1569,6 +1569,581 @@ + + + Layers + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_LayersPanel + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + bSizer14 + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + wxID_ANY + Custom Layers + + sbSizer11 + wxVERTICAL + 1 + none + + 5 + wxEXPAND + 1 + + + wxBOTH + + 2 + 0 + + gbSizer3 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + + 5 + 2 + 0 + wxALL + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Use custom stackup + + 0 + + + 0 + + 1 + m_cbCustomLayers + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnUseCustomLayers + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxALL + 1 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Copper layers + 0 + + 0 + + + 0 + + 1 + m_copperLayerCountLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 1 + 1 + wxALL|wxEXPAND + 1 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + "2" "4" "6" "8" "10" "12" "14" "16" "18" "20" "22" "24" "26" "28" "30" "32" "" + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 0 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_copperLayerCount + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + 2 + 0 + wxALL|wxEXPAND + 2 + 1 + + wxID_ANY + User Layers + + sbUserCustomerLayers + wxVERTICAL + 1 + none + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + 0 + + + + 1 + + + wxALIGN_LEFT + + wxALIGN_CENTER + 0 + 1 + wxALIGN_CENTER + 0 + + wxALIGN_CENTER + 1 + 180 + + 1 + 0 + Dock + 0 + Left + 0 + 0 + 1 + 0 + 0 + 1 + 1 + + 1 + + + 1 + 0 + 0 + wxID_ANY + + + + 0 + 0 + + 0 + + + 0 + -1,-1 + 1 + m_customUserLayersGrid + 1 + + + protected + 1 + + Resizable + wxALIGN_LEFT + 0 + + wxALIGN_CENTER + + 2 + 1 + -1,-1 + WX_GRID; widgets/wx_grid.h; forward_declare + 0 + + + + + OnGridSize + + + + 5 + wxEXPAND + 0 + + + bButtonSize11 + wxHORIZONTAL + none + + 5 + wxBOTTOM|wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Add Excluded Layer + + 0 + + 0 + + + 0 + -1,-1 + 1 + m_bpAddCustomLayer + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnAddCustomLayer + + + + 5 + wxEXPAND + 0 + + 0 + protected + 20 + + + + 5 + wxBOTTOM|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Delete Excluded Layer + + 0 + + 0 + + + 0 + -1,-1 + 1 + m_bpDeleteCustomLayer + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnDeleteCustomLayer + + + + + + + + + + + + + Clearance Overrides diff --git a/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.h b/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.h index f6f49e23c0..aa9d637b5c 100644 --- a/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.h +++ b/pcbnew/dialogs/dialog_footprint_properties_fp_editor_base.h @@ -68,6 +68,13 @@ class DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE : public DIALOG_SHIM wxCheckBox* m_excludeFromPosFiles; wxCheckBox* m_excludeFromBOM; wxCheckBox* m_cbDNP; + wxPanel* m_LayersPanel; + wxCheckBox* m_cbCustomLayers; + wxStaticText* m_copperLayerCountLabel; + wxChoice* m_copperLayerCount; + WX_GRID* m_customUserLayersGrid; + STD_BITMAP_BUTTON* m_bpAddCustomLayer; + STD_BITMAP_BUTTON* m_bpDeleteCustomLayer; wxPanel* m_PanelClearances; wxStaticText* m_staticTextInfo; wxStaticText* m_NetClearanceLabel; @@ -114,6 +121,9 @@ class DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE : public DIALOG_SHIM virtual void OnDeleteLayer( wxCommandEvent& event ) { event.Skip(); } virtual void OnChoice( wxCommandEvent& event ) { event.Skip(); } virtual void OnCheckBox( wxCommandEvent& event ) { event.Skip(); } + virtual void OnUseCustomLayers( wxCommandEvent& event ) { event.Skip(); } + virtual void OnAddCustomLayer( wxCommandEvent& event ) { event.Skip(); } + virtual void OnDeleteCustomLayer( wxCommandEvent& event ) { event.Skip(); } virtual void OnAddNettieGroup( wxCommandEvent& event ) { event.Skip(); } virtual void OnRemoveNettieGroup( wxCommandEvent& event ) { event.Skip(); } virtual void OnAddJumperGroup( wxCommandEvent& event ) { event.Skip(); } diff --git a/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp b/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp index 2d5a387fd3..31fc2199a4 100644 --- a/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp +++ b/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp @@ -156,11 +156,9 @@ DIALOG_NON_COPPER_ZONES_EDITOR::DIALOG_NON_COPPER_ZONES_EDITOR( PCB_BASE_FRAME* m_gap = nullptr; } - bool fpEditorMode = m_parent->IsType( FRAME_FOOTPRINT_EDITOR ); - m_staticTextLayerSelection->SetFont( KIUI::GetStatusFont( this ) ); - m_settings.SetupLayersList( m_layers, m_parent, LSET::AllNonCuMask(), fpEditorMode ); + m_settings.SetupLayersList( m_layers, m_parent, LSET::AllNonCuMask() ); SetupStandardButtons(); @@ -365,5 +363,3 @@ bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataFromWindow() *m_ptr = m_settings; return true; } - - diff --git a/pcbnew/dialogs/dialog_rule_area_properties.cpp b/pcbnew/dialogs/dialog_rule_area_properties.cpp index c87b9a4d82..2060e5e1d0 100644 --- a/pcbnew/dialogs/dialog_rule_area_properties.cpp +++ b/pcbnew/dialogs/dialog_rule_area_properties.cpp @@ -183,12 +183,10 @@ DIALOG_RULE_AREA_PROPERTIES::DIALOG_RULE_AREA_PROPERTIES( PCB_BASE_FRAME* aPar SetTitle( _( "Convert to Rule Area" ) ); } - m_isFpEditor = m_parent->IsType( FRAME_FOOTPRINT_EDITOR ); - BOARD* board = m_parent->GetBoard(); LSET layers = LSET::AllNonCuMask() | LSET::AllCuMask( board->GetCopperLayerCount() ); - m_zonesettings.SetupLayersList( m_layers, m_parent, layers, m_isFpEditor ); + m_zonesettings.SetupLayersList( m_layers, m_parent, layers ); SetupStandardButtons(); @@ -383,19 +381,35 @@ void DIALOG_RULE_AREA_PROPERTIES::OnLayerSelection( wxDataViewEvent& event ) m_layers->GetValue( layerID, row, LAYER_LIST_COLUMN_NAME ); bool selected = m_layers->GetToggleValue( row, LAYER_LIST_COLUMN_CHECK ); - // In footprint editor, we have only 3 possible layer selection: C_Cu, inner layers, B_Cu. + const auto setSelectedLayer = [&]() + { + m_zonesettings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ), selected ); + }; + + // In footprint editor, we may in "expand inner layer" mode, where we + // have only 3 possible layer selection: C_Cu, inner layers, B_Cu. // So row LAYER_LIST_ROW_ALL_INNER_LAYERS selection is fp editor specific. // in board editor, this row is a normal selection if( m_isFpEditor && row == LAYER_LIST_ROW_ALL_INNER_LAYERS ) { - if( selected ) - m_zonesettings.m_Layers |= LSET::InternalCuMask(); + const FOOTPRINT* fp = static_cast( m_parent->GetModel() ); + + if( !fp || fp->GetStackupMode() == FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS ) + { + if( selected ) + m_zonesettings.m_Layers |= LSET::InternalCuMask(); + else + m_zonesettings.m_Layers &= ~LSET::InternalCuMask(); + } else - m_zonesettings.m_Layers &= ~LSET::InternalCuMask(); + { + // We have a custom stackup footprint, so select just that one layer + setSelectedLayer(); + } } else { - m_zonesettings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ), selected ); + setSelectedLayer(); } } @@ -514,5 +528,3 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataFromWindow() *m_ptr = m_zonesettings; return true; } - - diff --git a/pcbnew/dialogs/dialog_shape_properties.cpp b/pcbnew/dialogs/dialog_shape_properties.cpp index 995fffaa7e..d273bd3d9f 100644 --- a/pcbnew/dialogs/dialog_shape_properties.cpp +++ b/pcbnew/dialogs/dialog_shape_properties.cpp @@ -992,11 +992,9 @@ DIALOG_SHAPE_PROPERTIES::DIALOG_SHAPE_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, // Configure the layers list selector if( m_parent->GetFrameType() == FRAME_FOOTPRINT_EDITOR ) { - LSET forbiddenLayers = LSET::ForbiddenFootprintLayers(); - - // If someone went to the trouble of setting the layer in a text editor, then there's - // very little sense in nagging them about it. - forbiddenLayers.set( m_item->GetLayer(), false ); + // In the footprint editor, turn off the layers that the footprint doesn't have + const LSET& brdLayers = aParent->GetBoard()->GetEnabledLayers(); + LSET forbiddenLayers = LSET::AllLayersMask() & ~brdLayers; m_LayerSelectionCtrl->SetNotAllowedLayerSet( forbiddenLayers ); } diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index bf5d37ddcd..47b412be17 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -27,6 +27,9 @@ #include +#include +#include + #include #include #include @@ -66,7 +69,6 @@ #include #include #include -#include FOOTPRINT::FOOTPRINT( BOARD* parent ) : @@ -82,6 +84,8 @@ FOOTPRINT::FOOTPRINT( BOARD* parent ) : m_allowMissingCourtyard( false ), m_allowSolderMaskBridges( false ), m_zoneConnection( ZONE_CONNECTION::INHERITED ), + m_stackupLayers( LSET{ F_Cu, In1_Cu, B_Cu } ), + m_stackupMode( FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS ), m_lastEditTime( 0 ), m_arflag( 0 ), m_link( 0 ), @@ -143,6 +147,9 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) : m_solderPasteMargin = aFootprint.m_solderPasteMargin; m_solderPasteMarginRatio = aFootprint.m_solderPasteMarginRatio; + m_stackupLayers = aFootprint.m_stackupLayers; + m_stackupMode = aFootprint.m_stackupMode; + m_libDescription = aFootprint.m_libDescription; m_keywords = aFootprint.m_keywords; m_path = aFootprint.m_path; @@ -4149,6 +4156,27 @@ void FOOTPRINT::InvalidateComponentClassCache() const } +void FOOTPRINT::SetStackupMode( FOOTPRINT_STACKUP aMode ) +{ + m_stackupMode = aMode; + + if( m_stackupMode == FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS ) + { + // Reset the stackup layers to the default values + m_stackupLayers = LSET{ F_Cu, In1_Cu, B_Cu }; + } +} + + +void FOOTPRINT::SetStackupLayers( LSET aLayers ) +{ + wxCHECK2( m_stackupMode == FOOTPRINT_STACKUP::CUSTOM_LAYERS, /*void*/ ); + + if( m_stackupMode == FOOTPRINT_STACKUP::CUSTOM_LAYERS ) + m_stackupLayers = std::move( aLayers ); +} + + static struct FOOTPRINT_DESC { FOOTPRINT_DESC() diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h index 0446e1184c..833d4be79c 100644 --- a/pcbnew/footprint.h +++ b/pcbnew/footprint.h @@ -86,6 +86,20 @@ enum FOOTPRINT_ATTR_T FP_DNP = 0x0040 }; +enum class FOOTPRINT_STACKUP +{ + /** + * The 'normal' stackup handling, where there is a single inner layer + * (In1) and rule areas using it expand to all inner layer on the host PCB. + */ + EXPAND_INNER_LAYERS, + /** + * Stackup handling where the footprint can have any number of copper layers, + * and objects on those layers go to the matching inner layer on the host PCB. + */ + CUSTOM_LAYERS, +}; + class FP_3DMODEL { public: @@ -287,8 +301,24 @@ public: std::optional GetLocalSolderPasteMarginRatio() const { return m_solderPasteMarginRatio; } void SetLocalSolderPasteMarginRatio( std::optional aRatio ) { m_solderPasteMarginRatio = aRatio; } - void SetLocalZoneConnection( ZONE_CONNECTION aType ) { m_zoneConnection = aType; } - ZONE_CONNECTION GetLocalZoneConnection() const { return m_zoneConnection; } + void SetLocalZoneConnection( ZONE_CONNECTION aType ) { m_zoneConnection = aType; } + ZONE_CONNECTION GetLocalZoneConnection() const { return m_zoneConnection; } + + /** + * Set the stackup mode for this footprint. + * + * This determines if the footprint lists its own layers or uses a default stackup, + * with "expansion" of inner layers to the PCB's inner layers. + */ + void SetStackupMode( FOOTPRINT_STACKUP aMode ); + FOOTPRINT_STACKUP GetStackupMode() const { return m_stackupMode; } + + /** + * If the footprint has a non-default stackup, set the layers that + * should be used for the stackup. + */ + void SetStackupLayers( LSET aLayers ); + const LSET& GetStackupLayers() const { return m_stackupLayers; } int GetAttributes() const { return m_attributes; } void SetAttributes( int aAttributes ) { m_attributes = aAttributes; } @@ -1119,6 +1149,10 @@ private: std::optional m_solderPasteMarginRatio; // Solder mask margin ratio of pad size // The final margin is the sum of these 2 values + LSET m_stackupLayers; // Layers in the stackup + FOOTPRINT_STACKUP m_stackupMode; // Stackup mode for this footprint + LSET m_privateLayers; // Layers visible only in the footprint editor + wxString m_libDescription; // File name and path for documentation file. wxString m_keywords; // Search keywords to find footprint in library. KIID_PATH m_path; // Path to associated symbol ([sheetUUID, .., symbolUUID]). @@ -1128,7 +1162,6 @@ private: timestamp_t m_lastEditTime; int m_arflag; // Use to trace ratsnest and auto routing. KIID m_link; // Temporary logical link used during editing - LSET m_privateLayers; // Layers visible only in the footprint editor std::vector m_3D_Drawings; // 3D models. wxArrayString* m_initial_comments; // s-expression comments in the footprint, diff --git a/pcbnew/footprint_edit_frame.cpp b/pcbnew/footprint_edit_frame.cpp index 9735b7459b..e76c7fdf76 100644 --- a/pcbnew/footprint_edit_frame.cpp +++ b/pcbnew/footprint_edit_frame.cpp @@ -528,14 +528,48 @@ void FOOTPRINT_EDIT_FRAME::restoreLastFootprint() void FOOTPRINT_EDIT_FRAME::updateEnabledLayers() { - // Enable one internal layer, because footprints support keepout areas that can be on - // internal layers only (therefore on the first internal layer). This is needed to handle - // these keepout in internal layers only. - GetBoard()->SetCopperLayerCount( 3 ); - GetBoard()->SetLayerName( In1_Cu, _( "Inner layers" ) ); + FOOTPRINT* footprint = static_cast( GetModel() ); + BOARD& board = *GetBoard(); - // Don't drop pre-existing user layers - LSET enabledLayers = GetBoard()->GetEnabledLayers(); + // All FPs have these layers enabled + LSET enabledLayers = LSET::AllTechMask() | LSET::UserMask(); + + const auto configureStackup = [&]( FOOTPRINT_STACKUP aMode, const LSET& aLayerSet ) + { + const LSET cuLayers = aLayerSet & LSET::AllCuMask(); + board.SetCopperLayerCount( cuLayers.count() ); + + switch( aMode ) + { + case FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS: + { + enabledLayers |= LSET{ F_Cu, In1_Cu, B_Cu }; + enabledLayers |= LSET::UserDefinedLayersMask( 4 ); + board.SetLayerName( In1_Cu, _( "Inner layers" ) ); + break; + } + case FOOTPRINT_STACKUP::CUSTOM_LAYERS: + { + // Nothing extra to add + + // Clear layer name defaults + board.SetLayerName( In1_Cu, wxEmptyString ); + break; + } + } + + enabledLayers |= aLayerSet; + }; + + if( footprint ) + { + configureStackup( footprint->GetStackupMode(), footprint->GetStackupLayers() ); + } + else + { + // If no footprint is loaded, we assume the default stackup mode + configureStackup( FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS, LSET{} ); + } if( m_originalFootprintCopy ) { @@ -560,7 +594,12 @@ void FOOTPRINT_EDIT_FRAME::updateEnabledLayers() } } - GetBoard()->SetEnabledLayers( enabledLayers ); + board.SetEnabledLayers( enabledLayers ); + + // Footprint Editor layer visibility is kept in the view, not the board (because the board + // just delegates to the project file, which we don't have). + for( const PCB_LAYER_ID& layer : GetBoard()->GetEnabledLayers() ) + GetCanvas()->GetView()->SetLayerVisible( layer, true ); } @@ -580,11 +619,6 @@ void FOOTPRINT_EDIT_FRAME::ReloadFootprint( FOOTPRINT* aFootprint ) updateEnabledLayers(); - // Footprint Editor layer visibility is kept in the view, not the board (because the board - // just delegates to the project file, which we don't have). - for( PCB_LAYER_ID layer : GetBoard()->GetEnabledLayers() ) - GetCanvas()->GetView()->SetLayerVisible( layer, true ); - const wxString libName = aFootprint->GetFPID().GetLibNickname(); if( IsCurrentFPFromBoard() ) diff --git a/pcbnew/footprint_editor_utils.cpp b/pcbnew/footprint_editor_utils.cpp index b7ccf16424..1bb918e9c2 100644 --- a/pcbnew/footprint_editor_utils.cpp +++ b/pcbnew/footprint_editor_utils.cpp @@ -150,12 +150,16 @@ void FOOTPRINT_EDIT_FRAME::editFootprintProperties( FOOTPRINT* aFootprint ) DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR dialog( this, aFootprint ); dialog.ShowQuasiModal(); + // Update design settings for footprint layers + updateEnabledLayers(); + // Update library tree and title in case of a name change wxDataViewItem treeItem = m_adapter->FindItem( oldFPID ); UpdateLibraryTree( treeItem, aFootprint ); UpdateTitle(); UpdateMsgPanel(); + UpdateUserInterface(); } diff --git a/pcbnew/pcb_base_edit_frame.cpp b/pcbnew/pcb_base_edit_frame.cpp index 415d09fdf1..51815aa11d 100644 --- a/pcbnew/pcb_base_edit_frame.cpp +++ b/pcbnew/pcb_base_edit_frame.cpp @@ -375,12 +375,6 @@ void PCB_BASE_EDIT_FRAME::configureToolbars() m_SelLayerBox->SetBoardFrame( this ); } - // In the footprint editor, some layers cannot be select (they are shown in the layer - // manager only to set the color and visibility, but not for selection) - // Disable them in layer box - if( IsType( FRAME_FOOTPRINT_EDITOR ) ) - m_SelLayerBox->SetNotAllowedLayerSet( LSET::ForbiddenFootprintLayers() ); - m_SelLayerBox->SetToolTip( _( "+/- to switch" ) ); m_SelLayerBox->Resync(); @@ -411,4 +405,4 @@ void PCB_BASE_EDIT_FRAME::configureToolbars() }; RegisterCustomToolbarControlFactory( ACTION_TOOLBAR_CONTROLS::layerSelector, layerSelectorFactory ); -} \ No newline at end of file +} diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp index 6f91d61c66..663097d91f 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp @@ -1274,6 +1274,21 @@ void PCB_IO_KICAD_SEXPR::format( const FOOTPRINT* aFootprint ) const m_out->Print( ")" ); } + // Expand inner layers is the default stackup mode + if( aFootprint->GetStackupMode() != FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS ) + { + m_out->Print( "(stackup" ); + + const LSET& fpLset = aFootprint->GetStackupLayers(); + for( PCB_LAYER_ID layer : fpLset.Seq() ) + { + wxString canonicalName( LSET::Name( layer ) ); + m_out->Print( "(layer %s)", m_out->Quotew( canonicalName ).c_str() ); + } + + m_out->Print( ")" ); + } + if( aFootprint->GetPrivateLayers().any() ) { m_out->Print( "(private_layers" ); diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h index c8c0655e66..f9ed7c3fdf 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h @@ -185,7 +185,8 @@ class PCB_IO_KICAD_SEXPR; // forward decl //#define SEXPR_BOARD_FILE_VERSION 20250401 // Time domain length tuning //#define SEXPR_BOARD_FILE_VERSION 20250513 // Groups can have design block lib_id //#define SEXPR_BOARD_FILE_VERSION 20250801 // (island) -> (island yes/no) -#define SEXPR_BOARD_FILE_VERSION 20250811 // press-fit pad fabr prop support +//#define SEXPR_BOARD_FILE_VERSION 20250811 // press-fit pad fabr prop support +#define SEXPR_BOARD_FILE_VERSION 20250818 // Support for custom layer counts in footprints #define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag #define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp index 7ef4b24a0c..86303d7cbd 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp @@ -4579,6 +4579,12 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a break; } + case T_stackup: + { + parseFootprintStackup( *footprint ); + break; + } + case T_tedit: parseHex(); NeedRIGHT(); @@ -5104,6 +5110,54 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a } +void PCB_IO_KICAD_SEXPR_PARSER::parseFootprintStackup( FOOTPRINT& aFootprint ) +{ + wxCHECK_RET( CurTok() == T_stackup, "Expected stackup token" ); + + // If we have a stackup list at all, we must be in custom layer mode + FOOTPRINT_STACKUP stackupMode = FOOTPRINT_STACKUP::CUSTOM_LAYERS; + LSET layers = LSET{}; + + for( T token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( CurTok() != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_layer: + { + NeedSYMBOLorNUMBER(); + const wxString layerName = CurText(); + + for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer ) + { + if( LayerName( layer ) == layerName ) + { + layers.set( ToLAYER_ID( layer ) ); + break; + } + } + + NeedRIGHT(); + break; + } + default: + { + Expecting( "layer" ); + break; + } + } + } + + // Set the mode first, so that the layer count is unlocked if needed + aFootprint.SetStackupMode( stackupMode ); + aFootprint.SetStackupLayers( layers ); +} + + PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent ) { wxCHECK_MSG( CurTok() == T_pad, nullptr, diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h index 138c3fdc0a..674b6a90cc 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h @@ -229,6 +229,7 @@ private: // Parse a footprint, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically. FOOTPRINT* parseFOOTPRINT_unchecked( wxArrayString* aInitialComments = nullptr ); + void parseFootprintStackup( FOOTPRINT& aFootprint ); PAD* parsePAD( FOOTPRINT* aParent = nullptr ); diff --git a/pcbnew/pcb_layer_box_selector.cpp b/pcbnew/pcb_layer_box_selector.cpp index 3632695b98..90b472d834 100644 --- a/pcbnew/pcb_layer_box_selector.cpp +++ b/pcbnew/pcb_layer_box_selector.cpp @@ -131,7 +131,7 @@ bool PCB_LAYER_BOX_SELECTOR::isLayerEnabled( int aLayer ) const LSET PCB_LAYER_BOX_SELECTOR::getEnabledLayers() const { - static LSET footprintEditorLayers = LSET::AllLayersMask() & ~LSET::ForbiddenFootprintLayers(); + static const LSET footprintEditorLayers = LSET::AllLayersMask(); if( m_boardFrame ) return m_boardFrame->GetBoard()->GetEnabledLayers(); diff --git a/pcbnew/widgets/appearance_controls.cpp b/pcbnew/widgets/appearance_controls.cpp index 196802b8b9..6dd9707598 100644 --- a/pcbnew/widgets/appearance_controls.cpp +++ b/pcbnew/widgets/appearance_controls.cpp @@ -1331,6 +1331,16 @@ void APPEARANCE_CONTROLS::setVisibleLayers( const LSET& aLayers ) } +bool APPEARANCE_CONTROLS::isLayerEnabled( PCB_LAYER_ID aLayer ) const +{ + // This used to be used for disabling some layers in the footprint editor, but + // now all layers are enabled in the footprint editor. + // But this function is the place to add logic if you do need to grey out a layer + // from the appearance panel for some reason. + return true; +} + + void APPEARANCE_CONTROLS::setVisibleObjects( GAL_SET aLayers ) { if( m_isFpEditor ) @@ -1794,7 +1804,7 @@ void APPEARANCE_CONTROLS::rebuildLayers() m_layerSettingsMap[layer] = setting.get(); - if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) ) + if( !isLayerEnabled( layer ) ) { setting->ctl_text->Disable(); setting->ctl_color->SetToolTip( wxEmptyString ); @@ -1838,7 +1848,7 @@ void APPEARANCE_CONTROLS::rebuildLayers() m_layerSettingsMap[layer] = setting.get(); - if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) ) + if( !isLayerEnabled( layer ) ) { setting->ctl_text->Disable(); setting->ctl_color->SetToolTip( wxEmptyString ); @@ -2092,7 +2102,7 @@ void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent ) PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() ); - if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) ) + if( !isLayerEnabled( layer ) ) return; m_frame->SetActiveLayer( layer ); diff --git a/pcbnew/widgets/appearance_controls.h b/pcbnew/widgets/appearance_controls.h index c28df43bdf..1531df4948 100644 --- a/pcbnew/widgets/appearance_controls.h +++ b/pcbnew/widgets/appearance_controls.h @@ -340,6 +340,8 @@ private: void setVisibleLayers( const LSET& aLayers ); + bool isLayerEnabled( PCB_LAYER_ID aLayer ) const; + void setVisibleObjects( GAL_SET aObjects ); LSET getVisibleLayers(); diff --git a/pcbnew/zone_settings.cpp b/pcbnew/zone_settings.cpp index 653b674c80..450304b80e 100644 --- a/pcbnew/zone_settings.cpp +++ b/pcbnew/zone_settings.cpp @@ -328,16 +328,11 @@ const ZONE_SETTINGS& ZONE_SETTINGS::GetDefaultSettings() // A helper for setting up a dialog list for specifying zone layers. Used by all three // zone settings dialogs. -void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* aFrame, - LSET aLayers, bool aFpEditorMode ) +void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* aFrame, LSET aLayers ) { BOARD* board = aFrame->GetBoard(); COLOR4D backgroundColor = aFrame->GetColorSettings()->GetColor( LAYER_PCB_BACKGROUND ); - // In the Footprint Editor In1_Cu is used as a proxy for "all inner layers" - if( aFpEditorMode ) - aLayers.set( In1_Cu ); - wxDataViewColumn* checkColumn = aList->AppendToggleColumn( wxEmptyString, wxDATAVIEW_CELL_ACTIVATABLE, wxCOL_WIDTH_DEFAULT, wxALIGN_CENTER ); @@ -351,9 +346,6 @@ void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* { wxString layerName = board->GetLayerName( layerID ); - if( aFpEditorMode && layerID == In1_Cu ) - layerName = _( "Inner layers" ); - // wxCOL_WIDTH_AUTOSIZE doesn't work on all platforms, so we calculate width here textWidth = std::max( textWidth, KIUI::GetTextSize( layerName, aList ).x ); @@ -385,5 +377,3 @@ void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* checkColumn->SetWidth( checkColSize ); layerColumn->SetWidth( layerColSize ); } - - diff --git a/pcbnew/zone_settings.h b/pcbnew/zone_settings.h index 0d88a35f18..e1f4dc0dc1 100644 --- a/pcbnew/zone_settings.h +++ b/pcbnew/zone_settings.h @@ -183,10 +183,8 @@ public: * A helper routine for the various zone dialogs (copper, non-copper, keepout). * @param aList the wxDataViewListCtrl to populate * @param aFrame the parent editor frame - * @param aFpEditorMode true to show a single "Inner Layers" item for all inner copper layers */ - void SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* aFrame, LSET aLayers, - bool aFpEditorMode ); + void SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* aFrame, LSET aLayers ); /** * Function ExportSetting