KiCad PCB EDA Suite
sim_plot_frame.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016 CERN
5  * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  * @author Maciej Suminski <maciej.suminski@cern.ch>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 3
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * https://www.gnu.org/licenses/gpl-3.0.html
22  * or you may search the http://www.gnu.org website for the version 3 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <wx/debug.h>
28 #include <wx/stc/stc.h>
29 
30 #include <project/project_file.h>
31 #include <sch_edit_frame.h>
32 #include <eeschema_id.h>
33 #include <kiway.h>
34 #include <confirm.h>
35 #include <bitmaps.h>
37 #include <widgets/tuner_slider.h>
39 #include "string_utils.h"
41 #include <pgm_base.h>
42 #include "ngspice.h"
43 #include "sim_plot_colors.h"
44 #include "sim_plot_frame.h"
45 #include "sim_plot_panel.h"
46 #include "spice_simulator.h"
47 #include "spice_reporter.h"
48 #include <menus_helpers.h>
49 #include <tool/tool_manager.h>
50 #include <tools/ee_actions.h>
51 #include <eeschema_settings.h>
52 #include <wx/ffile.h>
53 #include <wx/filedlg.h>
54 #include <dialog_shim.h>
55 
56 
58 {
59  int res = (int) aFirst | (int) aSecond;
60 
61  return (SIM_PLOT_TYPE) res;
62 }
63 
64 
66 {
67 public:
69  m_parent( aParent )
70  {
71  }
72 
73  REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
74  {
75  wxCommandEvent* event = new wxCommandEvent( EVT_SIM_REPORT );
76  event->SetString( aText );
77  wxQueueEvent( m_parent, event );
78  return *this;
79  }
80 
81  bool HasMessage() const override
82  {
83  return false; // Technically "indeterminate" rather than false.
84  }
85 
86  void OnSimStateChange( SPICE_SIMULATOR* aObject, SIM_STATE aNewState ) override
87  {
88  wxCommandEvent* event = nullptr;
89 
90  switch( aNewState )
91  {
92  case SIM_IDLE:
93  event = new wxCommandEvent( EVT_SIM_FINISHED );
94  break;
95 
96  case SIM_RUNNING:
97  event = new wxCommandEvent( EVT_SIM_STARTED );
98  break;
99 
100  default:
101  wxFAIL;
102  return;
103  }
104 
105  wxQueueEvent( m_parent, event );
106  }
107 
108 private:
110 };
111 
112 
113 SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
114  SIM_PLOT_FRAME_BASE( aParent ),
115  m_lastSimPlot( nullptr ),
116  m_plotNumber( 0 ),
117  m_simFinished( false )
118 {
119  SetKiway( this, aKiway );
120  m_signalsIconColorList = nullptr;
121 
123 
124  if( m_schematicFrame == nullptr )
125  throw std::runtime_error( "There is no schematic window" );
126 
127  // Give an icon
128  wxIcon icon;
129  icon.CopyFromBitmap( KiBitmap( BITMAPS::simulator ) );
130  SetIcon( icon );
131 
133 
134  if( !m_simulator )
135  {
136  throw std::runtime_error( "Could not create simulator instance" );
137  return;
138  }
139 
140  // Get the previous size and position of windows:
141  LoadSettings( config() );
142 
143  // Prepare the color list to plot traces
145 
146  // Give icons to menuitems
148 
149  m_simulator->Init();
150 
151  m_reporter = new SIM_THREAD_REPORTER( this );
152  m_simulator->SetReporter( m_reporter );
153 
154  // the settings dialog will be created later, on demand.
155  // if created in the ctor, for some obscure reason, there is an issue
156  // on Windows: when open it, the simulator frame is sent to the background.
157  // instead of being behind the dialog frame (as it does)
158  m_settingsDlg = nullptr;
159 
161 
162  Bind( EVT_SIM_UPDATE, &SIM_PLOT_FRAME::onSimUpdate, this );
163  Bind( EVT_SIM_REPORT, &SIM_PLOT_FRAME::onSimReport, this );
164  Bind( EVT_SIM_STARTED, &SIM_PLOT_FRAME::onSimStarted, this );
165  Bind( EVT_SIM_FINISHED, &SIM_PLOT_FRAME::onSimFinished, this );
166  Bind( EVT_SIM_CURSOR_UPDATE, &SIM_PLOT_FRAME::onCursorUpdate, this );
167 
168  // Toolbar buttons
169  m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _( "Run/Stop Simulation" ),
170  KiBitmap( BITMAPS::sim_run ), _( "Run Simulation" ), wxITEM_NORMAL );
171  m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _( "Add Signals" ),
172  KiBitmap( BITMAPS::sim_add_signal ), _( "Add signals to plot" ), wxITEM_NORMAL );
173  m_toolProbe = m_toolBar->AddTool( ID_SIM_PROBE, _( "Probe" ),
174  KiBitmap( BITMAPS::sim_probe ), _( "Probe signals on the schematic" ), wxITEM_NORMAL );
175  m_toolTune = m_toolBar->AddTool( ID_SIM_TUNE, _( "Tune" ),
176  KiBitmap( BITMAPS::sim_tune ), _( "Tune component values" ), wxITEM_NORMAL );
177  m_toolSettings = m_toolBar->AddTool( wxID_ANY, _( "Sim Parameters" ),
178  KiBitmap( BITMAPS::config ), _( "Simulation parameters and settings" ), wxITEM_NORMAL );
179 
180  // Start all toolbar buttons except settings as disabled
181  m_toolSimulate->Enable( false );
182  m_toolAddSignals->Enable( false );
183  m_toolProbe->Enable( false );
184  m_toolTune->Enable( false );
185  m_toolSettings->Enable( true );
186 
187  Bind( wxEVT_UPDATE_UI, &SIM_PLOT_FRAME::menuSimulateUpdate, this, m_toolSimulate->GetId() );
188  Bind( wxEVT_UPDATE_UI, &SIM_PLOT_FRAME::menuAddSignalsUpdate, this,
189  m_toolAddSignals->GetId() );
190  Bind( wxEVT_UPDATE_UI, &SIM_PLOT_FRAME::menuProbeUpdate, this, m_toolProbe->GetId() );
191  Bind( wxEVT_UPDATE_UI, &SIM_PLOT_FRAME::menuTuneUpdate, this, m_toolTune->GetId() );
192 
193  Bind( wxEVT_COMMAND_TOOL_CLICKED, &SIM_PLOT_FRAME::onSimulate, this, m_toolSimulate->GetId() );
194  Bind( wxEVT_COMMAND_TOOL_CLICKED, &SIM_PLOT_FRAME::onAddSignal, this,
195  m_toolAddSignals->GetId() );
196  Bind( wxEVT_COMMAND_TOOL_CLICKED, &SIM_PLOT_FRAME::onProbe, this, m_toolProbe->GetId() );
197  Bind( wxEVT_COMMAND_TOOL_CLICKED, &SIM_PLOT_FRAME::onTune, this, m_toolTune->GetId() );
198  Bind( wxEVT_COMMAND_TOOL_CLICKED, &SIM_PLOT_FRAME::onSettings, this, m_toolSettings->GetId() );
199 
200  Bind( EVT_WORKBOOK_MODIFIED, &SIM_PLOT_FRAME::onWorkbookModified, this );
201  Bind( EVT_WORKBOOK_CLR_MODIFIED, &SIM_PLOT_FRAME::onWorkbookClrModified, this );
202 
203  // Bind toolbar buttons event to existing menu event handlers, so they behave the same
204  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this,
205  m_runSimulation->GetId() );
206  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() );
207  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() );
208  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onTune, this, m_tuneValue->GetId() );
209  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onShowNetlist, this,
210  m_showNetlist->GetId() );
211  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this,
212  m_boardAdapter->GetId() );
213 
214  m_toolBar->Realize();
215 
216 #ifndef wxHAS_NATIVE_TABART
217  // Non-native default tab art has ugly gradients we don't want
218  m_workbook->SetArtProvider( new wxAuiSimpleTabArt() );
219 #endif
220 
221  // Ensure new items are taken in account by sizers:
222  Layout();
223 
224  // resize the subwindows size. At least on Windows, calling wxSafeYield before
225  // resizing the subwindows forces the wxSplitWindows size events automatically generated
226  // by wxWidgets to be executed before our resize code.
227  // Otherwise, the changes made by setSubWindowsSashSize are overwritten by one these
228  // events
229  wxSafeYield();
231 
232  // Ensure the window is on top
233  Raise();
234 
235  initWorkbook();
236  updateTitle();
237 }
238 
239 
241 {
242  m_simulator->SetReporter( nullptr );
243  delete m_reporter;
244  delete m_signalsIconColorList;
245 
246  if( m_settingsDlg )
247  m_settingsDlg->Destroy();
248 }
249 
250 
252 {
253  EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
254  wxASSERT( cfg );
255 
256  if( cfg )
257  {
259 
260  // Read subwindows sizes (should be > 0 )
266  }
267 
269 
270  NGSPICE* currentSim = dynamic_cast<NGSPICE*>( m_simulator.get() );
271 
272  if( currentSim )
273  m_simulator->Settings() = project.m_SchematicSettings->m_NgspiceSimulatorSettings;
274 }
275 
276 
278 {
279  EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
280  wxASSERT( cfg );
281 
282  if( cfg )
283  {
285 
286  cfg->m_Simulator.plot_panel_width = m_splitterLeftRight->GetSashPosition();
287  cfg->m_Simulator.plot_panel_height = m_splitterPlotAndConsole->GetSashPosition();
288  cfg->m_Simulator.signal_panel_height = m_splitterSignals->GetSashPosition();
289  cfg->m_Simulator.cursors_panel_height = m_splitterTuneValues->GetSashPosition();
291  }
292 
293  if( !m_isNonUserClose ) // If we're exiting the project has already been released.
294  {
296 
297  if( project.m_SchematicSettings )
298  project.m_SchematicSettings->m_NgspiceSimulatorSettings->SaveToFile();
299 
300  if( m_schematicFrame )
302  }
303 }
304 
305 
307 {
308  EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
309  wxASSERT( cfg );
310 
311  return cfg ? &cfg->m_Simulator.window : nullptr;
312 }
313 
314 
316 {
317  // Removed for the time being. We cannot run the simulation on simulator launch, as it may
318  // take a lot of time, confusing the user.
319  // TODO: Change workbook loading routines so that they don't run the simulation until the user
320  // initiates it.
321 
322  /*if( !m_simulator->Settings()->GetWorkbookFilename().IsEmpty() )
323  {
324  wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
325  filename.SetPath( Prj().GetProjectPath() );
326 
327  if( !loadWorkbook( filename.GetFullPath() ) )
328  m_simulator->Settings()->SetWorkbookFilename( "" );
329  }*/
330 }
331 
332 
334 {
335  wxFileName filename = Prj().AbsolutePath( m_simulator->Settings()->GetWorkbookFilename() );
336 
337  bool readOnly = false;
338  bool unsaved = false;
339 
340  if( filename.IsOk() && filename.FileExists() )
341  readOnly = !filename.IsFileWritable();
342  else
343  unsaved = true;
344 
345  wxString title;
346 
347  if( m_workbook->IsModified() )
348  title = wxT( "*" ) + filename.GetName();
349  else
350  title = filename.GetName();
351 
352  if( readOnly )
353  title += wxS( " " ) + _( "[Read Only]" );
354 
355  if( unsaved )
356  title += wxS( " " ) + _( "[Unsaved]" );
357 
358  title += wxT( " \u2014 " ) + _( "Spice Simulator" );
359 
360  SetTitle( title );
361 }
362 
363 
364 // A small helper struct to handle bitmaps initialization in menus
366 {
367  int m_MenuId;
369 };
370 
371 
373 {
374  // Give icons to menuitems of the main menubar
375  BM_MENU_INIT_ITEM bm_list[]
376  {
377  // File menu:
378  { wxID_NEW, BITMAPS::simulator },
379  { wxID_OPEN, BITMAPS::directory_open },
380  { wxID_SAVE, BITMAPS::save },
383  { wxID_CLOSE, BITMAPS::exit },
384 
385  // simulator menu:
392 
393  // View menu
394  { wxID_ZOOM_IN, BITMAPS::zoom_in },
395  { wxID_ZOOM_OUT, BITMAPS::zoom_out },
396  { wxID_ZOOM_FIT, BITMAPS::zoom_fit_in_page },
401 
402  { 0, BITMAPS::INVALID_BITMAP } // Sentinel
403  };
404 
405  // wxMenuItems are already created and attached to the m_mainMenu wxMenuBar.
406  // A problem is the fact setting bitmaps in wxMenuItems after they are attached
407  // to a wxMenu do not work in all cases.
408  // So the trick is:
409  // Remove the wxMenuItem from its wxMenu
410  // Set the bitmap
411  // Insert the modified wxMenuItem to its previous place
412  for( int ii = 0; bm_list[ii].m_MenuId; ++ii )
413  {
414  wxMenuItem* item = m_mainMenu->FindItem( bm_list[ii].m_MenuId );
415 
416  if( !item || ( bm_list[ii].m_Bitmap == BITMAPS::INVALID_BITMAP ) )
417  continue;
418 
419  wxMenu* menu = item->GetMenu();
420 
421  // Calculate the initial index of item inside the wxMenu parent.
422  wxMenuItemList& mlist = menu->GetMenuItems();
423  int mpos = mlist.IndexOf( item );
424 
425  if( mpos >= 0 ) // Should be always the case
426  {
427  // Modify the bitmap
428  menu->Remove( item );
429  AddBitmapToMenuItem( item, KiBitmap( bm_list[ii].m_Bitmap ) );
430 
431  // Insert item to its the initial index
432  menu->Insert( mpos, item );
433  }
434  }
435 }
436 
437 
439 {
442 
445 
448 
451 }
452 
453 
454 void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
455 {
456  wxCHECK_RET( m_exporter->CommandToSimType( getCurrentSimCommand() ) != ST_UNKNOWN,
457  "Unknown simulation type" );
458 
459  STRING_FORMATTER formatter;
460 
461  if( !m_settingsDlg )
462  m_settingsDlg = new DIALOG_SIM_SETTINGS( this, m_simulator->Settings() );
463 
464  m_simConsole->Clear();
466 
467  if( aSimCommand.IsEmpty() )
468  m_exporter->SetSimCommand( getCurrentSimCommand() );
469  else
470  m_exporter->SetSimCommand( aSimCommand );
471 
472 
473  if( !m_exporter->Format( &formatter, m_settingsDlg->GetNetlistOptions() ) )
474  {
475  DisplayErrorMessage( this, _( "There were errors during netlist export, aborted." ) );
476  return;
477  }
478 
479  m_simulator->LoadNetlist( formatter.GetString() );
480  updateTuners();
481  applyTuners();
482  m_simulator->Run();
483 }
484 
485 
487 {
488  m_simulator->Stop();
489 }
490 
491 
493 {
494  SIM_PANEL_BASE* plotPanel = nullptr;
496 
497  if( SIM_PANEL_BASE::IsPlottable( simType ) )
498  {
499  SIM_PLOT_PANEL* panel;
500  panel = new SIM_PLOT_PANEL( aSimCommand, m_workbook, this, wxID_ANY );
501 
503  Pgm().GetCommonSettings()->m_Input.scroll_modifier_zoom != 0 );
504 
505  plotPanel = dynamic_cast<SIM_PANEL_BASE*>( panel );
506  }
507  else
508  {
509  SIM_NOPLOT_PANEL* panel;
510  panel = new SIM_NOPLOT_PANEL( aSimCommand, m_workbook, wxID_ANY );
511  plotPanel = dynamic_cast<SIM_PANEL_BASE*>( panel );
512  }
513 
514  wxString pageTitle( m_simulator->TypeToName( simType, true ) );
515  pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), (unsigned int) ++m_plotNumber ) );
516 
517  m_workbook->AddPage( dynamic_cast<wxWindow*>( plotPanel ), pageTitle, true );
518 
519  return plotPanel;
520 }
521 
522 
523 void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName )
524 {
525  addPlot( aNetName, SPT_VOLTAGE, "V" );
526 }
527 
528 
529 void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName, const wxString& aParam )
530 {
531  addPlot( aDeviceName, SPT_CURRENT, aParam );
532 }
533 
534 
536 {
537  SIM_PANEL_BASE* plotPanel = getCurrentPlotWindow();
538 
539  if( !plotPanel )
540  return;
541 
542  // For now limit the tuner tool to RLC components
543  char primitiveType = NETLIST_EXPORTER_PSPICE::GetSpiceField( SF_PRIMITIVE, aSymbol, 0 )[0];
544 
545  if( primitiveType != SP_RESISTOR && primitiveType != SP_CAPACITOR
546  && primitiveType != SP_INDUCTOR )
547  return;
548 
549  const wxString componentName = aSymbol->GetField( REFERENCE_FIELD )->GetText();
550 
551  // Do not add multiple instances for the same component
552  auto tunerIt = std::find_if( m_tuners.begin(), m_tuners.end(), [&]( const TUNER_SLIDER* t )
553  {
554  return t->GetComponentName() == componentName;
555  }
556  );
557 
558  if( tunerIt != m_tuners.end() )
559  return; // We already have it
560 
561  try
562  {
563  TUNER_SLIDER* tuner = new TUNER_SLIDER( this, m_tunePanel, aSymbol );
564  m_tuneSizer->Add( tuner );
565  m_tuners.push_back( tuner );
566  m_tunePanel->Layout();
567  }
568  catch( const KI_PARAM_ERROR& e )
569  {
570  // Sorry, no bonus
571  DisplayErrorMessage( nullptr, e.What() );
572  }
573 }
574 
575 
576 void SIM_PLOT_FRAME::RemoveTuner( TUNER_SLIDER* aTuner, bool aErase )
577 {
578  if( aErase )
579  m_tuners.remove( aTuner );
580 
581  aTuner->Destroy();
582  m_tunePanel->Layout();
583 }
584 
585 
587 {
589 
590  return ( ( !curPage || curPage->GetType() == ST_UNKNOWN ) ?
591  nullptr :
592  dynamic_cast<SIM_PLOT_PANEL*>( curPage ) );
593 }
594 
595 
597 {
598  return m_exporter.get();
599 }
600 
601 
602 std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& SIM_PLOT_FRAME::GetSimulatorSettings()
603 {
604  wxASSERT( m_simulator->Settings() );
605 
606  return m_simulator->Settings();
607 }
608 
609 
610 void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam )
611 {
612  SIM_TYPE simType = m_exporter->GetSimType();
613 
614  if( simType == ST_UNKNOWN )
615  {
616  m_simConsole->AppendText( _( "Error: simulation type not defined!\n" ) );
617  m_simConsole->SetInsertionPointEnd();
618  return;
619  }
620  else if( !SIM_PANEL_BASE::IsPlottable( simType ) )
621  {
622  m_simConsole->AppendText( _( "Error: simulation type doesn't support plotting!\n" ) );
623  m_simConsole->SetInsertionPointEnd();
624  return;
625  }
626 
627  // Create a new plot if the current one displays a different type
628  SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
629 
630  if( !plotPanel || plotPanel->GetType() != simType )
631  {
632  plotPanel =
633  dynamic_cast<SIM_PLOT_PANEL*>( NewPlotPanel( m_exporter->GetUsedSimCommand() ) );
634  }
635 
636  wxASSERT( plotPanel );
637 
638  if( !plotPanel ) // Something is wrong
639  return;
640 
641  bool updated = false;
642  SIM_PLOT_TYPE xAxisType = getXAxisType( simType );
643 
644  if( xAxisType == SPT_LIN_FREQUENCY || xAxisType == SPT_LOG_FREQUENCY )
645  {
646  int baseType = aType & ~( SPT_AC_MAG | SPT_AC_PHASE );
647 
648  // Add two plots: magnitude & phase
649  updated |= updatePlot( aName, ( SIM_PLOT_TYPE )( baseType | SPT_AC_MAG ), aParam,
650  plotPanel );
651  updated |= updatePlot( aName, ( SIM_PLOT_TYPE )( baseType | SPT_AC_PHASE ), aParam,
652  plotPanel );
653  }
654  else
655  {
656  updated = updatePlot( aName, aType, aParam, plotPanel );
657  }
658 
659  if( updated )
660  {
662  }
663 }
664 
665 
666 void SIM_PLOT_FRAME::removePlot( const wxString& aPlotName )
667 {
668  SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
669 
670  if( !plotPanel )
671  return;
672 
673  wxASSERT( plotPanel->TraceShown( aPlotName ) );
674  m_workbook->DeleteTrace( plotPanel, aPlotName );
675  plotPanel->GetPlotWin()->Fit();
676 
678  wxCommandEvent dummy;
680 }
681 
682 
684 {
686 
687  if( m_settingsDlg )
689 }
690 
691 
692 bool SIM_PLOT_FRAME::updatePlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam,
693  SIM_PLOT_PANEL* aPlotPanel )
694 {
695  SIM_TYPE simType = m_exporter->GetSimType();
696  wxString spiceVector = m_exporter->ComponentToVector( aName, aType, aParam );
697 
698  wxString plotTitle = wxString::Format( "%s(%s)", aParam, aName );
699  if( aType & SPT_AC_MAG )
700  plotTitle += " (mag)";
701  else if( aType & SPT_AC_PHASE )
702  plotTitle += " (phase)";
703 
704  if( !SIM_PANEL_BASE::IsPlottable( simType ) )
705  {
706  // There is no plot to be shown
707  m_simulator->Command( wxString::Format( "print %s", spiceVector ).ToStdString() );
708 
709  return false;
710  }
711 
712  // First, handle the x axis
713  wxString xAxisName( m_simulator->GetXAxis( simType ) );
714 
715  if( xAxisName.IsEmpty() )
716  return false;
717 
718  auto data_x = m_simulator->GetMagPlot( (const char*) xAxisName.c_str() );
719  unsigned int size = data_x.size();
720 
721  if( data_x.empty() )
722  return false;
723 
724  std::vector<double> data_y;
725 
726  // Now, Y axis data
727  switch( m_exporter->GetSimType() )
728  {
729  case ST_AC:
730  wxASSERT_MSG( !( ( aType & SPT_AC_MAG ) && ( aType & SPT_AC_PHASE ) ),
731  "Cannot set both AC_PHASE and AC_MAG bits" );
732 
733  if( aType & SPT_AC_MAG )
734  data_y = m_simulator->GetMagPlot( (const char*) spiceVector.c_str() );
735  else if( aType & SPT_AC_PHASE )
736  data_y = m_simulator->GetPhasePlot( (const char*) spiceVector.c_str() );
737  else
738  wxASSERT_MSG( false, "Plot type missing AC_PHASE or AC_MAG bit" );
739 
740  break;
741 
742  case ST_NOISE:
743  case ST_DC:
744  case ST_TRANSIENT:
745  data_y = m_simulator->GetMagPlot( (const char*) spiceVector.c_str() );
746  break;
747 
748  default:
749  wxASSERT_MSG( false, "Unhandled plot type" );
750  return false;
751  }
752 
753  if( data_y.size() != size )
754  return false;
755 
756  // If we did a two-source DC analysis, we need to split the resulting vector and add traces
757  // for each input step
758  SPICE_DC_PARAMS source1, source2;
759 
760  if( m_exporter->GetSimType() == ST_DC &&
761  m_exporter->ParseDCCommand( m_exporter->GetUsedSimCommand(), &source1, &source2 ) )
762  {
763  if( !source2.m_source.IsEmpty() )
764  {
765  // Source 1 is the inner loop, so lets add traces for each Source 2 (outer loop) step
766  SPICE_VALUE v = source2.m_vstart;
767  wxString name;
768 
769  size_t offset = 0;
770  size_t outer = ( size_t )( ( source2.m_vend - v ) / source2.m_vincrement ).ToDouble();
771  size_t inner = data_x.size() / ( outer + 1 );
772 
773  wxASSERT( data_x.size() % ( outer + 1 ) == 0 );
774 
775  for( size_t idx = 0; idx <= outer; idx++ )
776  {
777  name = wxString::Format( "%s (%s = %s V)", plotTitle, source2.m_source,
778  v.ToString() );
779 
780  std::vector<double> sub_x( data_x.begin() + offset,
781  data_x.begin() + offset + inner );
782  std::vector<double> sub_y( data_y.begin() + offset,
783  data_y.begin() + offset + inner );
784 
785  m_workbook->AddTrace( aPlotPanel, name, aName, inner, sub_x.data(), sub_y.data(),
786  aType, aParam );
787 
788  v = v + source2.m_vincrement;
789  offset += inner;
790  }
791 
792  return true;
793  }
794  }
795 
796  m_workbook->AddTrace( aPlotPanel, plotTitle, aName, size, data_x.data(), data_y.data(), aType,
797  aParam );
798 
799  return true;
800 }
801 
802 
804 {
805  m_signals->ClearAll();
806 
807  SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
808 
809  if( !plotPanel )
810  return;
811 
812  wxSize size = m_signals->GetClientSize();
813  m_signals->AppendColumn( _( "Signal" ), wxLIST_FORMAT_LEFT, size.x );
814 
815  // Build an image list, to show the color of the corresponding trace
816  // in the plot panel
817  // This image list is used for trace and cursor lists
818  wxMemoryDC bmDC;
819  const int isize = bmDC.GetCharHeight();
820 
821  if( m_signalsIconColorList == nullptr )
822  m_signalsIconColorList = new wxImageList( isize, isize, false );
823  else
824  m_signalsIconColorList->RemoveAll();
825 
826  for( const auto& trace : GetCurrentPlot()->GetTraces() )
827  {
828  wxBitmap bitmap( isize, isize );
829  bmDC.SelectObject( bitmap );
830  wxColour tcolor = trace.second->GetPen().GetColour();
831 
832  wxColour bgColor = m_signals->wxWindow::GetBackgroundColour();
833  bmDC.SetPen( wxPen( bgColor ) );
834  bmDC.SetBrush( wxBrush( bgColor ) );
835  bmDC.DrawRectangle( 0, 0, isize, isize ); // because bmDC.Clear() does not work in wxGTK
836 
837  bmDC.SetPen( wxPen( tcolor ) );
838  bmDC.SetBrush( wxBrush( tcolor ) );
839  bmDC.DrawRectangle( 0, isize / 4 + 1, isize, isize / 2 );
840 
841  bmDC.SelectObject( wxNullBitmap ); // Needed to initialize bitmap
842 
843  bitmap.SetMask( new wxMask( bitmap, *wxBLACK ) );
844  m_signalsIconColorList->Add( bitmap );
845  }
846 
847  if( bmDC.IsOk() )
848  {
849  bmDC.SetBrush( wxNullBrush );
850  bmDC.SetPen( wxNullPen );
851  }
852 
853  m_signals->SetImageList( m_signalsIconColorList, wxIMAGE_LIST_SMALL );
854 
855  // Fill the signals listctrl. Keep the order of names and
856  // the order of icon color identical, because the icons
857  // are also used in cursor list, and the color index is
858  // calculated from the trace name index
859  int imgidx = 0;
860 
861  for( const auto& trace : plotPanel->GetTraces() )
862  {
863  m_signals->InsertItem( imgidx, trace.first, imgidx );
864  imgidx++;
865  }
866 }
867 
868 
870 {
871  const auto& spiceItems = m_exporter->GetSpiceItems();
872 
873  for( auto it = m_tuners.begin(); it != m_tuners.end(); /* iteration inside the loop */ )
874  {
875  const wxString& ref = (*it)->GetComponentName();
876 
877  if( std::find_if( spiceItems.begin(), spiceItems.end(), [&]( const SPICE_ITEM& item )
878  {
879  return item.m_refName == ref;
880  }) == spiceItems.end() )
881  {
882  // The component does not exist anymore, remove the associated tuner
883  TUNER_SLIDER* tuner = *it;
884  it = m_tuners.erase( it );
885  RemoveTuner( tuner, false );
886  }
887  else
888  {
889  ++it;
890  }
891  }
892 }
893 
894 
896 {
897  for( auto& tuner : m_tuners )
898  {
900  std::string command( "alter @" + tuner->GetSpiceName()
901  + "=" + tuner->GetValue().ToSpiceString() );
902 
903  m_simulator->Command( command );
904  }
905 }
906 
907 
908 bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
909 {
911 
912  wxTextFile file( aPath );
913 
914 #define DISPLAY_LOAD_ERROR( fmt ) DisplayErrorMessage( this, wxString::Format( _( fmt ), \
915  file.GetCurrentLine()+1 ) )
916 
917  if( !file.Open() )
918  return false;
919 
920  long plotsCount;
921 
922  if( !file.GetFirstLine().ToLong( &plotsCount ) ) // GetFirstLine instead of GetNextLine
923  {
924  DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is not an integer." );
925  file.Close();
926 
927  return false;
928  }
929 
930  for( long i = 0; i < plotsCount; ++i )
931  {
932  long plotType, tracesCount;
933 
934  if( !file.GetNextLine().ToLong( &plotType ) )
935  {
936  DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is not an integer." );
937  file.Close();
938 
939  return false;
940  }
941 
942  wxString simCommand = UnescapeString( file.GetNextLine() );
943  NewPlotPanel( simCommand );
944  StartSimulation( simCommand );
945 
946  // Perform simulation, so plots can be added with values
947  do
948  {
949  wxThread::This()->Sleep( 50 );
950  }
951  while( m_simulator->IsRunning() );
952 
953  if( !file.GetNextLine().ToLong( &tracesCount ) )
954  {
955  DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is not an integer." );
956  file.Close();
957 
958  return false;
959  }
960 
961  for( long j = 0; j < tracesCount; ++j )
962  {
963  long traceType;
964  wxString name, param;
965 
966  if( !file.GetNextLine().ToLong( &traceType ) )
967  {
968  DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is not an integer." );
969  file.Close();
970 
971  return false;
972  }
973 
974  name = file.GetNextLine();
975 
976  if( name.IsEmpty() )
977  {
978  DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is empty." );
979  file.Close();
980 
981  return false;
982  }
983 
984  param = file.GetNextLine();
985 
986  if( param.IsEmpty() )
987  {
988  DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is empty." );
989  file.Close();
990 
991  return false;
992  }
993 
994  addPlot( name, (SIM_PLOT_TYPE) traceType, param );
995  }
996  }
997 
998  file.Close();
999 
1000  wxFileName filename( aPath );
1001  filename.MakeRelativeTo( Prj().GetProjectPath() );
1002 
1003  // Remember the loaded workbook filename.
1004  m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() );
1005 
1006  // Successfully loading a workbook does not count as modifying it.
1008  return true;
1009 }
1010 
1011 
1012 bool SIM_PLOT_FRAME::saveWorkbook( const wxString& aPath )
1013 {
1014  wxFileName filename = aPath;
1015  filename.SetExt( WorkbookFileExtension );
1016 
1017  wxTextFile file( filename.GetFullPath() );
1018 
1019  if( file.Exists() )
1020  {
1021  if( !file.Open() )
1022  return false;
1023 
1024  file.Clear();
1025  }
1026  else
1027  {
1028  file.Create();
1029  }
1030 
1031  file.AddLine( wxString::Format( "%llu", m_workbook->GetPageCount() ) );
1032 
1033  for( size_t i = 0; i < m_workbook->GetPageCount(); i++ )
1034  {
1035  const SIM_PANEL_BASE* basePanel = dynamic_cast<const SIM_PANEL_BASE*>( m_workbook->GetPage( i ) );
1036 
1037  if( !basePanel )
1038  {
1039  file.AddLine( wxString::Format( "%llu", 0ull ) );
1040  continue;
1041  }
1042 
1043  file.AddLine( wxString::Format( "%d", basePanel->GetType() ) );
1044  file.AddLine( EscapeString( m_workbook->GetSimCommand( basePanel ), CTX_LINE ) );
1045 
1046  const SIM_PLOT_PANEL* plotPanel = dynamic_cast<const SIM_PLOT_PANEL*>( basePanel );
1047 
1048  if( !plotPanel )
1049  {
1050  file.AddLine( wxString::Format( "%llu", 0ull ) );
1051  continue;
1052  }
1053 
1054  file.AddLine( wxString::Format( "%llu", plotPanel->GetTraces().size() ) );
1055 
1056  for( const auto& trace : plotPanel->GetTraces() )
1057  {
1058  file.AddLine( wxString::Format( "%d", trace.second->GetType() ) );
1059  file.AddLine( trace.second->GetName() );
1060  file.AddLine( trace.second->GetParam() );
1061  }
1062  }
1063 
1064  bool res = file.Write();
1065  file.Close();
1066 
1067  // Store the filename of the last saved workbook.
1068  if( res )
1069  {
1070  filename.MakeRelativeTo( Prj().GetProjectPath() );
1071  m_simulator->Settings()->SetWorkbookFilename( filename.GetFullPath() );
1072  }
1073 
1075  return res;
1076 }
1077 
1078 
1080 {
1081  wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
1082 
1083  if( filename.GetName().IsEmpty() )
1084  {
1085  if( Prj().GetProjectName().IsEmpty() )
1086  {
1087  filename.SetName( _( "noname" ) );
1088  filename.SetExt( WorkbookFileExtension );
1089  }
1090  else
1091  {
1092  filename.SetName( Prj().GetProjectName() );
1093  filename.SetExt( WorkbookFileExtension );
1094  }
1095  }
1096 
1097  return filename.GetFullName();
1098 }
1099 
1100 
1102 {
1103  wxFileName path = m_simulator->Settings()->GetWorkbookFilename();
1104 
1105  path.Normalize( wxPATH_NORM_ALL, Prj().GetProjectPath() );
1106  return path.GetPath();
1107 }
1108 
1109 
1111 {
1112  switch( aType )
1113  {
1115  case ST_AC: return SPT_LIN_FREQUENCY;
1116  case ST_DC: return SPT_SWEEP;
1117  case ST_TRANSIENT: return SPT_TIME;
1118  default:
1119  wxASSERT_MSG( false, "Unhandled simulation type" );
1120  return (SIM_PLOT_TYPE) 0;
1121  }
1122 }
1123 
1124 
1125 void SIM_PLOT_FRAME::menuNewPlot( wxCommandEvent& aEvent )
1126 {
1127  SIM_TYPE type = m_exporter->GetSimType();
1128 
1129  if( SIM_PANEL_BASE::IsPlottable( type ) )
1130  NewPlotPanel( m_exporter->GetUsedSimCommand() );
1131 }
1132 
1133 
1134 void SIM_PLOT_FRAME::menuOpenWorkbook( wxCommandEvent& event )
1135 {
1136  wxFileDialog openDlg( this, _( "Open simulation workbook" ), getDefaultPath(), "",
1137  WorkbookFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
1138 
1139  if( openDlg.ShowModal() == wxID_CANCEL )
1140  return;
1141 
1142  loadWorkbook( openDlg.GetPath() );
1143 }
1144 
1145 
1146 void SIM_PLOT_FRAME::menuSaveWorkbook( wxCommandEvent& event )
1147 {
1148  if( !m_workbook->IsModified() )
1149  return;
1150 
1151  wxString filename = m_simulator->Settings()->GetWorkbookFilename();
1152 
1153  if( filename.IsEmpty() )
1154  {
1155  menuSaveWorkbookAs( event );
1156  return;
1157  }
1158 
1159  saveWorkbook( Prj().AbsolutePath( m_simulator->Settings()->GetWorkbookFilename() ) );
1160 }
1161 
1162 
1163 void SIM_PLOT_FRAME::menuSaveWorkbookAs( wxCommandEvent& event )
1164 {
1165  wxFileDialog saveAsDlg( this, _( "Save Simulation Workbook As" ), getDefaultPath(),
1167  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1168 
1169  if( saveAsDlg.ShowModal() == wxID_CANCEL )
1170  return;
1171 
1172  saveWorkbook( Prj().AbsolutePath( saveAsDlg.GetPath() ) );
1173 }
1174 
1175 
1176 void SIM_PLOT_FRAME::menuSaveImage( wxCommandEvent& event )
1177 {
1178  if( !GetCurrentPlot() )
1179  return;
1180 
1181  wxFileDialog saveDlg( this, _( "Save Plot as Image" ), "", "", PngFileWildcard(),
1182  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1183 
1184  if( saveDlg.ShowModal() == wxID_CANCEL )
1185  return;
1186 
1187  GetCurrentPlot()->GetPlotWin()->SaveScreenshot( saveDlg.GetPath(), wxBITMAP_TYPE_PNG );
1188 }
1189 
1190 
1191 void SIM_PLOT_FRAME::menuSaveCsv( wxCommandEvent& event )
1192 {
1193  if( !GetCurrentPlot() )
1194  return;
1195 
1196  const wxChar SEPARATOR = ';';
1197 
1198  wxFileDialog saveDlg( this, _( "Save Plot Data" ), "", "", CsvFileWildcard(),
1199  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1200 
1201  if( saveDlg.ShowModal() == wxID_CANCEL )
1202  return;
1203 
1204  wxFFile out( saveDlg.GetPath(), "wb" );
1205  bool timeWritten = false;
1206 
1207  for( const auto& t : GetCurrentPlot()->GetTraces() )
1208  {
1209  const TRACE* trace = t.second;
1210 
1211  if( !timeWritten )
1212  {
1213  out.Write( wxString::Format( "Time%c", SEPARATOR ) );
1214 
1215  for( double v : trace->GetDataX() )
1216  out.Write( wxString::Format( "%g%c", v, SEPARATOR ) );
1217 
1218  out.Write( "\r\n" );
1219  timeWritten = true;
1220  }
1221 
1222  out.Write( wxString::Format( "%s%c", t.first, SEPARATOR ) );
1223 
1224  for( double v : trace->GetDataY() )
1225  out.Write( wxString::Format( "%g%c", v, SEPARATOR ) );
1226 
1227  out.Write( "\r\n" );
1228  }
1229 
1230  out.Close();
1231 }
1232 
1233 
1234 void SIM_PLOT_FRAME::menuZoomIn( wxCommandEvent& event )
1235 {
1236  if( GetCurrentPlot() )
1238 }
1239 
1240 
1241 void SIM_PLOT_FRAME::menuZoomOut( wxCommandEvent& event )
1242 {
1243  if( GetCurrentPlot() )
1245 }
1246 
1247 
1248 void SIM_PLOT_FRAME::menuZoomFit( wxCommandEvent& event )
1249 {
1250  if( GetCurrentPlot() )
1251  GetCurrentPlot()->GetPlotWin()->Fit();
1252 }
1253 
1254 
1255 void SIM_PLOT_FRAME::menuShowGrid( wxCommandEvent& event )
1256 {
1258 
1259  if( plot )
1260  plot->ShowGrid( !plot->IsGridShown() );
1261 }
1262 
1263 
1264 void SIM_PLOT_FRAME::menuShowGridUpdate( wxUpdateUIEvent& event )
1265 {
1267 
1268  event.Check( plot ? plot->IsGridShown() : false );
1269 }
1270 
1271 
1272 void SIM_PLOT_FRAME::menuShowLegend( wxCommandEvent& event )
1273 {
1275 
1276  if( plot )
1277  plot->ShowLegend( !plot->IsLegendShown() );
1278 }
1279 
1280 
1281 void SIM_PLOT_FRAME::menuShowLegendUpdate( wxUpdateUIEvent& event )
1282 {
1284  event.Check( plot ? plot->IsLegendShown() : false );
1285 }
1286 
1287 
1288 void SIM_PLOT_FRAME::menuShowDotted( wxCommandEvent& event )
1289 {
1291 
1292  if( plot )
1293  plot->SetDottedCurrentPhase( !plot->GetDottedCurrentPhase() );
1294 }
1295 
1296 
1297 void SIM_PLOT_FRAME::menuShowDottedUpdate( wxUpdateUIEvent& event )
1298 {
1300 
1301  event.Check( plot ? plot->GetDottedCurrentPhase() : false );
1302 }
1303 
1304 
1305 void SIM_PLOT_FRAME::menuWhiteBackground( wxCommandEvent& event )
1306 {
1308 
1309  // Rebuild the color list to plot traces
1311 
1312  // Now send changes to all SIM_PLOT_PANEL
1313  for( size_t page = 0; page < m_workbook->GetPageCount(); page++ )
1314  {
1315  wxWindow* curPage = m_workbook->GetPage( page );
1316 
1317  // ensure it is truly a plot panel and not the (zero plots) placeholder
1318  // which is only SIM_PLOT_PANEL_BASE
1319  SIM_PLOT_PANEL* panel = dynamic_cast<SIM_PLOT_PANEL*>( curPage );
1320 
1321  if( panel )
1322  panel->UpdatePlotColors();
1323  }
1324 }
1325 
1326 
1327 void SIM_PLOT_FRAME::menuSimulateUpdate( wxUpdateUIEvent& event )
1328 {
1329  event.Enable( m_exporter->CommandToSimType( getCurrentSimCommand() ) != ST_UNKNOWN );
1330 }
1331 
1332 
1333 void SIM_PLOT_FRAME::menuAddSignalsUpdate( wxUpdateUIEvent& event )
1334 {
1335  event.Enable( m_simFinished );
1336 }
1337 
1338 
1339 void SIM_PLOT_FRAME::menuProbeUpdate( wxUpdateUIEvent& event )
1340 {
1341  event.Enable( m_simFinished );
1342 }
1343 
1344 
1345 void SIM_PLOT_FRAME::menuTuneUpdate( wxUpdateUIEvent& event )
1346 {
1347  event.Enable( m_simFinished );
1348 }
1349 
1350 
1351 void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event )
1352 {
1353 }
1354 
1355 
1356 void SIM_PLOT_FRAME::onPlotClosed( wxAuiNotebookEvent& event )
1357 {
1358  if( m_workbook->GetPageCount() == 0 )
1359  {
1360  m_signals->ClearAll();
1361  m_cursors->ClearAll();
1362  }
1363  else
1364  {
1365  updateSignalList();
1366  wxCommandEvent dummy;
1367  onCursorUpdate( dummy );
1368  }
1369 }
1370 
1371 
1372 void SIM_PLOT_FRAME::onPlotChanged( wxAuiNotebookEvent& event )
1373 {
1374  updateSignalList();
1375  wxCommandEvent dummy;
1376  onCursorUpdate( dummy );
1377 }
1378 
1379 
1380 void SIM_PLOT_FRAME::onPlotDragged( wxAuiNotebookEvent& event )
1381 {
1382 }
1383 
1384 
1385 void SIM_PLOT_FRAME::onSignalDblClick( wxMouseEvent& event )
1386 {
1387  // Remove signal from the plot panel when double clicked
1388  long idx = m_signals->GetFocusedItem();
1389 
1390  if( idx != wxNOT_FOUND )
1391  removePlot( m_signals->GetItemText( idx, 0 ) );
1392 }
1393 
1394 
1395 void SIM_PLOT_FRAME::onSignalRClick( wxListEvent& event )
1396 {
1397  int idx = event.GetIndex();
1398 
1399  if( idx != wxNOT_FOUND )
1400  m_signals->Select( idx );
1401 
1402  idx = m_signals->GetFirstSelected();
1403 
1404  if( idx != wxNOT_FOUND )
1405  {
1406  const wxString& netName = m_signals->GetItemText( idx, 0 );
1407  SIGNAL_CONTEXT_MENU ctxMenu( netName, this );
1408  m_signals->PopupMenu( &ctxMenu );
1409  }
1410 }
1411 
1412 
1413 void SIM_PLOT_FRAME::onWorkbookModified( wxCommandEvent& event )
1414 {
1415  updateTitle();
1416 }
1417 
1418 
1419 void SIM_PLOT_FRAME::onWorkbookClrModified( wxCommandEvent& event )
1420 {
1421  updateTitle();
1422 }
1423 
1424 
1425 void SIM_PLOT_FRAME::onSimulate( wxCommandEvent& event )
1426 {
1427  if( m_simulator->IsRunning() )
1428  StopSimulation();
1429  else
1430  StartSimulation();
1431 }
1432 
1433 
1434 void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event )
1435 {
1436  SIM_PANEL_BASE* plotPanelWindow = getCurrentPlotWindow();
1437 
1438  if( !m_settingsDlg )
1439  m_settingsDlg = new DIALOG_SIM_SETTINGS( this, m_simulator->Settings() );
1440 
1441  // Initial processing is required to e.g. display a list of power sources
1443 
1444  if( !m_exporter->ProcessNetlist( NET_ALL_FLAGS ) )
1445  {
1446  DisplayErrorMessage( this, _( "There were errors during netlist export, aborted." ) );
1447  return;
1448  }
1449 
1450  if( m_workbook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND )
1451  m_settingsDlg->SetSimCommand( m_workbook->GetSimCommand( plotPanelWindow ) );
1452 
1453  if( m_settingsDlg->ShowModal() == wxID_OK )
1454  {
1455  wxString oldCommand;
1456 
1457  if( m_workbook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND )
1458  oldCommand = m_workbook->GetSimCommand( plotPanelWindow );
1459  else
1460  oldCommand = wxString();
1461 
1462  wxString newCommand = m_settingsDlg->GetSimCommand();
1463  SIM_TYPE newSimType = NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( newCommand );
1464 
1465  // If it is a new simulation type, open a new plot
1466  // For the DC sim, check if sweep source type has changed (char 4 will contain 'v',
1467  // 'i', 'r' or 't'.
1468  if( !plotPanelWindow
1469  || ( plotPanelWindow && plotPanelWindow->GetType() != newSimType )
1470  || ( newSimType == ST_DC
1471  && oldCommand.Lower().GetChar( 4 ) != newCommand.Lower().GetChar( 4 ) ) )
1472  {
1473  plotPanelWindow = NewPlotPanel( newCommand );
1474  }
1475  else
1476  {
1477  // Update simulation command in the current plot
1478  m_workbook->SetSimCommand( plotPanelWindow, newCommand );
1479  }
1480 
1481  m_simulator->Init();
1482  }
1483 }
1484 
1485 
1486 void SIM_PLOT_FRAME::onAddSignal( wxCommandEvent& event )
1487 {
1488  wxCHECK_RET( m_simFinished, "No simulation results available" );
1489 
1490  SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
1491 
1492  if( !plotPanel || !m_exporter || plotPanel->GetType() != m_exporter->GetSimType() )
1493  {
1494  DisplayInfoMessage( this, _( "You need to run plot-providing simulation first." ) );
1495  return;
1496  }
1497 
1498  DIALOG_SIGNAL_LIST dialog( this, m_exporter.get() );
1499  dialog.ShowModal();
1500 }
1501 
1502 
1503 void SIM_PLOT_FRAME::onProbe( wxCommandEvent& event )
1504 {
1505  wxCHECK_RET( m_simFinished, "No simulation results available" );
1506 
1507  if( m_schematicFrame == nullptr )
1508  return;
1509 
1511  m_schematicFrame->Raise();
1512 }
1513 
1514 
1515 void SIM_PLOT_FRAME::onTune( wxCommandEvent& event )
1516 {
1517  wxCHECK_RET( m_simFinished, "No simulation results available" );
1518 
1519  if( m_schematicFrame == nullptr )
1520  return;
1521 
1523  m_schematicFrame->Raise();
1524 }
1525 
1526 
1527 void SIM_PLOT_FRAME::onShowNetlist( wxCommandEvent& event )
1528 {
1529  class NETLIST_VIEW_DIALOG : public DIALOG_SHIM
1530  {
1531  public:
1532  enum
1533  {
1534  MARGIN_LINE_NUMBERS
1535  };
1536 
1537  void onClose( wxCloseEvent& evt )
1538  {
1539  wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) );
1540  }
1541 
1542  NETLIST_VIEW_DIALOG( wxWindow* parent, wxString source) :
1543  DIALOG_SHIM( parent, wxID_ANY, "SPICE Netlist",
1544  wxDefaultPosition, wxDefaultSize,
1545  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
1546  {
1547  wxStyledTextCtrl* text = new wxStyledTextCtrl( this, wxID_ANY );
1548  text->SetMinSize( wxSize( 600, 400 ) );
1549 
1550  text->SetMarginWidth( MARGIN_LINE_NUMBERS, 50 );
1551  text->StyleSetForeground( wxSTC_STYLE_LINENUMBER, wxColour( 75, 75, 75 ) );
1552  text->StyleSetBackground( wxSTC_STYLE_LINENUMBER, wxColour( 220, 220, 220 ) );
1553  text->SetMarginType( MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER );
1554 
1555  wxFont fixedFont = KIUI::GetMonospacedUIFont();
1556 
1557  for( size_t i = 0; i < wxSTC_STYLE_MAX; ++i )
1558  text->StyleSetFont( i, fixedFont );
1559 
1560  text->StyleClearAll(); // Addresses a bug in wx3.0 where styles are not correctly set
1561 
1562  text->SetWrapMode( wxSTC_WRAP_WORD );
1563 
1564  text->SetText( source );
1565 
1566  text->SetLexer( wxSTC_LEX_SPICE );
1567 
1568  wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
1569  sizer->Add( text, 1, wxEXPAND );
1570  SetSizer( sizer );
1571 
1572  Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( NETLIST_VIEW_DIALOG::onClose ),
1573  nullptr, this );
1574 
1575  finishDialogSettings();
1576  }
1577  };
1578 
1579  if( m_schematicFrame == nullptr || m_simulator == nullptr )
1580  return;
1581 
1582  NETLIST_VIEW_DIALOG dlg( this, m_simulator->GetNetlist() );
1583  dlg.ShowModal();
1584 }
1585 
1586 
1587 bool SIM_PLOT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
1588 {
1589  if( m_workbook->IsModified() )
1590  {
1591  wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
1592 
1593  if( filename.GetName().IsEmpty() )
1594  {
1595  if( Prj().GetProjectName().IsEmpty() )
1596  filename.SetFullName( wxT( "noname.wbk" ) );
1597  else
1598  filename.SetFullName( Prj().GetProjectName() + wxT( ".wbk" ) );
1599  }
1600 
1601  wxString msg = _( "Save changes to '%s' before closing?" );
1602 
1603  return HandleUnsavedChanges( this, wxString::Format( msg, filename.GetFullName() ),
1604  [&]()->bool
1605  {
1606  return saveWorkbook( Prj().AbsolutePath( filename.GetFullName() ) );
1607  } );
1608  }
1609 
1610  return true;
1611 }
1612 
1613 
1615 {
1616  if( m_simulator->IsRunning() )
1617  m_simulator->Stop();
1618 
1619  // Cancel a running simProbe or simTune tool
1621 
1622  SaveSettings( config() );
1623  Destroy();
1624 }
1625 
1626 
1627 void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event )
1628 {
1629  wxSize size = m_cursors->GetClientSize();
1630  SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
1631  m_cursors->ClearAll();
1632 
1633  if( !plotPanel )
1634  return;
1635 
1637  m_cursors->SetImageList(m_signalsIconColorList, wxIMAGE_LIST_SMALL);
1638 
1639  // Fill the signals listctrl
1640  m_cursors->AppendColumn( _( "Signal" ), wxLIST_FORMAT_LEFT, size.x / 2 );
1641  const long X_COL = m_cursors->AppendColumn( plotPanel->GetLabelX(), wxLIST_FORMAT_LEFT,
1642  size.x / 4 );
1643 
1644  wxString labelY1 = plotPanel->GetLabelY1();
1645  wxString labelY2 = plotPanel->GetLabelY2();
1646  wxString labelY;
1647 
1648  if( !labelY2.IsEmpty() )
1649  labelY = labelY1 + " / " + labelY2;
1650  else
1651  labelY = labelY1;
1652 
1653  const long Y_COL = m_cursors->AppendColumn( labelY, wxLIST_FORMAT_LEFT, size.x / 4 );
1654 
1655  // Update cursor values
1656  int itemidx = 0;
1657 
1658  for( const auto& trace : plotPanel->GetTraces() )
1659  {
1660  if( CURSOR* cursor = trace.second->GetCursor() )
1661  {
1662  // Find the right icon color in list.
1663  // It is the icon used in m_signals list for the same trace
1664  long iconColor = m_signals->FindItem( -1, trace.first );
1665 
1666  const wxRealPoint coords = cursor->GetCoords();
1667  long idx = m_cursors->InsertItem( itemidx++, trace.first, iconColor );
1668  m_cursors->SetItem( idx, X_COL, SPICE_VALUE( coords.x ).ToSpiceString() );
1669  m_cursors->SetItem( idx, Y_COL, SPICE_VALUE( coords.y ).ToSpiceString() );
1670  }
1671  }
1672 }
1673 
1674 
1675 void SIM_PLOT_FRAME::onSimStarted( wxCommandEvent& aEvent )
1676 {
1677  m_toolBar->SetToolNormalBitmap( ID_SIM_RUN, KiBitmap( BITMAPS::sim_stop ) );
1678  SetCursor( wxCURSOR_ARROWWAIT );
1679 }
1680 
1681 
1682 void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
1683 {
1684  m_toolBar->SetToolNormalBitmap( ID_SIM_RUN, KiBitmap( BITMAPS::sim_run ) );
1685  SetCursor( wxCURSOR_ARROW );
1686 
1687  SIM_TYPE simType = m_exporter->GetSimType();
1688 
1689  if( simType == ST_UNKNOWN )
1690  return;
1691 
1692  SIM_PANEL_BASE* plotPanelWindow = getCurrentPlotWindow();
1693 
1694  if( !plotPanelWindow || plotPanelWindow->GetType() != simType )
1695  plotPanelWindow = NewPlotPanel( m_exporter->GetUsedSimCommand() );
1696 
1697  if( m_simulator->IsRunning() )
1698  return;
1699 
1700  // If there are any signals plotted, update them
1701  if( SIM_PANEL_BASE::IsPlottable( simType ) )
1702  {
1703  SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( plotPanelWindow );
1704  wxCHECK_RET( plotPanel, "not a SIM_PLOT_PANEL" );
1705 
1706  struct TRACE_DESC
1707  {
1708  wxString m_name;
1710  wxString m_param;
1711  };
1712 
1713  std::vector<struct TRACE_DESC> traceInfo;
1714 
1715  // Get information about all the traces on the plot, remove and add again
1716  for( auto& trace : plotPanel->GetTraces() )
1717  {
1718  struct TRACE_DESC placeholder;
1719  placeholder.m_name = trace.second->GetName();
1720  placeholder.m_type = trace.second->GetType();
1721  placeholder.m_param = trace.second->GetParam();
1722 
1723  traceInfo.push_back( placeholder );
1724  }
1725 
1726  for( auto& trace : traceInfo )
1727  {
1728  if( !updatePlot( trace.m_name, trace.m_type, trace.m_param, plotPanel ) )
1729  removePlot( trace.m_name );
1730  }
1731 
1732  updateSignalList();
1733  plotPanel->GetPlotWin()->UpdateAll();
1734  plotPanel->ResetScales();
1735  }
1736  else if( simType == ST_OP )
1737  {
1738  m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) );
1739  m_simConsole->SetInsertionPointEnd();
1740 
1741  for( const auto& vec : m_simulator->AllPlots() )
1742  {
1743  std::vector<double> val_list = m_simulator->GetRealPlot( vec, 1 );
1744 
1745  if( val_list.size() == 0 ) // The list of values can be empty!
1746  continue;
1747 
1748  double val = val_list.at( 0 );
1749  wxString outLine, signal;
1750  SIM_PLOT_TYPE type = m_exporter->VectorToSignal( vec, signal );
1751 
1752  const size_t tab = 25; //characters
1753  size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
1754 
1755  outLine.Printf( wxT( "%s%s" ),
1756  ( signal + wxT( ":" ) ).Pad( padding, wxUniChar( ' ' ) ),
1757  SPICE_VALUE( val ).ToSpiceString() );
1758 
1759  outLine.Append( type == SPT_CURRENT ? "A\n" : "V\n" );
1760 
1761  m_simConsole->AppendText( outLine );
1762  m_simConsole->SetInsertionPointEnd();
1763 
1764  // @todo display calculated values on the schematic
1765  }
1766  }
1767 
1768  m_simFinished = true;
1769 }
1770 
1771 
1772 void SIM_PLOT_FRAME::onSimUpdate( wxCommandEvent& aEvent )
1773 {
1774  if( m_simulator->IsRunning() )
1775  StopSimulation();
1776 
1777  if( GetCurrentPlot() != m_lastSimPlot )
1778  {
1779  // We need to rerun simulation, as the simulator currently stores
1780  // results for another plot
1781  StartSimulation();
1782  }
1783  else
1784  {
1785  // Incremental update
1786  m_simConsole->Clear();
1787 
1788  // Do not export netlist, it is already stored in the simulator
1789  applyTuners();
1790  m_simulator->Run();
1791  }
1792 }
1793 
1794 
1795 void SIM_PLOT_FRAME::onSimReport( wxCommandEvent& aEvent )
1796 {
1797  m_simConsole->AppendText( aEvent.GetString() + "\n" );
1798  m_simConsole->SetInsertionPointEnd();
1799 }
1800 
1801 
1803  SIM_PLOT_FRAME* aPlotFrame ) :
1804  m_signal( aSignal ),
1805  m_plotFrame( aPlotFrame )
1806 {
1808 
1809  AddMenuItem( this, HIDE_SIGNAL, _( "Hide Signal" ), _( "Erase the signal from plot screen" ),
1810  KiBitmap( BITMAPS::trash ) );
1811 
1812  TRACE* trace = plot->GetTrace( m_signal );
1813 
1814  if( trace->HasCursor() )
1815  AddMenuItem( this, HIDE_CURSOR, _( "Hide Cursor" ), KiBitmap( BITMAPS::pcb_target ) );
1816  else
1817  AddMenuItem( this, SHOW_CURSOR, _( "Show Cursor" ), KiBitmap( BITMAPS::pcb_target ) );
1818 
1819  Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( SIGNAL_CONTEXT_MENU::onMenuEvent ),
1820  nullptr, this );
1821 }
1822 
1823 
1825 {
1826  SIM_PLOT_PANEL* plot = m_plotFrame->GetCurrentPlot();
1827 
1828  switch( aEvent.GetId() )
1829  {
1830  case HIDE_SIGNAL:
1831  m_plotFrame->removePlot( m_signal );
1832  break;
1833 
1834  case SHOW_CURSOR:
1835  plot->EnableCursor( m_signal, true );
1836  break;
1837 
1838  case HIDE_CURSOR:
1839  plot->EnableCursor( m_signal, false );
1840  break;
1841  }
1842 }
1843 
1844 
1845 wxDEFINE_EVENT( EVT_SIM_UPDATE, wxCommandEvent );
1846 wxDEFINE_EVENT( EVT_SIM_REPORT, wxCommandEvent );
1847 
1848 wxDEFINE_EVENT( EVT_SIM_STARTED, wxCommandEvent );
1849 wxDEFINE_EVENT( EVT_SIM_FINISHED, wxCommandEvent );
Field Reference of part, i.e. "IC21".
void onAddSignal(wxCommandEvent &event)
#define ID_MENU_PROBE_SIGNALS
#define ID_SAVE_AS_IMAGE
void ZoomOut(const wxPoint &centerPoint=wxDefaultPosition)
Zoom out current view and refresh display.
Definition: mathplot.cpp:2127
bool saveWorkbook(const wxString &aPath)
Save plot settings to a file.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:231
wxString ToSpiceString() const
Return string value in Spice format (e.g.
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
wxToolBarToolBase * m_toolProbe
void setIconsForMenuItems()
Give icons to menuitems of the main menubar.
void onSimStarted(wxCommandEvent &aEvent)
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
void RemoveTuner(TUNER_SLIDER *aTuner, bool aErase=true)
Remove an existing tuner.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
bool GetPlotBgOpt() const
wxImageList * m_signalsIconColorList
SIM_PLOT_TYPE operator|(SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond)
void onPlotChanged(wxAuiNotebookEvent &event) override
void onPlotDragged(wxAuiNotebookEvent &event) override
SIM_PLOT_FRAME * m_parent
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:284
void EnableMouseWheelPan(bool enabled)
Enable/disable trackpad friendly panning (2-axis scroll wheel)
Definition: mathplot.h:1220
virtual APP_SETTINGS_BASE * config() const
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
void menuWhiteBackground(wxCommandEvent &event) override
void SetSimCommand(SIM_PANEL_BASE *aPlotPanel, const wxString &aSimCommand)
Definition: sim_workbook.h:56
void onSignalDblClick(wxMouseEvent &event) override
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:675
void SaveProjectSettings() override
Save changes to the project settings to the project (.pro) file.
bool SetSimCommand(const wxString &aCommand)
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
mpWindow * GetPlotWin() const
This file is part of the common library.
wxSplitterWindow * m_splitterSignals
bool HasCursor() const
void onPlotClosed(wxAuiNotebookEvent &event) override
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
Definition: bitmap.cpp:257
SIM_PANEL_BASE * NewPlotPanel(wxString aSimCommand)
Create a new plot panel for a given simulation type and adds it to the main notebook.
int m_splitterPlotAndConsoleSashPosition
void menuZoomFit(wxCommandEvent &event) override
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:145
Structure to represent a schematic symbol in the Spice simulation.
void initWorkbook()
Load the currently active workbook stored in the project settings.
wxFont GetMonospacedUIFont()
Definition: ui_common.cpp:82
bool AddPage(wxWindow *aPage, const wxString &aCaption, bool aSelect=false, const wxBitmap &aBitmap=wxNullBitmap)
const std::vector< double > & GetDataX() const
bool canCloseWindow(wxCloseEvent &aEvent) override
std::list< TUNER_SLIDER * > m_tuners
static TOOL_ACTION cancelInteractive
Definition: actions.h:62
void doCloseWindow() override
Class SIM_PLOT_FRAME_BASE.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
WINDOW_SETTINGS * GetWindowSettings(APP_SETTINGS_BASE *aCfg) override
Return a pointer to the window settings for this frame.
void menuNewPlot(wxCommandEvent &aEvent) override
void applyTuners()
Apply component values specified using tuner sliders to the current netlist.
SIM_PLOT_PANEL * GetCurrentPlot() const
Return the currently opened plot panel (or NULL if there is none).
wxString getDefaultPath()
Return the default path to be used in file browser dialog.
void AddVoltagePlot(const wxString &aNetName)
Add a voltage plot for a given net name.
void AddCurrentPlot(const wxString &aDeviceName, const wxString &aParam)
Add a current plot for a particular device.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:382
#define ID_MENU_WHITE_BG
std::shared_ptr< SPICE_SIMULATOR_SETTINGS > & GetSimulatorSettings()
Schematic editor (Eeschema) main window.
wxString CsvFileWildcard()
wxString getDefaultFilename()
Return the default filename (with extension) to be used in file browser dialog.
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:82
bool DeleteAllPages() override
void onWorkbookModified(wxCommandEvent &event)
void onSimUpdate(wxCommandEvent &aEvent)
bool updatePlot(const wxString &aName, SIM_PLOT_TYPE aType, const wxString &aParam, SIM_PLOT_PANEL *aPlotPanel)
Update plot in a particular SIM_PLOT_PANEL.
void menuOpenWorkbook(wxCommandEvent &event) override
void menuShowGrid(wxCommandEvent &event) override
void menuZoomIn(wxCommandEvent &event) override
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:70
void menuZoomOut(wxCommandEvent &event) override
SIM_THREAD_REPORTER * m_reporter
List of currently displayed tuners.
void OnSimStateChange(SPICE_SIMULATOR *aObject, SIM_STATE aNewState) override
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
std::shared_ptr< SPICE_SIMULATOR > m_simulator
void menuProbeUpdate(wxUpdateUIEvent &event) override
#define ID_SAVE_AS_CSV
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:64
wxString GetLabelY1() const
wxSplitterWindow * m_splitterTuneValues
static bool IsPlottable(SIM_TYPE aSimType)
static SIM_TYPE CommandToSimType(const wxString &aCmd)
Return simulation type basing on a simulation command directive.
void AddTuner(SCH_SYMBOL *aSymbol)
Add a tuner for a symbol.
void menuSaveCsv(wxCommandEvent &event) override
void onPlotClose(wxAuiNotebookEvent &event) override
void StartSimulation(const wxString &aSimCommand=wxEmptyString)
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:269
bool IsModified() const
Definition: sim_workbook.h:68
SCH_EDIT_FRAME * m_schematicFrame
void UpdateAll()
Refresh display.
Definition: mathplot.cpp:2403
bool AddTrace(SIM_PLOT_PANEL *aPlotPanel, const wxString &aTitle, const wxString &aName, int aPoints, const double *aX, const double *aY, SIM_PLOT_TYPE aType, const wxString &aParam)
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
SIM_STATE
const wxString & GetSimCommand() const
void setSubWindowsSashSize()
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:81
wxString ToString() const
Return string value as when converting double to string (e.g.
SIM_PLOT_PANEL * m_lastSimPlot
imagelists used to add a small colored icon to signal names and cursors name, the same color as the c...
wxString GetLabelX() const
void AddBitmapToMenuItem(wxMenuItem *aMenu, const wxBitmap &aImage)
Add a bitmap to a menuitem.
Definition: bitmap.cpp:243
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:99
#define ID_MENU_SHOW_NETLIST
wxString GetLabelY2() const
static TOOL_ACTION simTune
Definition: ee_actions.h:211
static void FillDefaultColorList(bool aWhiteBg)
Fills m_colorList by a default set of colors.
void removePlot(const wxString &aPlotName)
Remove a plot with a specific title.
< Helper class to handle Spice way of expressing values (e.g. 10.5 Meg) Helper class to recognize Spi...
Definition: spice_value.h:34
wxString getCurrentSimCommand() const
wxSplitterWindow * m_splitterLeftRight
void ZoomIn(const wxPoint &centerPoint=wxDefaultPosition)
Zoom into current view and refresh display.
Definition: mathplot.cpp:2070
wxMenuItem * m_runSimulation
#define ID_MENU_TUNE_SIGNALS
void onSimReport(wxCommandEvent &aEvent)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
SIM_TYPE
< Possible simulation types
Definition: sim_types.h:31
void menuTuneUpdate(wxUpdateUIEvent &event) override
void onSimFinished(wxCommandEvent &aEvent)
Interface to receive simulation updates from SPICE_SIMULATOR class.
SCHEMATIC & Schematic() const
Definition of file extensions used in Kicad.
void onShowNetlist(wxCommandEvent &event)
SIM_THREAD_REPORTER(SIM_PLOT_FRAME *aParent)
void menuShowLegendUpdate(wxUpdateUIEvent &event) override
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:260
void menuSaveWorkbookAs(wxCommandEvent &event) override
#define _(s)
wxToolBarToolBase * m_toolAddSignals
Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder.
SIM_PANEL_BASE * getCurrentPlotWindow() const
Return the currently opened plot panel (or NULL if there is none).
int m_splitterTuneValuesSashPosition
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
void onSignalRClick(wxListEvent &event) override
void ResetScales()
Update trace line style.
void onWorkbookClrModified(wxCommandEvent &event)
#define ID_MENU_SHOW_LEGEND
void menuAddSignalsUpdate(wxUpdateUIEvent &event) override
SEVERITY
void menuShowLegend(wxCommandEvent &event) override
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void onTune(wxCommandEvent &event)
wxToolBarToolBase * m_toolSimulate
wxString UnescapeString(const wxString &aSource)
void menuSaveImage(wxCommandEvent &event) override
#define ID_MENU_SET_SIMUL
wxString PngFileWildcard()
Implementing SIM_PLOT_FRAME_BASE.
bool loadWorkbook(const wxString &aPath)
Load plot settings from a file.
void SetNetlistExporter(NETLIST_EXPORTER_PSPICE_SIM *aExporter)
static wxString GetSpiceField(SPICE_FIELD aField, SCH_SYMBOL *aSymbol, unsigned aCtl)
Retrieve either the requested field value or the default value.
const wxString & GetSimCommand(const SIM_PANEL_BASE *aPlotPanel)
Definition: sim_workbook.h:62
void onCursorUpdate(wxCommandEvent &aEvent)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
bool DeleteTrace(SIM_PLOT_PANEL *aPlotPanel, const wxString &aName)
#define DISPLAY_LOAD_ERROR(fmt)
SIM_TYPE GetType() const
DIALOG_SIM_SETTINGS * m_settingsDlg
void Fit() override
Set view to fit global bounding box of all plot layers and refresh display.
Definition: mathplot.cpp:1910
const wxString What() const
Definition: ki_exception.h:57
void UpdatePlotColors()
Update plot colors
#define ID_MENU_ADD_SIGNAL
std::unique_ptr< NETLIST_EXPORTER_PSPICE_SIM > m_exporter
void updateNetlistExporter()
Reload the current schematic for the netlist exporter.
see class PGM_BASE
Schematic symbol object.
Definition: sch_symbol.h:78
void onSimulate(wxCommandEvent &event)
const char * name
Definition: DXF_plotter.cpp:56
void ClrModified()
SIGNAL_CONTEXT_MENU(const wxString &aSignal, SIM_PLOT_FRAME *aPlotFrame)
void onProbe(wxCommandEvent &event)
#define ID_MENU_SHOW_GRID
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:32
void menuSimulateUpdate(wxUpdateUIEvent &event) override
void updateSignalList()
Update the list of currently plotted signals.
#define ID_MENU_DOTTED
SIM_WORKBOOK * m_workbook
SIM_PLOT_TYPE getXAxisType(SIM_TYPE aType) const
Return X axis for a given simulation type.
unsigned int m_plotNumber
int m_splitterSignalsSashPosition
void updateTitle()
Set the main window title bar text.
void menuShowDotted(wxCommandEvent &event) override
wxDEFINE_EVENT(EVT_SIM_UPDATE, wxCommandEvent)
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
const std::vector< double > & GetDataY() const
int m_splitterLeftRightSashPosition
void menuShowDottedUpdate(wxUpdateUIEvent &event) override
static TOOL_ACTION simProbe
Definition: ee_actions.h:210
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:128
const NETLIST_EXPORTER_PSPICE_SIM * GetExporter() const
Return the netlist exporter object used for simulations.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
Custom widget to handle quick component values modification and simulation on the fly.
Definition: tuner_slider.h:42
wxString WorkbookFileWildcard()
bool SaveScreenshot(const wxString &filename, wxBitmapType type=wxBITMAP_TYPE_BMP, wxSize imageSize=wxDefaultSize, bool fit=false)
Draw the window on a wxBitmap, then save it to a file.
Definition: mathplot.cpp:2630
const std::map< wxString, TRACE * > & GetTraces() const
wxSplitterWindow * m_splitterPlotAndConsole
void menuShowGridUpdate(wxUpdateUIEvent &event) override
const std::string WorkbookFileExtension
bool HasMessage() const override
Returns true if the reporter client is non-empty.
void menuSaveWorkbook(wxCommandEvent &event) override
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:299
Implement an OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:414
SIM_PLOT_TYPE
Definition: sim_types.h:46
#define ID_MENU_RUN_SIM
Class is responsible for providing colors for traces on simulation plot.
Panel that was used as the most recent one for simulations.
void addPlot(const wxString &aName, SIM_PLOT_TYPE aType, const wxString &aParam)
Add a new plot to the current panel.
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
void onSettings(wxCommandEvent &event)
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
wxToolBarToolBase * m_toolTune
void onMenuEvent(wxMenuEvent &aEvent)
bool TraceShown(const wxString &aName) const
Cursor attached to a trace to follow its values:
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
Special netlist exporter flavor that allows one to override simulation commands.
void updateTuners()
Filter out tuners for components that do not exist anymore.
Hold a translatable error message and may be used when throwing exceptions containing a translated er...
Definition: ki_exception.h:44
wxToolBarToolBase * m_toolSettings
HOLDER_TYPE m_type
Definition: kiway_holder.h:76
SIM_PLOT_FRAME(KIWAY *aKiway, wxWindow *aParent)