Add a layer pair preset list
This will later be used for a quick switcher UI. This commit adds the data structures, set-up UI and project file persistance. Relates-To: https://gitlab.com/kicad/code/kicad/-/issues/15227
This commit is contained in:
+464
-150
@@ -22,26 +22,36 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
|
||||
#include <kiplatform/ui.h>
|
||||
#include <confirm.h>
|
||||
#include <lset.h>
|
||||
#include <board.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <pcb_layer_presentation.h>
|
||||
#include <footprint_editor_settings.h>
|
||||
#include <layer_pairs.h>
|
||||
#include <dialogs/dialog_layer_selection_base.h>
|
||||
#include <project/project_file.h>
|
||||
#include <router/router_tool.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <widgets/grid_icon_text_helpers.h>
|
||||
#include <widgets/grid_text_helpers.h>
|
||||
#include <widgets/layer_box_selector.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
#include <widgets/wx_grid_autosizer.h>
|
||||
|
||||
|
||||
// Column position by function:
|
||||
#define SELECT_COLNUM 0
|
||||
#define COLOR_COLNUM 1
|
||||
#define LAYERNAME_COLNUM 2
|
||||
#define LAYER_HK_COLUMN 3
|
||||
#define SELECT_COLNUM 0
|
||||
#define COLOR_COLNUM 1
|
||||
#define LAYERNAME_COLNUM 2
|
||||
#define LAYER_HK_COLUMN 3
|
||||
|
||||
|
||||
PCB_LAYER_PRESENTATION::PCB_LAYER_PRESENTATION( PCB_BASE_FRAME* aFrame ) : m_boardFrame( aFrame )
|
||||
@@ -72,6 +82,11 @@ wxString PCB_LAYER_PRESENTATION::getLayerName( int aLayer ) const
|
||||
return BOARD::GetStandardLayerName( ToLAYER_ID( aLayer ) );
|
||||
}
|
||||
|
||||
LSEQ PCB_LAYER_PRESENTATION::getOrderedEnabledLayers() const
|
||||
{
|
||||
return m_boardFrame->GetBoard()->GetEnabledLayers().UIOrder();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display a PCB layers list in a dialog to select one layer from this list.
|
||||
@@ -79,11 +94,11 @@ wxString PCB_LAYER_PRESENTATION::getLayerName( int aLayer ) const
|
||||
class PCB_ONE_LAYER_SELECTOR : public DIALOG_LAYER_SELECTION_BASE
|
||||
{
|
||||
public:
|
||||
PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD * aBrd, PCB_LAYER_ID aDefaultLayer,
|
||||
PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, PCB_LAYER_ID aDefaultLayer,
|
||||
LSET aNotAllowedLayersMask, bool aHideCheckBoxes = false );
|
||||
~PCB_ONE_LAYER_SELECTOR();
|
||||
|
||||
int GetLayerSelection() { return m_layerSelected; }
|
||||
int GetLayerSelection() { return m_layerSelected; }
|
||||
|
||||
private:
|
||||
// Event handlers
|
||||
@@ -111,8 +126,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
PCB_ONE_LAYER_SELECTOR::PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD* aBrd,
|
||||
PCB_LAYER_ID aDefaultLayer,
|
||||
PCB_ONE_LAYER_SELECTOR::PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, PCB_LAYER_ID aDefaultLayer,
|
||||
LSET aNotAllowedLayersMask, bool aHideCheckBoxes ) :
|
||||
DIALOG_LAYER_SELECTION_BASE( aParent ), m_layerPresentation( aParent )
|
||||
{
|
||||
@@ -120,7 +134,6 @@ PCB_ONE_LAYER_SELECTOR::PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD*
|
||||
|
||||
m_layerSelected = aDefaultLayer;
|
||||
m_notAllowedLayersMask = aNotAllowedLayersMask;
|
||||
m_brd = aBrd;
|
||||
|
||||
m_leftGridLayers->SetCellHighlightPenWidth( 0 );
|
||||
m_rightGridLayers->SetCellHighlightPenWidth( 0 );
|
||||
@@ -167,7 +180,7 @@ void PCB_ONE_LAYER_SELECTOR::OnMouseMove( wxUpdateUIEvent& aEvent )
|
||||
|
||||
if( row != wxNOT_FOUND && row < static_cast<int>( m_layersIdLeftColumn.size() ) )
|
||||
{
|
||||
m_layerSelected = m_layersIdLeftColumn[ row ];
|
||||
m_layerSelected = m_layersIdLeftColumn[row];
|
||||
m_leftGridLayers->SelectBlock( row, LAYERNAME_COLNUM, row, LAYER_HK_COLUMN );
|
||||
return;
|
||||
}
|
||||
@@ -180,8 +193,8 @@ void PCB_ONE_LAYER_SELECTOR::OnMouseMove( wxUpdateUIEvent& aEvent )
|
||||
if( row == wxNOT_FOUND || row >= static_cast<int>( m_layersIdRightColumn.size() ) )
|
||||
return;
|
||||
|
||||
m_layerSelected = m_layersIdRightColumn[ row ];
|
||||
m_rightGridLayers->SelectBlock( row, LAYERNAME_COLNUM, row, LAYERNAME_COLNUM);
|
||||
m_layerSelected = m_layersIdRightColumn[row];
|
||||
m_rightGridLayers->SelectBlock( row, LAYERNAME_COLNUM, row, LAYERNAME_COLNUM );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +213,7 @@ void PCB_ONE_LAYER_SELECTOR::buildList()
|
||||
int right_row = 0;
|
||||
wxString layername;
|
||||
|
||||
for( PCB_LAYER_ID layerid : m_brd->GetEnabledLayers().UIOrder() )
|
||||
for( PCB_LAYER_ID layerid : m_layerPresentation.getOrderedEnabledLayers() )
|
||||
{
|
||||
if( m_notAllowedLayersMask[layerid] )
|
||||
continue;
|
||||
@@ -217,7 +230,7 @@ void PCB_ONE_LAYER_SELECTOR::buildList()
|
||||
if( left_row )
|
||||
m_leftGridLayers->AppendRows( 1 );
|
||||
|
||||
m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
|
||||
m_leftGridLayers->SetCellBackgroundColour( left_row, COLOR_COLNUM, color );
|
||||
m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
|
||||
m_leftGridLayers->SetCellValue( left_row, LAYER_HK_COLUMN, getLayerHotKey( layerid ) );
|
||||
|
||||
@@ -258,7 +271,7 @@ void PCB_ONE_LAYER_SELECTOR::buildList()
|
||||
|
||||
void PCB_ONE_LAYER_SELECTOR::OnLeftGridCellClick( wxGridEvent& event )
|
||||
{
|
||||
m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
|
||||
m_layerSelected = m_layersIdLeftColumn[event.GetRow()];
|
||||
|
||||
if( IsQuasiModal() )
|
||||
EndQuasiModal( 1 );
|
||||
@@ -269,7 +282,7 @@ void PCB_ONE_LAYER_SELECTOR::OnLeftGridCellClick( wxGridEvent& event )
|
||||
|
||||
void PCB_ONE_LAYER_SELECTOR::OnRightGridCellClick( wxGridEvent& event )
|
||||
{
|
||||
m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
|
||||
m_layerSelected = m_layersIdRightColumn[event.GetRow()];
|
||||
|
||||
if( IsQuasiModal() )
|
||||
EndQuasiModal( 2 );
|
||||
@@ -281,13 +294,13 @@ void PCB_ONE_LAYER_SELECTOR::OnRightGridCellClick( wxGridEvent& event )
|
||||
PCB_LAYER_ID PCB_BASE_FRAME::SelectOneLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
|
||||
wxPoint aDlgPosition )
|
||||
{
|
||||
PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask, true );
|
||||
PCB_ONE_LAYER_SELECTOR dlg( this, aDefaultLayer, aNotAllowedLayersMask, true );
|
||||
|
||||
if( aDlgPosition != wxDefaultPosition )
|
||||
{
|
||||
wxSize dlgSize = dlg.GetSize();
|
||||
aDlgPosition.x -= dlgSize.x/2;
|
||||
aDlgPosition.y -= dlgSize.y/2;
|
||||
aDlgPosition.x -= dlgSize.x / 2;
|
||||
aDlgPosition.y -= dlgSize.y / 2;
|
||||
dlg.SetPosition( aDlgPosition );
|
||||
}
|
||||
|
||||
@@ -298,162 +311,463 @@ PCB_LAYER_ID PCB_BASE_FRAME::SelectOneLayer( PCB_LAYER_ID aDefaultLayer, LSET aN
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class that manages the UI for the copper layer pair presets list
|
||||
* based on an injected layer pair store.
|
||||
*/
|
||||
class COPPER_LAYERS_PAIR_PRESETS_UI
|
||||
{
|
||||
enum class COLNUMS
|
||||
{
|
||||
ENABLED,
|
||||
SWATCH,
|
||||
LAYERNAMES,
|
||||
USERNAME,
|
||||
};
|
||||
|
||||
public:
|
||||
COPPER_LAYERS_PAIR_PRESETS_UI( WX_GRID& aGrid, PCB_LAYER_PRESENTATION& aPresentation,
|
||||
LAYER_PAIR_SETTINGS& aLayerPairSettings ) :
|
||||
m_layerPresentation( aPresentation ), m_grid( aGrid ),
|
||||
m_layerPairSettings( aLayerPairSettings )
|
||||
{
|
||||
wxASSERT_MSG( m_grid.GetNumberRows() == 0, "Grid should be empty at controller start" );
|
||||
|
||||
configureGrid();
|
||||
fillGridFromStore();
|
||||
|
||||
m_grid.Bind( wxEVT_GRID_CELL_CHANGED,
|
||||
[this]( wxGridEvent& aEvent )
|
||||
{
|
||||
const int col = aEvent.GetCol();
|
||||
const int row = aEvent.GetRow();
|
||||
if( col == (int) COLNUMS::USERNAME )
|
||||
{
|
||||
onUserNameChanged( row, m_grid.GetCellValue( row, col ) );
|
||||
}
|
||||
else if( col == (int) COLNUMS::ENABLED )
|
||||
{
|
||||
onEnableChanged( row, m_grid.GetCellValue( row, col ) == wxS( "1" ) );
|
||||
}
|
||||
} );
|
||||
|
||||
m_grid.Bind( wxEVT_GRID_CELL_LEFT_DCLICK,
|
||||
[&]( wxGridEvent& aEvent )
|
||||
{
|
||||
const int row = aEvent.GetRow();
|
||||
const int col = aEvent.GetCol();
|
||||
|
||||
if( col == (int) COLNUMS::LAYERNAMES || col == (int) COLNUMS::SWATCH )
|
||||
{
|
||||
onPairActivated( row );
|
||||
}
|
||||
} );
|
||||
|
||||
m_autosizer =
|
||||
std::make_unique<WX_GRID_AUTOSIZER>( m_grid,
|
||||
WX_GRID_AUTOSIZER::COL_MIN_WIDTHS{
|
||||
{ (int) COLNUMS::LAYERNAMES, 72 },
|
||||
{ (int) COLNUMS::USERNAME, 72 },
|
||||
},
|
||||
(int) COLNUMS::USERNAME );
|
||||
}
|
||||
|
||||
void OnLayerPairAdded( const LAYER_PAIR& aLayerPair )
|
||||
{
|
||||
LAYER_PAIR_INFO layerPairInfo{ aLayerPair, true, std::nullopt };
|
||||
|
||||
const bool added = m_layerPairSettings.AddLayerPair( std::move( layerPairInfo ) );
|
||||
|
||||
if( added )
|
||||
{
|
||||
m_grid.AppendRows( 1 );
|
||||
fillRowFromLayerPair( m_grid.GetNumberRows() - 1, layerPairInfo );
|
||||
}
|
||||
}
|
||||
|
||||
void OnDeleteSelectedLayerPairs()
|
||||
{
|
||||
int row = m_grid.GetGridCursorRow();
|
||||
|
||||
const LAYER_PAIR_INFO& layerPairInfo = m_layerPairSettings.GetLayerPairs()[row];
|
||||
const bool removed = m_layerPairSettings.RemoveLayerPair( layerPairInfo.GetLayerPair() );
|
||||
|
||||
if( removed )
|
||||
{
|
||||
m_grid.DeleteRows( row );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void configureGrid()
|
||||
{
|
||||
m_grid.UseNativeColHeader( true );
|
||||
|
||||
m_grid.SetCellHighlightPenWidth( 0 );
|
||||
m_grid.SetColFormatBool( (int) COLNUMS::ENABLED );
|
||||
|
||||
m_grid.SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
|
||||
|
||||
m_grid.AutoSizeColumn( (int) COLNUMS::USERNAME );
|
||||
}
|
||||
|
||||
void fillGridFromStore()
|
||||
{
|
||||
std::span<const LAYER_PAIR_INFO> storePairs = m_layerPairSettings.GetLayerPairs();
|
||||
|
||||
m_grid.AppendRows( storePairs.size() );
|
||||
|
||||
int row = 0;
|
||||
for( const LAYER_PAIR_INFO& layerPairInfo : storePairs )
|
||||
{
|
||||
fillRowFromLayerPair( row, layerPairInfo );
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
wxString constructLayerPairLabel( const LAYER_PAIR& aLayerPair )
|
||||
{
|
||||
const wxString layerAName = m_layerPresentation.getLayerName( aLayerPair.GetLayerA() );
|
||||
const wxString layerBName = m_layerPresentation.getLayerName( aLayerPair.GetLayerB() );
|
||||
return layerAName + wxT( " / " ) + layerBName;
|
||||
}
|
||||
|
||||
void fillRowFromLayerPair( int aRow, const LAYER_PAIR_INFO& aLayerPairInfo )
|
||||
{
|
||||
wxASSERT_MSG( aRow < m_grid.GetNumberRows(), "Row index out of bounds" );
|
||||
|
||||
const LAYER_PAIR& layerPair = aLayerPairInfo.GetLayerPair();
|
||||
|
||||
const wxString layerNames = constructLayerPairLabel( layerPair );
|
||||
|
||||
m_grid.SetCellValue( aRow, (int) COLNUMS::LAYERNAMES, layerNames );
|
||||
|
||||
const std::optional<wxString> userName = aLayerPairInfo.GetName();
|
||||
if( userName )
|
||||
{
|
||||
m_grid.SetCellValue( aRow, (int) COLNUMS::USERNAME, *userName );
|
||||
}
|
||||
|
||||
m_grid.SetCellValue( aRow, (int) COLNUMS::ENABLED,
|
||||
aLayerPairInfo.IsEnabled() ? wxT( "1" ) : wxT( "0" ) );
|
||||
|
||||
// Set the color swatch
|
||||
std::unique_ptr<wxBitmap>& swatch = m_swatches.emplace_back(
|
||||
m_layerPresentation.CreateLayerPairIcon( layerPair, KiIconScale( &m_grid ) ) );
|
||||
|
||||
m_grid.SetCellRenderer( aRow, (int) COLNUMS::SWATCH,
|
||||
new GRID_CELL_ICON_RENDERER( *swatch ) );
|
||||
|
||||
m_grid.SetReadOnly( aRow, (int) COLNUMS::SWATCH );
|
||||
m_grid.SetReadOnly( aRow, (int) COLNUMS::LAYERNAMES );
|
||||
}
|
||||
|
||||
void onUserNameChanged( int aRow, const wxString& aNewValue )
|
||||
{
|
||||
LAYER_PAIR_INFO& changedPair = m_layerPairSettings.GetLayerPairs()[aRow];
|
||||
changedPair.SetName( aNewValue );
|
||||
}
|
||||
|
||||
void onEnableChanged( int aRow, bool aNewValue )
|
||||
{
|
||||
LAYER_PAIR_INFO& changedPair = m_layerPairSettings.GetLayerPairs()[aRow];
|
||||
changedPair.SetEnabled( aNewValue );
|
||||
}
|
||||
|
||||
void onPairActivated( int aRow )
|
||||
{
|
||||
const LAYER_PAIR_INFO& layerPairInfo = m_layerPairSettings.GetLayerPairs()[aRow];
|
||||
const LAYER_PAIR& layerPair = layerPairInfo.GetLayerPair();
|
||||
|
||||
m_layerPairSettings.SetCurrentLayerPair( layerPair );
|
||||
}
|
||||
|
||||
LAYER_PRESENTATION& m_layerPresentation;
|
||||
WX_GRID& m_grid;
|
||||
LAYER_PAIR_SETTINGS& m_layerPairSettings;
|
||||
|
||||
// Lifetime managment of the swatches
|
||||
std::vector<std::unique_ptr<wxBitmap>> m_swatches;
|
||||
|
||||
std::unique_ptr<WX_GRID_AUTOSIZER> m_autosizer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class that manages the UI for the copper layer pair selection
|
||||
* (left and right grids).
|
||||
*/
|
||||
class COPPER_LAYERS_PAIR_SELECTION_UI
|
||||
{
|
||||
enum class CU_LAYER_COLNUMS
|
||||
{
|
||||
SELECT = 0,
|
||||
COLOR = 1,
|
||||
LAYERNAME = 2,
|
||||
};
|
||||
|
||||
public:
|
||||
COPPER_LAYERS_PAIR_SELECTION_UI( wxGrid& aLeftGrid, wxGrid& aRightGrid,
|
||||
PCB_LAYER_PRESENTATION& aPresentation,
|
||||
LAYER_PAIR_SETTINGS& aLayerPairSettings ) :
|
||||
m_layerPresentation( aPresentation ), m_layerPairSettings( aLayerPairSettings ),
|
||||
m_leftGrid( aLeftGrid ), m_rightGrid( aRightGrid )
|
||||
{
|
||||
configureGrid( m_leftGrid );
|
||||
configureGrid( m_rightGrid );
|
||||
|
||||
for( const PCB_LAYER_ID& layerId : m_layerPresentation.getOrderedEnabledLayers() )
|
||||
{
|
||||
if( IsCopperLayer( layerId ) )
|
||||
{
|
||||
m_layersId.push_back( layerId );
|
||||
}
|
||||
}
|
||||
|
||||
fillLayerGrid( m_leftGrid );
|
||||
fillLayerGrid( m_rightGrid );
|
||||
|
||||
m_leftGrid.Bind( wxEVT_GRID_CELL_LEFT_CLICK,
|
||||
[this]( wxGridEvent& aEvent )
|
||||
{
|
||||
onLeftGridRowSelected( aEvent.GetRow() );
|
||||
} );
|
||||
|
||||
m_rightGrid.Bind( wxEVT_GRID_CELL_LEFT_CLICK,
|
||||
[this]( wxGridEvent& aEvent )
|
||||
{
|
||||
onRightGridRowSelected( aEvent.GetRow() );
|
||||
} );
|
||||
|
||||
m_layerPairSettings.Bind( PCB_CURRENT_LAYER_PAIR_CHANGED,
|
||||
[this]( wxCommandEvent& aEvent )
|
||||
{
|
||||
const LAYER_PAIR& newPair =
|
||||
m_layerPairSettings.GetCurrentLayerPair();
|
||||
setCurrentSelection( rowForLayer( newPair.GetLayerA() ),
|
||||
rowForLayer( newPair.GetLayerB() ) );
|
||||
} );
|
||||
}
|
||||
|
||||
private:
|
||||
void configureGrid( wxGrid& aGrid )
|
||||
{
|
||||
aGrid.SetCellHighlightPenWidth( 0 );
|
||||
aGrid.SetColFormatBool( (int) CU_LAYER_COLNUMS::SELECT );
|
||||
}
|
||||
|
||||
void fillLayerGrid( wxGrid& aGrid )
|
||||
{
|
||||
const wxColour bg = m_layerPresentation.getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
|
||||
|
||||
aGrid.AppendRows( m_layersId.size() - 1 );
|
||||
|
||||
int row = 0;
|
||||
for( const PCB_LAYER_ID& layerId : m_layersId )
|
||||
{
|
||||
const wxColour fg = m_layerPresentation.getLayerColor( layerId ).ToColour();
|
||||
const wxColour color(
|
||||
wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
|
||||
wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
|
||||
wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
|
||||
|
||||
const wxString layerName = wxT( " " ) + m_layerPresentation.getLayerName( layerId );
|
||||
|
||||
aGrid.SetCellBackgroundColour( row, (int) CU_LAYER_COLNUMS::COLOR, color );
|
||||
aGrid.SetCellValue( row, (int) CU_LAYER_COLNUMS::LAYERNAME, layerName );
|
||||
|
||||
row++;
|
||||
};
|
||||
|
||||
// Now fix min grid layer name column size (it also sets a minimal size)
|
||||
aGrid.AutoSizeColumn( (int) CU_LAYER_COLNUMS::LAYERNAME );
|
||||
}
|
||||
|
||||
PCB_LAYER_ID layerForRow( int aRow ) { return m_layersId.at( aRow ); }
|
||||
|
||||
int rowForLayer( PCB_LAYER_ID aLayerId )
|
||||
{
|
||||
for( unsigned i = 0; i < m_layersId.size(); ++i )
|
||||
{
|
||||
if( m_layersId[i] == aLayerId )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
wxASSERT_MSG( false, wxString::Format( "Unknown layer in grid: %d", aLayerId ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void onLeftGridRowSelected( int aRow )
|
||||
{
|
||||
LAYER_PAIR newPair{
|
||||
layerForRow( aRow ),
|
||||
layerForRow( m_rightCurrRow ),
|
||||
};
|
||||
setCurrentSelection( aRow, m_rightCurrRow );
|
||||
m_layerPairSettings.SetCurrentLayerPair( newPair );
|
||||
}
|
||||
|
||||
void onRightGridRowSelected( int aRow )
|
||||
{
|
||||
LAYER_PAIR newPair{
|
||||
layerForRow( m_leftCurrRow ),
|
||||
layerForRow( aRow ),
|
||||
};
|
||||
setCurrentSelection( m_leftCurrRow, aRow );
|
||||
m_layerPairSettings.SetCurrentLayerPair( newPair );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current layer selection.
|
||||
*
|
||||
* The layer pair must be copper layers that the selector this class
|
||||
* was constructed with knows about.
|
||||
*/
|
||||
void setCurrentSelection( int aLeftRow, int aRightRow )
|
||||
{
|
||||
const auto selectGridRow = [this]( wxGrid& aGrid, int aRow, bool aSelect )
|
||||
{
|
||||
// At start, there is no old row
|
||||
if( aRow < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
const wxString val = aSelect ? wxT( "1" ) : wxEmptyString;
|
||||
aGrid.SetCellValue( aRow, (int) CU_LAYER_COLNUMS::SELECT, val );
|
||||
aGrid.SetGridCursor( aRow, (int) CU_LAYER_COLNUMS::COLOR );
|
||||
};
|
||||
|
||||
if( m_leftCurrRow != aLeftRow )
|
||||
{
|
||||
selectGridRow( m_leftGrid, m_leftCurrRow, false );
|
||||
selectGridRow( m_leftGrid, aLeftRow, true );
|
||||
m_leftCurrRow = aLeftRow;
|
||||
}
|
||||
|
||||
if( m_rightCurrRow != aRightRow )
|
||||
{
|
||||
selectGridRow( m_rightGrid, m_rightCurrRow, false );
|
||||
selectGridRow( m_rightGrid, aRightRow, true );
|
||||
m_rightCurrRow = aRightRow;
|
||||
}
|
||||
}
|
||||
|
||||
PCB_LAYER_PRESENTATION& m_layerPresentation;
|
||||
LAYER_PAIR_SETTINGS& m_layerPairSettings;
|
||||
std::vector<PCB_LAYER_ID> m_layersId;
|
||||
wxGrid& m_leftGrid;
|
||||
wxGrid& m_rightGrid;
|
||||
|
||||
int m_leftCurrRow = -1;
|
||||
int m_rightCurrRow = -1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Display a pair PCB copper layers list in a dialog to select a layer pair from these lists.
|
||||
*
|
||||
* This is a higher level class that mostly glues together other controller classes and UI
|
||||
* elements.
|
||||
*/
|
||||
class SELECT_COPPER_LAYERS_PAIR_DIALOG : public DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE
|
||||
{
|
||||
public:
|
||||
SELECT_COPPER_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME* aParent, BOARD* aPcb,
|
||||
PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
|
||||
|
||||
void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
|
||||
SELECT_COPPER_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME& aParent,
|
||||
LAYER_PAIR_SETTINGS& aBoardSettings ) :
|
||||
DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( &aParent ),
|
||||
m_boardPairSettings( aBoardSettings ), m_dialogPairSettings( aBoardSettings ),
|
||||
m_layerPresentation( &aParent ),
|
||||
m_pairSelectionController( *m_leftGridLayers, *m_rightGridLayers, m_layerPresentation,
|
||||
m_dialogPairSettings ),
|
||||
m_presetsGridController( *m_presetsGrid, m_layerPresentation, m_dialogPairSettings )
|
||||
{
|
||||
aFrontLayer = m_frontLayer;
|
||||
aBackLayer = m_backLayer;
|
||||
m_addToPresetsButton->SetBitmap( KiBitmapBundle( BITMAPS::right ) );
|
||||
m_deleteRowButton->SetBitmap( KiBitmapBundle( BITMAPS::trash ) );
|
||||
|
||||
m_addToPresetsButton->Bind( wxEVT_BUTTON,
|
||||
[this]( wxCommandEvent& aEvent )
|
||||
{
|
||||
const LAYER_PAIR newPair =
|
||||
m_dialogPairSettings.GetCurrentLayerPair();
|
||||
m_presetsGridController.OnLayerPairAdded( newPair );
|
||||
} );
|
||||
|
||||
m_deleteRowButton->Bind( wxEVT_BUTTON,
|
||||
[this]( wxCommandEvent& aEvent )
|
||||
{
|
||||
m_presetsGridController.OnDeleteSelectedLayerPairs();
|
||||
} );
|
||||
|
||||
SetFocus();
|
||||
|
||||
GetSizer()->SetSizeHints( this );
|
||||
Center();
|
||||
}
|
||||
|
||||
bool TransferDataToWindow() override
|
||||
{
|
||||
m_presetsGrid->Freeze();
|
||||
m_leftGridLayers->Freeze();
|
||||
m_rightGridLayers->Freeze();
|
||||
|
||||
m_dialogPairSettings.SetCurrentLayerPair( m_boardPairSettings.GetCurrentLayerPair() );
|
||||
|
||||
m_rightGridLayers->Thaw();
|
||||
m_leftGridLayers->Thaw();
|
||||
m_presetsGrid->Thaw();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransferDataFromWindow() override
|
||||
{
|
||||
// Pull out the dialog's stored pairs
|
||||
std::span<const LAYER_PAIR_INFO> storePairs = m_dialogPairSettings.GetLayerPairs();
|
||||
|
||||
m_boardPairSettings.SetLayerPairs( storePairs );
|
||||
m_boardPairSettings.SetCurrentLayerPair( m_dialogPairSettings.GetCurrentLayerPair() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void OnLeftGridCellClick( wxGridEvent& event ) override;
|
||||
void OnRightGridCellClick( wxGridEvent& event ) override;
|
||||
|
||||
void buildList();
|
||||
|
||||
// The BOARD's pair store to be updated
|
||||
LAYER_PAIR_SETTINGS& m_boardPairSettings;
|
||||
// A local copy while we modify it
|
||||
LAYER_PAIR_SETTINGS m_dialogPairSettings;
|
||||
// Information about the layer presentation (colors, etc)
|
||||
PCB_LAYER_PRESENTATION m_layerPresentation;
|
||||
BOARD* m_brd;
|
||||
PCB_LAYER_ID m_frontLayer;
|
||||
PCB_LAYER_ID m_backLayer;
|
||||
int m_leftRowSelected;
|
||||
int m_rightRowSelected;
|
||||
|
||||
std::vector<PCB_LAYER_ID> m_layersId;
|
||||
// UI controllers
|
||||
COPPER_LAYERS_PAIR_SELECTION_UI m_pairSelectionController;
|
||||
COPPER_LAYERS_PAIR_PRESETS_UI m_presetsGridController;
|
||||
};
|
||||
|
||||
|
||||
int ROUTER_TOOL::SelectCopperLayerPair( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCB_SCREEN* screen = frame()->GetScreen();
|
||||
LAYER_PAIR_SETTINGS* const boardSettings = frame()->GetLayerPairSettings();
|
||||
|
||||
SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( frame(), frame()->GetBoard(), screen->m_Route_Layer_TOP,
|
||||
screen->m_Route_Layer_BOTTOM );
|
||||
if( !boardSettings )
|
||||
{
|
||||
// Should only be used for suitable frame types with layer pairs
|
||||
wxASSERT_MSG( false, "Could not access layer pair settings" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( *frame(), *boardSettings );
|
||||
|
||||
if( dlg.ShowModal() == wxID_OK )
|
||||
{
|
||||
dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
|
||||
const LAYER_PAIR layerPair = boardSettings->GetCurrentLayerPair();
|
||||
|
||||
// select the same layer for both layers is allowed (normal in some boards)
|
||||
// but could be a mistake. So display an info message
|
||||
if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
|
||||
if( layerPair.GetLayerA() == layerPair.GetLayerB() )
|
||||
{
|
||||
DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SELECT_COPPER_LAYERS_PAIR_DIALOG::SELECT_COPPER_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME* aParent,
|
||||
BOARD* aPcb,
|
||||
PCB_LAYER_ID aFrontLayer,
|
||||
PCB_LAYER_ID aBackLayer ) :
|
||||
DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( aParent ), m_layerPresentation( aParent )
|
||||
{
|
||||
m_frontLayer = aFrontLayer;
|
||||
m_backLayer = aBackLayer;
|
||||
m_leftRowSelected = 0;
|
||||
m_rightRowSelected = 0;
|
||||
m_brd = aPcb;
|
||||
|
||||
m_leftGridLayers->SetCellHighlightPenWidth( 0 );
|
||||
m_rightGridLayers->SetCellHighlightPenWidth( 0 );
|
||||
m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
|
||||
m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
|
||||
buildList();
|
||||
|
||||
SetFocus();
|
||||
|
||||
GetSizer()->SetSizeHints( this );
|
||||
Center();
|
||||
}
|
||||
|
||||
|
||||
void SELECT_COPPER_LAYERS_PAIR_DIALOG::buildList()
|
||||
{
|
||||
wxColour bg = m_layerPresentation.getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
|
||||
int row = 0;
|
||||
wxString layername;
|
||||
|
||||
for( PCB_LAYER_ID layerid : m_brd->GetEnabledLayers().UIOrder() )
|
||||
{
|
||||
if( !IsCopperLayer( layerid ) )
|
||||
continue;
|
||||
|
||||
wxColour fg = m_layerPresentation.getLayerColor( layerid ).ToColour();
|
||||
wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
|
||||
wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
|
||||
wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
|
||||
|
||||
layername = wxT( " " ) + m_layerPresentation.getLayerName( layerid );
|
||||
|
||||
if( row )
|
||||
m_leftGridLayers->AppendRows( 1 );
|
||||
|
||||
m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
|
||||
m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
|
||||
m_layersId.push_back( layerid );
|
||||
|
||||
if( m_frontLayer == layerid )
|
||||
{
|
||||
m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) );
|
||||
m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
|
||||
m_leftRowSelected = row;
|
||||
}
|
||||
|
||||
if( row )
|
||||
m_rightGridLayers->AppendRows( 1 );
|
||||
|
||||
m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
|
||||
m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
|
||||
|
||||
if( m_backLayer == layerid )
|
||||
{
|
||||
m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) );
|
||||
m_rightRowSelected = row;
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
// Now fix min grid layer name column size (it also sets a minimal size)
|
||||
m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
|
||||
m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
|
||||
}
|
||||
|
||||
|
||||
void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridCellClick( wxGridEvent& event )
|
||||
{
|
||||
int row = event.GetRow();
|
||||
PCB_LAYER_ID layer = m_layersId[row];
|
||||
|
||||
if( m_frontLayer == layer )
|
||||
return;
|
||||
|
||||
m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
|
||||
m_frontLayer = layer;
|
||||
m_leftRowSelected = row;
|
||||
m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxT( "1" ) );
|
||||
}
|
||||
|
||||
|
||||
void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridCellClick( wxGridEvent& event )
|
||||
{
|
||||
int row = event.GetRow();
|
||||
PCB_LAYER_ID layer = m_layersId[row];
|
||||
|
||||
if( m_backLayer == layer )
|
||||
return;
|
||||
|
||||
m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
|
||||
m_backLayer = layer;
|
||||
m_rightRowSelected = row;
|
||||
m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxT( "1" ) );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user