Try and sort out the mess that is trace names and trace titles.

Fixes https://gitlab.com/kicad/code/kicad/issues/14016
This commit is contained in:
Jeff Young 2023-02-26 17:09:56 +00:00
parent 51d46c0e73
commit beb177fa79
4 changed files with 120 additions and 96 deletions

View File

@ -237,42 +237,42 @@ void SIGNALS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
if( event.GetId() == MYID_MEASURE_MIN ) if( event.GetId() == MYID_MEASURE_MIN )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "MIN %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "MIN %s" ), signal ) );
} }
else if( event.GetId() == MYID_MEASURE_MAX ) else if( event.GetId() == MYID_MEASURE_MAX )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "MAX %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "MAX %s" ), signal ) );
} }
else if( event.GetId() == MYID_MEASURE_AVG ) else if( event.GetId() == MYID_MEASURE_AVG )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "AVG %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "AVG %s" ), signal ) );
} }
else if( event.GetId() == MYID_MEASURE_RMS ) else if( event.GetId() == MYID_MEASURE_RMS )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "RMS %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "RMS %s" ), signal ) );
} }
else if( event.GetId() == MYID_MEASURE_PP ) else if( event.GetId() == MYID_MEASURE_PP )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "PP %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "PP %s" ), signal ) );
} }
else if( event.GetId() == MYID_MEASURE_MIN_AT ) else if( event.GetId() == MYID_MEASURE_MIN_AT )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "MIN_AT %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "MIN_AT %s" ), signal ) );
} }
else if( event.GetId() == MYID_MEASURE_MAX_AT ) else if( event.GetId() == MYID_MEASURE_MAX_AT )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "MAX_AT %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "MAX_AT %s" ), signal ) );
} }
else if( event.GetId() == MYID_MEASURE_INTEGRAL ) else if( event.GetId() == MYID_MEASURE_INTEGRAL )
{ {
for( wxString signal : signals ) for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "INTEG %s" ), signal ) ); m_parent->AddMeasurement( wxString::Format( wxS( "INTEG %s" ), signal ) );
} }
else else
@ -963,16 +963,7 @@ void SIM_PLOT_FRAME::rebuildSignalsList()
// Add user-defined signals // Add user-defined signals
for( int ii = 0; ii < (int) m_userDefinedSignals.size(); ++ii ) for( int ii = 0; ii < (int) m_userDefinedSignals.size(); ++ii )
{ {
static wxRegEx regEx( wxS( "(^|[^a-z0-9_])([VIP])\\(" ), wxRE_ICASE ); addSignal( m_userDefinedSignals[ii], wxString::Format( wxS( "user%d" ), ii ) );
const wxString& signal = m_userDefinedSignals[ii];
if( regEx.Matches( signal ) )
{
wxString vecType = regEx.GetMatch( signal, 2 );
wxString spiceVecName = wxString::Format( wxS( "%s(user%d)" ), vecType, ii );
addSignal( signal, spiceVecName );
}
} }
std::sort( m_signals.begin(), m_signals.end(), std::sort( m_signals.begin(), m_signals.end(),
@ -1133,12 +1124,6 @@ wxString SIM_PLOT_FRAME::getTraceName( const wxString& aSignalName )
} }
wxString SIM_PLOT_FRAME::getTraceName( int aRow )
{
return getTraceName( m_signalsGrid->GetCellValue( aRow, COL_SIGNAL_NAME ) );
}
/** /**
* AC-small-signal analyses have two traces per signal, so we suffix the names. * AC-small-signal analyses have two traces per signal, so we suffix the names.
*/ */
@ -1165,10 +1150,35 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
if( col == COL_SIGNAL_SHOW ) if( col == COL_SIGNAL_SHOW )
{ {
wxString gainSuffix = _( " (gain)" );
wxString phaseSuffix = _( " (phase)" );
wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME );
wxUniChar firstChar = signal.Upper()[0];
wxString traceName = getTraceName( signal );
int traceType = SPT_UNKNOWN;
if( firstChar == 'V' )
traceType = SPT_VOLTAGE;
else if( firstChar == 'I' )
traceType = SPT_CURRENT;
else if( firstChar == 'P' )
traceType = SPT_POWER;
if( traceName.EndsWith( gainSuffix ) )
{
traceType |= SPT_AC_MAG;
traceName = traceName.Left( traceName.Length() - gainSuffix.Length() );
}
else if( traceName.EndsWith( phaseSuffix ) )
{
traceType |= SPT_AC_PHASE;
traceName = traceName.Left( traceName.Length() - phaseSuffix.Length() );
}
if( text == wxS( "1" ) ) if( text == wxS( "1" ) )
addTrace( getTraceName( row ) ); addTrace( traceName, (SIM_TRACE_TYPE) traceType );
else else
removeTrace( getTraceName( row ) ); removeTrace( traceName, (SIM_TRACE_TYPE) traceType );
// Update enabled/visible states of other controls // Update enabled/visible states of other controls
updateSignalsGrid(); updateSignalsGrid();
@ -1177,7 +1187,8 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
else if( col == COL_SIGNAL_COLOR ) else if( col == COL_SIGNAL_COLOR )
{ {
KIGFX::COLOR4D color( m_signalsGrid->GetCellValue( row, COL_SIGNAL_COLOR ) ); KIGFX::COLOR4D color( m_signalsGrid->GetCellValue( row, COL_SIGNAL_COLOR ) );
TRACE* trace = plot->GetTrace( getTraceName( row ) ); wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME );
TRACE* trace = plot->GetTrace( getTraceName( signal ) );
if( trace ) if( trace )
{ {
@ -1191,9 +1202,11 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
{ {
for( int ii = 0; ii < m_signalsGrid->GetNumberRows(); ++ii ) for( int ii = 0; ii < m_signalsGrid->GetNumberRows(); ++ii )
{ {
bool enable = ii == row && text == wxS( "1" ); wxString signal = m_signalsGrid->GetCellValue( ii, COL_SIGNAL_NAME );
int id = col == COL_CURSOR_1 ? 1 : 2;
bool enable = ii == row && text == wxS( "1" );
plot->EnableCursor( getTraceName( ii ), col == COL_CURSOR_1 ? 1 : 2, enable ); plot->EnableCursor( signal, getTraceName( signal ), id, enable );
OnModify(); OnModify();
} }
@ -1627,10 +1640,17 @@ void SIM_PLOT_FRAME::doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType )
void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector<wxString>& aNewSignals ) void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector<wxString>& aNewSignals )
{ {
for( const wxString& signal : m_userDefinedSignals ) SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
if( plotPanel )
{ {
if( !alg::contains( aNewSignals, signal ) ) for( const wxString& signal : m_userDefinedSignals )
removeTrace( m_userDefinedSignalToSpiceVecName[ signal ] ); {
if( !alg::contains( aNewSignals, signal ) )
plotPanel->DeleteTrace( m_userDefinedSignalToSpiceVecName[ signal ] );
}
plotPanel->GetPlotWin()->Fit();
} }
m_userDefinedSignals = aNewSignals; m_userDefinedSignals = aNewSignals;
@ -1645,59 +1665,27 @@ void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector<wxString>& aNewSig
} }
void SIM_PLOT_FRAME::addTrace( const wxString& aSignalName ) void SIM_PLOT_FRAME::addTrace( const wxString& aSignalName, SIM_TRACE_TYPE aTraceType )
{ {
if( aSignalName.IsEmpty() ) if( aSignalName.IsEmpty() )
return; return;
wxString baseSignal = aSignalName; if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() )
wxString gainSuffix = _( " (gain)" ); updateTrace( aSignalName, (SIM_TRACE_TYPE) aTraceType, plotPanel );
wxString phaseSuffix = _( " (phase)" );
wxUniChar firstChar = aSignalName.Upper()[0];
int traceType = SPT_UNKNOWN;
if( firstChar == 'V' )
traceType = SPT_VOLTAGE;
else if( firstChar == 'I' )
traceType = SPT_CURRENT;
else if( firstChar == 'P' )
traceType = SPT_POWER;
if( aSignalName.EndsWith( gainSuffix ) )
{
traceType |= SPT_AC_MAG;
baseSignal = aSignalName.Left( aSignalName.Length() - gainSuffix.Length() );
}
else if( aSignalName.EndsWith( phaseSuffix ) )
{
traceType |= SPT_AC_PHASE;
baseSignal = aSignalName.Left( aSignalName.Length() - phaseSuffix.Length() );
}
if( traceType != SPT_UNKNOWN )
{
if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() )
updateTrace( baseSignal, (SIM_TRACE_TYPE) traceType, plotPanel );
}
} }
void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName ) void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName, SIM_TRACE_TYPE aTraceType )
{ {
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() )
{
if( !plotPanel ) plotPanel->DeleteTrace( getTraceTitle( aSignalName, aTraceType ) );
return; plotPanel->GetPlotWin()->Fit();
}
wxASSERT( plotPanel->TraceShown( aSignalName ) );
if( plotPanel->DeleteTrace( aSignalName ) )
OnModify();
plotPanel->GetPlotWin()->Fit();
updateSignalsGrid(); updateSignalsGrid();
updateCursors(); updateCursors();
OnModify();
} }
@ -1817,7 +1805,9 @@ void SIM_PLOT_FRAME::updateSignalsGrid()
for( int row = 0; row < m_signalsGrid->GetNumberRows(); ++row ) for( int row = 0; row < m_signalsGrid->GetNumberRows(); ++row )
{ {
if( TRACE* trace = plot ? plot->GetTrace( getTraceName( row ) ) : nullptr ) wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME );
if( TRACE* trace = plot ? plot->GetTrace( getTraceName( signal ) ) : nullptr )
{ {
m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) ); m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) );
@ -2053,9 +2043,18 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
return false; return false;
} }
param = file.GetNextLine(); wxString baseName = name;
wxString gainSuffix = _( " (gain)" );
wxString phaseSuffix = _( " (phase)" );
addTrace( name ); if( baseName.EndsWith( gainSuffix ) )
baseName = baseName.Left( baseName.Length() - gainSuffix.Length() );
else if( baseName.EndsWith( phaseSuffix ) )
baseName = baseName.Left( baseName.Length() - phaseSuffix.Length() );
addTrace( baseName, (SIM_TRACE_TYPE) traceType );
param = file.GetNextLine();
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
TRACE* trace = plotPanel ? plotPanel->GetTrace( name ) : nullptr; TRACE* trace = plotPanel ? plotPanel->GetTrace( name ) : nullptr;
@ -2063,17 +2062,16 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
if( version >= 4 && trace ) if( version >= 4 && trace )
{ {
auto addCursor = auto addCursor =
[]( int aCursorId, SIM_PLOT_PANEL* aPlotPanel, TRACE* aTrace, double x ) [&]( int aCursorId, TRACE* aTrace, double x )
{ {
CURSOR* cursor = new CURSOR( aTrace, aPlotPanel ); CURSOR* cursor = new CURSOR( aTrace, plotPanel );
mpWindow* win = aPlotPanel->GetPlotWin();
cursor->SetName( aTrace->GetName() ); cursor->SetName( name );
cursor->SetPen( wxPen( aTrace->GetTraceColour() ) ); cursor->SetPen( wxPen( aTrace->GetTraceColour() ) );
cursor->SetCoordX( x ); cursor->SetCoordX( x );
aTrace->SetCursor( aCursorId, cursor ); aTrace->SetCursor( aCursorId, cursor );
win->AddLayer( cursor ); plotPanel->GetPlotWin()->AddLayer( cursor );
}; };
wxArrayString items = wxSplit( param, '|' ); wxArrayString items = wxSplit( param, '|' );
@ -2097,7 +2095,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
parts[0].AfterFirst( '=' ).ToDouble( &val ); parts[0].AfterFirst( '=' ).ToDouble( &val );
m_cursorFormats[0][0].FromString( parts[1] ); m_cursorFormats[0][0].FromString( parts[1] );
m_cursorFormats[0][1].FromString( parts[2] ); m_cursorFormats[0][1].FromString( parts[2] );
addCursor( 1, plotPanel, trace, val ); addCursor( 1, trace, val );
} }
} }
else if( item.StartsWith( wxS( "cursor2" ) ) ) else if( item.StartsWith( wxS( "cursor2" ) ) )
@ -2110,7 +2108,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
parts[0].AfterFirst( '=' ).ToDouble( &val ); parts[0].AfterFirst( '=' ).ToDouble( &val );
m_cursorFormats[1][0].FromString( parts[1] ); m_cursorFormats[1][0].FromString( parts[1] );
m_cursorFormats[1][1].FromString( parts[2] ); m_cursorFormats[1][1].FromString( parts[2] );
addCursor( 2, plotPanel, trace, val ); addCursor( 2, trace, val );
} }
} }
else if( item.StartsWith( wxS( "cursorD" ) ) ) else if( item.StartsWith( wxS( "cursorD" ) ) )
@ -2165,6 +2163,28 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
LoadSimulator(); LoadSimulator();
rebuildSignalsList(); rebuildSignalsList();
if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() )
{
for( const auto& [ traceName, trace ] : plotPanel->GetTraces() )
{
for( int cursorId : { 1, 2 } )
{
if( CURSOR* cursor = trace->GetCursor( cursorId ) )
{
for( const auto& [ signalName, vecName ] : m_userDefinedSignalToSpiceVecName )
{
if( vecName == traceName )
{
cursor->SetName( signalName );
break;
}
}
}
}
}
}
rebuildSignalsGrid( m_filter->GetValue() ); rebuildSignalsGrid( m_filter->GetValue() );
updateSignalsGrid(); updateSignalsGrid();
updateCursors(); updateCursors();
@ -2576,7 +2596,10 @@ void SIM_PLOT_FRAME::updateCursors()
auto formatValue = auto formatValue =
[this]( double aValue, int aCursorId, int aCol ) -> wxString [this]( double aValue, int aCursorId, int aCol ) -> wxString
{ {
return SPICE_VALUE( aValue ).ToString( m_cursorFormats[ aCursorId ][ aCol ] ); if( !m_simFinished && aCol == 1 )
return wxS( "--" );
else
return SPICE_VALUE( aValue ).ToString( m_cursorFormats[ aCursorId ][ aCol ] );
}; };
for( const auto& [name, trace] : plotPanel->GetTraces() ) for( const auto& [name, trace] : plotPanel->GetTraces() )
@ -2843,7 +2866,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
if( placeholder.m_current ) if( placeholder.m_current )
updateTrace( placeholder.m_name, placeholder.m_type, plotPanel ); updateTrace( placeholder.m_name, placeholder.m_type, plotPanel );
else else
removeTrace( placeholder.m_name ); removeTrace( placeholder.m_name, placeholder.m_type );
} }
rebuildSignalsGrid( m_filter->GetValue() ); rebuildSignalsGrid( m_filter->GetValue() );
@ -2890,6 +2913,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
m_schematicFrame->RefreshOperatingPointDisplay(); m_schematicFrame->RefreshOperatingPointDisplay();
updateCursors();
for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row ) for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row )
UpdateMeasurement( row ); UpdateMeasurement( row );

