|
|
|
@ -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 ); |
|
|
|
} |
|
|
|
|
|
|
|
@ -299,161 +312,462 @@ PCB_LAYER_ID PCB_BASE_FRAME::SelectOneLayer( PCB_LAYER_ID aDefaultLayer, LSET aN |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Display a pair PCB copper layers list in a dialog to select a layer pair from these lists. |
|
|
|
* Class that manages the UI for the copper layer pair presets list |
|
|
|
* based on an injected layer pair store. |
|
|
|
*/ |
|
|
|
class SELECT_COPPER_LAYERS_PAIR_DIALOG : public DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE |
|
|
|
class COPPER_LAYERS_PAIR_PRESETS_UI |
|
|
|
{ |
|
|
|
enum class COLNUMS |
|
|
|
{ |
|
|
|
ENABLED, |
|
|
|
SWATCH, |
|
|
|
LAYERNAMES, |
|
|
|
USERNAME, |
|
|
|
}; |
|
|
|
|
|
|
|
public: |
|
|
|
SELECT_COPPER_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME* aParent, BOARD* aPcb, |
|
|
|
PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer ); |
|
|
|
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 GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer ) |
|
|
|
void OnLayerPairAdded( const LAYER_PAIR& aLayerPair ) |
|
|
|
{ |
|
|
|
aFrontLayer = m_frontLayer; |
|
|
|
aBackLayer = m_backLayer; |
|
|
|
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 OnLeftGridCellClick( wxGridEvent& event ) override; |
|
|
|
void OnRightGridCellClick( wxGridEvent& event ) override; |
|
|
|
void configureGrid() |
|
|
|
{ |
|
|
|
m_grid.UseNativeColHeader( true ); |
|
|
|
|
|
|
|
void buildList(); |
|
|
|
m_grid.SetCellHighlightPenWidth( 0 ); |
|
|
|
m_grid.SetColFormatBool( (int) COLNUMS::ENABLED ); |
|
|
|
|
|
|
|
PCB_LAYER_PRESENTATION m_layerPresentation; |
|
|
|
BOARD* m_brd; |
|
|
|
PCB_LAYER_ID m_frontLayer; |
|
|
|
PCB_LAYER_ID m_backLayer; |
|
|
|
int m_leftRowSelected; |
|
|
|
int m_rightRowSelected; |
|
|
|
m_grid.SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows ); |
|
|
|
|
|
|
|
std::vector<PCB_LAYER_ID> m_layersId; |
|
|
|
}; |
|
|
|
m_grid.AutoSizeColumn( (int) COLNUMS::USERNAME ); |
|
|
|
} |
|
|
|
|
|
|
|
void fillGridFromStore() |
|
|
|
{ |
|
|
|
std::span<const LAYER_PAIR_INFO> storePairs = m_layerPairSettings.GetLayerPairs(); |
|
|
|
|
|
|
|
int ROUTER_TOOL::SelectCopperLayerPair( const TOOL_EVENT& aEvent ) |
|
|
|
{ |
|
|
|
PCB_SCREEN* screen = frame()->GetScreen(); |
|
|
|
m_grid.AppendRows( storePairs.size() ); |
|
|
|
|
|
|
|
SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( frame(), frame()->GetBoard(), screen->m_Route_Layer_TOP, |
|
|
|
screen->m_Route_Layer_BOTTOM ); |
|
|
|
int row = 0; |
|
|
|
for( const LAYER_PAIR_INFO& layerPairInfo : storePairs ) |
|
|
|
{ |
|
|
|
fillRowFromLayerPair( row, layerPairInfo ); |
|
|
|
row++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( dlg.ShowModal() == wxID_OK ) |
|
|
|
wxString constructLayerPairLabel( const LAYER_PAIR& aLayerPair ) |
|
|
|
{ |
|
|
|
dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM ); |
|
|
|
const wxString layerAName = m_layerPresentation.getLayerName( aLayerPair.GetLayerA() ); |
|
|
|
const wxString layerBName = m_layerPresentation.getLayerName( aLayerPair.GetLayerB() ); |
|
|
|
return layerAName + wxT( " / " ) + layerBName; |
|
|
|
} |
|
|
|
|
|
|
|
// 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 ) |
|
|
|
DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) ); |
|
|
|
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 ); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
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 ); |
|
|
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
void onPairActivated( int aRow ) |
|
|
|
{ |
|
|
|
const LAYER_PAIR_INFO& layerPairInfo = m_layerPairSettings.GetLayerPairs()[aRow]; |
|
|
|
const LAYER_PAIR& layerPair = layerPairInfo.GetLayerPair(); |
|
|
|
|
|
|
|
m_leftGridLayers->SetCellHighlightPenWidth( 0 ); |
|
|
|
m_rightGridLayers->SetCellHighlightPenWidth( 0 ); |
|
|
|
m_leftGridLayers->SetColFormatBool( SELECT_COLNUM ); |
|
|
|
m_rightGridLayers->SetColFormatBool( SELECT_COLNUM ); |
|
|
|
buildList(); |
|
|
|
m_layerPairSettings.SetCurrentLayerPair( layerPair ); |
|
|
|
} |
|
|
|
|
|
|
|
SetFocus(); |
|
|
|
LAYER_PRESENTATION& m_layerPresentation; |
|
|
|
WX_GRID& m_grid; |
|
|
|
LAYER_PAIR_SETTINGS& m_layerPairSettings; |
|
|
|
|
|
|
|
GetSizer()->SetSizeHints( this ); |
|
|
|
Center(); |
|
|
|
} |
|
|
|
// Lifetime managment of the swatches
|
|
|
|
std::vector<std::unique_ptr<wxBitmap>> m_swatches; |
|
|
|
|
|
|
|
std::unique_ptr<WX_GRID_AUTOSIZER> m_autosizer; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
void SELECT_COPPER_LAYERS_PAIR_DIALOG::buildList() |
|
|
|
/**
|
|
|
|
* Class that manages the UI for the copper layer pair selection |
|
|
|
* (left and right grids). |
|
|
|
*/ |
|
|
|
class COPPER_LAYERS_PAIR_SELECTION_UI |
|
|
|
{ |
|
|
|
wxColour bg = m_layerPresentation.getLayerColor( LAYER_PCB_BACKGROUND ).ToColour(); |
|
|
|
int row = 0; |
|
|
|
wxString layername; |
|
|
|
enum class CU_LAYER_COLNUMS |
|
|
|
{ |
|
|
|
SELECT = 0, |
|
|
|
COLOR = 1, |
|
|
|
LAYERNAME = 2, |
|
|
|
}; |
|
|
|
|
|
|
|
for( PCB_LAYER_ID layerid : m_brd->GetEnabledLayers().UIOrder() ) |
|
|
|
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 ) |
|
|
|
{ |
|
|
|
if( !IsCopperLayer( layerid ) ) |
|
|
|
continue; |
|
|
|
configureGrid( m_leftGrid ); |
|
|
|
configureGrid( m_rightGrid ); |
|
|
|
|
|
|
|
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 ) ); |
|
|
|
for( const PCB_LAYER_ID& layerId : m_layerPresentation.getOrderedEnabledLayers() ) |
|
|
|
{ |
|
|
|
if( IsCopperLayer( layerId ) ) |
|
|
|
{ |
|
|
|
m_layersId.push_back( layerId ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
layername = wxT( " " ) + m_layerPresentation.getLayerName( 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() ) ); |
|
|
|
} ); |
|
|
|
} |
|
|
|
|
|
|
|
if( row ) |
|
|
|
m_leftGridLayers->AppendRows( 1 ); |
|
|
|
private: |
|
|
|
void configureGrid( wxGrid& aGrid ) |
|
|
|
{ |
|
|
|
aGrid.SetCellHighlightPenWidth( 0 ); |
|
|
|
aGrid.SetColFormatBool( (int) CU_LAYER_COLNUMS::SELECT ); |
|
|
|
} |
|
|
|
|
|
|
|
m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color ); |
|
|
|
m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername ); |
|
|
|
m_layersId.push_back( layerid ); |
|
|
|
void fillLayerGrid( wxGrid& aGrid ) |
|
|
|
{ |
|
|
|
const wxColour bg = m_layerPresentation.getLayerColor( LAYER_PCB_BACKGROUND ).ToColour(); |
|
|
|
|
|
|
|
if( m_frontLayer == layerid ) |
|
|
|
aGrid.AppendRows( m_layersId.size() - 1 ); |
|
|
|
|
|
|
|
int row = 0; |
|
|
|
for( const PCB_LAYER_ID& layerId : m_layersId ) |
|
|
|
{ |
|
|
|
m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) ); |
|
|
|
m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM ); |
|
|
|
m_leftRowSelected = row; |
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( row ) |
|
|
|
m_rightGridLayers->AppendRows( 1 ); |
|
|
|
wxASSERT_MSG( false, wxString::Format( "Unknown layer in grid: %d", aLayerId ) ); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color ); |
|
|
|
m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername ); |
|
|
|
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 ); |
|
|
|
} |
|
|
|
|
|
|
|
if( m_backLayer == layerid ) |
|
|
|
/**
|
|
|
|
* 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 ) |
|
|
|
{ |
|
|
|
m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) ); |
|
|
|
m_rightRowSelected = row; |
|
|
|
selectGridRow( m_leftGrid, m_leftCurrRow, false ); |
|
|
|
selectGridRow( m_leftGrid, aLeftRow, true ); |
|
|
|
m_leftCurrRow = aLeftRow; |
|
|
|
} |
|
|
|
|
|
|
|
row++; |
|
|
|
if( m_rightCurrRow != aRightRow ) |
|
|
|
{ |
|
|
|
selectGridRow( m_rightGrid, m_rightCurrRow, false ); |
|
|
|
selectGridRow( m_rightGrid, aRightRow, true ); |
|
|
|
m_rightCurrRow = aRightRow; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Now fix min grid layer name column size (it also sets a minimal size)
|
|
|
|
m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM ); |
|
|
|
m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM ); |
|
|
|
} |
|
|
|
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; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridCellClick( wxGridEvent& event ) |
|
|
|
/**
|
|
|
|
* 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 |
|
|
|
{ |
|
|
|
int row = event.GetRow(); |
|
|
|
PCB_LAYER_ID layer = m_layersId[row]; |
|
|
|
public: |
|
|
|
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 ) |
|
|
|
{ |
|
|
|
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(); |
|
|
|
|
|
|
|
if( m_frontLayer == layer ) |
|
|
|
return; |
|
|
|
m_dialogPairSettings.SetCurrentLayerPair( m_boardPairSettings.GetCurrentLayerPair() ); |
|
|
|
|
|
|
|
m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString ); |
|
|
|
m_frontLayer = layer; |
|
|
|
m_leftRowSelected = row; |
|
|
|
m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxT( "1" ) ); |
|
|
|
} |
|
|
|
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: |
|
|
|
// 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; |
|
|
|
// UI controllers
|
|
|
|
COPPER_LAYERS_PAIR_SELECTION_UI m_pairSelectionController; |
|
|
|
COPPER_LAYERS_PAIR_PRESETS_UI m_presetsGridController; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridCellClick( wxGridEvent& event ) |
|
|
|
int ROUTER_TOOL::SelectCopperLayerPair( const TOOL_EVENT& aEvent ) |
|
|
|
{ |
|
|
|
int row = event.GetRow(); |
|
|
|
PCB_LAYER_ID layer = m_layersId[row]; |
|
|
|
LAYER_PAIR_SETTINGS* const boardSettings = frame()->GetLayerPairSettings(); |
|
|
|
|
|
|
|
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 ) |
|
|
|
{ |
|
|
|
const LAYER_PAIR layerPair = boardSettings->GetCurrentLayerPair(); |
|
|
|
|
|
|
|
if( m_backLayer == layer ) |
|
|
|
return; |
|
|
|
// select the same layer for both layers is allowed (normal in some boards)
|
|
|
|
// but could be a mistake. So display an info message
|
|
|
|
if( layerPair.GetLayerA() == layerPair.GetLayerB() ) |
|
|
|
{ |
|
|
|
DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString ); |
|
|
|
m_backLayer = layer; |
|
|
|
m_rightRowSelected = row; |
|
|
|
m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxT( "1" ) ); |
|
|
|
return 0; |
|
|
|
} |