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.
This commit is contained in:
parent
78746b77c6
commit
83dd06e5d1
|
@ -354,13 +354,13 @@ if( KICAD_SPICE )
|
||||||
tools/simulator_control.cpp
|
tools/simulator_control.cpp
|
||||||
sim/ngspice_circuit_model.cpp
|
sim/ngspice_circuit_model.cpp
|
||||||
sim/ngspice.cpp
|
sim/ngspice.cpp
|
||||||
|
sim/sim_notebook.cpp
|
||||||
sim/sim_panel_base.cpp
|
sim/sim_panel_base.cpp
|
||||||
sim/sim_plot_colors.cpp
|
sim/sim_plot_colors.cpp
|
||||||
sim/sim_plot_frame.cpp
|
sim/sim_plot_frame.cpp
|
||||||
sim/sim_plot_frame_base.cpp
|
sim/sim_plot_frame_base.cpp
|
||||||
sim/sim_plot_panel.cpp
|
sim/sim_plot_panel.cpp
|
||||||
sim/sim_property.cpp
|
sim/sim_property.cpp
|
||||||
sim/sim_workbook.cpp
|
|
||||||
sim/spice_simulator.cpp
|
sim/spice_simulator.cpp
|
||||||
sim/spice_value.cpp
|
sim/spice_value.cpp
|
||||||
sim/toolbars_sim_plot_frame.cpp
|
sim/toolbars_sim_plot_frame.cpp
|
||||||
|
|
|
@ -22,28 +22,25 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sim/sim_workbook.h>
|
#include <sim/sim_notebook.h>
|
||||||
|
|
||||||
|
|
||||||
SIM_WORKBOOK::SIM_WORKBOOK() : wxAuiNotebook()
|
SIM_NOTEBOOK::SIM_NOTEBOOK() :
|
||||||
{
|
wxAuiNotebook()
|
||||||
m_modified = false;
|
{ }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 ) :
|
aSize, long aStyle ) :
|
||||||
wxAuiNotebook( aParent, aId, aPos, aSize, 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;
|
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 ) )
|
if( wxAuiNotebook::AddPage( page, text, select, imageId ) )
|
||||||
{
|
{
|
||||||
setModified();
|
wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) );
|
||||||
return true;
|
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() )
|
if( wxAuiNotebook::DeleteAllPages() )
|
||||||
{
|
{
|
||||||
setModified();
|
wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) );
|
||||||
return true;
|
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 ) )
|
if( wxAuiNotebook::DeletePage( page ) )
|
||||||
{
|
{
|
||||||
setModified();
|
wxPostEvent( GetParent(), wxCommandEvent( EVT_WORKBOOK_MODIFIED ) );
|
||||||
return true;
|
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_MODIFIED, wxCommandEvent );
|
||||||
wxDEFINE_EVENT( EVT_WORKBOOK_CLR_MODIFIED, wxCommandEvent );
|
|
|
@ -22,69 +22,32 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SIM_WORKBOOK__
|
#ifndef SIM_NOTEBOOK_H
|
||||||
#define __SIM_WORKBOOK__
|
#define SIM_NOTEBOOK_H
|
||||||
|
|
||||||
#include <dialog_sim_command.h>
|
#include <dialog_sim_command.h>
|
||||||
#include <sim/sim_panel_base.h>
|
#include <sim/sim_panel_base.h>
|
||||||
#include <sim/sim_plot_panel.h>
|
#include <sim/sim_plot_panel.h>
|
||||||
|
|
||||||
|
|
||||||
class SIM_WORKBOOK : public wxAuiNotebook
|
class SIM_NOTEBOOK : public wxAuiNotebook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SIM_WORKBOOK();
|
SIM_NOTEBOOK();
|
||||||
SIM_WORKBOOK( wxWindow* aParent, wxWindowID aId=wxID_ANY, const wxPoint&
|
SIM_NOTEBOOK( wxWindow* aParent, wxWindowID aId = wxID_ANY,
|
||||||
aPos=wxDefaultPosition, const wxSize& aSize=wxDefaultSize, long
|
const wxPoint& aPos = wxDefaultPosition, const wxSize& aSize = wxDefaultSize,
|
||||||
aStyle=wxAUI_NB_DEFAULT_STYLE );
|
long aStyle = wxAUI_NB_DEFAULT_STYLE );
|
||||||
|
|
||||||
// Methods from wxAuiNotebook
|
// 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 AddPage( wxWindow* aPage, const wxString& aText, bool aSelect, int aImageId ) override;
|
||||||
|
|
||||||
bool DeleteAllPages() override;
|
bool DeleteAllPages() override;
|
||||||
bool DeletePage( size_t aPage ) 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_MODIFIED, wxCommandEvent );
|
||||||
wxDECLARE_EVENT( EVT_WORKBOOK_CLR_MODIFIED, wxCommandEvent );
|
|
||||||
|
|
||||||
#endif // __SIM_WORKBOOK__
|
#endif // SIM_NOTEBOOK_H
|
|
@ -35,8 +35,6 @@
|
||||||
|
|
||||||
class SIM_PANEL_BASE : public wxWindow
|
class SIM_PANEL_BASE : public wxWindow
|
||||||
{
|
{
|
||||||
friend class SIM_WORKBOOK;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SIM_PANEL_BASE();
|
SIM_PANEL_BASE();
|
||||||
SIM_PANEL_BASE( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id,
|
SIM_PANEL_BASE( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id,
|
||||||
|
@ -50,14 +48,8 @@ public:
|
||||||
|
|
||||||
SIM_TYPE GetType() const;
|
SIM_TYPE GetType() const;
|
||||||
|
|
||||||
protected:
|
const wxString& GetSimCommand() const { return m_simCommand; }
|
||||||
// We use `protected` here because members should be accessible from outside only through a
|
void SetSimCommand( const wxString& aSimCommand )
|
||||||
// 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 )
|
|
||||||
{
|
{
|
||||||
wxCHECK_RET( GetType() == NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ),
|
wxCHECK_RET( GetType() == NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ),
|
||||||
"Cannot change the type of simulation of the existing plot panel" );
|
"Cannot change the type of simulation of the existing plot panel" );
|
||||||
|
@ -65,8 +57,8 @@ protected:
|
||||||
m_simCommand = aSimCommand;
|
m_simCommand = aSimCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int getSimOptions() const { return m_simOptions; }
|
const int GetSimOptions() const { return m_simOptions; }
|
||||||
void setSimOptions( int aOptions ) { m_simOptions = aOptions; }
|
void SetSimOptions( int aOptions ) { m_simOptions = aOptions; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxString m_simCommand;
|
wxString m_simCommand;
|
||||||
|
|
|
@ -330,7 +330,8 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||||
m_darkMode( true ),
|
m_darkMode( true ),
|
||||||
m_plotNumber( 0 ),
|
m_plotNumber( 0 ),
|
||||||
m_simFinished( false ),
|
m_simFinished( false ),
|
||||||
m_outputCounter( 1 )
|
m_outputCounter( 1 ),
|
||||||
|
m_workbookModified( false )
|
||||||
{
|
{
|
||||||
SetKiway( this, aKiway );
|
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_FINISHED, &SIM_PLOT_FRAME::onSimFinished, this );
|
||||||
Bind( EVT_SIM_CURSOR_UPDATE, &SIM_PLOT_FRAME::onCursorUpdate, this );
|
Bind( EVT_SIM_CURSOR_UPDATE, &SIM_PLOT_FRAME::onCursorUpdate, this );
|
||||||
|
|
||||||
Bind( EVT_WORKBOOK_MODIFIED, &SIM_PLOT_FRAME::onWorkbookModified, this );
|
Bind( EVT_WORKBOOK_MODIFIED, &SIM_PLOT_FRAME::onNotebookModified, this );
|
||||||
Bind( EVT_WORKBOOK_CLR_MODIFIED, &SIM_PLOT_FRAME::onWorkbookClrModified, this );
|
|
||||||
|
|
||||||
#ifndef wxHAS_NATIVE_TABART
|
#ifndef wxHAS_NATIVE_TABART
|
||||||
// Default non-native tab art has ugly gradients we don't want
|
// Default non-native tab art has ugly gradients we don't want
|
||||||
m_workbook->SetArtProvider( new wxAuiSimpleTabArt() );
|
m_plotNotebook->SetArtProvider( new wxAuiSimpleTabArt() );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Ensure new items are taken in account by sizers:
|
// Ensure new items are taken in account by sizers:
|
||||||
|
@ -482,16 +482,16 @@ void SIM_PLOT_FRAME::ShowChangedLanguage()
|
||||||
|
|
||||||
updateTitle();
|
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<SIM_PLOT_PANEL*>( m_workbook->GetPage( ii ) );
|
SIM_PANEL_BASE* plot = dynamic_cast<SIM_PLOT_PANEL*>( m_plotNotebook->GetPage( ii ) );
|
||||||
|
|
||||||
plot->OnLanguageChanged();
|
plot->OnLanguageChanged();
|
||||||
|
|
||||||
wxString pageTitle( m_simulator->TypeToName( plot->GetType(), true ) );
|
wxString pageTitle( m_simulator->TypeToName( plot->GetType(), true ) );
|
||||||
pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), ii+1 /* 1-based */ ) );
|
pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), ii+1 /* 1-based */ ) );
|
||||||
|
|
||||||
m_workbook->SetPageText( ii, pageTitle );
|
m_plotNotebook->SetPageText( ii, pageTitle );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_filter->SetHint( _( "Filter" ) );
|
m_filter->SetHint( _( "Filter" ) );
|
||||||
|
@ -582,19 +582,14 @@ WINDOW_SETTINGS* SIM_PLOT_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
|
||||||
|
|
||||||
void SIM_PLOT_FRAME::initWorkbook()
|
void SIM_PLOT_FRAME::initWorkbook()
|
||||||
{
|
{
|
||||||
// Removed for the time being. We cannot run the simulation on simulator launch, as it may
|
if( !m_simulator->Settings()->GetWorkbookFilename().IsEmpty() )
|
||||||
// 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() )
|
|
||||||
{
|
{
|
||||||
wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
|
wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
|
||||||
filename.SetPath( Prj().GetProjectPath() );
|
filename.SetPath( Prj().GetProjectPath() );
|
||||||
|
|
||||||
if( !loadWorkbook( filename.GetFullPath() ) )
|
if( !LoadWorkbook( filename.GetFullPath() ) )
|
||||||
m_simulator->Settings()->SetWorkbookFilename( "" );
|
m_simulator->Settings()->SetWorkbookFilename( "" );
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -614,7 +609,7 @@ void SIM_PLOT_FRAME::updateTitle()
|
||||||
readOnly = !filename.IsFileWritable();
|
readOnly = !filename.IsFileWritable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_workbook->IsModified() )
|
if( m_workbookModified )
|
||||||
title = wxT( "*" ) + filename.GetName();
|
title = wxT( "*" ) + filename.GetName();
|
||||||
else
|
else
|
||||||
title = filename.GetName();
|
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()
|
void SIM_PLOT_FRAME::StartSimulation()
|
||||||
{
|
{
|
||||||
if( m_circuitModel->CommandToSimType( GetCurrentSimCommand() ) == ST_UNKNOWN )
|
if( m_circuitModel->CommandToSimType( GetCurrentSimCommand() ) == ST_UNKNOWN )
|
||||||
|
@ -739,11 +820,11 @@ void SIM_PLOT_FRAME::StartSimulation()
|
||||||
if( !plotWindow )
|
if( !plotWindow )
|
||||||
{
|
{
|
||||||
plotWindow = NewPlotPanel( schTextSimCommand, m_circuitModel->GetSimOptions() );
|
plotWindow = NewPlotPanel( schTextSimCommand, m_circuitModel->GetSimOptions() );
|
||||||
m_workbook->SetSimCommand( plotWindow, schTextSimCommand );
|
m_workbookModified = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_circuitModel->SetSimCommandOverride( m_workbook->GetSimCommand( plotWindow ) );
|
m_circuitModel->SetSimCommandOverride( plotWindow->GetSimCommand() );
|
||||||
|
|
||||||
if( plotWindow->GetType() == schTextSimType
|
if( plotWindow->GetType() == schTextSimType
|
||||||
&& schTextSimCommand != m_circuitModel->GetLastSchTextSimCommand() )
|
&& schTextSimCommand != m_circuitModel->GetLastSchTextSimCommand() )
|
||||||
|
@ -752,95 +833,27 @@ void SIM_PLOT_FRAME::StartSimulation()
|
||||||
"Do you wish to update the Simulation Command?" ) ) )
|
"Do you wish to update the Simulation Command?" ) ) )
|
||||||
{
|
{
|
||||||
m_circuitModel->SetSimCommandOverride( wxEmptyString );
|
m_circuitModel->SetSimCommandOverride( wxEmptyString );
|
||||||
m_workbook->SetSimCommand( plotWindow, schTextSimCommand );
|
plotWindow->SetSimCommand( schTextSimCommand );
|
||||||
|
m_workbookModified = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_circuitModel->SetSimOptions( GetCurrentOptions() );
|
m_circuitModel->SetSimOptions( GetCurrentOptions() );
|
||||||
|
|
||||||
wxString errors;
|
if( !LoadSimulator() )
|
||||||
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 );
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
rebuildSignalsList();
|
||||||
|
rebuildSignalsGrid( m_filter->GetValue() );
|
||||||
|
|
||||||
std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
|
std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
|
||||||
|
|
||||||
if( simulatorLock.owns_lock() )
|
if( simulatorLock.owns_lock() )
|
||||||
{
|
{
|
||||||
wxBusyCursor toggle;
|
wxBusyCursor toggle;
|
||||||
wxString unconnected = wxString( wxS( "unconnected-(" ) );
|
|
||||||
|
|
||||||
unconnected.Replace( '(', '_' ); // Convert to SPICE markup
|
|
||||||
|
|
||||||
m_simConsole->Clear();
|
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();
|
applyTuners();
|
||||||
|
|
||||||
|
@ -862,7 +875,7 @@ SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( const wxString& aSimCommand, int a
|
||||||
|
|
||||||
if( SIM_PANEL_BASE::IsPlottable( simType ) )
|
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<SIM_PANEL_BASE*>( panel );
|
plotPanel = dynamic_cast<SIM_PANEL_BASE*>( panel );
|
||||||
|
|
||||||
COMMON_SETTINGS::INPUT cfg = Pgm().GetCommonSettings()->m_Input;
|
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
|
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<SIM_PANEL_BASE*>( panel );
|
plotPanel = dynamic_cast<SIM_PANEL_BASE*>( panel );
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString pageTitle( m_simulator->TypeToName( simType, true ) );
|
wxString pageTitle( m_simulator->TypeToName( simType, true ) );
|
||||||
pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), (unsigned int) ++m_plotNumber ) );
|
pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), (unsigned int) ++m_plotNumber ) );
|
||||||
|
|
||||||
m_workbook->AddPage( dynamic_cast<wxWindow*>( plotPanel ), pageTitle, true );
|
m_plotNotebook->AddPage( dynamic_cast<wxWindow*>( plotPanel ), pageTitle, true );
|
||||||
|
|
||||||
return plotPanel;
|
return plotPanel;
|
||||||
}
|
}
|
||||||
|
@ -955,13 +968,10 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
if( traceType != SPT_UNKNOWN )
|
if( traceType != SPT_UNKNOWN )
|
||||||
|
{
|
||||||
addTrace( baseSignal, (SIM_TRACE_TYPE) traceType );
|
addTrace( baseSignal, (SIM_TRACE_TYPE) traceType );
|
||||||
}
|
m_workbookModified = true;
|
||||||
|
}
|
||||||
if( !GetCurrentPlot()->GetTrace( signalName ) )
|
|
||||||
{
|
|
||||||
aEvent.Veto();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -983,6 +993,7 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
|
||||||
trace->SetTraceColour( color.ToColour() );
|
trace->SetTraceColour( color.ToColour() );
|
||||||
plot->UpdateTraceStyle( trace );
|
plot->UpdateTraceStyle( trace );
|
||||||
plot->UpdatePlotColors();
|
plot->UpdatePlotColors();
|
||||||
|
m_workbookModified = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( col == COL_CURSOR_1 || col == COL_CURSOR_2 )
|
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" );
|
bool enable = ii == row && text == wxS( "1" );
|
||||||
|
|
||||||
plot->EnableCursor( signalName, col == COL_CURSOR_1 ? 1 : 2, enable );
|
plot->EnableCursor( signalName, col == COL_CURSOR_1 ? 1 : 2, enable );
|
||||||
|
m_workbookModified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update cursor checkboxes (which are really radio buttons)
|
// 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[ aRow ] = m_measurementFormats[ aRow + 1 ];
|
||||||
|
|
||||||
m_measurementFormats.pop_back();
|
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_]+\\)" ) );
|
"([a-zA-Z])\\([a-zA-Z0-9_]+\\)" ) );
|
||||||
|
|
||||||
|
m_workbookModified = true;
|
||||||
|
|
||||||
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
|
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
|
||||||
|
|
||||||
if( !plotPanel )
|
if( !plotPanel )
|
||||||
|
@ -1140,12 +1156,14 @@ void SIM_PLOT_FRAME::updateMeasurement( int aRow )
|
||||||
void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName )
|
void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName )
|
||||||
{
|
{
|
||||||
addTrace( aNetName, SPT_VOLTAGE );
|
addTrace( aNetName, SPT_VOLTAGE );
|
||||||
|
m_workbookModified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName )
|
void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName )
|
||||||
{
|
{
|
||||||
addTrace( aDeviceName, SPT_CURRENT );
|
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_sizerTuners->Add( tuner );
|
||||||
m_tuners.push_back( tuner );
|
m_tuners.push_back( tuner );
|
||||||
m_panelTuners->Layout();
|
m_panelTuners->Layout();
|
||||||
|
m_workbookModified = true;
|
||||||
}
|
}
|
||||||
catch( const KI_PARAM_ERROR& e )
|
catch( const KI_PARAM_ERROR& e )
|
||||||
{
|
{
|
||||||
|
@ -1225,6 +1244,7 @@ void SIM_PLOT_FRAME::RemoveTuner( TUNER_SLIDER* aTuner, bool aErase )
|
||||||
|
|
||||||
aTuner->Destroy();
|
aTuner->Destroy();
|
||||||
m_panelTuners->Layout();
|
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 );
|
m_measurementsGrid->SetCellValue( row, COL_MEASUREMENT, aCmd + wxS( " " ) + aSignal );
|
||||||
|
|
||||||
updateMeasurement( row );
|
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 )
|
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();
|
SIM_TYPE simType = m_circuitModel->GetSimType();
|
||||||
|
|
||||||
if( simType == ST_UNKNOWN )
|
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();
|
m_simConsole->SetInsertionPointEnd();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if( !SIM_PANEL_BASE::IsPlottable( simType ) )
|
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();
|
m_simConsole->SetInsertionPointEnd();
|
||||||
return;
|
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<SIM_PLOT_PANEL*>( NewPlotPanel( m_circuitModel->GetSimCommand(),
|
|
||||||
m_circuitModel->GetSimOptions() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxASSERT( plotPanel );
|
|
||||||
|
|
||||||
if( !plotPanel ) // Something is wrong
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool updated = false;
|
|
||||||
SIM_TRACE_TYPE xAxisType = getXAxisType( simType );
|
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 magnitude or phase wasn't specified, then add both
|
||||||
if( baseType == aType )
|
updateTrace( aName, (SIM_TRACE_TYPE) ( aType | SPT_AC_MAG ), plotPanel );
|
||||||
{
|
updateTrace( aName, (SIM_TRACE_TYPE) ( aType | SPT_AC_PHASE ), plotPanel );
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
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;
|
return;
|
||||||
|
|
||||||
wxASSERT( plotPanel->TraceShown( aSignalName ) );
|
wxASSERT( plotPanel->TraceShown( aSignalName ) );
|
||||||
m_workbook->DeleteTrace( plotPanel, aSignalName );
|
|
||||||
|
if( plotPanel->DeleteTrace( aSignalName ) )
|
||||||
|
m_workbookModified = true;
|
||||||
|
|
||||||
plotPanel->GetPlotWin()->Fit();
|
plotPanel->GetPlotWin()->Fit();
|
||||||
|
|
||||||
updateSignalsGrid();
|
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_PLOT_PANEL* aPlotPanel )
|
||||||
{
|
{
|
||||||
SIM_TYPE simType = m_circuitModel->GetSimType();
|
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
|
// There is no plot to be shown
|
||||||
m_simulator->Command( wxString::Format( wxT( "print %s" ), aName ).ToStdString() );
|
m_simulator->Command( wxString::Format( wxT( "print %s" ), aName ).ToStdString() );
|
||||||
|
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, handle the x axis
|
// First, handle the x axis
|
||||||
wxString xAxisName( m_simulator->GetXAxis( simType ) );
|
wxString xAxisName( m_simulator->GetXAxis( simType ) );
|
||||||
|
|
||||||
if( xAxisName.IsEmpty() )
|
if( xAxisName.IsEmpty() )
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
std::vector<double> data_x = m_simulator->GetMagPlot( (const char*) xAxisName.c_str() );
|
std::vector<double> data_x = m_simulator->GetMagPlot( (const char*) xAxisName.c_str() );
|
||||||
unsigned int size = data_x.size();
|
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" ) );
|
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
|
// If we did a two-source DC analysis, we need to split the resulting vector and add traces
|
||||||
// for each input step
|
// for each input step
|
||||||
SPICE_DC_PARAMS source1, source2;
|
SPICE_DC_PARAMS source1, source2;
|
||||||
|
|
||||||
if( m_circuitModel->GetSimType() == ST_DC
|
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
|
name = wxString::Format( wxT( "%s (%s = %s V)" ),
|
||||||
SPICE_VALUE v = source2.m_vstart;
|
traceTitle,
|
||||||
wxString name;
|
source2.m_source,
|
||||||
|
v.ToString() );
|
||||||
|
|
||||||
size_t offset = 0;
|
if( TRACE* trace = aPlotPanel->AddTrace( name, aName, aType ) )
|
||||||
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++ )
|
|
||||||
{
|
{
|
||||||
name = wxString::Format( wxT( "%s (%s = %s V)" ),
|
if( data_y.size() >= size )
|
||||||
traceTitle,
|
{
|
||||||
source2.m_source,
|
std::vector<double> sub_x( data_x.begin() + offset,
|
||||||
v.ToString() );
|
data_x.begin() + offset + inner );
|
||||||
|
std::vector<double> sub_y( data_y.begin() + offset,
|
||||||
|
data_y.begin() + offset + inner );
|
||||||
|
|
||||||
std::vector<double> sub_x( data_x.begin() + offset,
|
aPlotPanel->SetTraceData( trace, inner, sub_x.data(), sub_y.data() );
|
||||||
data_x.begin() + offset + inner );
|
}
|
||||||
std::vector<double> 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
v = v + source2.m_vincrement;
|
||||||
|
offset += inner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if( TRACE* trace = aPlotPanel->AddTrace( traceTitle, aName, aType ) )
|
||||||
m_workbook->AddTrace( aPlotPanel, traceTitle, aName, size, data_x.data(), data_y.data(), aType );
|
{
|
||||||
|
if( data_y.size() >= size )
|
||||||
return true;
|
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 )
|
bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
|
||||||
{
|
{
|
||||||
m_workbook->DeleteAllPages();
|
m_plotNotebook->DeleteAllPages();
|
||||||
|
|
||||||
wxTextFile file( aPath );
|
wxTextFile file( aPath );
|
||||||
|
|
||||||
|
@ -1643,14 +1649,6 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
|
||||||
}
|
}
|
||||||
|
|
||||||
NewPlotPanel( simCommand, simOptions );
|
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 ) )
|
if( !file.GetNextLine().ToLong( &tracesCount ) )
|
||||||
{
|
{
|
||||||
|
@ -1774,7 +1772,12 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadSimulator();
|
||||||
|
|
||||||
|
rebuildSignalsList();
|
||||||
|
rebuildSignalsGrid( m_filter->GetValue() );
|
||||||
updateSignalsGrid();
|
updateSignalsGrid();
|
||||||
|
|
||||||
wxCommandEvent dummy;
|
wxCommandEvent dummy;
|
||||||
onCursorUpdate( dummy );
|
onCursorUpdate( dummy );
|
||||||
|
|
||||||
|
@ -1787,7 +1790,9 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
|
||||||
m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() );
|
m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() );
|
||||||
|
|
||||||
// Successfully loading a workbook does not count as modifying it.
|
// Successfully loading a workbook does not count as modifying it.
|
||||||
m_workbook->ClrModified();
|
m_workbookModified = false;
|
||||||
|
updateTitle();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1813,11 +1818,11 @@ bool SIM_PLOT_FRAME::SaveWorkbook( const wxString& aPath )
|
||||||
|
|
||||||
file.AddLine( wxT( "version 4" ) );
|
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<const SIM_PANEL_BASE*>( m_workbook->GetPage( i ) );
|
const SIM_PANEL_BASE* basePanel = dynamic_cast<const SIM_PANEL_BASE*>( m_plotNotebook->GetPage( i ) );
|
||||||
|
|
||||||
if( !basePanel )
|
if( !basePanel )
|
||||||
{
|
{
|
||||||
|
@ -1827,8 +1832,8 @@ bool SIM_PLOT_FRAME::SaveWorkbook( const wxString& aPath )
|
||||||
|
|
||||||
file.AddLine( wxString::Format( wxT( "%d" ), basePanel->GetType() ) );
|
file.AddLine( wxString::Format( wxT( "%d" ), basePanel->GetType() ) );
|
||||||
|
|
||||||
wxString command = m_workbook->GetSimCommand( basePanel );
|
wxString command = basePanel->GetSimCommand();
|
||||||
int options = m_workbook->GetSimOptions( basePanel );
|
int options = basePanel->GetSimOptions();
|
||||||
|
|
||||||
if( options & NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS )
|
if( options & NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS )
|
||||||
command += wxT( "\n.kicad adjustpaths" );
|
command += wxT( "\n.kicad adjustpaths" );
|
||||||
|
@ -1902,7 +1907,9 @@ bool SIM_PLOT_FRAME::SaveWorkbook( const wxString& aPath )
|
||||||
m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() );
|
m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_workbook->ClrModified();
|
m_workbookModified = false;
|
||||||
|
updateTitle();
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1930,9 +1937,9 @@ void SIM_PLOT_FRAME::ToggleDarkModePlots()
|
||||||
SIM_PLOT_COLORS::FillDefaultColorList( m_darkMode );
|
SIM_PLOT_COLORS::FillDefaultColorList( m_darkMode );
|
||||||
|
|
||||||
// Now send changes to all SIM_PLOT_PANEL
|
// 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
|
// ensure it is truly a plot panel and not the (zero plots) placeholder
|
||||||
// which is only SIM_PLOT_PANEL_BASE
|
// 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 )
|
void SIM_PLOT_FRAME::onNotebookModified( wxCommandEvent& event )
|
||||||
{
|
|
||||||
updateTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIM_PLOT_FRAME::onWorkbookClrModified( wxCommandEvent& event )
|
|
||||||
{
|
{
|
||||||
|
m_workbookModified = true;
|
||||||
updateTitle();
|
updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1999,10 +2001,10 @@ bool SIM_PLOT_FRAME::EditSimCommand()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_workbook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND )
|
if( m_plotNotebook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND )
|
||||||
{
|
{
|
||||||
dlg.SetSimCommand( m_workbook->GetSimCommand( plotPanelWindow ) );
|
dlg.SetSimCommand( plotPanelWindow->GetSimCommand() );
|
||||||
dlg.SetSimOptions( m_workbook->GetSimOptions( plotPanelWindow ) );
|
dlg.SetSimOptions( plotPanelWindow->GetSimOptions() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2013,8 +2015,8 @@ bool SIM_PLOT_FRAME::EditSimCommand()
|
||||||
{
|
{
|
||||||
wxString oldCommand;
|
wxString oldCommand;
|
||||||
|
|
||||||
if( m_workbook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND )
|
if( m_plotNotebook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND )
|
||||||
oldCommand = m_workbook->GetSimCommand( plotPanelWindow );
|
oldCommand = plotPanelWindow->GetSimCommand();
|
||||||
else
|
else
|
||||||
oldCommand = wxString();
|
oldCommand = wxString();
|
||||||
|
|
||||||
|
@ -2038,14 +2040,15 @@ bool SIM_PLOT_FRAME::EditSimCommand()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( m_workbook->GetPageIndex( plotPanelWindow ) == 0 )
|
if( m_plotNotebook->GetPageIndex( plotPanelWindow ) == 0 )
|
||||||
m_circuitModel->SetSimCommandOverride( newCommand );
|
m_circuitModel->SetSimCommandOverride( newCommand );
|
||||||
|
|
||||||
// Update simulation command in the current plot
|
// Update simulation command in the current plot
|
||||||
m_workbook->SetSimCommand( plotPanelWindow, newCommand );
|
plotPanelWindow->SetSimCommand( newCommand );
|
||||||
m_workbook->SetSimOptions( plotPanelWindow, newOptions );
|
plotPanelWindow->SetSimOptions( newOptions );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_workbookModified = true;
|
||||||
m_simulator->Init();
|
m_simulator->Init();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2056,7 +2059,7 @@ bool SIM_PLOT_FRAME::EditSimCommand()
|
||||||
|
|
||||||
bool SIM_PLOT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
|
bool SIM_PLOT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
|
||||||
{
|
{
|
||||||
if( m_workbook->IsModified() )
|
if( m_workbookModified )
|
||||||
{
|
{
|
||||||
wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
|
wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
|
||||||
|
|
||||||
|
@ -2372,10 +2375,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
for( const struct TRACE_DESC& trace : traceInfo )
|
for( const struct TRACE_DESC& trace : traceInfo )
|
||||||
{
|
updateTrace( trace.m_name, trace.m_type, plotPanel );
|
||||||
if( !updateTrace( trace.m_name, trace.m_type, plotPanel ) )
|
|
||||||
removeTrace( trace.m_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
rebuildSignalsGrid( m_filter->GetValue() );
|
rebuildSignalsGrid( m_filter->GetValue() );
|
||||||
plotPanel->GetPlotWin()->UpdateAll();
|
plotPanel->GetPlotWin()->UpdateAll();
|
||||||
|
|
|
@ -50,7 +50,7 @@ class NGSPICE_CIRCUIT_MODEL;
|
||||||
|
|
||||||
#include <sim/sim_plot_panel.h>
|
#include <sim/sim_plot_panel.h>
|
||||||
#include <sim/sim_panel_base.h>
|
#include <sim/sim_panel_base.h>
|
||||||
#include <sim/sim_workbook.h>
|
#include <sim/sim_notebook.h>
|
||||||
|
|
||||||
class SIM_THREAD_REPORTER;
|
class SIM_THREAD_REPORTER;
|
||||||
class TUNER_SLIDER;
|
class TUNER_SLIDER;
|
||||||
|
@ -62,6 +62,12 @@ public:
|
||||||
SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent );
|
SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent );
|
||||||
~SIM_PLOT_FRAME();
|
~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();
|
void StartSimulation();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -208,18 +214,18 @@ public:
|
||||||
|
|
||||||
wxString GetCurrentSimCommand() const
|
wxString GetCurrentSimCommand() const
|
||||||
{
|
{
|
||||||
if( getCurrentPlotWindow() == nullptr )
|
if( getCurrentPlotWindow() )
|
||||||
return m_circuitModel->GetSchTextSimCommand();
|
return getCurrentPlotWindow()->GetSimCommand();
|
||||||
else
|
else
|
||||||
return m_workbook->GetSimCommand( getCurrentPlotWindow() );
|
return m_circuitModel->GetSchTextSimCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetCurrentOptions() const
|
int GetCurrentOptions() const
|
||||||
{
|
{
|
||||||
if( getCurrentPlotWindow() == nullptr )
|
if( getCurrentPlotWindow() )
|
||||||
return m_circuitModel->GetSimOptions();
|
return getCurrentPlotWindow()->GetSimOptions();
|
||||||
else
|
else
|
||||||
return m_workbook->GetSimOptions( getCurrentPlotWindow() );
|
return m_circuitModel->GetSimOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulator doesn't host a tool framework
|
// Simulator doesn't host a tool framework
|
||||||
|
@ -266,9 +272,15 @@ private:
|
||||||
* @param aType describes the type of plot.
|
* @param aType describes the type of plot.
|
||||||
* @param aParam is the parameter for the device/net (e.g. I, Id, V).
|
* @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.
|
||||||
* @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.
|
* Rebuild the filtered list of signals in the signals grid.
|
||||||
|
@ -295,7 +307,7 @@ private:
|
||||||
*/
|
*/
|
||||||
SIM_PANEL_BASE* getCurrentPlotWindow() const
|
SIM_PANEL_BASE* getCurrentPlotWindow() const
|
||||||
{
|
{
|
||||||
return dynamic_cast<SIM_PANEL_BASE*>( m_workbook->GetCurrentPage() );
|
return dynamic_cast<SIM_PANEL_BASE*>( m_plotNotebook->GetCurrentPage() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -319,8 +331,7 @@ private:
|
||||||
void onCursorsGridCellChanged( wxGridEvent& aEvent ) override;
|
void onCursorsGridCellChanged( wxGridEvent& aEvent ) override;
|
||||||
void onMeasurementsGridCellChanged( wxGridEvent& aEvent ) override;
|
void onMeasurementsGridCellChanged( wxGridEvent& aEvent ) override;
|
||||||
|
|
||||||
void onWorkbookModified( wxCommandEvent& event );
|
void onNotebookModified( wxCommandEvent& event );
|
||||||
void onWorkbookClrModified( wxCommandEvent& event );
|
|
||||||
|
|
||||||
bool canCloseWindow( wxCloseEvent& aEvent ) override;
|
bool canCloseWindow( wxCloseEvent& aEvent ) override;
|
||||||
void doCloseWindow() override;
|
void doCloseWindow() override;
|
||||||
|
@ -364,6 +375,7 @@ private:
|
||||||
unsigned int m_plotNumber;
|
unsigned int m_plotNumber;
|
||||||
bool m_simFinished;
|
bool m_simFinished;
|
||||||
unsigned int m_outputCounter;
|
unsigned int m_outputCounter;
|
||||||
|
bool m_workbookModified;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
|
|
|
@ -43,11 +43,11 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const
|
||||||
|
|
||||||
m_sizerPlot = new wxBoxSizer( wxHORIZONTAL );
|
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_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_workbook->SetMinSize( wxSize( 200,-1 ) );
|
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 );
|
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 );
|
this->Centre( wxBOTH );
|
||||||
|
|
||||||
// Connect Events
|
// Connect Events
|
||||||
m_workbook->Connect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this );
|
m_plotNotebook->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_plotNotebook->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_plotNotebook->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_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_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_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 );
|
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()
|
SIM_PLOT_FRAME_BASE::~SIM_PLOT_FRAME_BASE()
|
||||||
{
|
{
|
||||||
// Disconnect Events
|
// Disconnect Events
|
||||||
m_workbook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIM_PLOT_FRAME_BASE::onPlotDragged ), NULL, this );
|
m_plotNotebook->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_plotNotebook->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_plotNotebook->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_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_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_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 );
|
m_signalsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( SIM_PLOT_FRAME_BASE::onSignalsGridCellChanged ), NULL, this );
|
||||||
|
|
|
@ -307,7 +307,7 @@
|
||||||
<property name="window_name"></property>
|
<property name="window_name"></property>
|
||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
<object class="splitteritem" expanded="1">
|
<object class="splitteritem" expanded="1">
|
||||||
<object class="wxPanel" expanded="0">
|
<object class="wxPanel" expanded="1">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
|
@ -358,7 +358,7 @@
|
||||||
<property name="window_extra_style"></property>
|
<property name="window_extra_style"></property>
|
||||||
<property name="window_name"></property>
|
<property name="window_name"></property>
|
||||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||||
<object class="wxBoxSizer" expanded="0">
|
<object class="wxBoxSizer" expanded="1">
|
||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">m_sizerPlot</property>
|
<property name="name">m_sizerPlot</property>
|
||||||
<property name="orient">wxHORIZONTAL</property>
|
<property name="orient">wxHORIZONTAL</property>
|
||||||
|
@ -402,7 +402,7 @@
|
||||||
<property name="minimize_button">0</property>
|
<property name="minimize_button">0</property>
|
||||||
<property name="minimum_size">200,-1</property>
|
<property name="minimum_size">200,-1</property>
|
||||||
<property name="moveable">1</property>
|
<property name="moveable">1</property>
|
||||||
<property name="name">m_workbook</property>
|
<property name="name">m_plotNotebook</property>
|
||||||
<property name="pane_border">1</property>
|
<property name="pane_border">1</property>
|
||||||
<property name="pane_position"></property>
|
<property name="pane_position"></property>
|
||||||
<property name="pane_size"></property>
|
<property name="pane_size"></property>
|
||||||
|
@ -413,7 +413,7 @@
|
||||||
<property name="show">1</property>
|
<property name="show">1</property>
|
||||||
<property name="size"></property>
|
<property name="size"></property>
|
||||||
<property name="style">wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_MIDDLE_CLICK_CLOSE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TOP</property>
|
<property name="style">wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_MIDDLE_CLICK_CLOSE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TOP</property>
|
||||||
<property name="subclass">SIM_WORKBOOK; sim_workbook.h; Not forward_declare</property>
|
<property name="subclass">SIM_NOTEBOOK; sim_notebook.h; </property>
|
||||||
<property name="tab_ctrl_height">-1</property>
|
<property name="tab_ctrl_height">-1</property>
|
||||||
<property name="toolbar_pane">0</property>
|
<property name="toolbar_pane">0</property>
|
||||||
<property name="tooltip"></property>
|
<property name="tooltip"></property>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
class ACTION_TOOLBAR;
|
class ACTION_TOOLBAR;
|
||||||
class WX_GRID;
|
class WX_GRID;
|
||||||
|
|
||||||
#include "sim_workbook.h"
|
#include "sim_notebook.h"
|
||||||
#include "kiway_player.h"
|
#include "kiway_player.h"
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
#include <wx/aui/aui.h>
|
#include <wx/aui/aui.h>
|
||||||
|
@ -50,7 +50,7 @@ class SIM_PLOT_FRAME_BASE : public KIWAY_PLAYER
|
||||||
wxSplitterWindow* m_splitterPlotAndConsole;
|
wxSplitterWindow* m_splitterPlotAndConsole;
|
||||||
wxPanel* m_plotPanel;
|
wxPanel* m_plotPanel;
|
||||||
wxBoxSizer* m_sizerPlot;
|
wxBoxSizer* m_sizerPlot;
|
||||||
SIM_WORKBOOK* m_workbook;
|
SIM_NOTEBOOK* m_plotNotebook;
|
||||||
wxPanel* m_panelConsole;
|
wxPanel* m_panelConsole;
|
||||||
wxBoxSizer* m_sizerConsole;
|
wxBoxSizer* m_sizerConsole;
|
||||||
wxTextCtrl* m_simConsole;
|
wxTextCtrl* m_simConsole;
|
||||||
|
|
|
@ -551,7 +551,7 @@ void SIM_PLOT_PANEL::updateAxes( SIM_TRACE_TYPE aNewTraceType )
|
||||||
|
|
||||||
void SIM_PLOT_PANEL::prepareDCAxes()
|
void SIM_PLOT_PANEL::prepareDCAxes()
|
||||||
{
|
{
|
||||||
wxString sim_cmd = getSimCommand().Lower();
|
wxString sim_cmd = GetSimCommand().Lower();
|
||||||
wxString rem;
|
wxString rem;
|
||||||
|
|
||||||
if( sim_cmd.StartsWith( ".dc", &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,
|
TRACE* SIM_PLOT_PANEL::AddTrace( const wxString& aTitle, const wxString& aName,
|
||||||
const double* aX, const double* aY, SIM_TRACE_TYPE aType )
|
SIM_TRACE_TYPE aType )
|
||||||
{
|
{
|
||||||
TRACE* trace = nullptr;
|
TRACE* trace = nullptr;
|
||||||
|
|
||||||
|
auto it = m_traces.find( aTitle );
|
||||||
|
|
||||||
|
if( it != m_traces.end() )
|
||||||
|
return it->second;
|
||||||
|
|
||||||
updateAxes( aType );
|
updateAxes( aType );
|
||||||
|
|
||||||
// Find previous entry, if there is one
|
if( GetType() == ST_TRANSIENT )
|
||||||
auto prev = m_traces.find( aTitle );
|
|
||||||
bool addedNewEntry = ( prev == m_traces.end() );
|
|
||||||
|
|
||||||
if( addedNewEntry )
|
|
||||||
{
|
{
|
||||||
if( GetType() == ST_TRANSIENT )
|
bool hasVoltageTraces = false;
|
||||||
|
|
||||||
|
for( const auto& [ name, candidate ] : m_traces )
|
||||||
{
|
{
|
||||||
bool hasVoltageTraces = false;
|
if( candidate->GetType() & SPT_VOLTAGE )
|
||||||
|
|
||||||
for( const auto& [ name, candidate ] : m_traces )
|
|
||||||
{
|
{
|
||||||
if( candidate->GetType() & SPT_VOLTAGE )
|
hasVoltageTraces = true;
|
||||||
{
|
break;
|
||||||
hasVoltageTraces = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !hasVoltageTraces )
|
|
||||||
{
|
|
||||||
if( m_axis_y2 )
|
|
||||||
m_axis_y2->SetMasterScale( nullptr );
|
|
||||||
|
|
||||||
if( m_axis_y3 )
|
|
||||||
m_axis_y3->SetMasterScale( nullptr );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New entry
|
if( !hasVoltageTraces )
|
||||||
trace = new TRACE( aName, aType );
|
{
|
||||||
trace->SetTraceColour( m_colors.GenerateColor( m_traces ) );
|
if( m_axis_y2 )
|
||||||
UpdateTraceStyle( trace );
|
m_axis_y2->SetMasterScale( nullptr );
|
||||||
m_traces[ aTitle ] = trace;
|
|
||||||
|
|
||||||
m_plotWin->AddLayer( (mpLayer*) trace );
|
if( m_axis_y3 )
|
||||||
}
|
m_axis_y3->SetMasterScale( nullptr );
|
||||||
else
|
}
|
||||||
{
|
|
||||||
trace = prev->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<double> tmp( aY, aY + aPoints );
|
std::vector<double> tmp( aY, aY + aPoints );
|
||||||
|
|
||||||
if( GetType() == ST_AC )
|
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
|
tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for( int i = 0; i < aPoints; i++ )
|
for( unsigned int i = 0; i < aPoints; i++ )
|
||||||
{
|
{
|
||||||
// log( 0 ) is not valid.
|
// log( 0 ) is not valid.
|
||||||
if( tmp[i] != 0 )
|
if( tmp[i] != 0 )
|
||||||
|
@ -747,20 +747,18 @@ bool SIM_PLOT_PANEL::addTrace( const wxString& aTitle, const wxString& aName, in
|
||||||
|
|
||||||
trace->SetData( std::vector<double>( aX, aX + aPoints ), tmp );
|
trace->SetData( std::vector<double>( 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 );
|
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 );
|
trace->SetScale( m_axis_x, m_axis_y3 );
|
||||||
else
|
else
|
||||||
trace->SetScale( m_axis_x, m_axis_y1 );
|
trace->SetScale( m_axis_x, m_axis_y1 );
|
||||||
|
|
||||||
m_plotWin->UpdateAll();
|
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 );
|
auto it = m_traces.find( aName );
|
||||||
|
|
||||||
|
|
|
@ -185,8 +185,6 @@ protected:
|
||||||
|
|
||||||
class SIM_PLOT_PANEL : public SIM_PANEL_BASE
|
class SIM_PLOT_PANEL : public SIM_PANEL_BASE
|
||||||
{
|
{
|
||||||
friend class SIM_WORKBOOK;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id,
|
SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id,
|
||||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||||
|
@ -303,11 +301,11 @@ public:
|
||||||
return m_plotWin;
|
return m_plotWin;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
TRACE* AddTrace( const wxString& aTitle, const wxString& aName, SIM_TRACE_TYPE aType );
|
||||||
bool addTrace( const wxString& aTitle, const wxString& aName, int aPoints, const double* aX,
|
|
||||||
const double* aY, 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:
|
private:
|
||||||
///< @brief Construct the plot axes for DC simulation plot.
|
///< @brief Construct the plot axes for DC simulation plot.
|
||||||
|
|
Loading…
Reference in New Issue