View File

@ -262,13 +262,12 @@ private:
*/ */
void doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType ); void doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType );
void addTrace( const wxString& aSignalName ); void addTrace( const wxString& aSignalName, SIM_TRACE_TYPE aType );
/** /**
* For user-defined traces we have a separate SPICE vector name. * For user-defined traces we have a separate SPICE vector name.
*/ */
wxString getTraceName( const wxString& aSignalName ); wxString getTraceName( const wxString& aSignalName );
wxString getTraceName( int aRow );
/** /**
* AC-small-signal analyses have specific trace titles. Other analyses use the raw signal * AC-small-signal analyses have specific trace titles. Other analyses use the raw signal
@ -279,17 +278,16 @@ private:
/** /**
* Remove a plot with a specific title. * Remove a plot with a specific title.
* *
* @param aSignalName is the full plot title (e.g. I(Net-C1-Pad1)). * @param aName is the SPICE vector name, such as "I(Net-C1-Pad1)".
*/ */
void removeTrace( const wxString& aSignalName ); void removeTrace( const wxString& aName, SIM_TRACE_TYPE aTraceType );
/** /**
* Update a trace in a particular SIM_PLOT_PANEL. If the panel does not contain the given * Update a trace in a particular SIM_PLOT_PANEL. If the panel does not contain the given
* trace, then add it. * trace, then add it.
* *
* @param aName is the device/net name. * @param aName is the SPICE vector name, such as "I(Net-C1-Pad1)".
* @param aTraceType describes the type of plot. * @param aTraceType describes the type of plot.
* @param aParam is the parameter for the device/net (e.g. I, Id, V).
* @param aPlotPanel is the panel that should receive the update. * @param aPlotPanel is the panel that should receive the update.
*/ */
void updateTrace( const wxString& aName, SIM_TRACE_TYPE aTraceType, SIM_PLOT_PANEL* aPlotPanel ); void updateTrace( const wxString& aName, SIM_TRACE_TYPE aTraceType, SIM_PLOT_PANEL* aPlotPanel );

