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_icon_text_helpers.h>
#include <widgets/wx_html_report_box.h>
#include <widgets/wx_grid.h>
#include <wx/treebook.h>
#include <project/net_settings.h>
// PCBNEW columns of netclasses grid
// columns of netclasses grid
enum {
GRID_NAME = 0,
@ -65,9 +64,6 @@ enum {
GRID_END
};
constexpr int EESCHEMA_COL_OFFSET = GRID_FIRST_EESCHEMA - GRID_FIRST_PCBNEW;
std::vector<BITMAPS> g_lineStyleIcons;
wxArrayString g_lineStyleNames;
@ -102,47 +98,14 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_
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
Freeze();
m_netclassGrid->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() ];
// Calculate a min best size to handle longest usual numeric values:
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 ] );
}
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
m_netclassGrid->EnsureColLabelsVisible();
@ -233,6 +248,10 @@ void PANEL_SETUP_NETCLASSES::onUnitsChanged( wxCommandEvent& aEvent )
m_netSettings = tempNetSettings;
TransferDataFromWindow();
m_schUnitsProvider->SetUserUnits( m_frame->GetUserUnits() );
m_pcbUnitsProvider->SetUserUnits( m_frame->GetUserUnits() );
TransferDataToWindow();
m_netSettings = saveNetSettings;
@ -250,35 +269,27 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
{
m_netclassGrid->SetCellValue( aRow, GRID_NAME, nc->GetName() );
if( m_isEEschema )
{
constexpr int ECO = EESCHEMA_COL_OFFSET;
m_netclassGrid->SetUnitValue( aRow, GRID_WIREWIDTH, nc->GetWireWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_BUSWIDTH, nc->GetBusWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_WIREWIDTH - ECO, nc->GetWireWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_BUSWIDTH - ECO, nc->GetBusWidth() );
wxString colorAsString = nc->GetSchematicColor().ToCSSString();
m_netclassGrid->SetCellValue( aRow, GRID_SCHEMATIC_COLOR, colorAsString );
wxString colorAsString = nc->GetSchematicColor().ToCSSString();
m_netclassGrid->SetCellValue( aRow, GRID_SCHEMATIC_COLOR - ECO, colorAsString );
int lineStyleIdx = std::max( 0, nc->GetLineStyle() );
int lineStyleIdx = std::max( 0, nc->GetLineStyle() );
if( lineStyleIdx >= (int) g_lineStyleNames.size() )
lineStyleIdx = 0;
if( lineStyleIdx >= (int) g_lineStyleNames.size() )
lineStyleIdx = 0;
m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE, g_lineStyleNames[ lineStyleIdx ] );
m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE - EESCHEMA_COL_OFFSET,
g_lineStyleNames[ lineStyleIdx ] );
}
else
{
m_netclassGrid->SetUnitValue( aRow, GRID_CLEARANCE, nc->GetClearance() );
m_netclassGrid->SetUnitValue( aRow, GRID_TRACKSIZE, nc->GetTrackWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_VIASIZE, nc->GetViaDiameter() );
m_netclassGrid->SetUnitValue( aRow, GRID_VIADRILL, nc->GetViaDrill() );
m_netclassGrid->SetUnitValue( aRow, GRID_uVIASIZE, nc->GetuViaDiameter() );
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_GAP, nc->GetDiffPairGap() );
}
m_netclassGrid->SetUnitValue( aRow, GRID_CLEARANCE, nc->GetClearance() );
m_netclassGrid->SetUnitValue( aRow, GRID_TRACKSIZE, nc->GetTrackWidth() );
m_netclassGrid->SetUnitValue( aRow, GRID_VIASIZE, nc->GetViaDiameter() );
m_netclassGrid->SetUnitValue( aRow, GRID_VIADRILL, nc->GetViaDrill() );
m_netclassGrid->SetUnitValue( aRow, GRID_uVIASIZE, nc->GetuViaDiameter() );
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_GAP, nc->GetDiffPairGap() );
};
m_netclassGrid->ClearRows();
@ -348,31 +359,24 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
{
nc->SetName( m_netclassGrid->GetCellValue( aRow, GRID_NAME ) );
if( m_isEEschema )
{
constexpr int ECO = EESCHEMA_COL_OFFSET;
nc->SetWireWidth( m_netclassGrid->GetUnitValue( aRow, GRID_WIREWIDTH ) );
nc->SetBusWidth( m_netclassGrid->GetUnitValue( aRow, GRID_BUSWIDTH ) );
nc->SetWireWidth( m_netclassGrid->GetUnitValue( aRow, GRID_WIREWIDTH - ECO ) );
nc->SetBusWidth( m_netclassGrid->GetUnitValue( aRow, GRID_BUSWIDTH - ECO ) );
wxString color = m_netclassGrid->GetCellValue( aRow, GRID_SCHEMATIC_COLOR );
nc->SetSchematicColor( wxColour( color ) );
wxString color = m_netclassGrid->GetCellValue( aRow, GRID_SCHEMATIC_COLOR - ECO );
nc->SetSchematicColor( wxColour( color ) );
wxString lineStyle = m_netclassGrid->GetCellValue( aRow, GRID_LINESTYLE );
nc->SetLineStyle( g_lineStyleNames.Index( lineStyle ) );
wxASSERT_MSG( nc->GetLineStyle() >= 0, "Line style name not found." );
wxString lineStyle = m_netclassGrid->GetCellValue( aRow, GRID_LINESTYLE - ECO );
nc->SetLineStyle( g_lineStyleNames.Index( lineStyle ) );
wxASSERT_MSG( nc->GetLineStyle() >= 0, "Line style name not found." );
}
else
{
nc->SetClearance( m_netclassGrid->GetUnitValue( aRow, GRID_CLEARANCE ) );
nc->SetTrackWidth( m_netclassGrid->GetUnitValue( aRow, GRID_TRACKSIZE ) );
nc->SetViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_VIASIZE ) );
nc->SetViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_VIADRILL ) );
nc->SetuViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_uVIASIZE ) );
nc->SetuViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_uVIADRILL ) );
nc->SetDiffPairWidth( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH ) );
nc->SetDiffPairGap( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_GAP ) );
}
nc->SetClearance( m_netclassGrid->GetUnitValue( aRow, GRID_CLEARANCE ) );
nc->SetTrackWidth( m_netclassGrid->GetUnitValue( aRow, GRID_TRACKSIZE ) );
nc->SetViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_VIASIZE ) );
nc->SetViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_VIADRILL ) );
nc->SetuViaDiameter( m_netclassGrid->GetUnitValue( aRow, GRID_uVIASIZE ) );
nc->SetuViaDrill( m_netclassGrid->GetUnitValue( aRow, GRID_uVIADRILL ) );
nc->SetDiffPairWidth( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_WIDTH ) );
nc->SetDiffPairGap( m_netclassGrid->GetUnitValue( aRow, GRID_DIFF_PAIR_GAP ) );
};
m_netSettings->m_NetClasses.clear();
@ -484,9 +488,6 @@ void PANEL_SETUP_NETCLASSES::OnNetclassGridMouseEvent( wxMouseEvent& aEvent )
wxString tip;
if( m_isEEschema && col > GRID_NAME )
col += EESCHEMA_COL_OFFSET;
switch( col )
{
case GRID_CLEARANCE: tip = _( "Minimum copper clearance" ); break;
@ -525,22 +526,8 @@ void PANEL_SETUP_NETCLASSES::OnAddNetclassClick( wxCommandEvent& event )
m_netclassGrid->AppendRows();
// Copy values of the default class:
if( m_isEEschema )
{
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 );
}
}
for( int col = 1; col < m_netclassGrid->GetNumberCols(); col++ )
m_netclassGrid->SetCellValue( row, col, m_netclassGrid->GetCellValue( 0, col ) );
m_netclassGrid->MakeCellVisible( 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,
long style, const wxString& name ) :
wxGrid( parent, id, pos, size, style, name ),
m_weOwnTable( false ),
m_unitsProvider( nullptr )
m_weOwnTable( false )
{
SetDefaultCellOverflow( false );
@ -158,20 +157,25 @@ void WX_GRID::onCellEditorHidden( wxGridEvent& aEvent )
{
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 col = aEvent.GetCol();
CallAfter(
[this, row, col]()
[this, row, col, unitsProvider]()
{
wxString stringValue = GetCellValue( row, col );
if( m_eval->Process( stringValue ) )
{
int val = m_unitsProvider->ValueFromString( m_eval->Result() );
wxString evalValue = m_unitsProvider->StringFromValue( val, true );
int val = unitsProvider->ValueFromString( m_eval->Result() );
wxString evalValue = unitsProvider->StringFromValue( val, true );
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_eval = std::make_unique<NUMERIC_EVALUATOR>( m_unitsProvider->GetUserUnits() );
m_unitsProviders[ aCol ] = aProvider;
if( !m_eval )
m_eval = std::make_unique<NUMERIC_EVALUATOR>( aProvider->GetUserUnits() );
}
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 );
if( alg::contains( m_autoEvalCols, aCol ) )
{
m_eval->SetDefaultUnits( m_unitsProvider->GetUserUnits() );
m_eval->SetDefaultUnits( unitsProvider->GetUserUnits() );
if( m_eval->Process( stringValue ) )
stringValue = m_eval->Result();
}
return m_unitsProvider->ValueFromString( stringValue );
return unitsProvider->ValueFromString( stringValue );
}
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

@ -68,11 +68,14 @@ private:
void AdjustAssignmentGridColumns( int aWidth );
private:
EDA_DRAW_FRAME* m_frame;
PAGED_DIALOG* m_parent;
bool m_isEEschema;
std::shared_ptr<NET_SETTINGS> m_netSettings;
std::set<wxString> m_netNames;
EDA_DRAW_FRAME* m_frame;
PAGED_DIALOG* m_parent;
bool m_isEEschema;
std::shared_ptr<NET_SETTINGS> m_netSettings;
std::set<wxString> m_netNames;
std::unique_ptr<UNITS_PROVIDER> m_schUnitsProvider;
std::unique_ptr<UNITS_PROVIDER> m_pcbUnitsProvider;
int* m_originalColWidths;
bool m_netclassesDirty; // The netclass drop-down menus need rebuilding

View File

@ -85,7 +85,7 @@ public:
* Set a UNITS_PROVIDER to enable use of unit- and eval-based Getters.
* @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; }
@ -156,7 +156,7 @@ protected:
protected:
bool m_weOwnTable;
UNITS_PROVIDER* m_unitsProvider;
std::map<int, UNITS_PROVIDER*> m_unitsProviders;
std::unique_ptr<NUMERIC_EVALUATOR> m_eval;
std::vector<int> m_autoEvalCols;