From 83dd06e5d1c47b97b4c52ae200fb2f5b90d9fbf5 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 12 Feb 2023 14:55:00 +0000 Subject: [PATCH] Allow opening of workbook when simulation frame is opened. This involved splitting creation of traces from setting of trace data. Also renamed SIM_WORKBOOK to SIM_NOTEBOOK. This class is a subclass of wxAiuNotebook and represents the collection of simulation plot tabs. It is NOT the same thing as a simulation workbook, which contains other stuff such as measurements, plotted signals, colours, etc. This also removes a bunch of "friend" declarations. --- eeschema/CMakeLists.txt | 2 +- .../{sim_workbook.cpp => sim_notebook.cpp} | 74 +-- .../sim/{sim_workbook.h => sim_notebook.h} | 57 +-- eeschema/sim/sim_panel_base.h | 16 +- eeschema/sim/sim_plot_frame.cpp | 422 +++++++++--------- eeschema/sim/sim_plot_frame.h | 36 +- eeschema/sim/sim_plot_frame_base.cpp | 22 +- eeschema/sim/sim_plot_frame_base.fbp | 8 +- eeschema/sim/sim_plot_frame_base.h | 4 +- eeschema/sim/sim_plot_panel.cpp | 86 ++-- eeschema/sim/sim_plot_panel.h | 10 +- 11 files changed, 328 insertions(+), 409 deletions(-) rename eeschema/sim/{sim_workbook.cpp => sim_notebook.cpp} (54%) rename eeschema/sim/{sim_workbook.h => sim_notebook.h} (51%) diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index a0d72f5397..8d839e53ff 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -354,13 +354,13 @@ if( KICAD_SPICE ) tools/simulator_control.cpp sim/ngspice_circuit_model.cpp sim/ngspice.cpp + sim/sim_notebook.cpp sim/sim_panel_base.cpp sim/sim_plot_colors.cpp sim/sim_plot_frame.cpp sim/sim_plot_frame_base.cpp sim/sim_plot_panel.cpp sim/sim_property.cpp - sim/sim_workbook.cpp sim/spice_simulator.cpp sim/spice_value.cpp sim/toolbars_sim_plot_frame.cpp diff --git a/eeschema/sim/sim_workbook.cpp b/eeschema/sim/sim_notebook.cpp similarity index 54% rename from eeschema/sim/sim_workbook.cpp rename to eeschema/sim/sim_notebook.cpp index f4c7c8dafb..5a58a2c3a9 100644 --- a/eeschema/sim/sim_workbook.cpp +++ b/eeschema/sim/sim_notebook.cpp @@ -22,28 +22,25 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include -SIM_WORKBOOK::SIM_WORKBOOK() : wxAuiNotebook() -{ - m_modified = false; -} +SIM_NOTEBOOK::SIM_NOTEBOOK() : + wxAuiNotebook() +{ } -SIM_WORKBOOK::SIM_WORKBOOK( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos, const wxSize& +SIM_NOTEBOOK::SIM_NOTEBOOK( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos, const wxSize& aSize, long aStyle ) : wxAuiNotebook( aParent, aId, aPos, aSize, aStyle ) -{ - m_modified = false; -} +{ } -bool SIM_WORKBOOK::AddPage( wxWindow* page, const wxString& caption, bool select, const wxBitmap& bitmap ) +bool SIM_NOTEBOOK::AddPage( wxWindow* page, const wxString& caption, bool select, const wxBitmap& bitmap ) { - if( wxAuiNotebook::AddPage( page, caption, select, bitmap ) ) + if( wxAuiNotebook::AddPage( page, caption, select, bitmap ) ) { - setModified(); + wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) ); return true; } @@ -51,11 +48,11 @@ bool SIM_WORKBOOK::AddPage( wxWindow* page, const wxString& caption, bool select } -bool SIM_WORKBOOK::AddPage( wxWindow* page, const wxString& text, bool select, int imageId ) +bool SIM_NOTEBOOK::AddPage( wxWindow* page, const wxString& text, bool select, int imageId ) { if( wxAuiNotebook::AddPage( page, text, select, imageId ) ) { - setModified(); + wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) ); return true; } @@ -63,11 +60,11 @@ bool SIM_WORKBOOK::AddPage( wxWindow* page, const wxString& text, bool select, i } -bool SIM_WORKBOOK::DeleteAllPages() +bool SIM_NOTEBOOK::DeleteAllPages() { if( wxAuiNotebook::DeleteAllPages() ) { - setModified(); + wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) ); return true; } @@ -75,11 +72,11 @@ bool SIM_WORKBOOK::DeleteAllPages() } -bool SIM_WORKBOOK::DeletePage( size_t page ) +bool SIM_NOTEBOOK::DeletePage( size_t page ) { if( wxAuiNotebook::DeletePage( page ) ) { - setModified(); + wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) ); return true; } @@ -87,45 +84,4 @@ bool SIM_WORKBOOK::DeletePage( size_t page ) } -bool SIM_WORKBOOK::AddTrace( SIM_PLOT_PANEL* aPlotPanel, const wxString& aTitle, - const wxString& aName, int aPoints, const double* aX, const double* aY, - SIM_TRACE_TYPE aType ) -{ - if( aPoints && aPlotPanel->addTrace( aTitle, aName, aPoints, aX, aY, aType ) ) - { - setModified(); - return true; - } - - return false; -} - - -bool SIM_WORKBOOK::DeleteTrace( SIM_PLOT_PANEL* aPlotPanel, const wxString& aName ) -{ - if( aPlotPanel->deleteTrace( aName ) ) - { - setModified(); - return true; - } - - return false; -} - - -void SIM_WORKBOOK::ClrModified() -{ - m_modified = false; - wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_CLR_MODIFIED ) ); -} - - -void SIM_WORKBOOK::setModified() -{ - m_modified = true; - wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) ); -} - - wxDEFINE_EVENT( EVT_WORKBOOK_MODIFIED, wxCommandEvent ); -wxDEFINE_EVENT( EVT_WORKBOOK_CLR_MODIFIED, wxCommandEvent ); diff --git a/eeschema/sim/sim_workbook.h b/eeschema/sim/sim_notebook.h similarity index 51% rename from eeschema/sim/sim_workbook.h rename to eeschema/sim/sim_notebook.h index 4b3d2ddbce..c84b0c61f0 100644 --- a/eeschema/sim/sim_workbook.h +++ b/eeschema/sim/sim_notebook.h @@ -22,69 +22,32 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __SIM_WORKBOOK__ -#define __SIM_WORKBOOK__ +#ifndef SIM_NOTEBOOK_H +#define SIM_NOTEBOOK_H #include #include #include -class SIM_WORKBOOK : public wxAuiNotebook +class SIM_NOTEBOOK : public wxAuiNotebook { public: - SIM_WORKBOOK(); - SIM_WORKBOOK( wxWindow* aParent, wxWindowID aId=wxID_ANY, const wxPoint& - aPos=wxDefaultPosition, const wxSize& aSize=wxDefaultSize, long - aStyle=wxAUI_NB_DEFAULT_STYLE ); + SIM_NOTEBOOK(); + SIM_NOTEBOOK( wxWindow* aParent, wxWindowID aId = wxID_ANY, + const wxPoint& aPos = wxDefaultPosition, const wxSize& aSize = wxDefaultSize, + long aStyle = wxAUI_NB_DEFAULT_STYLE ); // Methods from wxAuiNotebook - bool AddPage( wxWindow* aPage, const wxString& aCaption, bool aSelect=false, const wxBitmap& aBitmap=wxNullBitmap ); + bool AddPage( wxWindow* aPage, const wxString& aCaption, bool aSelect=false, + const wxBitmap& aBitmap = wxNullBitmap ); bool AddPage( wxWindow* aPage, const wxString& aText, bool aSelect, int aImageId ) override; bool DeleteAllPages() override; bool DeletePage( size_t aPage ) override; - - // Custom methods - - bool AddTrace( SIM_PLOT_PANEL* aPlotPanel, const wxString& aTitle, const wxString& aName, - int aPoints, const double* aX, const double* aY, SIM_TRACE_TYPE aType ); - bool DeleteTrace( SIM_PLOT_PANEL* aPlotPanel, const wxString& aName ); - - void SetSimCommand( SIM_PANEL_BASE* aPlotPanel, const wxString& aSimCommand ) - { - aPlotPanel->setSimCommand( aSimCommand ); - setModified(); - } - - const wxString& GetSimCommand( const SIM_PANEL_BASE* aPlotPanel ) - { - return aPlotPanel->getSimCommand(); - } - - void SetSimOptions( SIM_PANEL_BASE* aPlotPanel, int aOptions ) - { - aPlotPanel->setSimOptions( aOptions ); - setModified(); - } - - int GetSimOptions( const SIM_PANEL_BASE* aPlotPanel ) - { - return aPlotPanel->getSimOptions(); - } - - void ClrModified(); - bool IsModified() const { return m_modified; } - -private: - void setModified(); - - ///< Dirty bit, indicates something in the workbook has changed - bool m_modified; }; wxDECLARE_EVENT( EVT_WORKBOOK_MODIFIED, wxCommandEvent ); -wxDECLARE_EVENT( EVT_WORKBOOK_CLR_MODIFIED, wxCommandEvent ); -#endif // __SIM_WORKBOOK__ +#endif // SIM_NOTEBOOK_H diff --git a/eeschema/sim/sim_panel_base.h b/eeschema/sim/sim_panel_base.h index ccee79b552..8b5ea65ccb 100644 --- a/eeschema/sim/sim_panel_base.h +++ b/eeschema/sim/sim_panel_base.h @@ -35,8 +35,6 @@ class SIM_PANEL_BASE : public wxWindow { - friend class SIM_WORKBOOK; - public: SIM_PANEL_BASE(); SIM_PANEL_BASE( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id, @@ -50,14 +48,8 @@ public: SIM_TYPE GetType() const; -protected: - // We use `protected` here because members should be accessible from outside only through a - // workbook object, to prevent anyone from modifying the state without its knowledge. Otherwise - // we risk some things not getting saved. - - const wxString& getSimCommand() const { return m_simCommand; } - - void setSimCommand( const wxString& aSimCommand ) + const wxString& GetSimCommand() const { return m_simCommand; } + void SetSimCommand( const wxString& aSimCommand ) { wxCHECK_RET( GetType() == NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ), "Cannot change the type of simulation of the existing plot panel" ); @@ -65,8 +57,8 @@ protected: m_simCommand = aSimCommand; } - const int getSimOptions() const { return m_simOptions; } - void setSimOptions( int aOptions ) { m_simOptions = aOptions; } + const int GetSimOptions() const { return m_simOptions; } + void SetSimOptions( int aOptions ) { m_simOptions = aOptions; } private: wxString m_simCommand; diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index c0319033cf..8966d7365d 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -330,7 +330,8 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_darkMode( true ), m_plotNumber( 0 ), m_simFinished( false ), - m_outputCounter( 1 ) + m_outputCounter( 1 ), + m_workbookModified( false ) { SetKiway( this, aKiway ); @@ -415,12 +416,11 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : Bind( EVT_SIM_FINISHED, &SIM_PLOT_FRAME::onSimFinished, this ); Bind( EVT_SIM_CURSOR_UPDATE, &SIM_PLOT_FRAME::onCursorUpdate, this ); - Bind( EVT_WORKBOOK_MODIFIED, &SIM_PLOT_FRAME::onWorkbookModified, this ); - Bind( EVT_WORKBOOK_CLR_MODIFIED, &SIM_PLOT_FRAME::onWorkbookClrModified, this ); + Bind( EVT_WORKBOOK_MODIFIED, &SIM_PLOT_FRAME::onNotebookModified, this ); #ifndef wxHAS_NATIVE_TABART // Default non-native tab art has ugly gradients we don't want - m_workbook->SetArtProvider( new wxAuiSimpleTabArt() ); + m_plotNotebook->SetArtProvider( new wxAuiSimpleTabArt() ); #endif // Ensure new items are taken in account by sizers: @@ -482,16 +482,16 @@ void SIM_PLOT_FRAME::ShowChangedLanguage() updateTitle(); - for( int ii = 0; ii < (int) m_workbook->GetPageCount(); ++ii ) + for( int ii = 0; ii < (int) m_plotNotebook->GetPageCount(); ++ii ) { - SIM_PANEL_BASE* plot = dynamic_cast( m_workbook->GetPage( ii ) ); + SIM_PANEL_BASE* plot = dynamic_cast( m_plotNotebook->GetPage( ii ) ); plot->OnLanguageChanged(); wxString pageTitle( m_simulator->TypeToName( plot->GetType(), true ) ); pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), ii+1 /* 1-based */ ) ); - m_workbook->SetPageText( ii, pageTitle ); + m_plotNotebook->SetPageText( ii, pageTitle ); } m_filter->SetHint( _( "Filter" ) ); @@ -582,19 +582,14 @@ WINDOW_SETTINGS* SIM_PLOT_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg ) void SIM_PLOT_FRAME::initWorkbook() { - // Removed for the time being. We cannot run the simulation on simulator launch, as it may - // take a lot of time, confusing the user. - // TODO: Change workbook loading routines so that they don't run the simulation until the user - // initiates it. - - /*if( !m_simulator->Settings()->GetWorkbookFilename().IsEmpty() ) + if( !m_simulator->Settings()->GetWorkbookFilename().IsEmpty() ) { wxFileName filename = m_simulator->Settings()->GetWorkbookFilename(); filename.SetPath( Prj().GetProjectPath() ); - if( !loadWorkbook( filename.GetFullPath() ) ) + if( !LoadWorkbook( filename.GetFullPath() ) ) m_simulator->Settings()->SetWorkbookFilename( "" ); - }*/ + } } @@ -614,7 +609,7 @@ void SIM_PLOT_FRAME::updateTitle() readOnly = !filename.IsFileWritable(); } - if( m_workbook->IsModified() ) + if( m_workbookModified ) title = wxT( "*" ) + filename.GetName(); else title = filename.GetName(); @@ -721,6 +716,92 @@ void SIM_PLOT_FRAME::rebuildSignalsGrid( wxString aFilter ) } +void SIM_PLOT_FRAME::rebuildSignalsList() +{ + m_signals.clear(); + + int options = GetCurrentOptions(); + SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( GetCurrentSimCommand() ); + wxString unconnected = wxString( wxS( "unconnected-(" ) ); + + unconnected.Replace( '(', '_' ); // Convert to SPICE markup + + if( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES ) + { + for( const std::string& net : m_circuitModel->GetNets() ) + { + // netnames are escaped (can contain "{slash}" for '/') Unscape them: + wxString netname = UnescapeString( net ); + + if( netname == "GND" || netname == "0" || netname.StartsWith( unconnected ) ) + continue; + + if( simType == ST_AC ) + { + m_signals.push_back( wxString::Format( _( "V(%s) (gain)" ), netname ) ); + m_signals.push_back( wxString::Format( _( "V(%s) (phase)" ), netname ) ); + } + else + { + m_signals.push_back( wxString::Format( "V(%s)", netname ) ); + } + } + } + + if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS ) + && ( simType == ST_TRANSIENT || simType == ST_DC ) ) + { + for( const SPICE_ITEM& item : m_circuitModel->GetItems() ) + { + // Add all possible currents for the device. + for( const std::string& name : item.model->SpiceGenerator().CurrentNames( item ) ) + m_signals.push_back( name ); + } + } + + if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS ) + && ( simType == ST_TRANSIENT || simType == ST_DC ) ) + { + for( const SPICE_ITEM& item : m_circuitModel->GetItems() ) + { + if( item.model->GetPinCount() >= 2 ) + { + wxString name = item.model->SpiceGenerator().ItemName( item ); + m_signals.push_back( wxString::Format( wxS( "P(%s)" ), name ) ); + } + } + } + + // Add .PROBE directives + for( const wxString& directive : m_circuitModel->GetDirectives() ) + { + wxString directiveParams; + + if( directive.Upper().StartsWith( wxS( ".PROBE" ), &directiveParams ) ) + m_signals.push_back( directiveParams.Trim( false ) ); + } +} + + +bool SIM_PLOT_FRAME::LoadSimulator() +{ + wxString errors; + WX_STRING_REPORTER reporter( &errors ); + + if( !m_schematicFrame->ReadyToNetlist( _( "Simulator requires a fully annotated schematic." ) ) ) + return false; + + if( !m_simulator->Attach( m_circuitModel, reporter ) ) + { + DisplayErrorMessage( this, _( "Errors during netlist generation.\n\n" ) + + errors ); + return false; + } + + return true; +} + + void SIM_PLOT_FRAME::StartSimulation() { if( m_circuitModel->CommandToSimType( GetCurrentSimCommand() ) == ST_UNKNOWN ) @@ -739,11 +820,11 @@ void SIM_PLOT_FRAME::StartSimulation() if( !plotWindow ) { plotWindow = NewPlotPanel( schTextSimCommand, m_circuitModel->GetSimOptions() ); - m_workbook->SetSimCommand( plotWindow, schTextSimCommand ); + m_workbookModified = true; } else { - m_circuitModel->SetSimCommandOverride( m_workbook->GetSimCommand( plotWindow ) ); + m_circuitModel->SetSimCommandOverride( plotWindow->GetSimCommand() ); if( plotWindow->GetType() == schTextSimType && schTextSimCommand != m_circuitModel->GetLastSchTextSimCommand() ) @@ -752,95 +833,27 @@ void SIM_PLOT_FRAME::StartSimulation() "Do you wish to update the Simulation Command?" ) ) ) { m_circuitModel->SetSimCommandOverride( wxEmptyString ); - m_workbook->SetSimCommand( plotWindow, schTextSimCommand ); + plotWindow->SetSimCommand( schTextSimCommand ); + m_workbookModified = true; } } } m_circuitModel->SetSimOptions( GetCurrentOptions() ); - wxString errors; - WX_STRING_REPORTER reporter( &errors ); - - if( !m_schematicFrame->ReadyToNetlist( _( "Simulator requires a fully annotated schematic." ) ) - || !m_simulator->Attach( m_circuitModel, reporter ) ) - { - DisplayErrorMessage( this, _( "Errors during netlist generation; simulation aborted.\n\n" ) - + errors ); + if( !LoadSimulator() ) return; - } + + rebuildSignalsList(); + rebuildSignalsGrid( m_filter->GetValue() ); std::unique_lock simulatorLock( m_simulator->GetMutex(), std::try_to_lock ); if( simulatorLock.owns_lock() ) { wxBusyCursor toggle; - wxString unconnected = wxString( wxS( "unconnected-(" ) ); - - unconnected.Replace( '(', '_' ); // Convert to SPICE markup m_simConsole->Clear(); - m_signals.clear(); - - int options = m_circuitModel->GetSimOptions(); - SIM_TYPE simType = m_circuitModel->GetSimType(); - - if( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES ) - { - for( const std::string& net : m_circuitModel->GetNets() ) - { - // netnames are escaped (can contain "{slash}" for '/') Unscape them: - wxString netname = UnescapeString( net ); - - if( netname == "GND" || netname == "0" || netname.StartsWith( unconnected ) ) - continue; - - if( simType == ST_AC ) - { - m_signals.push_back( wxString::Format( _( "V(%s) (gain)" ), netname ) ); - m_signals.push_back( wxString::Format( _( "V(%s) (phase)" ), netname ) ); - } - else - { - m_signals.push_back( wxString::Format( "V(%s)", netname ) ); - } - } - } - - if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS ) - && ( simType == ST_TRANSIENT || simType == ST_DC ) ) - { - for( const SPICE_ITEM& item : m_circuitModel->GetItems() ) - { - // Add all possible currents for the device. - for( const std::string& name : item.model->SpiceGenerator().CurrentNames( item ) ) - m_signals.push_back( name ); - } - } - - if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS ) - && ( simType == ST_TRANSIENT || simType == ST_DC ) ) - { - for( const SPICE_ITEM& item : m_circuitModel->GetItems() ) - { - if( item.model->GetPinCount() >= 2 ) - { - wxString name = item.model->SpiceGenerator().ItemName( item ); - m_signals.push_back( wxString::Format( wxS( "P(%s)" ), name ) ); - } - } - } - - // Add .PROBE directives - for( const wxString& directive : m_circuitModel->GetDirectives() ) - { - wxString directiveParams; - - if( directive.Upper().StartsWith( wxS( ".PROBE" ), &directiveParams ) ) - m_signals.push_back( directiveParams.Trim( false ) ); - } - - rebuildSignalsGrid( m_filter->GetValue() ); applyTuners(); @@ -862,7 +875,7 @@ SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( const wxString& aSimCommand, int a if( SIM_PANEL_BASE::IsPlottable( simType ) ) { - SIM_PLOT_PANEL* panel = new SIM_PLOT_PANEL( aSimCommand, aOptions, m_workbook, wxID_ANY ); + SIM_PLOT_PANEL* panel = new SIM_PLOT_PANEL( aSimCommand, aOptions, m_plotNotebook, wxID_ANY ); plotPanel = dynamic_cast( panel ); COMMON_SETTINGS::INPUT cfg = Pgm().GetCommonSettings()->m_Input; @@ -870,14 +883,14 @@ SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( const wxString& aSimCommand, int a } else { - SIM_NOPLOT_PANEL* panel = new SIM_NOPLOT_PANEL( aSimCommand, aOptions, m_workbook, wxID_ANY ); + SIM_NOPLOT_PANEL* panel = new SIM_NOPLOT_PANEL( aSimCommand, aOptions, m_plotNotebook, wxID_ANY ); plotPanel = dynamic_cast( panel ); } wxString pageTitle( m_simulator->TypeToName( simType, true ) ); pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), (unsigned int) ++m_plotNumber ) ); - m_workbook->AddPage( dynamic_cast( plotPanel ), pageTitle, true ); + m_plotNotebook->AddPage( dynamic_cast( plotPanel ), pageTitle, true ); return plotPanel; } @@ -955,13 +968,10 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) } if( traceType != SPT_UNKNOWN ) + { addTrace( baseSignal, (SIM_TRACE_TYPE) traceType ); - } - - if( !GetCurrentPlot()->GetTrace( signalName ) ) - { - aEvent.Veto(); - return; + m_workbookModified = true; + } } } else @@ -983,6 +993,7 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) trace->SetTraceColour( color.ToColour() ); plot->UpdateTraceStyle( trace ); plot->UpdatePlotColors(); + m_workbookModified = true; } } else if( col == COL_CURSOR_1 || col == COL_CURSOR_2 ) @@ -993,6 +1004,7 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) bool enable = ii == row && text == wxS( "1" ); plot->EnableCursor( signalName, col == COL_CURSOR_1 ? 1 : 2, enable ); + m_workbookModified = true; } // Update cursor checkboxes (which are really radio buttons) @@ -1054,6 +1066,8 @@ void SIM_PLOT_FRAME::DeleteMeasurement( int aRow ) m_measurementFormats[ aRow ] = m_measurementFormats[ aRow + 1 ]; m_measurementFormats.pop_back(); + + m_workbookModified = true; } @@ -1090,6 +1104,8 @@ void SIM_PLOT_FRAME::updateMeasurement( int aRow ) " +" "([a-zA-Z])\\([a-zA-Z0-9_]+\\)" ) ); + m_workbookModified = true; + SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); if( !plotPanel ) @@ -1140,12 +1156,14 @@ void SIM_PLOT_FRAME::updateMeasurement( int aRow ) void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName ) { addTrace( aNetName, SPT_VOLTAGE ); + m_workbookModified = true; } void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName ) { addTrace( aDeviceName, SPT_CURRENT ); + m_workbookModified = true; } @@ -1177,6 +1195,7 @@ void SIM_PLOT_FRAME::AddTuner( const SCH_SHEET_PATH& aSheetPath, SCH_SYMBOL* aSy m_sizerTuners->Add( tuner ); m_tuners.push_back( tuner ); m_panelTuners->Layout(); + m_workbookModified = true; } catch( const KI_PARAM_ERROR& e ) { @@ -1225,6 +1244,7 @@ void SIM_PLOT_FRAME::RemoveTuner( TUNER_SLIDER* aTuner, bool aErase ) aTuner->Destroy(); m_panelTuners->Layout(); + m_workbookModified = true; } @@ -1244,6 +1264,7 @@ void SIM_PLOT_FRAME::AddMeasurement( const wxString& aCmd, const wxString& aSign m_measurementsGrid->SetCellValue( row, COL_MEASUREMENT, aCmd + wxS( " " ) + aSignal ); updateMeasurement( row ); + m_workbookModified = true; } @@ -1264,60 +1285,45 @@ const NGSPICE_CIRCUIT_MODEL* SIM_PLOT_FRAME::GetExporter() const void SIM_PLOT_FRAME::addTrace( const wxString& aName, SIM_TRACE_TYPE aType ) { + SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + + if( !plotPanel ) + { + m_simConsole->AppendText( _( "Error: no current simulation.\n" ) ); + m_simConsole->SetInsertionPointEnd(); + return; + } + SIM_TYPE simType = m_circuitModel->GetSimType(); if( simType == ST_UNKNOWN ) { - m_simConsole->AppendText( _( "Error: simulation type not defined!\n" ) ); + m_simConsole->AppendText( _( "Error: simulation type not defined.\n" ) ); m_simConsole->SetInsertionPointEnd(); return; } else if( !SIM_PANEL_BASE::IsPlottable( simType ) ) { - m_simConsole->AppendText( _( "Error: simulation type doesn't support plotting!\n" ) ); + m_simConsole->AppendText( _( "Error: simulation type doesn't support plotting.\n" ) ); m_simConsole->SetInsertionPointEnd(); return; } - // Create a new plot if the current one displays a different type - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); - - if( !plotPanel || plotPanel->GetType() != simType ) - { - plotPanel = dynamic_cast( NewPlotPanel( m_circuitModel->GetSimCommand(), - m_circuitModel->GetSimOptions() ) ); - } - - wxASSERT( plotPanel ); - - if( !plotPanel ) // Something is wrong - return; - - bool updated = false; SIM_TRACE_TYPE xAxisType = getXAxisType( simType ); - if( xAxisType == SPT_LIN_FREQUENCY || xAxisType == SPT_LOG_FREQUENCY ) + if( ( xAxisType == SPT_LIN_FREQUENCY || xAxisType == SPT_LOG_FREQUENCY ) + && ( aType & ( SPT_AC_MAG | SPT_AC_PHASE ) ) == 0 ) { - int baseType = aType & ~( SPT_AC_MAG | SPT_AC_PHASE ); - // If magnitude or phase wasn't specified, then add both - if( baseType == aType ) - { - updated |= updateTrace( aName, (SIM_TRACE_TYPE) ( baseType | SPT_AC_MAG ), plotPanel ); - updated |= updateTrace( aName, (SIM_TRACE_TYPE) ( baseType | SPT_AC_PHASE ), plotPanel ); - } - else - { - updated |= updateTrace( aName, (SIM_TRACE_TYPE) ( aType ), plotPanel ); - } + updateTrace( aName, (SIM_TRACE_TYPE) ( aType | SPT_AC_MAG ), plotPanel ); + updateTrace( aName, (SIM_TRACE_TYPE) ( aType | SPT_AC_PHASE ), plotPanel ); } else { - updated = updateTrace( aName, aType, plotPanel ); + updateTrace( aName, aType, plotPanel ); } - if( updated ) - updateSignalsGrid(); + updateSignalsGrid(); } @@ -1329,7 +1335,10 @@ void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName ) return; wxASSERT( plotPanel->TraceShown( aSignalName ) ); - m_workbook->DeleteTrace( plotPanel, aSignalName ); + + if( plotPanel->DeleteTrace( aSignalName ) ) + m_workbookModified = true; + plotPanel->GetPlotWin()->Fit(); updateSignalsGrid(); @@ -1338,7 +1347,7 @@ void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName ) } -bool SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, +void SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, SIM_PLOT_PANEL* aPlotPanel ) { SIM_TYPE simType = m_circuitModel->GetSimType(); @@ -1359,14 +1368,14 @@ bool SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, // There is no plot to be shown m_simulator->Command( wxString::Format( wxT( "print %s" ), aName ).ToStdString() ); - return false; + return; } // First, handle the x axis wxString xAxisName( m_simulator->GetXAxis( simType ) ); if( xAxisName.IsEmpty() ) - return false; + return; std::vector data_x = m_simulator->GetMagPlot( (const char*) xAxisName.c_str() ); unsigned int size = data_x.size(); @@ -1399,56 +1408,53 @@ bool SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, wxFAIL_MSG( wxT( "Unhandled plot type" ) ); } - if( data_y.size() == 0 ) - return false; // Signal no longer exists - else - wxCHECK_MSG( data_y.size() >= size, false, wxT( "Not enough y data values to plot" ) ); - // If we did a two-source DC analysis, we need to split the resulting vector and add traces // for each input step SPICE_DC_PARAMS source1, source2; if( m_circuitModel->GetSimType() == ST_DC - && m_circuitModel->ParseDCCommand( m_circuitModel->GetSimCommand(), &source1, &source2 ) ) + && m_circuitModel->ParseDCCommand( m_circuitModel->GetSimCommand(), &source1, &source2 ) + && !source2.m_source.IsEmpty() ) { - if( !source2.m_source.IsEmpty() ) + // Source 1 is the inner loop, so lets add traces for each Source 2 (outer loop) step + SPICE_VALUE v = source2.m_vstart; + wxString name; + + size_t offset = 0; + size_t outer = ( size_t )( ( source2.m_vend - v ) / source2.m_vincrement ).ToDouble(); + size_t inner = data_x.size() / ( outer + 1 ); + + wxASSERT( data_x.size() % ( outer + 1 ) == 0 ); + + for( size_t idx = 0; idx <= outer; idx++ ) { - // Source 1 is the inner loop, so lets add traces for each Source 2 (outer loop) step - SPICE_VALUE v = source2.m_vstart; - wxString name; + name = wxString::Format( wxT( "%s (%s = %s V)" ), + traceTitle, + source2.m_source, + v.ToString() ); - size_t offset = 0; - size_t outer = ( size_t )( ( source2.m_vend - v ) / source2.m_vincrement ).ToDouble(); - size_t inner = data_x.size() / ( outer + 1 ); - - wxASSERT( data_x.size() % ( outer + 1 ) == 0 ); - - for( size_t idx = 0; idx <= outer; idx++ ) + if( TRACE* trace = aPlotPanel->AddTrace( name, aName, aType ) ) { - name = wxString::Format( wxT( "%s (%s = %s V)" ), - traceTitle, - source2.m_source, - v.ToString() ); + if( data_y.size() >= size ) + { + std::vector sub_x( data_x.begin() + offset, + data_x.begin() + offset + inner ); + std::vector sub_y( data_y.begin() + offset, + data_y.begin() + offset + inner ); - std::vector sub_x( data_x.begin() + offset, - data_x.begin() + offset + inner ); - std::vector sub_y( data_y.begin() + offset, - data_y.begin() + offset + inner ); - - m_workbook->AddTrace( aPlotPanel, name, aName, inner, sub_x.data(), sub_y.data(), - aType ); - - v = v + source2.m_vincrement; - offset += inner; + aPlotPanel->SetTraceData( trace, inner, sub_x.data(), sub_y.data() ); + } } - return true; + v = v + source2.m_vincrement; + offset += inner; } } - - m_workbook->AddTrace( aPlotPanel, traceTitle, aName, size, data_x.data(), data_y.data(), aType ); - - return true; + else if( TRACE* trace = aPlotPanel->AddTrace( traceTitle, aName, aType ) ) + { + if( data_y.size() >= size ) + aPlotPanel->SetTraceData( trace, size, data_x.data(), data_y.data() ); + } } @@ -1557,7 +1563,7 @@ void SIM_PLOT_FRAME::applyTuners() bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) { - m_workbook->DeleteAllPages(); + m_plotNotebook->DeleteAllPages(); wxTextFile file( aPath ); @@ -1643,14 +1649,6 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) } NewPlotPanel( simCommand, simOptions ); - StartSimulation(); - - // Perform simulation, so plots can be added with values - do - { - wxThread::This()->Sleep( 50 ); - } - while( m_simulator->IsRunning() ); if( !file.GetNextLine().ToLong( &tracesCount ) ) { @@ -1774,7 +1772,12 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) } } + LoadSimulator(); + + rebuildSignalsList(); + rebuildSignalsGrid( m_filter->GetValue() ); updateSignalsGrid(); + wxCommandEvent dummy; onCursorUpdate( dummy ); @@ -1787,7 +1790,9 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() ); // Successfully loading a workbook does not count as modifying it. - m_workbook->ClrModified(); + m_workbookModified = false; + updateTitle(); + return true; } @@ -1813,11 +1818,11 @@ bool SIM_PLOT_FRAME::SaveWorkbook( const wxString& aPath ) file.AddLine( wxT( "version 4" ) ); - file.AddLine( wxString::Format( wxT( "%llu" ), m_workbook->GetPageCount() ) ); + file.AddLine( wxString::Format( wxT( "%llu" ), m_plotNotebook->GetPageCount() ) ); - for( size_t i = 0; i < m_workbook->GetPageCount(); i++ ) + for( size_t i = 0; i < m_plotNotebook->GetPageCount(); i++ ) { - const SIM_PANEL_BASE* basePanel = dynamic_cast( m_workbook->GetPage( i ) ); + const SIM_PANEL_BASE* basePanel = dynamic_cast( m_plotNotebook->GetPage( i ) ); if( !basePanel ) { @@ -1827,8 +1832,8 @@ bool SIM_PLOT_FRAME::SaveWorkbook( const wxString& aPath ) file.AddLine( wxString::Format( wxT( "%d" ), basePanel->GetType() ) ); - wxString command = m_workbook->GetSimCommand( basePanel ); - int options = m_workbook->GetSimOptions( basePanel ); + wxString command = basePanel->GetSimCommand(); + int options = basePanel->GetSimOptions(); if( options & NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS ) command += wxT( "\n.kicad adjustpaths" ); @@ -1902,7 +1907,9 @@ bool SIM_PLOT_FRAME::SaveWorkbook( const wxString& aPath ) m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() ); } - m_workbook->ClrModified(); + m_workbookModified = false; + updateTitle(); + return res; } @@ -1930,9 +1937,9 @@ void SIM_PLOT_FRAME::ToggleDarkModePlots() SIM_PLOT_COLORS::FillDefaultColorList( m_darkMode ); // Now send changes to all SIM_PLOT_PANEL - for( size_t page = 0; page < m_workbook->GetPageCount(); page++ ) + for( size_t page = 0; page < m_plotNotebook->GetPageCount(); page++ ) { - wxWindow* curPage = m_workbook->GetPage( page ); + wxWindow* curPage = m_plotNotebook->GetPage( page ); // ensure it is truly a plot panel and not the (zero plots) placeholder // which is only SIM_PLOT_PANEL_BASE @@ -1972,14 +1979,9 @@ void SIM_PLOT_FRAME::onPlotDragged( wxAuiNotebookEvent& event ) } -void SIM_PLOT_FRAME::onWorkbookModified( wxCommandEvent& event ) -{ - updateTitle(); -} - - -void SIM_PLOT_FRAME::onWorkbookClrModified( wxCommandEvent& event ) +void SIM_PLOT_FRAME::onNotebookModified( wxCommandEvent& event ) { + m_workbookModified = true; updateTitle(); } @@ -1999,10 +2001,10 @@ bool SIM_PLOT_FRAME::EditSimCommand() return false; } - if( m_workbook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND ) + if( m_plotNotebook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND ) { - dlg.SetSimCommand( m_workbook->GetSimCommand( plotPanelWindow ) ); - dlg.SetSimOptions( m_workbook->GetSimOptions( plotPanelWindow ) ); + dlg.SetSimCommand( plotPanelWindow->GetSimCommand() ); + dlg.SetSimOptions( plotPanelWindow->GetSimOptions() ); } else { @@ -2013,8 +2015,8 @@ bool SIM_PLOT_FRAME::EditSimCommand() { wxString oldCommand; - if( m_workbook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND ) - oldCommand = m_workbook->GetSimCommand( plotPanelWindow ); + if( m_plotNotebook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND ) + oldCommand = plotPanelWindow->GetSimCommand(); else oldCommand = wxString(); @@ -2038,14 +2040,15 @@ bool SIM_PLOT_FRAME::EditSimCommand() } else { - if( m_workbook->GetPageIndex( plotPanelWindow ) == 0 ) + if( m_plotNotebook->GetPageIndex( plotPanelWindow ) == 0 ) m_circuitModel->SetSimCommandOverride( newCommand ); // Update simulation command in the current plot - m_workbook->SetSimCommand( plotPanelWindow, newCommand ); - m_workbook->SetSimOptions( plotPanelWindow, newOptions ); + plotPanelWindow->SetSimCommand( newCommand ); + plotPanelWindow->SetSimOptions( newOptions ); } + m_workbookModified = true; m_simulator->Init(); return true; } @@ -2056,7 +2059,7 @@ bool SIM_PLOT_FRAME::EditSimCommand() bool SIM_PLOT_FRAME::canCloseWindow( wxCloseEvent& aEvent ) { - if( m_workbook->IsModified() ) + if( m_workbookModified ) { wxFileName filename = m_simulator->Settings()->GetWorkbookFilename(); @@ -2372,10 +2375,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) } for( const struct TRACE_DESC& trace : traceInfo ) - { - if( !updateTrace( trace.m_name, trace.m_type, plotPanel ) ) - removeTrace( trace.m_name ); - } + updateTrace( trace.m_name, trace.m_type, plotPanel ); rebuildSignalsGrid( m_filter->GetValue() ); plotPanel->GetPlotWin()->UpdateAll(); diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h index 1f7bd60528..e2e612d86f 100644 --- a/eeschema/sim/sim_plot_frame.h +++ b/eeschema/sim/sim_plot_frame.h @@ -50,7 +50,7 @@ class NGSPICE_CIRCUIT_MODEL; #include #include -#include +#include class SIM_THREAD_REPORTER; class TUNER_SLIDER; @@ -62,6 +62,12 @@ public: SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ); ~SIM_PLOT_FRAME(); + /** + * Check and load the current netlist into the simulator. + * @return true if document is fully annotated and netlist was loaded successfully. + */ + bool LoadSimulator(); + void StartSimulation(); /** @@ -208,18 +214,18 @@ public: wxString GetCurrentSimCommand() const { - if( getCurrentPlotWindow() == nullptr ) - return m_circuitModel->GetSchTextSimCommand(); + if( getCurrentPlotWindow() ) + return getCurrentPlotWindow()->GetSimCommand(); else - return m_workbook->GetSimCommand( getCurrentPlotWindow() ); + return m_circuitModel->GetSchTextSimCommand(); } int GetCurrentOptions() const { - if( getCurrentPlotWindow() == nullptr ) - return m_circuitModel->GetSimOptions(); + if( getCurrentPlotWindow() ) + return getCurrentPlotWindow()->GetSimOptions(); else - return m_workbook->GetSimOptions( getCurrentPlotWindow() ); + return m_circuitModel->GetSimOptions(); } // Simulator doesn't host a tool framework @@ -266,9 +272,15 @@ private: * @param aType 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. - * @return True if a plot was successfully added/updated. */ - bool updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, SIM_PLOT_PANEL* aPlotPanel ); + void updateTrace( const wxString& aName, SIM_TRACE_TYPE aType, SIM_PLOT_PANEL* aPlotPanel ); + + /** + * Rebuild the list of signals available from the netlist. + * + * Note: this is not the filtered list. See rebuildSignalsGrid() for that. + */ + void rebuildSignalsList(); /** * Rebuild the filtered list of signals in the signals grid. @@ -295,7 +307,7 @@ private: */ SIM_PANEL_BASE* getCurrentPlotWindow() const { - return dynamic_cast( m_workbook->GetCurrentPage() ); + return dynamic_cast( m_plotNotebook->GetCurrentPage() ); } /** @@ -319,8 +331,7 @@ private: void onCursorsGridCellChanged( wxGridEvent& aEvent ) override; void onMeasurementsGridCellChanged( wxGridEvent& aEvent ) override; - void onWorkbookModified( wxCommandEvent& event ); - void onWorkbookClrModified( wxCommandEvent& event ); + void onNotebookModified( wxCommandEvent& event ); bool canCloseWindow( wxCloseEvent& aEvent ) override; void doCloseWindow() override; @@ -364,6 +375,7 @@ private: unsigned int m_plotNumber; bool m_simFinished; unsigned int m_outputCounter; + bool m_workbookModified; }; // Commands diff --git a/eeschema/sim/sim_plot_frame_base.cpp b/eeschema/sim/sim_plot_frame_base.cpp index 438bdc900d..375d7fbb0f 100644 --- a/eeschema/sim/sim_plot_frame_base.cpp +++ b/eeschema/sim/sim_plot_frame_base.cpp @@ -43,11 +43,11 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const m_sizerPlot = new wxBoxSizer( wxHORIZONTAL ); - m_workbook = new SIM_WORKBOOK( m_plotPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_MIDDLE_CLICK_CLOSE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TOP ); - m_workbook->SetMinSize( wxSize( 200,-1 ) ); + m_plotNotebook = new SIM_NOTEBOOK( m_plotPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_MIDDLE_CLICK_CLOSE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TOP ); + m_plotNotebook->SetMinSize( wxSize( 200,-1 ) ); - m_sizerPlot->Add( m_workbook, 1, wxEXPAND, 5 ); + m_sizerPlot->Add( m_plotNotebook, 1, wxEXPAND, 5 ); m_plotPanel->SetSizer( m_sizerPlot ); @@ -284,10 +284,10 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const this->Centre( wxBOTH ); // Connect Events - m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this ); - m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this ); - m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this ); - m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClosed ), NULL, this ); + m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this ); + m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this ); + m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this ); + m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClosed ), NULL, this ); m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::OnFilterMouseMoved ), NULL, this ); m_filter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::OnFilterText ), NULL, this ); m_signalsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( SIM_PLOT_FRAME_BASE::onSignalsGridCellChanged ), NULL, this ); @@ -298,10 +298,10 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const SIM_PLOT_FRAME_BASE::~SIM_PLOT_FRAME_BASE() { // Disconnect Events - m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this ); - m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this ); - m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this ); - m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClosed ), NULL, this ); + m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this ); + m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotChanged ), NULL, this ); + m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClose ), NULL, this ); + m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotClosed ), NULL, this ); m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( SIM_PLOT_FRAME_BASE::OnFilterMouseMoved ), NULL, this ); m_filter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::OnFilterText ), NULL, this ); m_signalsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( SIM_PLOT_FRAME_BASE::onSignalsGridCellChanged ), NULL, this ); diff --git a/eeschema/sim/sim_plot_frame_base.fbp b/eeschema/sim/sim_plot_frame_base.fbp index da185c6da7..4d7a990d22 100644 --- a/eeschema/sim/sim_plot_frame_base.fbp +++ b/eeschema/sim/sim_plot_frame_base.fbp @@ -307,7 +307,7 @@ - + 1 1 1 @@ -358,7 +358,7 @@ wxTAB_TRAVERSAL - + m_sizerPlot wxHORIZONTAL @@ -402,7 +402,7 @@ 0 200,-1 1 - m_workbook + m_plotNotebook 1 @@ -413,7 +413,7 @@ 1 wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_MIDDLE_CLICK_CLOSE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TOP - SIM_WORKBOOK; sim_workbook.h; Not forward_declare + SIM_NOTEBOOK; sim_notebook.h; -1 0 diff --git a/eeschema/sim/sim_plot_frame_base.h b/eeschema/sim/sim_plot_frame_base.h index bfbb502767..932886a248 100644 --- a/eeschema/sim/sim_plot_frame_base.h +++ b/eeschema/sim/sim_plot_frame_base.h @@ -13,7 +13,7 @@ class ACTION_TOOLBAR; class WX_GRID; -#include "sim_workbook.h" +#include "sim_notebook.h" #include "kiway_player.h" #include #include @@ -50,7 +50,7 @@ class SIM_PLOT_FRAME_BASE : public KIWAY_PLAYER wxSplitterWindow* m_splitterPlotAndConsole; wxPanel* m_plotPanel; wxBoxSizer* m_sizerPlot; - SIM_WORKBOOK* m_workbook; + SIM_NOTEBOOK* m_plotNotebook; wxPanel* m_panelConsole; wxBoxSizer* m_sizerConsole; wxTextCtrl* m_simConsole; diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index 67fec6f8f2..e5a3a73717 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -551,7 +551,7 @@ void SIM_PLOT_PANEL::updateAxes( SIM_TRACE_TYPE aNewTraceType ) void SIM_PLOT_PANEL::prepareDCAxes() { - wxString sim_cmd = getSimCommand().Lower(); + wxString sim_cmd = GetSimCommand().Lower(); wxString rem; if( sim_cmd.StartsWith( ".dc", &rem ) ) @@ -676,67 +676,67 @@ void SIM_PLOT_PANEL::UpdateTraceStyle( TRACE* trace ) } -bool SIM_PLOT_PANEL::addTrace( const wxString& aTitle, const wxString& aName, int aPoints, - const double* aX, const double* aY, SIM_TRACE_TYPE aType ) +TRACE* SIM_PLOT_PANEL::AddTrace( const wxString& aTitle, const wxString& aName, + SIM_TRACE_TYPE aType ) { TRACE* trace = nullptr; + auto it = m_traces.find( aTitle ); + + if( it != m_traces.end() ) + return it->second; + updateAxes( aType ); - // Find previous entry, if there is one - auto prev = m_traces.find( aTitle ); - bool addedNewEntry = ( prev == m_traces.end() ); - - if( addedNewEntry ) + if( GetType() == ST_TRANSIENT ) { - if( GetType() == ST_TRANSIENT ) + bool hasVoltageTraces = false; + + for( const auto& [ name, candidate ] : m_traces ) { - bool hasVoltageTraces = false; - - for( const auto& [ name, candidate ] : m_traces ) + if( candidate->GetType() & SPT_VOLTAGE ) { - if( candidate->GetType() & SPT_VOLTAGE ) - { - hasVoltageTraces = true; - break; - } - } - - if( !hasVoltageTraces ) - { - if( m_axis_y2 ) - m_axis_y2->SetMasterScale( nullptr ); - - if( m_axis_y3 ) - m_axis_y3->SetMasterScale( nullptr ); + hasVoltageTraces = true; + break; } } - // New entry - trace = new TRACE( aName, aType ); - trace->SetTraceColour( m_colors.GenerateColor( m_traces ) ); - UpdateTraceStyle( trace ); - m_traces[ aTitle ] = trace; + if( !hasVoltageTraces ) + { + if( m_axis_y2 ) + m_axis_y2->SetMasterScale( nullptr ); - m_plotWin->AddLayer( (mpLayer*) trace ); - } - else - { - trace = prev->second; + if( m_axis_y3 ) + m_axis_y3->SetMasterScale( nullptr ); + } } + trace = new TRACE( aName, aType ); + trace->SetTraceColour( m_colors.GenerateColor( m_traces ) ); + UpdateTraceStyle( trace ); + m_traces[ aTitle ] = trace; + + m_plotWin->AddLayer( (mpLayer*) trace ); + + return trace; +} + + +void SIM_PLOT_PANEL::SetTraceData( TRACE* trace, unsigned int aPoints, const double* aX, + const double* aY ) +{ std::vector tmp( aY, aY + aPoints ); if( GetType() == ST_AC ) { - if( aType & SPT_AC_PHASE ) + if( trace->GetType() & SPT_AC_PHASE ) { - for( int i = 0; i < aPoints; i++ ) + for( unsigned int i = 0; i < aPoints; i++ ) tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees } else { - for( int i = 0; i < aPoints; i++ ) + for( unsigned int i = 0; i < aPoints; i++ ) { // log( 0 ) is not valid. if( tmp[i] != 0 ) @@ -747,20 +747,18 @@ bool SIM_PLOT_PANEL::addTrace( const wxString& aTitle, const wxString& aName, in trace->SetData( std::vector( aX, aX + aPoints ), tmp ); - if( ( aType & SPT_AC_PHASE ) || ( aType & SPT_CURRENT ) ) + if( ( trace->GetType() & SPT_AC_PHASE ) || ( trace->GetType() & SPT_CURRENT ) ) trace->SetScale( m_axis_x, m_axis_y2 ); - else if( aType & SPT_POWER ) + else if( trace->GetType() & SPT_POWER ) trace->SetScale( m_axis_x, m_axis_y3 ); else trace->SetScale( m_axis_x, m_axis_y1 ); m_plotWin->UpdateAll(); - - return addedNewEntry; } -bool SIM_PLOT_PANEL::deleteTrace( const wxString& aName ) +bool SIM_PLOT_PANEL::DeleteTrace( const wxString& aName ) { auto it = m_traces.find( aName ); diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index efc847ce78..4e20bb27f9 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -185,8 +185,6 @@ protected: class SIM_PLOT_PANEL : public SIM_PANEL_BASE { - friend class SIM_WORKBOOK; - public: SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, @@ -303,11 +301,11 @@ public: return m_plotWin; } -protected: - bool addTrace( const wxString& aTitle, const wxString& aName, int aPoints, const double* aX, - const double* aY, SIM_TRACE_TYPE aType ); + TRACE* AddTrace( const wxString& aTitle, const wxString& aName, SIM_TRACE_TYPE aType ); - bool deleteTrace( const wxString& aName ); + void SetTraceData( TRACE* aTrace, unsigned int aPoints, const double* aX, const double* aY ); + + bool DeleteTrace( const wxString& aName ); private: ///< @brief Construct the plot axes for DC simulation plot.