View File

@ -802,9 +802,10 @@ bool SIM_PLOT_PANEL::DeleteTrace( const wxString& aName )
} }
void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, int aCursorId, bool aEnable ) void SIM_PLOT_PANEL::EnableCursor( const wxString& aSignalName, const wxString aTraceName,
int aCursorId, bool aEnable )
{ {
TRACE* t = GetTrace( aName ); TRACE* t = GetTrace( aTraceName );
if( t == nullptr || t->HasCursor( aCursorId ) == aEnable ) if( t == nullptr || t->HasCursor( aCursorId ) == aEnable )
return; return;
@ -816,7 +817,7 @@ void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, int aCursorId, bool aE
int width = win->GetXScreen() - win->GetMarginLeft() - win->GetMarginRight(); int width = win->GetXScreen() - win->GetMarginLeft() - win->GetMarginRight();
int center = win->GetMarginLeft() + KiROUND( width * ( aCursorId == 1 ? 0.4 : 0.6 ) ); int center = win->GetMarginLeft() + KiROUND( width * ( aCursorId == 1 ? 0.4 : 0.6 ) );
cursor->SetName( aName ); cursor->SetName( aSignalName );
cursor->SetX( center ); cursor->SetX( center );
cursor->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) ); cursor->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) );

View File

@ -282,7 +282,7 @@ public:
} }
///< Toggle cursor for a particular trace. ///< Toggle cursor for a particular trace.
void EnableCursor( const wxString& aName, int aCursorId, bool aEnable ); void EnableCursor( const wxString& aSignalName, const wxString aTraceName, int aCursorId, bool aEnable );
///< Reset scale ranges to fit the current traces. ///< Reset scale ranges to fit the current traces.
void ResetScales(); void ResetScales();