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 )
{
for( wxString signal : signals )
for( const wxString& signal : signals )
m_parent->AddMeasurement( wxString::Format( wxS( "MIN %s" ), signal ) );
}
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 ) );
}
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 ) );
}
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 ) );
}
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 ) );
}
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 ) );
}
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 ) );
}
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 ) );
}
else
@ -963,16 +963,7 @@ void SIM_PLOT_FRAME::rebuildSignalsList()
// Add user-defined signals
for( int ii = 0; ii < (int) m_userDefinedSignals.size(); ++ii )
{
static wxRegEx regEx( wxS( "(^|[^a-z0-9_])([VIP])\\(" ), wxRE_ICASE );
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 );
}
addSignal( m_userDefinedSignals[ii], wxString::Format( wxS( "user%d" ), ii ) );
}
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.
*/
@ -1165,10 +1150,35 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
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" ) )
addTrace( getTraceName( row ) );
addTrace( traceName, (SIM_TRACE_TYPE) traceType );
else
removeTrace( getTraceName( row ) );
removeTrace( traceName, (SIM_TRACE_TYPE) traceType );
// Update enabled/visible states of other controls
updateSignalsGrid();
@ -1177,7 +1187,8 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
else if( col == 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 )
{
@ -1191,9 +1202,11 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
{
for( int ii = 0; ii < m_signalsGrid->GetNumberRows(); ++ii )
{
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();
}
@ -1626,11 +1639,18 @@ void SIM_PLOT_FRAME::doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType )
void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector<wxString>& aNewSignals )
{
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
if( plotPanel )
{
for( const wxString& signal : m_userDefinedSignals )
{
if( !alg::contains( aNewSignals, signal ) )
removeTrace( m_userDefinedSignalToSpiceVecName[ signal ] );
plotPanel->DeleteTrace( m_userDefinedSignalToSpiceVecName[ signal ] );
}
plotPanel->GetPlotWin()->Fit();
}
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() )
return;
wxString baseSignal = aSignalName;
wxString gainSuffix = _( " (gain)" );
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( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() )
updateTrace( aSignalName, (SIM_TRACE_TYPE) aTraceType, plotPanel );
}
if( traceType != SPT_UNKNOWN )
void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName, SIM_TRACE_TYPE aTraceType )
{
if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() )
updateTrace( baseSignal, (SIM_TRACE_TYPE) traceType, plotPanel );
}
}
void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName )
{
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
if( !plotPanel )
return;
wxASSERT( plotPanel->TraceShown( aSignalName ) );
if( plotPanel->DeleteTrace( aSignalName ) )
OnModify();
plotPanel->DeleteTrace( getTraceTitle( aSignalName, aTraceType ) );
plotPanel->GetPlotWin()->Fit();
}
updateSignalsGrid();
updateCursors();
OnModify();
}
@ -1817,7 +1805,9 @@ void SIM_PLOT_FRAME::updateSignalsGrid()
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" ) );
@ -2053,9 +2043,18 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
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();
TRACE* trace = plotPanel ? plotPanel->GetTrace( name ) : nullptr;
@ -2063,17 +2062,16 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
if( version >= 4 && trace )
{
auto addCursor =
[]( int aCursorId, SIM_PLOT_PANEL* aPlotPanel, TRACE* aTrace, double x )
[&]( int aCursorId, TRACE* aTrace, double x )
{
CURSOR* cursor = new CURSOR( aTrace, aPlotPanel );
mpWindow* win = aPlotPanel->GetPlotWin();
CURSOR* cursor = new CURSOR( aTrace, plotPanel );
cursor->SetName( aTrace->GetName() );
cursor->SetName( name );
cursor->SetPen( wxPen( aTrace->GetTraceColour() ) );
cursor->SetCoordX( x );
aTrace->SetCursor( aCursorId, cursor );
win->AddLayer( cursor );
plotPanel->GetPlotWin()->AddLayer( cursor );
};
wxArrayString items = wxSplit( param, '|' );
@ -2097,7 +2095,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
parts[0].AfterFirst( '=' ).ToDouble( &val );
m_cursorFormats[0][0].FromString( parts[1] );
m_cursorFormats[0][1].FromString( parts[2] );
addCursor( 1, plotPanel, trace, val );
addCursor( 1, trace, val );
}
}
else if( item.StartsWith( wxS( "cursor2" ) ) )
@ -2110,7 +2108,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
parts[0].AfterFirst( '=' ).ToDouble( &val );
m_cursorFormats[1][0].FromString( parts[1] );
m_cursorFormats[1][1].FromString( parts[2] );
addCursor( 2, plotPanel, trace, val );
addCursor( 2, trace, val );
}
}
else if( item.StartsWith( wxS( "cursorD" ) ) )
@ -2165,6 +2163,28 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
LoadSimulator();
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() );
updateSignalsGrid();
updateCursors();
@ -2576,6 +2596,9 @@ void SIM_PLOT_FRAME::updateCursors()
auto formatValue =
[this]( double aValue, int aCursorId, int aCol ) -> wxString
{
if( !m_simFinished && aCol == 1 )
return wxS( "--" );
else
return SPICE_VALUE( aValue ).ToString( m_cursorFormats[ aCursorId ][ aCol ] );
};
@ -2843,7 +2866,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
if( placeholder.m_current )
updateTrace( placeholder.m_name, placeholder.m_type, plotPanel );
else
removeTrace( placeholder.m_name );
removeTrace( placeholder.m_name, placeholder.m_type );
}
rebuildSignalsGrid( m_filter->GetValue() );
@ -2890,6 +2913,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
m_schematicFrame->RefreshOperatingPointDisplay();
updateCursors();
for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row )
UpdateMeasurement( row );

View File

@ -262,13 +262,12 @@ private:
*/
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.
*/
wxString getTraceName( const wxString& aSignalName );
wxString getTraceName( int aRow );
/**
* 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.
*
* @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
* 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 aParam is the parameter for the device/net (e.g. I, Id, V).
* @param aPlotPanel is the panel that should receive the update.
*/
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 )
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 center = win->GetMarginLeft() + KiROUND( width * ( aCursorId == 1 ? 0.4 : 0.6 ) );
cursor->SetName( aName );
cursor->SetName( aSignalName );
cursor->SetX( center );
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.
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.
void ResetScales();