kicad/pcbnew/dialogs/dialog_imported_layers.cpp

296 lines
9.7 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
* 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 <http://www.gnu.org/licenses/>.
*/
#include <layers_id_colors_and_visibility.h>
#include <dialog_imported_layers.h>
#include <wx/msgdlg.h>
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 );
// Auto select the first item to improve ease-of-use
m_unmatched_layers_list->SetItemState( 0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
}
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<INPUT_LAYER_DESC>& 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;
}
int maxTextWidth = 0;
for( const INPUT_LAYER_DESC& layer : m_input_layers )
maxTextWidth = std::max( maxTextWidth, GetTextExtent( layer.Name ).x );
// Initialize columns in the wxListCtrl elements:
wxListItem importedLayersHeader;
importedLayersHeader.SetId( 0 );
importedLayersHeader.SetText( _( "Imported Layer" ) );
importedLayersHeader.SetWidth( maxTextWidth + 15 );
m_unmatched_layers_list->InsertColumn( 0, importedLayersHeader );
int kicadMaxTextWidth = GetTextExtent( wxT( "User.Drawings" ) ).x;
wxListItem kicadLayersHeader;
kicadLayersHeader.SetId( 0 );
kicadLayersHeader.SetText( _( "KiCad Layer" ) );
kicadLayersHeader.SetWidth( kicadMaxTextWidth + 5 );
m_kicad_layers_list->InsertColumn( 0, kicadLayersHeader );
kicadLayersHeader.SetId( 1 );
importedLayersHeader.SetWidth( maxTextWidth + 15 );
kicadLayersHeader.SetWidth( kicadMaxTextWidth + 5 );
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;
}
// Auto select the first item to improve ease-of-use
m_unmatched_layers_list->SetItemState( 0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
// 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;
}
// Auto select the first item to improve ease-of-use
m_kicad_layers_list->SetItemState( 0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
m_sdbSizerOK->SetDefault();
Fit();
FinishDialogSettings();
}
LAYER_MAP DIALOG_IMPORTED_LAYERS::GetMapModal( wxWindow* aParent,
const std::vector<INPUT_LAYER_DESC>& 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;
}