Handle multiple unitProviders in a WX_GRID.

This allows us to provide a more consistent and less buggy presentation
of the netclasses grid in both eeschema and pcbnew.

Fixes https://gitlab.com/kicad/code/kicad/issues/12826
This commit is contained in:
Jeff Young 2022-11-04 12:20:53 +00:00
parent ae9405a4d3
commit cf581137d8
4 changed files with 130 additions and 124 deletions

View File

@ -37,12 +37,11 @@
#include <widgets/grid_color_swatch_helpers.h> #include <widgets/grid_color_swatch_helpers.h>
#include <widgets/grid_icon_text_helpers.h> #include <widgets/grid_icon_text_helpers.h>
#include <widgets/wx_html_report_box.h> #include <widgets/wx_html_report_box.h>
#include <widgets/wx_grid.h>
#include <wx/treebook.h> #include <wx/treebook.h>
#include <project/net_settings.h> #include <project/net_settings.h>
// PCBNEW columns of netclasses grid // columns of netclasses grid
enum { enum {
GRID_NAME = 0, GRID_NAME = 0,
@ -65,9 +64,6 @@ enum {
GRID_END GRID_END
}; };
constexpr int EESCHEMA_COL_OFFSET = GRID_FIRST_EESCHEMA - GRID_FIRST_PCBNEW;
std::vector<BITMAPS> g_lineStyleIcons; std::vector<BITMAPS> g_lineStyleIcons;
wxArrayString g_lineStyleNames; wxArrayString g_lineStyleNames;
@ -102,47 +98,14 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_
m_netclassesDirty = true; m_netclassesDirty = true;
m_netclassGrid->SetUnitsProvider( m_frame ); m_schUnitsProvider = std::make_unique<UNITS_PROVIDER>( schIUScale, m_frame->GetUserUnits() );
m_pcbUnitsProvider = std::make_unique<UNITS_PROVIDER>( pcbIUScale, m_frame->GetUserUnits() );
// Prevent Size events from firing before we are ready // Prevent Size events from firing before we are ready
Freeze(); Freeze();
m_netclassGrid->BeginBatch(); m_netclassGrid->BeginBatch();
m_assignmentGrid->BeginBatch(); m_assignmentGrid->BeginBatch();
if( m_isEEschema )
{
constexpr int ECO = EESCHEMA_COL_OFFSET;
m_netclassGrid->DeleteCols( GRID_FIRST_PCBNEW, GRID_FIRST_EESCHEMA - GRID_FIRST_PCBNEW );
m_netclassGrid->SetAutoEvalCols( { GRID_WIREWIDTH - ECO, GRID_BUSWIDTH - ECO } );
wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( aParent ) );
attr->SetEditor( new GRID_CELL_COLOR_SELECTOR( aParent, m_netclassGrid ) );
m_netclassGrid->SetColAttr( GRID_SCHEMATIC_COLOR - ECO, attr );
attr = new wxGridCellAttr;
attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( g_lineStyleIcons, g_lineStyleNames ) );
attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( g_lineStyleIcons, g_lineStyleNames ) );
m_netclassGrid->SetColAttr( GRID_LINESTYLE - ECO, attr );
m_colorDefaultHelpText->SetFont( KIUI::GetInfoFont( this ).Italic() );
}
else
{
m_netclassGrid->DeleteCols( GRID_FIRST_EESCHEMA, GRID_END - GRID_FIRST_EESCHEMA );
m_netclassGrid->SetAutoEvalCols( { GRID_CLEARANCE,
GRID_TRACKSIZE,
GRID_VIASIZE,
GRID_VIADRILL,
GRID_uVIASIZE,
GRID_uVIADRILL,
GRID_DIFF_PAIR_WIDTH,
GRID_DIFF_PAIR_GAP } );
m_colorDefaultHelpText->Hide();
}
m_originalColWidths = new int[ m_netclassGrid->GetNumberCols() ]; m_originalColWidths = new int[ m_netclassGrid->GetNumberCols() ];
// Calculate a min best size to handle longest usual numeric values: // Calculate a min best size to handle longest usual numeric values:
int min_best_width = m_netclassGrid->GetTextExtent( "555,555555 mils" ).x; int min_best_width = m_netclassGrid->GetTextExtent( "555,555555 mils" ).x;
@ -163,6 +126,58 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_
m_netclassGrid->SetColSize( i, m_originalColWidths[ i ] ); m_netclassGrid->SetColSize( i, m_originalColWidths[ i ] );
} }
for( int i = GRID_FIRST_PCBNEW; i < GRID_END; ++i )
{
if( i >= GRID_FIRST_EESCHEMA )
{
m_netclassGrid->SetUnitsProvider( m_schUnitsProvider.get(), i );
if( !m_isEEschema )
{
m_netclassGrid->HideCol( i );
m_originalColWidths[ i ] = 0;
}
}
else
{
m_netclassGrid->SetUnitsProvider( m_pcbUnitsProvider.get(), i );
if( m_isEEschema )
{
m_netclassGrid->HideCol( i );
m_originalColWidths[ i ] = 0;
}
}
}
wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetRenderer( new GRID_CELL_COLOR_RENDERER( aParent ) );
attr->SetEditor( new GRID_CELL_COLOR_SELECTOR( aParent, m_netclassGrid ) );
m_netclassGrid->SetColAttr( GRID_SCHEMATIC_COLOR, attr );
attr = new wxGridCellAttr;
attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( g_lineStyleIcons, g_lineStyleNames ) );
attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( g_lineStyleIcons, g_lineStyleNames ) );
m_netclassGrid->SetColAttr( GRID_LINESTYLE, attr );
if( m_isEEschema )
m_colorDefaultHelpText->SetFont( KIUI::GetInfoFont( this ).Italic() );
else
m_colorDefaultHelpText->Hide();
m_netclassGrid->SetAutoEvalCols( { GRID_WIREWIDTH,
GRID_BUSWIDTH,
GRID_CLEARANCE,
GRID_TRACKSIZE,
GRID_VIASIZE,
GRID_VIADRILL,
GRID_uVIASIZE,
GRID_uVIADRILL,
GRID_DIFF_PAIR_WIDTH,
GRID_DIFF_PAIR_GAP } );
// Be sure the column labels are readable // Be sure the column labels are readable
m_netclassGrid->EnsureColLabelsVisible(); m_netclassGrid->EnsureColLabelsVisible();
@ -233,6 +248,10 @@ void PANEL_SETUP_NETCLASSES::onUnitsChanged( wxCommandEvent& aEvent )
m_netSettings = tempNetSettings; m_netSettings = tempNetSettings;
TransferDataFromWindow(); TransferDataFromWindow();
m_schUnitsProvider->SetUserUnits( m_frame->GetUserUnits() );
m_pcbUnitsProvider->SetUserUnits( m_frame->GetUserUnits() );
TransferDataToWindow(); TransferDataToWindow();
m_netSettings = saveNetSettings; m_netSettings = saveNetSettings;
@ -250,26 +269,19 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
{ {
m_netclassGrid->SetCellValue( aRow, GRID_NAME, nc->GetName() ); m_netclassGrid->SetCellValue( aRow, GRID_NAME, nc->GetName() );
if( m_isEEschema ) m_netclassGrid->SetUnitValue( aRow, GRID_WIREWIDTH, nc->GetWireWidth() );
{ m_netclassGrid->SetUnitValue( aRow, GRID_BUSWIDTH, nc->GetBusWidth() );
constexpr int ECO = EESCHEMA_COL_OFFSET;
m_netclassGrid->SetUnitValue( aRow, GRID_WIREWIDTH - ECO, nc->GetWireWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_BUSWIDTH - ECO, nc->GetBusWidth() );
wxString colorAsString = nc->GetSchematicColor().ToCSSString(); wxString colorAsString = nc->GetSchematicColor().ToCSSString();
m_netclassGrid->SetCellValue( aRow, GRID_SCHEMATIC_COLOR - ECO, colorAsString ); m_netclassGrid->SetCellValue( aRow, GRID_SCHEMATIC_COLOR, colorAsString );
int lineStyleIdx = std::max( 0, nc->GetLineStyle() ); int lineStyleIdx = std::max( 0, nc->GetLineStyle() );
if( lineStyleIdx >= (int) g_lineStyleNames.size() ) if( lineStyleIdx >= (int) g_lineStyleNames.size() )
lineStyleIdx = 0; lineStyleIdx = 0;
m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE - EESCHEMA_COL_OFFSET, m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE, g_lineStyleNames[ lineStyleIdx ] );
g_lineStyleNames[ lineStyleIdx ] );
}
else
{
m_netclassGrid->SetUnitValue( aRow, GRID_CLEARANCE, nc->GetClearance() ); m_netclassGrid->SetUnitValue( aRow, GRID_CLEARANCE, nc->GetClearance() );
m_netclassGrid->SetUnitValue( aRow, GRID_TRACKSIZE, nc->GetTrackWidth() ); m_netclassGrid->SetUnitValue( aRow, GRID_TRACKSIZE, nc->GetTrackWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_VIASIZE, nc->GetViaDiameter() ); m_netclassGrid->SetUnitValue( aRow, GRID_VIASIZE, nc->GetViaDiameter() );
@ -278,7 +290,6 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
m_netclassGrid->SetUnitValue( aRow, GRID_uVIADRILL, nc->GetuViaDrill() ); m_netclassGrid->SetUnitValue( aRow, GRID_uVIADRILL, nc->GetuViaDrill() );
m_netclassGrid->SetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH, nc->GetDiffPairWidth() ); m_netclassGrid->SetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH, nc->GetDiffPairWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_DIFF_PAIR_GAP, nc->GetDiffPairGap() ); m_netclassGrid->SetUnitValue( aRow, GRID_DIFF_PAIR_GAP, nc->GetDiffPairGap() );
}
}; };
m_netclassGrid->ClearRows(); m_netclassGrid->ClearRows();
@ -348,22 +359,16 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
{ {
nc->SetName( m_netclassGrid->GetCellValue( aRow, GRID_NAME ) ); nc->SetName( m_netclassGrid->GetCellValue( aRow, GRID_NAME ) );
if( m_isEEschema ) nc->SetWireWidth( m_netclassGrid->GetUnitValue( aRow, GRID_WIREWIDTH ) );
{ nc->SetBusWidth( m_netclassGrid->GetUnitValue( aRow, GRID_BUSWIDTH ) );
constexpr int ECO = EESCHEMA_COL_OFFSET;
nc->SetWireWidth( m_netclassGrid->GetUnitValue( aRow, GRID_WIREWIDTH - ECO ) ); wxString color = m_netclassGrid->GetCellValue( aRow, GRID_SCHEMATIC_COLOR );
nc->SetBusWidth( m_netclassGrid->GetUnitValue( aRow, GRID_BUSWIDTH - ECO ) );
wxString color = m_netclassGrid->GetCellValue( aRow, GRID_SCHEMATIC_COLOR - ECO );
nc->SetSchematicColor( wxColour( color ) ); nc->SetSchematicColor( wxColour( color ) );
wxString lineStyle = m_netclassGrid->GetCellValue( aRow, GRID_LINESTYLE - ECO ); wxString lineStyle = m_netclassGrid->GetCellValue( aRow, GRID_LINESTYLE );
nc->SetLineStyle( g_lineStyleNames.Index( lineStyle ) ); nc->SetLineStyle( g_lineStyleNames.Index( lineStyle ) );
wxASSERT_MSG( nc->GetLineStyle() >= 0, "Line style name not found." ); wxASSERT_MSG( nc->GetLineStyle() >= 0, "Line style name not found." );
}
else
{
nc->SetClearance( m_netclassGrid->GetUnitValue( aRow, GRID_CLEARANCE ) ); nc->SetClearance( m_netclassGrid->GetUnitValue( aRow, GRID_CLEARANCE ) );
nc->SetTrackWidth( m_netclassGrid->GetUnitValue( aRow, GRID_TRACKSIZE ) ); nc->SetTrackWidth( m_netclassGrid->GetUnitValue( aRow, GRID_TRACKSIZE ) );
nc->SetViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_VIASIZE ) ); nc->SetViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_VIASIZE ) );
@ -372,7 +377,6 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
nc->SetuViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_uVIADRILL ) ); nc->SetuViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_uVIADRILL ) );
nc->SetDiffPairWidth( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH ) ); nc->SetDiffPairWidth( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH ) );
nc->SetDiffPairGap( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_GAP ) ); nc->SetDiffPairGap( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_GAP ) );
}
}; };
m_netSettings->m_NetClasses.clear(); m_netSettings->m_NetClasses.clear();
@ -484,9 +488,6 @@ void PANEL_SETUP_NETCLASSES::OnNetclassGridMouseEvent( wxMouseEvent& aEvent )
wxString tip; wxString tip;
if( m_isEEschema && col > GRID_NAME )
col += EESCHEMA_COL_OFFSET;
switch( col ) switch( col )
{ {
case GRID_CLEARANCE: tip = _( "Minimum copper clearance" ); break; case GRID_CLEARANCE: tip = _( "Minimum copper clearance" ); break;
@ -525,22 +526,8 @@ void PANEL_SETUP_NETCLASSES::OnAddNetclassClick( wxCommandEvent& event )
m_netclassGrid->AppendRows(); m_netclassGrid->AppendRows();
// Copy values of the default class: // Copy values of the default class:
if( m_isEEschema ) for( int col = 1; col < m_netclassGrid->GetNumberCols(); col++ )
{ m_netclassGrid->SetCellValue( row, col, m_netclassGrid->GetCellValue( 0, col ) );
for( int col = GRID_FIRST_EESCHEMA; col < GRID_END; col++ )
{
wxString defaultValue = m_netclassGrid->GetCellValue( 0, col - EESCHEMA_COL_OFFSET );
m_netclassGrid->SetCellValue( row, col - EESCHEMA_COL_OFFSET, defaultValue );
}
}
else
{
for( int col = GRID_FIRST_PCBNEW; col < GRID_FIRST_EESCHEMA; col++ )
{
wxString defaultValue = m_netclassGrid->GetCellValue( 0, col );
m_netclassGrid->SetCellValue( row, col, defaultValue );
}
}
m_netclassGrid->MakeCellVisible( row, 0 ); m_netclassGrid->MakeCellVisible( row, 0 );
m_netclassGrid->SetGridCursor( row, 0 ); m_netclassGrid->SetGridCursor( row, 0 );

View File

@ -34,8 +34,7 @@
WX_GRID::WX_GRID( wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, WX_GRID::WX_GRID( wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
long style, const wxString& name ) : long style, const wxString& name ) :
wxGrid( parent, id, pos, size, style, name ), wxGrid( parent, id, pos, size, style, name ),
m_weOwnTable( false ), m_weOwnTable( false )
m_unitsProvider( nullptr )
{ {
SetDefaultCellOverflow( false ); SetDefaultCellOverflow( false );
@ -158,20 +157,25 @@ void WX_GRID::onCellEditorHidden( wxGridEvent& aEvent )
{ {
if( alg::contains( m_autoEvalCols, aEvent.GetCol() ) ) if( alg::contains( m_autoEvalCols, aEvent.GetCol() ) )
{ {
m_eval->SetDefaultUnits( m_unitsProvider->GetUserUnits() ); UNITS_PROVIDER* unitsProvider = m_unitsProviders[ aEvent.GetCol() ];
if( !unitsProvider )
unitsProvider = m_unitsProviders.begin()->second;
m_eval->SetDefaultUnits( unitsProvider->GetUserUnits() );
int row = aEvent.GetRow(); int row = aEvent.GetRow();
int col = aEvent.GetCol(); int col = aEvent.GetCol();
CallAfter( CallAfter(
[this, row, col]() [this, row, col, unitsProvider]()
{ {
wxString stringValue = GetCellValue( row, col ); wxString stringValue = GetCellValue( row, col );
if( m_eval->Process( stringValue ) ) if( m_eval->Process( stringValue ) )
{ {
int val = m_unitsProvider->ValueFromString( m_eval->Result() ); int val = unitsProvider->ValueFromString( m_eval->Result() );
wxString evalValue = m_unitsProvider->StringFromValue( val, true ); wxString evalValue = unitsProvider->StringFromValue( val, true );
if( stringValue != evalValue ) if( stringValue != evalValue )
{ {
@ -322,32 +326,44 @@ bool WX_GRID::CommitPendingChanges( bool aQuietMode )
} }
void WX_GRID::SetUnitsProvider( UNITS_PROVIDER* aProvider ) void WX_GRID::SetUnitsProvider( UNITS_PROVIDER* aProvider, int aCol )
{ {
m_unitsProvider = aProvider; m_unitsProviders[ aCol ] = aProvider;
m_eval = std::make_unique<NUMERIC_EVALUATOR>( m_unitsProvider->GetUserUnits() );
if( !m_eval )
m_eval = std::make_unique<NUMERIC_EVALUATOR>( aProvider->GetUserUnits() );
} }
int WX_GRID::GetUnitValue( int aRow, int aCol ) int WX_GRID::GetUnitValue( int aRow, int aCol )
{ {
UNITS_PROVIDER* unitsProvider = m_unitsProviders[ aCol ];
if( !unitsProvider )
unitsProvider = m_unitsProviders.begin()->second;
wxString stringValue = GetCellValue( aRow, aCol ); wxString stringValue = GetCellValue( aRow, aCol );
if( alg::contains( m_autoEvalCols, aCol ) ) if( alg::contains( m_autoEvalCols, aCol ) )
{ {
m_eval->SetDefaultUnits( m_unitsProvider->GetUserUnits() ); m_eval->SetDefaultUnits( unitsProvider->GetUserUnits() );
if( m_eval->Process( stringValue ) ) if( m_eval->Process( stringValue ) )
stringValue = m_eval->Result(); stringValue = m_eval->Result();
} }
return m_unitsProvider->ValueFromString( stringValue ); return unitsProvider->ValueFromString( stringValue );
} }
void WX_GRID::SetUnitValue( int aRow, int aCol, int aValue ) void WX_GRID::SetUnitValue( int aRow, int aCol, int aValue )
{ {
SetCellValue( aRow, aCol, m_unitsProvider->StringFromValue( aValue, true ) ); UNITS_PROVIDER* unitsProvider = m_unitsProviders[ aCol ];
if( !unitsProvider )
unitsProvider = m_unitsProviders.begin()->second;
SetCellValue( aRow, aCol, unitsProvider->StringFromValue( aValue, true ) );
} }

View File

@ -74,6 +74,9 @@ private:
std::shared_ptr<NET_SETTINGS> m_netSettings; std::shared_ptr<NET_SETTINGS> m_netSettings;
std::set<wxString> m_netNames; std::set<wxString> m_netNames;
std::unique_ptr<UNITS_PROVIDER> m_schUnitsProvider;
std::unique_ptr<UNITS_PROVIDER> m_pcbUnitsProvider;
int* m_originalColWidths; int* m_originalColWidths;
bool m_netclassesDirty; // The netclass drop-down menus need rebuilding bool m_netclassesDirty; // The netclass drop-down menus need rebuilding
int m_hoveredCol; // Column being hovered over, for tooltips int m_hoveredCol; // Column being hovered over, for tooltips

View File

@ -85,7 +85,7 @@ public:
* Set a UNITS_PROVIDER to enable use of unit- and eval-based Getters. * Set a UNITS_PROVIDER to enable use of unit- and eval-based Getters.
* @param aProvider * @param aProvider
*/ */
void SetUnitsProvider( UNITS_PROVIDER* aProvider ); void SetUnitsProvider( UNITS_PROVIDER* aProvider, int aCol = 0 );
void SetAutoEvalCols( const std::vector<int>& aCols ) { m_autoEvalCols = aCols; } void SetAutoEvalCols( const std::vector<int>& aCols ) { m_autoEvalCols = aCols; }
@ -156,7 +156,7 @@ protected:
protected: protected:
bool m_weOwnTable; bool m_weOwnTable;
UNITS_PROVIDER* m_unitsProvider; std::map<int, UNITS_PROVIDER*> m_unitsProviders;
std::unique_ptr<NUMERIC_EVALUATOR> m_eval; std::unique_ptr<NUMERIC_EVALUATOR> m_eval;
std::vector<int> m_autoEvalCols; std::vector<int> m_autoEvalCols;