diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index d535d0d630..bcf9038099 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -112,6 +112,8 @@ set( PCBNEW_DIALOGS dialogs/dialog_graphic_item_properties_base.cpp dialogs/dialog_import_settings.cpp dialogs/dialog_import_settings_base.cpp + dialogs/dialog_imported_layers_base.cpp + dialogs/dialog_imported_layers.cpp dialogs/dialog_rule_area_properties.cpp dialogs/dialog_rule_area_properties_base.cpp dialogs/dialog_layer_selection_base.cpp diff --git a/pcbnew/dialogs/dialog_imported_layers.cpp b/pcbnew/dialogs/dialog_imported_layers.cpp new file mode 100644 index 0000000000..6d6f04aec0 --- /dev/null +++ b/pcbnew/dialogs/dialog_imported_layers.cpp @@ -0,0 +1,278 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2020 Roberto Fernandez Bautista + * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + + +#include +#include + + +PCB_LAYER_ID DIALOG_IMPORTED_LAYERS::GetSelectedLayerID() +{ + // First check if there is a KiCad element selected + wxString selectedKiCadLayerName; + long itemIndex = -1; + + if( ( itemIndex = m_kicad_layers_list->GetNextItem( + itemIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ) ) + != wxNOT_FOUND ) + { + selectedKiCadLayerName = m_kicad_layers_list->GetItemText( itemIndex ); + } + else + { + return PCB_LAYER_ID::UNDEFINED_LAYER; + } + + // There should only be one selected (or none) as the list is set with wxLC_SINGLE_SEL style + wxASSERT_MSG( ( m_kicad_layers_list->GetNextItem( + itemIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ) ) + == wxNOT_FOUND, + "There are more than one KiCad layer selected (unexpected)" ); + + for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer ) + { + if( LayerName( ToLAYER_ID( layer ) ) == selectedKiCadLayerName ) + return ToLAYER_ID( layer ); + } + + return PCB_LAYER_ID::UNDEFINED_LAYER; +} + + +PCB_LAYER_ID DIALOG_IMPORTED_LAYERS::GetAutoMatchLayerID( wxString aInputLayerName ) +{ + for( INPUT_LAYER_DESC inputLayerDesc : m_input_layers ) + { + if( inputLayerDesc.Name == aInputLayerName ) + return inputLayerDesc.AutoMapLayer; + } + + return PCB_LAYER_ID::UNDEFINED_LAYER; +} + + +void DIALOG_IMPORTED_LAYERS::AddMappings() +{ + PCB_LAYER_ID selectedKiCadLayerID = GetSelectedLayerID(); + + if( selectedKiCadLayerID == PCB_LAYER_ID::UNDEFINED_LAYER ) + return; + + // Now iterate through each selected layer in the unmatched layers list + int itemIndex = -1; + wxArrayInt rowsToDelete; + + while( ( itemIndex = m_unmatched_layers_list->GetNextItem( + itemIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ) ) + != wxNOT_FOUND ) + { + wxString selectedLayerName = m_unmatched_layers_list->GetItemText( itemIndex ); + wxString kiName = LayerName( selectedKiCadLayerID ); + + // add layer pair to the GUI list and also to the map + long newItemIndex = m_matched_layers_list->InsertItem( 0, selectedLayerName ); + m_matched_layers_list->SetItem( newItemIndex, 1, kiName ); + + m_matched_layers_map.insert( { selectedLayerName, selectedKiCadLayerID } ); + + // remove selected layer from vector and also GUI list + for( auto iter = m_unmatched_layer_names.begin(); iter != m_unmatched_layer_names.end(); + ++iter ) + { + if( *iter == selectedLayerName ) + { + m_unmatched_layer_names.erase( iter ); + break; + } + } + + rowsToDelete.Add( itemIndex ); + } + + DeleteListItems( rowsToDelete, m_unmatched_layers_list ); +} + + +void DIALOG_IMPORTED_LAYERS::RemoveMappings( int aStatus ) +{ + wxArrayInt rowsToDelete; + int itemIndex = -1; + + while( ( itemIndex = m_matched_layers_list->GetNextItem( itemIndex, wxLIST_NEXT_ALL, aStatus ) ) + != wxNOT_FOUND ) + { + wxString selectedLayerName = m_matched_layers_list->GetItemText( itemIndex, 0 ); + + wxCHECK( m_matched_layers_map.find( selectedLayerName ) != m_matched_layers_map.end(), + /*void*/ ); + + m_matched_layers_map.erase( selectedLayerName ); + rowsToDelete.Add( itemIndex ); + + m_unmatched_layers_list->InsertItem( 0, selectedLayerName ); + m_unmatched_layer_names.push_back( selectedLayerName ); + } + + DeleteListItems( rowsToDelete, m_matched_layers_list ); +} + + +void DIALOG_IMPORTED_LAYERS::DeleteListItems( const wxArrayInt& aRowsToDelete, + wxListCtrl* aListCtrl ) +{ + for( long n = ( aRowsToDelete.GetCount() - 1 ); 0 <= n; n-- ) + { + aListCtrl->DeleteItem( aRowsToDelete[n] ); + } +} + + +void DIALOG_IMPORTED_LAYERS::OnAutoMatchLayersClicked( wxCommandEvent& event ) +{ + // Iterate through each selected layer in the unmatched layers list + int itemIndex = -1; + wxArrayInt rowsToDelete; + + while( ( itemIndex = m_unmatched_layers_list->GetNextItem( + itemIndex, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE ) ) + != wxNOT_FOUND ) + { + wxString layerName = m_unmatched_layers_list->GetItemText( itemIndex ); + PCB_LAYER_ID autoMatchLayer = GetAutoMatchLayerID( layerName ); + + if( autoMatchLayer == PCB_LAYER_ID::UNDEFINED_LAYER ) + continue; + + wxString kiName = LayerName( autoMatchLayer ); + + // add layer pair to the GUI list and also to the map + long newItemIndex = m_matched_layers_list->InsertItem( 0, layerName ); + m_matched_layers_list->SetItem( newItemIndex, 1, kiName ); + + m_matched_layers_map.insert( { layerName, autoMatchLayer } ); + + // remove selected layer from vector and also GUI list + for( auto iter = m_unmatched_layer_names.begin(); iter != m_unmatched_layer_names.end(); + ++iter ) + { + if( *iter == layerName ) + { + m_unmatched_layer_names.erase( iter ); + break; + } + } + + rowsToDelete.Add( itemIndex ); + } + + DeleteListItems( rowsToDelete, m_unmatched_layers_list ); +} + + +DIALOG_IMPORTED_LAYERS::DIALOG_IMPORTED_LAYERS( wxWindow* aParent, + const std::vector& aLayerDesc ) + : DIALOG_IMPORTED_LAYERS_BASE( aParent ) +{ + LSET kiCadLayers; + + // Read in the input layers + for( INPUT_LAYER_DESC inLayer : aLayerDesc ) + { + m_input_layers.push_back( inLayer ); + m_unmatched_layer_names.push_back( inLayer.Name ); + kiCadLayers |= inLayer.PermittedLayers; + } + + + // Initialize columns in the wxListCtrl elements: + wxListItem importedLayersHeader; + importedLayersHeader.SetId( 0 ); + importedLayersHeader.SetText( _( "Imported Layer" ) ); + importedLayersHeader.SetWidth( 200 ); + m_unmatched_layers_list->InsertColumn( 0, importedLayersHeader ); + + wxListItem kicadLayersHeader; + kicadLayersHeader.SetId( 0 ); + kicadLayersHeader.SetText( _( "KiCad Layer" ) ); + kicadLayersHeader.SetWidth( 100 ); + m_kicad_layers_list->InsertColumn( 0, kicadLayersHeader ); + + kicadLayersHeader.SetId( 1 ); + m_matched_layers_list->InsertColumn( 0, importedLayersHeader ); + m_matched_layers_list->InsertColumn( 1, kicadLayersHeader ); + + + // Load the input layer list to unmatched layers + int row = 0; + + for( wxString importedLayerName : m_unmatched_layer_names ) + { + wxListItem item; + item.SetId( row ); + item.SetText( importedLayerName ); + m_unmatched_layers_list->InsertItem( item ); + ++row; + } + + // Load the KiCad Layer names + row = 0; + LSEQ kicadLayersSeq = kiCadLayers.Seq(); + + for( PCB_LAYER_ID layer : kicadLayersSeq ) + { + wxString kiName = LayerName( layer ); + + wxListItem item; + item.SetId( row ); + item.SetText( kiName ); + m_kicad_layers_list->InsertItem( item ); + ++row; + } + + m_sdbSizerOK->SetDefault(); + + FinishDialogSettings(); +} + + +LAYER_MAP DIALOG_IMPORTED_LAYERS::GetMapModal( wxWindow* aParent, + const std::vector& aLayerDesc ) +{ + DIALOG_IMPORTED_LAYERS dlg( aParent, aLayerDesc ); + bool dataOk = false; + + while( !dataOk ) + { + dlg.ShowModal(); + + if( dlg.m_unmatched_layer_names.size() > 0 ) + { + wxMessageBox( _( "All layers must be matched. Please click on 'Auto-Matched Layers' " + "to automatically match the remaining layers." ), + _( "Unmatched Layers" ), wxICON_ERROR | wxOK ); + } + else + { + dataOk = true; + } + } + + return dlg.m_matched_layers_map; +} diff --git a/pcbnew/dialogs/dialog_imported_layers.h b/pcbnew/dialogs/dialog_imported_layers.h new file mode 100644 index 0000000000..1f1861c3b5 --- /dev/null +++ b/pcbnew/dialogs/dialog_imported_layers.h @@ -0,0 +1,68 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2020 Roberto Fernandez Bautista + * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef DIALOG_IMPORTED_LAYERS_H +#define DIALOG_IMPORTED_LAYERS_H + +#include +#include // INPUT_LAYER_DESC + + +class DIALOG_IMPORTED_LAYERS : public DIALOG_IMPORTED_LAYERS_BASE +{ +private: + const int selected = wxLIST_STATE_SELECTED; + const int allitems = wxLIST_STATE_DONTCARE; + + std::vector m_input_layers; + std::vector m_unmatched_layer_names; + LAYER_MAP m_matched_layers_map; + + //Helper functions + PCB_LAYER_ID GetSelectedLayerID(); + PCB_LAYER_ID GetAutoMatchLayerID( wxString aInputLayerName ); + void AddMappings(); + void RemoveMappings( int aStatus ); + void DeleteListItems( const wxArrayInt& aRowsToDelete, wxListCtrl* aListCtrl ); + + //Event Handlers + void OnAutoMatchLayersClicked( wxCommandEvent& event ) override; + + void OnUnMatchedDoubleClick( wxListEvent& event ) override { AddMappings(); } + void OnAddClicked( wxCommandEvent& event ) override { AddMappings(); } + void OnMatchedDoubleClick( wxListEvent& event ) override { RemoveMappings( selected ); } + void OnRemoveClicked( wxCommandEvent& event ) override { RemoveMappings( selected ); } + void OnRemoveAllClicked( wxCommandEvent& event ) override { RemoveMappings( allitems ); } + +public: + DIALOG_IMPORTED_LAYERS( wxWindow* aParent, const std::vector& aLayerDesc ); + + /** + * @brief Creates and shows a dialog (modal) and returns the data from it after completion. + * If the dialog is closed or cancel is pressed, returns an empty LAYER_MAP + * @param aParent Parent window for the invoked dialog. + * @param aLayerDesc + * @return Mapped layers + */ + static LAYER_MAP GetMapModal( wxWindow* aParent, + const std::vector& aLayerDesc ); +}; + +#endif // DIALOG_IMPORTED_LAYERS_H diff --git a/pcbnew/dialogs/dialog_imported_layers_base.cpp b/pcbnew/dialogs/dialog_imported_layers_base.cpp new file mode 100644 index 0000000000..cff6ae9ca9 --- /dev/null +++ b/pcbnew/dialogs/dialog_imported_layers_base.cpp @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_imported_layers_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_IMPORTED_LAYERS_BASE::DIALOG_IMPORTED_LAYERS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( 600,350 ), wxDefaultSize ); + + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerTop; + bSizerTop = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticBoxSizer* sbSizer1; + sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Unmatched Layers") ), wxHORIZONTAL ); + + wxBoxSizer* bSizerUnmatched; + bSizerUnmatched = new wxBoxSizer( wxVERTICAL ); + + m_staticText1 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Imported Layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1->Wrap( -1 ); + bSizerUnmatched->Add( m_staticText1, 0, wxALL, 5 ); + + m_unmatched_layers_list = new wxListCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( 200,-1 ), wxLC_NO_HEADER|wxLC_REPORT ); + m_unmatched_layers_list->SetMaxSize( wxSize( 300,-1 ) ); + + bSizerUnmatched->Add( m_unmatched_layers_list, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); + + + sbSizer1->Add( bSizerUnmatched, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizerKiCad; + bSizerKiCad = new wxBoxSizer( wxVERTICAL ); + + m_staticText2 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("KiCad Layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText2->Wrap( -1 ); + bSizerKiCad->Add( m_staticText2, 0, wxALL, 5 ); + + m_kicad_layers_list = new wxListCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( 120,-1 ), wxLC_NO_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL ); + m_kicad_layers_list->SetMinSize( wxSize( 120,-1 ) ); + m_kicad_layers_list->SetMaxSize( wxSize( 150,-1 ) ); + + bSizerKiCad->Add( m_kicad_layers_list, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); + + + sbSizer1->Add( bSizerKiCad, 0, wxEXPAND, 5 ); + + + bSizerTop->Add( sbSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + wxStaticBoxSizer* sbSizer2; + sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + m_button_add = new wxButton( sbSizer2->GetStaticBox(), wxID_ANY, _(">"), wxDefaultPosition, wxSize( 30,100 ), 0 ); + m_button_add->SetFont( wxFont( 9, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_button_add->SetToolTip( _("Add selected layers to matched layers list.") ); + + sbSizer2->Add( m_button_add, 0, wxALL, 5 ); + + m_button_remove = new wxButton( sbSizer2->GetStaticBox(), wxID_ANY, _("<"), wxDefaultPosition, wxSize( 30,100 ), 0 ); + m_button_remove->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_button_remove->SetToolTip( _("Remove selected layers from matched layers list.") ); + + sbSizer2->Add( m_button_remove, 0, wxALL, 5 ); + + m_button_removeall = new wxButton( sbSizer2->GetStaticBox(), wxID_ANY, _("<<"), wxDefaultPosition, wxSize( 30,50 ), 0 ); + m_button_removeall->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_button_removeall->SetToolTip( _("Remove all matched layers.") ); + + sbSizer2->Add( m_button_removeall, 0, wxALL, 5 ); + + + bSizerTop->Add( sbSizer2, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 ); + + wxStaticBoxSizer* sbSizer3; + sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Matched Layers") ), wxHORIZONTAL ); + + m_matched_layers_list = new wxListCtrl( sbSizer3->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( 300,-1 ), wxLC_REPORT ); + m_matched_layers_list->SetMaxSize( wxSize( 500,-1 ) ); + + sbSizer3->Add( m_matched_layers_list, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); + + + bSizerTop->Add( sbSizer3, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 ); + + + bSizerMain->Add( bSizerTop, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizerBottom; + bSizerBottom = new wxBoxSizer( wxHORIZONTAL ); + + m_button_automatch = new wxButton( this, wxID_ANY, _("Auto-Match Layers"), wxDefaultPosition, wxDefaultSize, 0 ); + m_button_automatch->SetToolTip( _("Automatically match any unmatched layers to their KiCad equivalent.") ); + + bSizerBottom->Add( m_button_automatch, 0, wxALL, 5 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizer->Realize(); + + bSizerBottom->Add( m_sdbSizer, 1, wxALL|wxEXPAND, 5 ); + + + bSizerMain->Add( bSizerBottom, 0, wxEXPAND|wxLEFT, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnClose ) ); + this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnUpdateUI ) ); + m_unmatched_layers_list->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnUnMatchedDoubleClick ), NULL, this ); + m_kicad_layers_list->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnUnMatchedDoubleClick ), NULL, this ); + m_button_add->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnAddClicked ), NULL, this ); + m_button_remove->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnRemoveClicked ), NULL, this ); + m_button_removeall->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnRemoveAllClicked ), NULL, this ); + m_matched_layers_list->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnMatchedDoubleClick ), NULL, this ); + m_button_automatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnAutoMatchLayersClicked ), NULL, this ); +} + +DIALOG_IMPORTED_LAYERS_BASE::~DIALOG_IMPORTED_LAYERS_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnClose ) ); + this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnUpdateUI ) ); + m_unmatched_layers_list->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnUnMatchedDoubleClick ), NULL, this ); + m_kicad_layers_list->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnUnMatchedDoubleClick ), NULL, this ); + m_button_add->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnAddClicked ), NULL, this ); + m_button_remove->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnRemoveClicked ), NULL, this ); + m_button_removeall->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnRemoveAllClicked ), NULL, this ); + m_matched_layers_list->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnMatchedDoubleClick ), NULL, this ); + m_button_automatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORTED_LAYERS_BASE::OnAutoMatchLayersClicked ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_imported_layers_base.fbp b/pcbnew/dialogs/dialog_imported_layers_base.fbp new file mode 100644 index 0000000000..8389875b06 --- /dev/null +++ b/pcbnew/dialogs/dialog_imported_layers_base.fbp @@ -0,0 +1,773 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_imported_layers_base + 1000 + none + + 1 + dialog_imported_layers_base + + . + + 1 + 1 + 1 + 1 + UI + 1 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + 600,350 + DIALOG_IMPORTED_LAYERS_BASE + + 795,476 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Edit Mapping of Imported Layers + + + + + OnClose + OnUpdateUI + + + bSizerMain + wxVERTICAL + protected + + 5 + wxEXPAND|wxRIGHT|wxLEFT + 1 + + + bSizerTop + wxHORIZONTAL + none + + 5 + wxEXPAND|wxTOP|wxRIGHT|wxLEFT + 1 + + wxID_ANY + Unmatched Layers + + sbSizer1 + wxHORIZONTAL + 1 + none + + 5 + wxEXPAND + 1 + + + bSizerUnmatched + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Imported Layers + 0 + + 0 + + + 0 + + 1 + m_staticText1 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + 300,-1 + + 0 + + 1 + m_unmatched_layers_list + 1 + + + protected + 1 + + Resizable + 1 + 200,-1 + wxLC_NO_HEADER|wxLC_REPORT + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnUnMatchedDoubleClick + + + + + + 5 + wxEXPAND + 0 + + + bSizerKiCad + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + KiCad Layers + 0 + + 0 + -1,-1 + + 0 + + 1 + m_staticText2 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + 150,-1 + + 0 + 120,-1 + 1 + m_kicad_layers_list + 1 + + + protected + 1 + + Resizable + 1 + 120,-1 + wxLC_NO_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnUnMatchedDoubleClick + + + + + + + + 5 + wxEXPAND|wxLEFT|wxRIGHT|wxTOP + 0 + + wxID_ANY + + + sbSizer2 + wxVERTICAL + 1 + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + ,90,90,9,75,0 + 0 + 0 + wxID_ANY + > + + 0 + + 0 + + + 0 + + 1 + m_button_add + 1 + + + protected + 1 + + + + Resizable + 1 + 30,100 + + ; ; forward_declare + 0 + Add selected layers to matched layers list. + + wxFILTER_NONE + wxDefaultValidator + + + + + OnAddClicked + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + ,90,90,-1,75,0 + 0 + 0 + wxID_ANY + < + + 0 + + 0 + + + 0 + + 1 + m_button_remove + 1 + + + protected + 1 + + + + Resizable + 1 + 30,100 + + ; ; forward_declare + 0 + Remove selected layers from matched layers list. + + wxFILTER_NONE + wxDefaultValidator + + + + + OnRemoveClicked + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + ,90,90,-1,75,0 + 0 + 0 + wxID_ANY + << + + 0 + + 0 + + + 0 + + 1 + m_button_removeall + 1 + + + protected + 1 + + + + Resizable + 1 + 30,50 + + ; ; forward_declare + 0 + Remove all matched layers. + + wxFILTER_NONE + wxDefaultValidator + + + + + OnRemoveAllClicked + + + + + + 5 + wxEXPAND|wxLEFT|wxRIGHT|wxTOP + 1 + + wxID_ANY + Matched Layers + + sbSizer3 + wxHORIZONTAL + 1 + none + + 5 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + 500,-1 + + 0 + + 1 + m_matched_layers_list + 1 + + + protected + 1 + + Resizable + 1 + 300,-1 + wxLC_REPORT + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnMatchedDoubleClick + + + + + + + + 5 + wxEXPAND|wxLEFT + 0 + + + bSizerBottom + wxHORIZONTAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Auto-Match Layers + + 0 + + 0 + + + 0 + + 1 + m_button_automatch + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + Automatically match any unmatched layers to their KiCad equivalent. + + wxFILTER_NONE + wxDefaultValidator + + + + + OnAutoMatchLayersClicked + + + + 5 + wxALL|wxEXPAND + 1 + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer + protected + + + + + + + + diff --git a/pcbnew/dialogs/dialog_imported_layers_base.h b/pcbnew/dialogs/dialog_imported_layers_base.h new file mode 100644 index 0000000000..3f05afddf7 --- /dev/null +++ b/pcbnew/dialogs/dialog_imported_layers_base.h @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_IMPORTED_LAYERS_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_IMPORTED_LAYERS_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxBoxSizer* bSizerMain; + wxStaticText* m_staticText1; + wxListCtrl* m_unmatched_layers_list; + wxStaticText* m_staticText2; + wxListCtrl* m_kicad_layers_list; + wxButton* m_button_add; + wxButton* m_button_remove; + wxButton* m_button_removeall; + wxListCtrl* m_matched_layers_list; + wxButton* m_button_automatch; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } + virtual void OnUnMatchedDoubleClick( wxListEvent& event ) { event.Skip(); } + virtual void OnAddClicked( wxCommandEvent& event ) { event.Skip(); } + virtual void OnRemoveClicked( wxCommandEvent& event ) { event.Skip(); } + virtual void OnRemoveAllClicked( wxCommandEvent& event ) { event.Skip(); } + virtual void OnMatchedDoubleClick( wxListEvent& event ) { event.Skip(); } + virtual void OnAutoMatchLayersClicked( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_IMPORTED_LAYERS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Edit Mapping of Imported Layers"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 795,476 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_IMPORTED_LAYERS_BASE(); + +}; + diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 0a8cdfcb0a..562a864831 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -49,6 +49,8 @@ #include #include #include +#include +#include //#define USE_INSTRUMENTATION 1 @@ -587,6 +589,20 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); + + if( pluginType == IO_MGR::CADSTAR_PCB_ARCHIVE ) + { + // TODO: Generalise this so that it is applicable to all non-kicad plugins + CADSTAR_PCB_ARCHIVE_PLUGIN* cadstarPlugin = nullptr; + + cadstarPlugin = dynamic_cast( (PLUGIN*) pi ); + + wxCHECK( cadstarPlugin, false ); + + cadstarPlugin->RegisterLayerMappingCallback( + std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, std::placeholders::_1 ) ); + } + // This will rename the file if there is an autosave and the user want to recover CheckForAutoSaveFile( fullFileName ); diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp index 586209b802..dac6b9db36 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp @@ -82,6 +82,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::Load( ::BOARD* aBoard ) } loadBoardStackup(); + remapUnsureLayers(); loadDesignRules(); loadComponentLibrary(); loadGroups(); @@ -116,13 +117,29 @@ void CADSTAR_PCB_ARCHIVE_LOADER::Load( ::BOARD* aBoard ) } -void CADSTAR_PCB_ARCHIVE_LOADER::logBoardStackupWarning( - const wxString& aCadstarLayerName, const PCB_LAYER_ID& aKiCadLayer ) +void CADSTAR_PCB_ARCHIVE_LOADER::logBoardStackupWarning( const wxString& aCadstarLayerName, + const PCB_LAYER_ID& aKiCadLayer ) { - wxLogWarning( wxString::Format( - _( "The CADSTAR layer '%s' has no KiCad equivalent. All elements on this " - "layer have been mapped to KiCad layer '%s' instead." ), - aCadstarLayerName, LSET::Name( aKiCadLayer ) ) ); + if( mLogLayerWarnings ) + { + wxLogWarning( wxString::Format( + _( "The CADSTAR layer '%s' has no KiCad equivalent. All elements on this " + "layer have been mapped to KiCad layer '%s' instead." ), + aCadstarLayerName, LSET::Name( aKiCadLayer ) ) ); + } +} + + +void CADSTAR_PCB_ARCHIVE_LOADER::logBoardStackupMessage( const wxString& aCadstarLayerName, + const PCB_LAYER_ID& aKiCadLayer ) +{ + if( mLogLayerWarnings ) + { + wxLogMessage( wxString::Format( + _( "The CADSTAR layer '%s' has been assumed to be a technical layer. All " + "elements on this layer have been mapped to KiCad layer '%s'." ), + aCadstarLayerName, LSET::Name( aKiCadLayer ) ) ); + } } @@ -255,11 +272,46 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadBoardStackup() else kicadLayerID = PCB_LAYER_ID::F_Adhes; - wxLogMessage( wxString::Format( - _( "The CADSTAR layer '%s' has been assumed to be an adhesive layer. " - "All elements on this layer have been mapped to KiCad layer '%s'." ), - curLayer.Name, LSET::Name( kicadLayerID ) ) ); - //TODO: allow user to decide if this is actually an adhesive layer or not. + logBoardStackupMessage( curLayer.Name, kicadLayerID ); + } + else if( curLayer.Name.Lower().Contains( "silk" ) + || curLayer.Name.Lower().Contains( "legend" ) ) + { + if( numElecAndPowerLayers > 0 ) + kicadLayerID = PCB_LAYER_ID::B_SilkS; + else + kicadLayerID = PCB_LAYER_ID::F_SilkS; + + logBoardStackupMessage( curLayer.Name, kicadLayerID ); + } + else if( curLayer.Name.Lower().Contains( "assembly" ) + || curLayer.Name.Lower().Contains( "fabrication" ) ) + { + if( numElecAndPowerLayers > 0 ) + kicadLayerID = PCB_LAYER_ID::B_Fab; + else + kicadLayerID = PCB_LAYER_ID::F_Fab; + + logBoardStackupMessage( curLayer.Name, kicadLayerID ); + } + else if( curLayer.Name.Lower().Contains( "resist" ) + || curLayer.Name.Lower().Contains( "mask" ) ) + { + if( numElecAndPowerLayers > 0 ) + kicadLayerID = PCB_LAYER_ID::B_Mask; + else + kicadLayerID = PCB_LAYER_ID::F_Mask; + + logBoardStackupMessage( curLayer.Name, kicadLayerID ); + } + else if( curLayer.Name.Lower().Contains( "paste" ) ) + { + if( numElecAndPowerLayers > 0 ) + kicadLayerID = PCB_LAYER_ID::B_Paste; + else + kicadLayerID = PCB_LAYER_ID::F_Paste; + + logBoardStackupMessage( curLayer.Name, kicadLayerID ); } else { @@ -269,7 +321,6 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadBoardStackup() kicadLayerID = PCB_LAYER_ID::Eco1_User; logBoardStackupWarning( curLayer.Name, kicadLayerID ); - //TODO: allow user to decide which layer this should be mapped onto. } break; @@ -413,6 +464,58 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadBoardStackup() } +void CADSTAR_PCB_ARCHIVE_LOADER::remapUnsureLayers() +{ + LSET enabledLayers = mBoard->GetEnabledLayers(); + LSET validRemappingLayers = enabledLayers | LSET::AllBoardTechMask() | + LSET::UserMask() | LSET::UserDefinedLayers(); + + std::vector inputLayers; + std::map cadstarLayerNameMap; + + for( std::pair layerPair : mLayermap ) + { + LAYER* curLayer = &Assignments.Layerdefs.Layers.at( layerPair.first ); + + //Only remap layers that we aren't sure about + if( curLayer->Type == LAYER_TYPE::DOC + || ( curLayer->Type == LAYER_TYPE::NONELEC + && curLayer->SubType == LAYER_SUBTYPE::LAYERSUBTYPE_NONE ) ) + { + INPUT_LAYER_DESC iLdesc; + iLdesc.Name = curLayer->Name; + iLdesc.PermittedLayers = validRemappingLayers; + iLdesc.AutoMapLayer = layerPair.second; + + inputLayers.push_back( iLdesc ); + cadstarLayerNameMap.insert( { curLayer->Name, curLayer->ID } ); + } + } + + if( inputLayers.size() == 0 ) + return; + + // Callback: + LAYER_MAP reMappedLayers = mLayerMappingHandler( inputLayers ); + + for( std::pair layerPair : reMappedLayers ) + { + if( layerPair.second == PCB_LAYER_ID::UNDEFINED_LAYER ) + { + wxASSERT_MSG( false, "Unexpected Layer ID" ); + continue; + } + + LAYER_ID cadstarLayerID = cadstarLayerNameMap.at( layerPair.first ); + mLayermap.at( cadstarLayerID ) = layerPair.second; + enabledLayers |= LSET( layerPair.second ); + } + + mBoard->SetEnabledLayers( enabledLayers ); + mBoard->SetVisibleLayers( enabledLayers ); +} + + void CADSTAR_PCB_ARCHIVE_LOADER::loadDesignRules() { BOARD_DESIGN_SETTINGS& ds = mBoard->GetDesignSettings(); diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.h b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.h index 336b98ea14..4a01016a8a 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.h +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.h @@ -27,6 +27,7 @@ #define CADSTAR_PCB_ARCHIVE_LOADER_H_ #include +#include // LAYER_MAPPING_HANDLER definition #include #include @@ -35,9 +36,12 @@ class BOARD; class CADSTAR_PCB_ARCHIVE_LOADER : public CADSTAR_PCB_ARCHIVE_PARSER { public: - explicit CADSTAR_PCB_ARCHIVE_LOADER( wxString aFilename ) + explicit CADSTAR_PCB_ARCHIVE_LOADER( + wxString aFilename, LAYER_MAPPING_HANDLER aLayerMappingHandler, bool aLogLayerWarnings ) : CADSTAR_PCB_ARCHIVE_PARSER( aFilename ) { + mLayerMappingHandler = aLayerMappingHandler; + mLogLayerWarnings = aLogLayerWarnings; mBoard = nullptr; mDesignCenter.x = 0; mDesignCenter.y = 0; @@ -67,6 +71,8 @@ public: private: + LAYER_MAPPING_HANDLER mLayerMappingHandler; ///< Callback to get layer mapping + bool mLogLayerWarnings; ///< Used in loadBoardStackup() ::BOARD* mBoard; std::map mLayermap; ///< Map between Cadstar and KiCad Layers. ///< Populated by loadBoardStackup(). @@ -105,6 +111,7 @@ private: // Functions for loading individual elements: void loadBoardStackup(); + void remapUnsureLayers(); ///< Callback mLayerMappingHandler for layers we aren't sure of void loadDesignRules(); void loadComponentLibrary(); void loadGroups(); @@ -120,8 +127,10 @@ private: void loadNets(); // Helper functions for element loading: - void logBoardStackupWarning( - const wxString& aCadstarLayerName, const PCB_LAYER_ID& aKiCadLayer ); + void logBoardStackupWarning( const wxString& aCadstarLayerName, + const PCB_LAYER_ID& aKiCadLayer ); + void logBoardStackupMessage( const wxString& aCadstarLayerName, + const PCB_LAYER_ID& aKiCadLayer ); void loadLibraryFigures( const SYMDEF_PCB& aComponent, MODULE* aModule ); void loadLibraryCoppers( const SYMDEF_PCB& aComponent, MODULE* aModule ); void loadLibraryAreas( const SYMDEF_PCB& aComponent, MODULE* aModule ); diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.cpp index 572c3cc02c..fcd6dce4c3 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.cpp +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.cpp @@ -30,10 +30,35 @@ #include +LAYER_MAP CADSTAR_PCB_ARCHIVE_PLUGIN::DefaultLayerMappingCallback( + const std::vector& aInputLayerDescriptionVector ) +{ + LAYER_MAP retval; + + // Just return a the auto-mapped layers + for( INPUT_LAYER_DESC layerDesc : aInputLayerDescriptionVector ) + { + retval.insert( { layerDesc.Name, layerDesc.AutoMapLayer } ); + } + + return retval; +} + + +void CADSTAR_PCB_ARCHIVE_PLUGIN::RegisterLayerMappingCallback( + LAYER_MAPPING_HANDLER aLayerMappingHandler ) +{ + m_layer_mapping_handler = aLayerMappingHandler; + m_show_layer_mapping_warnings = false; // only show warnings with default callback +} + + CADSTAR_PCB_ARCHIVE_PLUGIN::CADSTAR_PCB_ARCHIVE_PLUGIN() { - m_board = nullptr; - m_props = nullptr; + m_board = nullptr; + m_props = nullptr; + m_layer_mapping_handler = CADSTAR_PCB_ARCHIVE_PLUGIN::DefaultLayerMappingCallback; + m_show_layer_mapping_warnings = true; } @@ -60,7 +85,8 @@ BOARD* CADSTAR_PCB_ARCHIVE_PLUGIN::Load( m_props = aProperties; m_board = aAppendToMe ? aAppendToMe : new BOARD(); - CADSTAR_PCB_ARCHIVE_LOADER tempPCB( aFileName ); + CADSTAR_PCB_ARCHIVE_LOADER tempPCB( + aFileName, m_layer_mapping_handler, m_show_layer_mapping_warnings ); tempPCB.Load( m_board ); //center the board: diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.h b/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.h index 8a69ea64bb..20a9ad11c8 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.h +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_plugin.h @@ -29,6 +29,44 @@ #include +#include // PCB_LAYER_ID + + +/** + * @brief Describes an imported layer and how it could be mapped to KiCad Layers + */ +struct INPUT_LAYER_DESC +{ + wxString Name; ///< Imported layer name as displayed in original application. + LSET PermittedLayers; ///< KiCad layers that the imported layer can be mapped onto. + PCB_LAYER_ID AutoMapLayer; ///< Best guess as to what the equivalent KiCad layer might be. + + INPUT_LAYER_DESC() + { + Name = wxEmptyString; + PermittedLayers = LSET(); + AutoMapLayer = PCB_LAYER_ID::UNDEFINED_LAYER; + } +}; + +/** + * A CADSTAR layer name. + */ +typedef wxString INPUT_LAYER_NAME; + +/** + * @brief Map of CADSTAR (INPUT_LAYER_NAME) to KiCad Layers. + * If the mapped KiCad layer is UNDEFINED_LAYER, then the CADSTAR layer will not + * be imported + */ +typedef std::map LAYER_MAP; + +/** + * @brief Pointer to a function that takes a map of Cadstar and KiCad layers + * and returns a re-mapped version. If the re-mapped layer + */ +typedef std::function& )> LAYER_MAPPING_HANDLER; + class CADSTAR_PCB_ARCHIVE_PLUGIN : public PLUGIN { @@ -50,12 +88,29 @@ public: // ------------------------------------------------------ + /** + * @brief Default callback - just returns the automapped layers + * @param aInputLayerDescriptionVector + * @return Auto-mapped layers + */ + static LAYER_MAP DefaultLayerMappingCallback( + const std::vector& aInputLayerDescriptionVector ); + + /** + * @brief Register a different handler to be called when mapping of Cadstar to KiCad + * layers occurs + * @param aLayerMappingHandler + */ + void RegisterLayerMappingCallback( LAYER_MAPPING_HANDLER aLayerMappingHandler ); + CADSTAR_PCB_ARCHIVE_PLUGIN(); ~CADSTAR_PCB_ARCHIVE_PLUGIN(); private: - const PROPERTIES* m_props; - BOARD* m_board; + const PROPERTIES* m_props; + BOARD* m_board; + LAYER_MAPPING_HANDLER m_layer_mapping_handler; + bool m_show_layer_mapping_warnings; }; #endif // CADSTAR_ARCHIVE_PLUGIN_H_