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-2018 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/stc/stc.h>
28 
29 #include <sch_edit_frame.h>
30 #include <eeschema_id.h>
31 #include <kiway.h>
32 #include <confirm.h>
33 #include <bitmaps.h>
35 #include <widgets/tuner_slider.h>
38 #include <pgm_base.h>
39 #include "sim_plot_frame.h"
40 #include "sim_plot_panel.h"
41 #include "spice_simulator.h"
42 #include "spice_reporter.h"
43 #include <menus_helpers.h>
45 #include <tool/tool_manager.h>
46 #include <tools/ee_actions.h>
47 #include <eeschema_settings.h>
48 
50 {
51  int res = (int) aFirst | (int) aSecond;
52 
53  return (SIM_PLOT_TYPE) res;
54 }
55 
56 
58 {
59 public:
61  : m_parent( aParent )
62  {
63  }
64 
65  REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
66  {
67  wxCommandEvent* event = new wxCommandEvent( EVT_SIM_REPORT );
68  event->SetString( aText );
69  wxQueueEvent( m_parent, event );
70  return *this;
71  }
72 
73  bool HasMessage() const override
74  {
75  return false; // Technically "indeterminate" rather than false.
76  }
77 
78  void OnSimStateChange( SPICE_SIMULATOR* aObject, SIM_STATE aNewState ) override
79  {
80  wxCommandEvent* event = NULL;
81 
82  switch( aNewState )
83  {
84  case SIM_IDLE:
85  event = new wxCommandEvent( EVT_SIM_FINISHED );
86  break;
87 
88  case SIM_RUNNING:
89  event = new wxCommandEvent( EVT_SIM_STARTED );
90  break;
91 
92  default:
93  wxFAIL;
94  return;
95  }
96 
97  wxQueueEvent( m_parent, event );
98  }
99 
100 private:
102 };
103 
104 
105 TRACE_DESC::TRACE_DESC( const NETLIST_EXPORTER_PSPICE_SIM& aExporter, const wxString& aName,
106  SIM_PLOT_TYPE aType, const wxString& aParam )
107  : m_name( aName ), m_type( aType ), m_param( aParam )
108 {
109  // Title generation
110  m_title = wxString::Format( "%s(%s)", aParam, aName );
111 
112  if( aType & SPT_AC_MAG )
113  m_title += " (mag)";
114  else if( aType & SPT_AC_PHASE )
115  m_title += " (phase)";
116 }
117 
118 // Store the path of saved workbooks during the session
120 
121 SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
122  : SIM_PLOT_FRAME_BASE( aParent ),
123  m_lastSimPlot( nullptr ),
124  m_welcomePanel( nullptr ),
125  m_plotNumber( 0 )
126 {
127  SetKiway( this, aKiway );
129 
131 
132  if( m_schematicFrame == NULL )
133  throw std::runtime_error( "There is no schematic window" );
134 
135  // Give an icon
136  wxIcon icon;
137  icon.CopyFromBitmap( KiBitmap( simulator_xpm ) );
138  SetIcon( icon );
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 
150 
151  if( !m_simulator )
152  {
153  throw std::runtime_error( "Could not create simulator instance" );
154  return;
155  }
156 
157  m_simulator->Init();
158 
159  if( m_savedWorkbooksPath.IsEmpty() )
160  {
162  }
163 
164  m_reporter = new SIM_THREAD_REPORTER( this );
165  m_simulator->SetReporter( m_reporter );
166 
168 
169  Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SIM_PLOT_FRAME::onClose ), NULL, this );
170  Connect( EVT_SIM_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onSimUpdate ), NULL, this );
171  Connect( EVT_SIM_REPORT, wxCommandEventHandler( SIM_PLOT_FRAME::onSimReport ), NULL, this );
172  Connect( EVT_SIM_STARTED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimStarted ), NULL, this );
173  Connect( EVT_SIM_FINISHED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimFinished ), NULL, this );
174  Connect( EVT_SIM_CURSOR_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onCursorUpdate ), NULL, this );
175 
176  // Toolbar buttons
177  m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _( "Run/Stop Simulation" ),
178  KiBitmap( sim_run_xpm ), _( "Run Simulation" ), wxITEM_NORMAL );
179  m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _( "Add Signals" ),
180  KiBitmap( sim_add_signal_xpm ), _( "Add signals to plot" ), wxITEM_NORMAL );
181  m_toolProbe = m_toolBar->AddTool( ID_SIM_PROBE, _( "Probe" ),
182  KiBitmap( sim_probe_xpm ), _( "Probe signals on the schematic" ), wxITEM_NORMAL );
183  m_toolTune = m_toolBar->AddTool( ID_SIM_TUNE, _( "Tune" ),
184  KiBitmap( sim_tune_xpm ), _( "Tune component values" ), wxITEM_NORMAL );
185  m_toolSettings = m_toolBar->AddTool( wxID_ANY, _( "Settings" ),
186  KiBitmap( sim_settings_xpm ), _( "Simulation settings" ), wxITEM_NORMAL );
187 
188  Connect( m_toolSimulate->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
189  wxCommandEventHandler( SIM_PLOT_FRAME::onSimulate ), NULL, this );
190  Connect( m_toolAddSignals->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
191  wxCommandEventHandler( SIM_PLOT_FRAME::onAddSignal ), NULL, this );
192  Connect( m_toolProbe->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
193  wxCommandEventHandler( SIM_PLOT_FRAME::onProbe ), NULL, this );
194  Connect( m_toolTune->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
195  wxCommandEventHandler( SIM_PLOT_FRAME::onTune ), NULL, this );
196  Connect( m_toolSettings->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
197  wxCommandEventHandler( SIM_PLOT_FRAME::onSettings ), NULL, this );
198 
199  // Bind toolbar buttons event to existing menu event handlers, so they behave the same
200  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this, m_runSimulation->GetId() );
201  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() );
202  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() );
203  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onTune, this, m_tuneValue->GetId() );
204  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onShowNetlist, this, m_showNetlist->GetId() );
205  Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this, m_settings->GetId() );
206 
207  m_toolBar->Realize();
208 
210  m_plotNotebook->AddPage( m_welcomePanel, _( "Welcome!" ), 1, true );
211 
212  // the settings dialog will be created later, on demand.
213  // if created in the ctor, for some obscure reason, there is an issue
214  // on Windows: when open it, the simulator frame is sent to the background.
215  // instead of being behind the dialog frame (as it does)
217 
218  // resize the subwindows size. At least on Windows, calling wxSafeYield before
219  // resizing the subwindows forces the wxSplitWindows size events automatically generated
220  // by wxWidgets to be executed before our resize code.
221  // Otherwise, the changes made by setSubWindowsSashSize are overwritten by one these
222  // events
223  wxSafeYield();
225 
226  // Ensure the window is on top
227  Raise();
228 }
229 
230 
232 {
233  m_simulator->SetReporter( nullptr );
234  delete m_reporter;
235  delete m_signalsIconColorList;
236 
237  if( m_settingsDlg )
238  m_settingsDlg->Destroy();
239 }
240 
241 
243 {
244  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
245  wxASSERT( cfg );
246 
247  if( cfg )
248  {
250 
251  cfg->m_Simulator.plot_panel_width = m_splitterLeftRight->GetSashPosition();
252  cfg->m_Simulator.plot_panel_height = m_splitterPlotAndConsole->GetSashPosition();
253  cfg->m_Simulator.signal_panel_height = m_splitterSignals->GetSashPosition();
254  cfg->m_Simulator.cursors_panel_height = m_splitterTuneValues->GetSashPosition();
255  cfg->m_Simulator.white_background = m_plotUseWhiteBg;
256  }
257 }
258 
259 
261 {
262  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
263  wxASSERT( cfg );
264 
265  if( cfg )
266  {
268 
269  // Read subwindows sizes (should be > 0 )
270  m_splitterLeftRightSashPosition = cfg->m_Simulator.plot_panel_width;
271  m_splitterPlotAndConsoleSashPosition = cfg->m_Simulator.plot_panel_height;
272  m_splitterSignalsSashPosition = cfg->m_Simulator.signal_panel_height;
273  m_splitterTuneValuesSashPosition = cfg->m_Simulator.cursors_panel_height;
274  m_plotUseWhiteBg = cfg->m_Simulator.white_background;
275  }
276 }
277 
278 
280 {
281  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
282  wxASSERT( cfg );
283 
284  return cfg ? &cfg->m_Simulator.window : nullptr;
285 }
286 
287 
288 // A small helper struct to handle bitmaps initialisation in menus
290 {
291  int m_MenuId;
293 };
294 
295 
297 {
298  // Give icons to menuitems of the main menubar
299  BM_MENU_INIT_ITEM bm_list[]
300  {
301  // File menu:
302  { wxID_NEW, simulator_xpm },
303  { wxID_OPEN,directory_browser_xpm },
304  { wxID_SAVE, directory_xpm},
307  { wxID_CLOSE, exit_xpm},
308 
309  // simulator menu:
316 
317  // View menu
318  { wxID_ZOOM_IN, zoom_in_xpm},
319  { wxID_ZOOM_OUT, zoom_out_xpm},
320  { wxID_ZOOM_FIT, zoom_fit_in_page_xpm},
325 
326  { 0, nullptr } // Sentinel
327  };
328 
329  // wxMenuItems are already created and attached to the m_mainMenu wxMenuBar.
330  // A problem is the fact setting bitmaps in wxMenuItems after they are attached
331  // to a wxMenu do not work in all cases.
332  // So the trick is:
333  // Remove the wxMenuItem from its wxMenu
334  // Set the bitmap
335  // Insert the modified wxMenuItem to its previous place
336  for( int ii = 0; bm_list[ii].m_MenuId; ++ii )
337  {
338  wxMenuItem* item = m_mainMenu->FindItem( bm_list[ii].m_MenuId );
339 
340  if( !item || !bm_list[ii].m_Bitmap)
341  continue;
342 
343  wxMenu* menu = item->GetMenu();
344  // Calculate the initial index of item inside the wxMenu parent
345  wxMenuItemList& mlist = menu->GetMenuItems();
346  int mpos = mlist.IndexOf( item );
347 
348  if( mpos >= 0 ) // Should be always the case
349  {
350  // Modify the bitmap
351  menu->Remove( item );
352  AddBitmapToMenuItem( item, KiBitmap( bm_list[ii].m_Bitmap ) );
353  // Insert item to its the initial index
354  menu->Insert( mpos, item );
355  }
356  }
357 }
358 
359 
361 {
364 
367 
370 
373 }
374 
375 
376 wxColor SIM_PLOT_FRAME::GetPlotColor( int aColorId )
377 {
378  // return the wxColor selected in color list or BLACK is not in list
379  if( aColorId >= 0 && aColorId < (int)m_colorList.size() )
380  return m_colorList[aColorId];
381 
382  return wxColor( 0, 0, 0 );
383 }
384 
385 
387 {
388  m_colorList.clear();
389 
390  if( aWhiteBg )
391  {
392  m_colorList.emplace_back( 255, 255, 255 ); // Bg color
393  m_colorList.emplace_back( 0, 0, 0 ); // Fg color (texts)
394  m_colorList.emplace_back( 130, 130, 130 ); // Axis color
395  m_colorList.emplace_back( 0, 0, 0 ); // cursors color
396  }
397  else
398  {
399  m_colorList.emplace_back( 0, 0, 0 ); // Bg color
400  m_colorList.emplace_back( 255, 255, 255 ); // Fg color (texts)
401  m_colorList.emplace_back( 130, 130, 130 ); // Axis color
402  m_colorList.emplace_back( 255, 255, 255 ); // cursors color
403  }
404 
405  // Add a list of color for traces, starting at index SIM_TRACE_COLOR
406  m_colorList.emplace_back( 0xE4, 0x1A, 0x1C );
407  m_colorList.emplace_back( 0x37, 0x7E, 0xB8 );
408  m_colorList.emplace_back( 0x4D, 0xAF, 0x4A );
409  m_colorList.emplace_back( 0x98, 0x4E, 0xA3 );
410  m_colorList.emplace_back( 0xFF, 0x7F, 0x00 );
411  m_colorList.emplace_back( 0xFF, 0xFF, 0x33 );
412  m_colorList.emplace_back( 0xA6, 0x56, 0x28 );
413  m_colorList.emplace_back( 0xF7, 0x81, 0xBF );
414  m_colorList.emplace_back( 0x66, 0xC2, 0xA5 );
415  m_colorList.emplace_back( 0xFC, 0x8D, 0x62 );
416  m_colorList.emplace_back( 0x8D, 0xA0, 0xCB );
417  m_colorList.emplace_back( 0xE7, 0x8A, 0xC3 );
418  m_colorList.emplace_back( 0xA6, 0xD8, 0x54 );
419  m_colorList.emplace_back( 0xFF, 0xD9, 0x2F );
420  m_colorList.emplace_back( 0xE5, 0xC4, 0x94 );
421  m_colorList.emplace_back( 0xB3, 0xB3, 0xB3 );
422 
423 }
424 
425 
426 void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
427 {
428  STRING_FORMATTER formatter;
429 
430  if( !m_settingsDlg )
431  m_settingsDlg = new DIALOG_SIM_SETTINGS( this );
432 
433  m_simConsole->Clear();
435 
436  if( aSimCommand.IsEmpty() )
437  {
438  SIM_PANEL_BASE* plotPanel = currentPlotWindow();
439  if( plotPanel )
440  m_exporter->SetSimCommand( m_plots[plotPanel].m_simCommand );
441  }
442  else
443  {
444  m_exporter->SetSimCommand( aSimCommand );
445  }
446 
447  if( !m_exporter->Format( &formatter, m_settingsDlg->GetNetlistOptions() ) )
448  {
449  DisplayError( this, _( "There were errors during netlist export, aborted." ) );
450  return;
451  }
452 
453  if( m_exporter->GetSimType() == ST_UNKNOWN )
454  {
455  DisplayInfoMessage( this, _( "You need to select the simulation settings first." ) );
456  return;
457  }
458 
459  m_simulator->LoadNetlist( formatter.GetString() );
460  updateTuners();
461  applyTuners();
462  m_simulator->Run();
463 }
464 
465 
467 {
468  m_simulator->Stop();
469 }
470 
471 
473 {
474  return m_simulator ? m_simulator->IsRunning() : false;
475 }
476 
477 
479 {
480  SIM_PANEL_BASE* plotPanel;
481 
482  if( SIM_PANEL_BASE::IsPlottable( aSimType ) )
483  {
484  SIM_PLOT_PANEL* panel;
485  panel = new SIM_PLOT_PANEL( aSimType, m_plotNotebook, this, wxID_ANY );
486 
488  Pgm().GetCommonSettings()->m_Input.scroll_modifier_zoom != 0 );
489 
490  plotPanel = dynamic_cast<SIM_PANEL_BASE*>( panel );
491  }
492  else
493  {
494  SIM_NOPLOT_PANEL* panel;
495  panel = new SIM_NOPLOT_PANEL( aSimType, m_plotNotebook, wxID_ANY );
496  plotPanel = dynamic_cast<SIM_PANEL_BASE*>( panel );
497  }
498 
499  if( m_welcomePanel )
500  {
501  m_plotNotebook->DeletePage( 0 );
502  m_welcomePanel = nullptr;
503  }
504 
505  wxString pageTitle( m_simulator->TypeToName( aSimType, true ) );
506  pageTitle.Prepend( wxString::Format( _( "Plot%u - " ), (unsigned int) ++m_plotNumber ) );
507 
508  m_plotNotebook->AddPage( dynamic_cast<wxWindow*>( plotPanel ), pageTitle, true );
509  m_plots[plotPanel] = PLOT_INFO();
510 
511  return plotPanel;
512 }
513 
514 
515 void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName )
516 {
517  addPlot( aNetName, SPT_VOLTAGE, "V" );
518 }
519 
520 
521 void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName, const wxString& aParam )
522 {
523  addPlot( aDeviceName, SPT_CURRENT, aParam );
524 }
525 
526 
528 {
529  SIM_PANEL_BASE* plotPanel = currentPlotWindow();
530 
531  if( !plotPanel || plotPanel == m_welcomePanel )
532  return;
533 
534  // For now limit the tuner tool to RLC components
535  char primitiveType = NETLIST_EXPORTER_PSPICE::GetSpiceField( SF_PRIMITIVE, aComponent, 0 )[0];
536 
537  if( primitiveType != SP_RESISTOR && primitiveType != SP_CAPACITOR && primitiveType != SP_INDUCTOR )
538  return;
539 
540  const wxString componentName = aComponent->GetField( REFERENCE )->GetText();
541 
542  // Do not add multiple instances for the same component
543  auto tunerIt = std::find_if( m_tuners.begin(), m_tuners.end(), [&]( const TUNER_SLIDER* t )
544  {
545  return t->GetComponentName() == componentName;
546  }
547  );
548 
549  if( tunerIt != m_tuners.end() )
550  return; // We already have it
551 
552  try
553  {
554  TUNER_SLIDER* tuner = new TUNER_SLIDER( this, m_tunePanel, aComponent );
555  m_tuneSizer->Add( tuner );
556  m_tuners.push_back( tuner );
557  m_tunePanel->Layout();
558  }
559  catch( const KI_PARAM_ERROR& e )
560  {
561  // Sorry, no bonus
562  DisplayError( nullptr, e.What() );
563  }
564 }
565 
566 
567 void SIM_PLOT_FRAME::RemoveTuner( TUNER_SLIDER* aTuner, bool aErase )
568 {
569  if( aErase )
570  m_tuners.remove( aTuner );
571 
572  aTuner->Destroy();
573  m_tunePanel->Layout();
574 }
575 
576 
578 {
579  SIM_PANEL_BASE* curPage = currentPlotWindow();
580 
581  return ( ( !curPage || curPage->GetType() == ST_UNKNOWN ) ?
582  nullptr :
583  dynamic_cast<SIM_PLOT_PANEL*>( curPage ) );
584 }
585 
586 
588 {
589  return m_exporter.get();
590 }
591 
592 
593 void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam )
594 {
595  SIM_TYPE simType = m_exporter->GetSimType();
596 
597  if( simType == ST_UNKNOWN )
598  {
599  m_simConsole->AppendText( _( "Error: simulation type not defined!\n" ) );
600  m_simConsole->SetInsertionPointEnd();
601  return;
602  }
603  else if( !SIM_PANEL_BASE::IsPlottable( simType ) )
604  {
605  m_simConsole->AppendText( _( "Error: simulation type doesn't support plotting!\n" ) );
606  m_simConsole->SetInsertionPointEnd();
607  return;
608  }
609 
610  // Create a new plot if the current one displays a different type
611  SIM_PLOT_PANEL* plotPanel = CurrentPlot();
612 
613  if( !plotPanel || plotPanel->GetType() != simType )
614  plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( NewPlotPanel( simType ) );
615 
616  wxASSERT( plotPanel );
617 
618  if( !plotPanel ) // Something is wrong
619  return;
620 
621  TRACE_DESC descriptor( *m_exporter, aName, aType, aParam );
622 
623  bool updated = false;
624  SIM_PLOT_TYPE xAxisType = GetXAxisType( simType );
625 
626  if( xAxisType == SPT_LIN_FREQUENCY || xAxisType == SPT_LOG_FREQUENCY )
627  {
628  int baseType = descriptor.GetType() & ~( SPT_AC_MAG | SPT_AC_PHASE );
629 
630  // Add two plots: magnitude & phase
631  TRACE_DESC mag_desc( *m_exporter, descriptor, (SIM_PLOT_TYPE)( baseType | SPT_AC_MAG ) );
632  TRACE_DESC phase_desc( *m_exporter, descriptor, (SIM_PLOT_TYPE)( baseType | SPT_AC_PHASE ) );
633 
634  updated |= updatePlot( mag_desc, plotPanel );
635  updated |= updatePlot( phase_desc, plotPanel );
636  }
637  else
638  {
639  updated = updatePlot( descriptor, plotPanel );
640  }
641 
642  if( updated )
643  {
645  }
646 }
647 
648 
649 void SIM_PLOT_FRAME::removePlot( const wxString& aPlotName, bool aErase )
650 {
651  SIM_PLOT_PANEL* plotPanel = CurrentPlot();
652 
653  if( !plotPanel )
654  return;
655 
656  if( aErase )
657  {
658  auto& traceMap = m_plots[plotPanel].m_traces;
659  auto traceIt = traceMap.find( aPlotName );
660  wxASSERT( traceIt != traceMap.end() );
661  traceMap.erase( traceIt );
662  }
663 
664  wxASSERT( plotPanel->TraceShown( aPlotName ) );
665  plotPanel->DeleteTrace( aPlotName );
666  plotPanel->GetPlotWin()->Fit();
667 
669  wxCommandEvent dummy;
671 }
672 
673 
675 {
677 }
678 
679 
680 bool SIM_PLOT_FRAME::updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL* aPanel )
681 {
682  SIM_TYPE simType = m_exporter->GetSimType();
683  wxString spiceVector = m_exporter->ComponentToVector(
684  aDescriptor.GetName(), aDescriptor.GetType(), aDescriptor.GetParam() );
685 
686  if( !SIM_PANEL_BASE::IsPlottable( simType ) )
687  {
688  // There is no plot to be shown
689  m_simulator->Command( wxString::Format( "print %s", spiceVector ).ToStdString() );
690 
691  return false;
692  }
693 
694  // First, handle the x axis
695  wxString xAxisName( m_simulator->GetXAxis( simType ) );
696 
697  if( xAxisName.IsEmpty() )
698  return false;
699 
700  auto data_x = m_simulator->GetMagPlot( (const char*) xAxisName.c_str() );
701  unsigned int size = data_x.size();
702 
703  if( data_x.empty() )
704  return false;
705 
706  SIM_PLOT_TYPE plotType = aDescriptor.GetType();
707  std::vector<double> data_y;
708 
709  // Now, Y axis data
710  switch( m_exporter->GetSimType() )
711  {
712  case ST_AC:
713  {
714  wxASSERT_MSG( !( ( plotType & SPT_AC_MAG ) && ( plotType & SPT_AC_PHASE ) ),
715  "Cannot set both AC_PHASE and AC_MAG bits" );
716 
717  if( plotType & SPT_AC_MAG )
718  data_y = m_simulator->GetMagPlot( (const char*) spiceVector.c_str() );
719  else if( plotType & SPT_AC_PHASE )
720  data_y = m_simulator->GetPhasePlot( (const char*) spiceVector.c_str() );
721  else
722  wxASSERT_MSG( false, "Plot type missing AC_PHASE or AC_MAG bit" );
723  }
724  break;
725 
726  case ST_NOISE:
727  case ST_DC:
728  case ST_TRANSIENT:
729  {
730  data_y = m_simulator->GetMagPlot( (const char*) spiceVector.c_str() );
731  }
732  break;
733 
734  default:
735  wxASSERT_MSG( false, "Unhandled plot type" );
736  return false;
737  }
738 
739  if( data_y.size() != size )
740  return false;
741 
742  // If we did a two-source DC analysis, we need to split the resulting vector and add traces
743  // for each input step
744  SPICE_DC_PARAMS source1, source2;
745 
746  if( m_exporter->GetSimType() == ST_DC &&
747  m_exporter->ParseDCCommand( m_exporter->GetUsedSimCommand(), &source1, &source2 ) )
748  {
749  if( !source2.m_source.IsEmpty() )
750  {
751  // Source 1 is the inner loop, so lets add traces for each Source 2 (outer loop) step
752  SPICE_VALUE v = source2.m_vstart;
753  wxString name;
754 
755  size_t offset = 0;
756  size_t outer = ( size_t )( ( source2.m_vend - v ) / source2.m_vincrement ).ToDouble();
757  size_t inner = data_x.size() / ( outer + 1 );
758 
759  wxASSERT( data_x.size() % ( outer + 1 ) == 0 );
760 
761  for( size_t idx = 0; idx <= outer; idx++ )
762  {
763  name = wxString::Format( "%s (%s = %s V)", aDescriptor.GetTitle(),
764  source2.m_source, v.ToString() );
765 
766  std::vector<double> sub_x( data_x.begin() + offset,
767  data_x.begin() + offset + inner );
768  std::vector<double> sub_y( data_y.begin() + offset,
769  data_y.begin() + offset + inner );
770 
771  if( aPanel->AddTrace( name, inner,
772  sub_x.data(), sub_y.data(), aDescriptor.GetType() ) )
773  {
774  m_plots[aPanel].m_traces.insert( std::make_pair( name, aDescriptor ) );
775  }
776 
777  v = v + source2.m_vincrement;
778  offset += inner;
779  }
780 
781  return true;
782  }
783  }
784 
785  if( aPanel->AddTrace( aDescriptor.GetTitle(), size,
786  data_x.data(), data_y.data(), aDescriptor.GetType() ) )
787  {
788  m_plots[aPanel].m_traces.insert( std::make_pair( aDescriptor.GetTitle(), aDescriptor ) );
789  }
790 
791  return true;
792 }
793 
794 
796 {
797  m_signals->ClearAll();
798 
799  SIM_PLOT_PANEL* plotPanel = CurrentPlot();
800 
801  if( !plotPanel )
802  return;
803 
804  wxSize size = m_signals->GetClientSize();
805  m_signals->AppendColumn( _( "Signal" ), wxLIST_FORMAT_LEFT, size.x );
806 
807  // Build an image list, to show the color of the corresponding trace
808  // in the plot panel
809  // This image list is used for trace and cursor lists
810  wxMemoryDC bmDC;
811  const int isize = bmDC.GetCharHeight();
812 
814  m_signalsIconColorList = new wxImageList( isize, isize, false );
815  else
816  m_signalsIconColorList->RemoveAll();
817 
818  for( const auto& trace : CurrentPlot()->GetTraces() )
819  {
820  wxBitmap bitmap( isize, isize );
821  bmDC.SelectObject( bitmap );
822  wxColour tcolor = trace.second->GetTraceColour();
823 
824  wxColour bgColor = m_signals->wxWindow::GetBackgroundColour();
825  bmDC.SetPen( wxPen( bgColor ) );
826  bmDC.SetBrush( wxBrush( bgColor ) );
827  bmDC.DrawRectangle( 0, 0, isize, isize ); // because bmDC.Clear() does not work in wxGTK
828 
829  bmDC.SetPen( wxPen( tcolor ) );
830  bmDC.SetBrush( wxBrush( tcolor ) );
831  bmDC.DrawRectangle( 0, isize / 4 + 1, isize, isize / 2 );
832 
833  bmDC.SelectObject( wxNullBitmap ); // Needed to initialize bitmap
834 
835  bitmap.SetMask( new wxMask( bitmap, *wxBLACK ) );
836  m_signalsIconColorList->Add( bitmap );
837  }
838 
839  if( bmDC.IsOk() )
840  {
841  bmDC.SetBrush( wxNullBrush );
842  bmDC.SetPen( wxNullPen );
843  }
844 
845  m_signals->SetImageList( m_signalsIconColorList, wxIMAGE_LIST_SMALL );
846 
847  // Fill the signals listctrl. Keep the order of names and
848  // the order of icon color identical, because the icons
849  // are also used in cursor list, and the color index is
850  // calculated from the trace name index
851  int imgidx = 0;
852 
853  for( const auto& trace : m_plots[plotPanel].m_traces )
854  {
855  m_signals->InsertItem( imgidx, trace.first, imgidx );
856  imgidx++;
857  }
858 }
859 
860 
862 {
863  const auto& spiceItems = m_exporter->GetSpiceItems();
864 
865  for( auto it = m_tuners.begin(); it != m_tuners.end(); /* iteration inside the loop */ )
866  {
867  const wxString& ref = (*it)->GetComponentName();
868 
869  if( std::find_if( spiceItems.begin(), spiceItems.end(), [&]( const SPICE_ITEM& item )
870  {
871  return item.m_refName == ref;
872  }) == spiceItems.end() )
873  {
874  // The component does not exist anymore, remove the associated tuner
875  TUNER_SLIDER* tuner = *it;
876  it = m_tuners.erase( it );
877  RemoveTuner( tuner, false );
878  }
879  else
880  {
881  ++it;
882  }
883  }
884 }
885 
886 
888 {
889  for( auto& tuner : m_tuners )
890  {
892  std::string command( "alter @" + tuner->GetSpiceName()
893  + "=" + tuner->GetValue().ToSpiceString() );
894 
895  m_simulator->Command( command );
896  }
897 }
898 
899 
900 bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
901 {
902  m_plots.clear();
903  m_plotNotebook->DeleteAllPages();
904 
905  wxTextFile file( aPath );
906 
907  if( !file.Open() )
908  return false;
909 
910  long plotsCount;
911 
912  if( !file.GetFirstLine().ToLong( &plotsCount ) ) // GetFirstLine instead of GetNextLine
913  return false;
914 
915  for( long i = 0; i < plotsCount; ++i )
916  {
917  long plotType, tracesCount;
918 
919  if( !file.GetNextLine().ToLong( &plotType ) )
920  return false;
921 
922  SIM_PANEL_BASE* plotPanel = NewPlotPanel( (SIM_TYPE) plotType );
923  m_plots[plotPanel].m_simCommand = file.GetNextLine();
924  StartSimulation( m_plots[plotPanel].m_simCommand );
925 
926  // Perform simulation, so plots can be added with values
927  do
928  {
929  wxThread::This()->Sleep( 50 );
930  }
931  while( IsSimulationRunning() );
932 
933  if( !file.GetNextLine().ToLong( &tracesCount ) )
934  return false;
935 
936  for( long j = 0; j < tracesCount; ++j )
937  {
938  long traceType;
939  wxString name, param;
940 
941  if( !file.GetNextLine().ToLong( &traceType ) )
942  return false;
943 
944  name = file.GetNextLine();
945  param = file.GetNextLine();
946 
947  if( name.IsEmpty() || param.IsEmpty() )
948  return false;
949 
950  addPlot( name, (SIM_PLOT_TYPE) traceType, param );
951  }
952  }
953 
954  return true;
955 }
956 
957 
958 bool SIM_PLOT_FRAME::saveWorkbook( const wxString& aPath )
959 {
960 
961  wxString savePath = aPath;
962 
963  if( !savePath.Lower().EndsWith(".wbk"))
964  {
965  savePath += ".wbk";
966  };
967 
968 
969  wxTextFile file( savePath );
970 
971  if( file.Exists() )
972  {
973  if( !file.Open() )
974  return false;
975 
976  file.Clear();
977  }
978  else
979  {
980  file.Create();
981  }
982 
983  file.AddLine( wxString::Format( "%llu", m_plots.size() ) );
984 
985  for( const auto& plot : m_plots )
986  {
987  if( plot.first )
988  {
989  file.AddLine( wxString::Format( "%d", plot.first->GetType() ) );
990  file.AddLine( plot.second.m_simCommand );
991  file.AddLine( wxString::Format( "%llu", plot.second.m_traces.size() ) );
992 
993  for( const auto& trace : plot.second.m_traces )
994  {
995  file.AddLine( wxString::Format( "%d", trace.second.GetType() ) );
996  file.AddLine( trace.second.GetName() );
997  file.AddLine( trace.second.GetParam() );
998  }
999  }
1000  }
1001 
1002  bool res = file.Write();
1003  file.Close();
1004 
1005  return res;
1006 }
1007 
1008 
1010 {
1011  switch( aType )
1012  {
1013  case ST_AC:
1014  return SPT_LIN_FREQUENCY;
1016 
1017  case ST_DC:
1018  return SPT_SWEEP;
1019 
1020  case ST_TRANSIENT:
1021  return SPT_TIME;
1022 
1023  default:
1024  wxASSERT_MSG( false, "Unhandled simulation type" );
1025  return (SIM_PLOT_TYPE) 0;
1026  }
1027 }
1028 
1029 
1030 void SIM_PLOT_FRAME::menuNewPlot( wxCommandEvent& aEvent )
1031 {
1032  SIM_TYPE type = m_exporter->GetSimType();
1033 
1034  if( SIM_PANEL_BASE::IsPlottable( type ) )
1035  {
1036  SIM_PLOT_PANEL* prevPlot = CurrentPlot();
1037  SIM_PLOT_PANEL* newPlot = dynamic_cast<SIM_PLOT_PANEL*>( NewPlotPanel( type ) );
1038 
1039  // If the previous plot had the same type, copy the simulation command
1040  if( prevPlot )
1041  m_plots[newPlot].m_simCommand = m_plots[prevPlot].m_simCommand;
1042  }
1043 }
1044 
1045 
1046 void SIM_PLOT_FRAME::menuOpenWorkbook( wxCommandEvent& event )
1047 {
1048  wxFileDialog openDlg( this, _( "Open simulation workbook" ), m_savedWorkbooksPath, "",
1049  WorkbookFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
1050 
1051  if( openDlg.ShowModal() == wxID_CANCEL )
1052  return;
1053 
1054  m_savedWorkbooksPath = openDlg.GetDirectory();
1055 
1056  if( !loadWorkbook( openDlg.GetPath() ) )
1057  DisplayError( this, _( "There was an error while opening the workbook file" ) );
1058 }
1059 
1060 
1061 void SIM_PLOT_FRAME::menuSaveWorkbook( wxCommandEvent& event )
1062 {
1063  if( !CurrentPlot() )
1064  return;
1065 
1066  wxFileDialog saveDlg( this, _( "Save Simulation Workbook" ), m_savedWorkbooksPath, "",
1067  WorkbookFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1068 
1069  if( saveDlg.ShowModal() == wxID_CANCEL )
1070  return;
1071 
1072  m_savedWorkbooksPath = saveDlg.GetDirectory();
1073 
1074  if( !saveWorkbook( saveDlg.GetPath() ) )
1075  DisplayError( this, _( "There was an error while saving the workbook file" ) );
1076 }
1077 
1078 
1079 void SIM_PLOT_FRAME::menuSaveImage( wxCommandEvent& event )
1080 {
1081  if( !CurrentPlot() )
1082  return;
1083 
1084  wxFileDialog saveDlg( this, _( "Save Plot as Image" ), "", "",
1085  PngFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1086 
1087  if( saveDlg.ShowModal() == wxID_CANCEL )
1088  return;
1089 
1090  CurrentPlot()->GetPlotWin()->SaveScreenshot( saveDlg.GetPath(), wxBITMAP_TYPE_PNG );
1091 }
1092 
1093 
1094 void SIM_PLOT_FRAME::menuSaveCsv( wxCommandEvent& event )
1095 {
1096  if( !CurrentPlot() )
1097  return;
1098 
1099  const wxChar SEPARATOR = ';';
1100 
1101  wxFileDialog saveDlg( this, _( "Save Plot Data" ), "", "",
1102  CsvFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1103 
1104  if( saveDlg.ShowModal() == wxID_CANCEL )
1105  return;
1106 
1107  wxFile out( saveDlg.GetPath(), wxFile::write );
1108  bool timeWritten = false;
1109 
1110  for( const auto& t : CurrentPlot()->GetTraces() )
1111  {
1112  const TRACE* trace = t.second;
1113 
1114  if( !timeWritten )
1115  {
1116  out.Write( wxString::Format( "Time%c", SEPARATOR ) );
1117 
1118  for( double v : trace->GetDataX() )
1119  out.Write( wxString::Format( "%f%c", v, SEPARATOR ) );
1120 
1121  out.Write( "\r\n" );
1122  timeWritten = true;
1123  }
1124 
1125  out.Write( wxString::Format( "%s%c", t.first, SEPARATOR ) );
1126 
1127  for( double v : trace->GetDataY() )
1128  out.Write( wxString::Format( "%f%c", v, SEPARATOR ) );
1129 
1130  out.Write( "\r\n" );
1131  }
1132 
1133  out.Close();
1134 }
1135 
1136 
1137 void SIM_PLOT_FRAME::menuZoomIn( wxCommandEvent& event )
1138 {
1139  if( CurrentPlot() )
1140  CurrentPlot()->GetPlotWin()->ZoomIn();
1141 }
1142 
1143 
1144 void SIM_PLOT_FRAME::menuZoomOut( wxCommandEvent& event )
1145 {
1146  if( CurrentPlot() )
1147  CurrentPlot()->GetPlotWin()->ZoomOut();
1148 }
1149 
1150 
1151 void SIM_PLOT_FRAME::menuZoomFit( wxCommandEvent& event )
1152 {
1153  if( CurrentPlot() )
1154  CurrentPlot()->GetPlotWin()->Fit();
1155 }
1156 
1157 
1158 void SIM_PLOT_FRAME::menuShowGrid( wxCommandEvent& event )
1159 {
1160  SIM_PLOT_PANEL* plot = CurrentPlot();
1161 
1162  if( plot )
1163  plot->ShowGrid( !plot->IsGridShown() );
1164 }
1165 
1166 
1167 void SIM_PLOT_FRAME::menuShowGridUpdate( wxUpdateUIEvent& event )
1168 {
1169  SIM_PLOT_PANEL* plot = CurrentPlot();
1170 
1171  event.Check( plot ? plot->IsGridShown() : false );
1172 }
1173 
1174 
1175 void SIM_PLOT_FRAME::menuShowLegend( wxCommandEvent& event )
1176 {
1177  SIM_PLOT_PANEL* plot = CurrentPlot();
1178 
1179  if( plot )
1180  plot->ShowLegend( !plot->IsLegendShown() );
1181 }
1182 
1183 
1184 void SIM_PLOT_FRAME::menuShowLegendUpdate( wxUpdateUIEvent& event )
1185 {
1186  SIM_PLOT_PANEL* plot = CurrentPlot();
1187  event.Check( plot ? plot->IsLegendShown() : false );
1188 }
1189 
1190 
1191 void SIM_PLOT_FRAME::menuShowDotted( wxCommandEvent& event )
1192 {
1193  SIM_PLOT_PANEL* plot = CurrentPlot();
1194 
1195  if( plot )
1196  plot->SetDottedCurrentPhase( !plot->GetDottedCurrentPhase() );
1197 }
1198 
1199 
1200 void SIM_PLOT_FRAME::menuShowDottedUpdate( wxUpdateUIEvent& event )
1201 {
1202  SIM_PLOT_PANEL* plot = CurrentPlot();
1203 
1204  event.Check( plot ? plot->GetDottedCurrentPhase() : false );
1205 }
1206 
1207 
1208 void SIM_PLOT_FRAME::menuWhiteBackground( wxCommandEvent& event )
1209 {
1211 
1212  // Rebuild the color list to plot traces
1214 
1215  // Now send changes to all SIM_PLOT_PANEL
1216  for( size_t page = 0; page < m_plotNotebook->GetPageCount(); page++ )
1217  {
1218  wxWindow* curPage = m_plotNotebook->GetPage( page );
1219 
1220  if( curPage == m_welcomePanel )
1221  continue;
1222 
1223  static_cast<SIM_PLOT_PANEL*>( curPage )->UpdatePlotColors();
1224  }
1225 }
1226 
1227 
1228 void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event )
1229 {
1230  int idx = event.GetSelection();
1231 
1232  if( idx == wxNOT_FOUND )
1233  return;
1234 
1235  SIM_PANEL_BASE* plotPanel =
1236  dynamic_cast<SIM_PANEL_BASE*>( m_plotNotebook->GetPage( idx ) );
1237 
1238  m_plots.erase( plotPanel );
1239  updateSignalList();
1240  wxCommandEvent dummy;
1241  onCursorUpdate( dummy );
1242 }
1243 
1244 
1245 void SIM_PLOT_FRAME::onPlotChanged( wxAuiNotebookEvent& event )
1246 {
1247  updateSignalList();
1248  wxCommandEvent dummy;
1249  onCursorUpdate( dummy );
1250 }
1251 
1252 
1253 void SIM_PLOT_FRAME::onSignalDblClick( wxMouseEvent& event )
1254 {
1255  // Remove signal from the plot panel when double clicked
1256  long idx = m_signals->GetFocusedItem();
1257 
1258  if( idx != wxNOT_FOUND )
1259  removePlot( m_signals->GetItemText( idx, 0 ) );
1260 }
1261 
1262 
1263 void SIM_PLOT_FRAME::onSignalRClick( wxListEvent& event )
1264 {
1265  int idx = event.GetIndex();
1266 
1267  if( idx != wxNOT_FOUND )
1268  m_signals->Select( idx );
1269 
1270  idx = m_signals->GetFirstSelected();
1271 
1272  if( idx != wxNOT_FOUND )
1273  {
1274  const wxString& netName = m_signals->GetItemText( idx, 0 );
1275  SIGNAL_CONTEXT_MENU ctxMenu( netName, this );
1276  m_signals->PopupMenu( &ctxMenu );
1277  }
1278 }
1279 
1280 
1281 void SIM_PLOT_FRAME::onSimulate( wxCommandEvent& event )
1282 {
1283  if( IsSimulationRunning() )
1284  StopSimulation();
1285  else
1286  StartSimulation();
1287 }
1288 
1289 
1290 void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event )
1291 {
1292  SIM_PANEL_BASE* plotPanelWindow = currentPlotWindow();
1293 
1294  // Initial processing is required to e.g. display a list of power sources
1296 
1297  if( !m_exporter->ProcessNetlist( NET_ALL_FLAGS ) )
1298  {
1299  DisplayError( this, _( "There were errors during netlist export, aborted." ) );
1300  return;
1301  }
1302 
1303  if( !m_settingsDlg )
1304  m_settingsDlg = new DIALOG_SIM_SETTINGS( this );
1305 
1306  if( plotPanelWindow != m_welcomePanel )
1307  m_settingsDlg->SetSimCommand( m_plots[plotPanelWindow].m_simCommand );
1308 
1310 
1311  if( m_settingsDlg->ShowModal() == wxID_OK )
1312  {
1313  wxString newCommand = m_settingsDlg->GetSimCommand();
1314  SIM_TYPE newSimType = NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( newCommand );
1315 
1316  // If it is a new simulation type, open a new plot
1317  if( !plotPanelWindow || ( plotPanelWindow && plotPanelWindow->GetType() != newSimType ) )
1318  {
1319  plotPanelWindow = NewPlotPanel( newSimType );
1320  }
1321 
1322  m_plots[plotPanelWindow].m_simCommand = newCommand;
1323  }
1324 }
1325 
1326 
1327 void SIM_PLOT_FRAME::onAddSignal( wxCommandEvent& event )
1328 {
1329  SIM_PLOT_PANEL* plotPanel = CurrentPlot();
1330 
1331  if( !plotPanel || !m_exporter || plotPanel->GetType() != m_exporter->GetSimType() )
1332  {
1333  DisplayInfoMessage( this, _( "You need to run plot-providing simulation first." ) );
1334  return;
1335  }
1336 
1337  DIALOG_SIGNAL_LIST dialog( this, m_exporter.get() );
1338  dialog.ShowModal();
1339 }
1340 
1341 
1342 void SIM_PLOT_FRAME::onProbe( wxCommandEvent& event )
1343 {
1344  if( m_schematicFrame == NULL )
1345  return;
1346 
1348  m_schematicFrame->Raise();
1349 }
1350 
1351 
1352 void SIM_PLOT_FRAME::onTune( wxCommandEvent& event )
1353 {
1354  if( m_schematicFrame == NULL )
1355  return;
1356 
1358  m_schematicFrame->Raise();
1359 }
1360 
1361 void SIM_PLOT_FRAME::onShowNetlist( wxCommandEvent& event )
1362 {
1363  class NETLIST_VIEW_DIALOG : public wxDialog
1364  {
1365  public:
1366  enum
1367  {
1368  MARGIN_LINE_NUMBERS
1369  };
1370 
1371  void onClose( wxCloseEvent& evt )
1372  {
1373  EndModal( GetReturnCode() );
1374  }
1375 
1376  NETLIST_VIEW_DIALOG(wxWindow* parent, wxString source) :
1377  wxDialog(parent, wxID_ANY, "SPICE Netlist",
1378  wxDefaultPosition, wxSize(1500,900),
1379  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
1380  {
1381  wxStyledTextCtrl* text = new wxStyledTextCtrl( this, wxID_ANY );
1382 
1383  text->SetMarginWidth( MARGIN_LINE_NUMBERS, 50 );
1384  text->StyleSetForeground( wxSTC_STYLE_LINENUMBER, wxColour( 75, 75, 75 ) );
1385  text->StyleSetBackground( wxSTC_STYLE_LINENUMBER, wxColour( 220, 220, 220 ) );
1386  text->SetMarginType( MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER );
1387 
1388  text->SetWrapMode( wxSTC_WRAP_WORD );
1389 
1390  text->SetText( source );
1391 
1392  text->StyleClearAll();
1393  text->SetLexer( wxSTC_LEX_SPICE );
1394 
1395  wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
1396  sizer->Add( text, 1, wxEXPAND );
1397  SetSizer( sizer );
1398 
1399  Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( NETLIST_VIEW_DIALOG::onClose ), NULL,
1400  this );
1401  }
1402  };
1403 
1404  if( m_schematicFrame == NULL || m_simulator == NULL )
1405  return;
1406 
1407  NETLIST_VIEW_DIALOG dlg( this, m_simulator->GetNetlist() );
1408  dlg.ShowModal();
1409 }
1410 
1411 
1412 void SIM_PLOT_FRAME::onClose( wxCloseEvent& aEvent )
1413 {
1414  SaveSettings( config() );
1415 
1416  if( IsSimulationRunning() )
1417  m_simulator->Stop();
1418 
1419  // Cancel a running simProbe or simTune tool
1421 
1422  Destroy();
1423 }
1424 
1425 
1426 void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event )
1427 {
1428  wxSize size = m_cursors->GetClientSize();
1429  SIM_PLOT_PANEL* plotPanel = CurrentPlot();
1430  m_cursors->ClearAll();
1431 
1432  if( !plotPanel )
1433  return;
1434 
1436  m_cursors->SetImageList(m_signalsIconColorList, wxIMAGE_LIST_SMALL);
1437 
1438  // Fill the signals listctrl
1439  m_cursors->AppendColumn( _( "Signal" ), wxLIST_FORMAT_LEFT, size.x / 2 );
1440  const long X_COL = m_cursors->AppendColumn( plotPanel->GetLabelX(), wxLIST_FORMAT_LEFT, size.x / 4 );
1441 
1442  wxString labelY1 = plotPanel->GetLabelY1();
1443  wxString labelY2 = plotPanel->GetLabelY2();
1444  wxString labelY;
1445 
1446  if( !labelY2.IsEmpty() )
1447  labelY = labelY1 + " / " + labelY2;
1448  else
1449  labelY = labelY1;
1450 
1451  const long Y_COL = m_cursors->AppendColumn( labelY, wxLIST_FORMAT_LEFT, size.x / 4 );
1452 
1453  // Update cursor values
1454  int itemidx = 0;
1455 
1456  for( const auto& trace : plotPanel->GetTraces() )
1457  {
1458  if( CURSOR* cursor = trace.second->GetCursor() )
1459  {
1460  // Find the right icon color in list.
1461  // It is the icon used in m_signals list for the same trace
1462  long iconColor = m_signals->FindItem( -1, trace.first );
1463 
1464  const wxRealPoint coords = cursor->GetCoords();
1465  long idx = m_cursors->InsertItem( itemidx++, trace.first, iconColor );
1466  m_cursors->SetItem( idx, X_COL, SPICE_VALUE( coords.x ).ToSpiceString() );
1467  m_cursors->SetItem( idx, Y_COL, SPICE_VALUE( coords.y ).ToSpiceString() );
1468  }
1469  }
1470 }
1471 
1472 
1473 void SIM_PLOT_FRAME::onSimStarted( wxCommandEvent& aEvent )
1474 {
1475  m_toolBar->SetToolNormalBitmap( ID_SIM_RUN, KiBitmap( sim_stop_xpm ) );
1476  SetCursor( wxCURSOR_ARROWWAIT );
1477 }
1478 
1479 
1480 void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
1481 {
1482  m_toolBar->SetToolNormalBitmap( ID_SIM_RUN, KiBitmap( sim_run_xpm ) );
1483  SetCursor( wxCURSOR_ARROW );
1484 
1485  SIM_TYPE simType = m_exporter->GetSimType();
1486 
1487  if( simType == ST_UNKNOWN )
1488  return;
1489 
1490  SIM_PANEL_BASE* plotPanelWindow = currentPlotWindow();
1491 
1492  if( !plotPanelWindow || plotPanelWindow->GetType() != simType )
1493  plotPanelWindow = NewPlotPanel( simType );
1494 
1495  if( IsSimulationRunning() )
1496  return;
1497 
1498  // If there are any signals plotted, update them
1499  if( SIM_PANEL_BASE::IsPlottable( simType ) )
1500  {
1501  TRACE_MAP& traceMap = m_plots[plotPanelWindow].m_traces;
1502  SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( plotPanelWindow );
1503 
1504  wxCHECK_RET( plotPanel, "not a SIM_PLOT_PANEL" );
1505 
1506  for( auto it = traceMap.begin(); it != traceMap.end(); /* iteration occurs in the loop */)
1507  {
1508  if( !updatePlot( it->second, plotPanel ) )
1509  {
1510  removePlot( it->first, false );
1511  it = traceMap.erase( it ); // remove a plot that does not exist anymore
1512  }
1513  else
1514  {
1515  ++it;
1516  }
1517  }
1518 
1519  updateSignalList();
1520  plotPanel->GetPlotWin()->UpdateAll();
1521  plotPanel->ResetScales();
1522  }
1523  else if( simType == ST_OP )
1524  {
1525  m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) );
1526  m_simConsole->SetInsertionPointEnd();
1527 
1528  for( const auto& vec : m_simulator->AllPlots() )
1529  {
1530  double val = m_simulator->GetRealPlot( vec, 1 ).at( 0 );
1531 
1532  wxString outLine, signal;
1533  SIM_PLOT_TYPE type = m_exporter->VectorToSignal( vec, signal );
1534 
1535  const size_t tab = 25; //characters
1536  size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
1537 
1538  outLine.Printf( wxT( "%s%s" ), ( signal + wxT( ":" ) ).Pad( padding, wxUniChar( ' ' ) ),
1539  SPICE_VALUE( val ).ToSpiceString() );
1540 
1541  outLine.Append( type == SPT_CURRENT ? "A\n" : "V\n" );
1542 
1543  m_simConsole->AppendText( outLine );
1544  m_simConsole->SetInsertionPointEnd();
1545 
1546  // @todo display calculated values on the schematic
1547  }
1548  }
1549 }
1550 
1551 
1552 void SIM_PLOT_FRAME::onSimUpdate( wxCommandEvent& aEvent )
1553 {
1554  if( IsSimulationRunning() )
1555  StopSimulation();
1556 
1557  if( CurrentPlot() != m_lastSimPlot )
1558  {
1559  // We need to rerun simulation, as the simulator currently stores
1560  // results for another plot
1561  StartSimulation();
1562  }
1563  else
1564  {
1565  // Incremental update
1566  m_simConsole->Clear();
1567  // Do not export netlist, it is already stored in the simulator
1568  applyTuners();
1569  m_simulator->Run();
1570  }
1571 }
1572 
1573 
1574 void SIM_PLOT_FRAME::onSimReport( wxCommandEvent& aEvent )
1575 {
1576  m_simConsole->AppendText( aEvent.GetString() + "\n" );
1577  m_simConsole->SetInsertionPointEnd();
1578 }
1579 
1580 
1582  SIM_PLOT_FRAME* aPlotFrame )
1583  : m_signal( aSignal ), m_plotFrame( aPlotFrame )
1584 {
1586 
1587  AddMenuItem( this, HIDE_SIGNAL, _( "Hide Signal" ),
1588  _( "Erase the signal from plot screen" ),
1589  KiBitmap( delete_xpm ) );
1590 
1591  TRACE* trace = plot->GetTrace( m_signal );
1592 
1593  if( trace->HasCursor() )
1594  AddMenuItem( this, HIDE_CURSOR, _( "Hide Cursor" ), KiBitmap( pcb_target_xpm ) );
1595  else
1596  AddMenuItem( this, SHOW_CURSOR, _( "Show Cursor" ), KiBitmap( pcb_target_xpm ) );
1597 
1598  Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( SIGNAL_CONTEXT_MENU::onMenuEvent ), NULL, this );
1599 }
1600 
1601 
1603 {
1604  SIM_PLOT_PANEL* plot = m_plotFrame->CurrentPlot();
1605 
1606  switch( aEvent.GetId() )
1607  {
1608  case HIDE_SIGNAL:
1609  m_plotFrame->removePlot( m_signal );
1610  break;
1611 
1612  case SHOW_CURSOR:
1613  plot->EnableCursor( m_signal, true );
1614  break;
1615 
1616  case HIDE_CURSOR:
1617  plot->EnableCursor( m_signal, false );
1618  break;
1619  }
1620 }
1621 
1622 wxDEFINE_EVENT( EVT_SIM_UPDATE, wxCommandEvent );
1623 wxDEFINE_EVENT( EVT_SIM_REPORT, wxCommandEvent );
1624 
1625 wxDEFINE_EVENT( EVT_SIM_STARTED, wxCommandEvent );
1626 wxDEFINE_EVENT( EVT_SIM_FINISHED, wxCommandEvent );
const BITMAP_OPAQUE simulator_xpm[1]
Definition: simulator.cpp:52
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
void onAddSignal(wxCommandEvent &event)
#define ID_MENU_PROBE_SIGNALS
const BITMAP_OPAQUE swap_layer_xpm[1]
Definition: swap_layer.cpp:33
#define ID_SAVE_AS_IMAGE
void ZoomOut(const wxPoint &centerPoint=wxDefaultPosition)
Zoom out current view and refresh display.
Definition: mathplot.cpp:2306
bool IsLegendShown() const
bool saveWorkbook(const wxString &aPath)
Saves plot settings to a file.
wxString ToSpiceString() const
Returns string value in Spice format (e.g.
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
Function SetKiway.
wxToolBarToolBase * m_toolProbe
void setIconsForMenuItems()
Give icons to menuitems of the main menubar.
void onSimStarted(wxCommandEvent &aEvent)
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
void RemoveTuner(TUNER_SLIDER *aTuner, bool aErase=true)
Removes an existing tuner.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:104
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Function Report is a pure virtual function to override in the derived object.
bool GetPlotBgOpt() const
const BITMAP_OPAQUE pcb_target_xpm[1]
Definition: pcb_target.cpp:42
wxImageList * m_signalsIconColorList
imagelists uset to add a small coloured icon to signal names and cursors name, the same color as the ...
SIM_PLOT_TYPE operator|(SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond)
void onPlotChanged(wxAuiNotebookEvent &event) override
PNG memory record (file in memory).
Definition: bitmap_def.h:29
SIM_PLOT_FRAME * m_parent
const BITMAP_OPAQUE add_dashed_line_xpm[1]
void EnableMouseWheelPan(bool enabled)
Enable/disable trackpad friendly panning (2-axis scroll wheel)
Definition: mathplot.h:1217
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 onSignalDblClick(wxMouseEvent &event) override
bool SetSimCommand(const wxString &aCommand)
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Saves common frame parameters to a configuration data file.
mpWindow * GetPlotWin() const
Getter for math plot window
This file is part of the common library.
wxSplitterWindow * m_splitterSignals
const wxString & GetTitle() const
SIM_PANEL_BASE * NewPlotPanel(SIM_TYPE aSimType)
Creates a new plot panel for a given simulation type and adds it to the main notebook.
bool HasCursor() const
SEVERITY
Definition: ui_common.h:45
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Function AddMenuItem is an inline helper function to create and insert a menu item with an icon into ...
Definition: bitmap.cpp:232
void ShowLegend(bool aEnable)
int m_splitterPlotAndConsoleSashPosition
void menuZoomFit(wxCommandEvent &event) override
Structure to represent a schematic component in the Spice simulation.
const std::vector< double > & GetDataX() const
std::list< TUNER_SLIDER * > m_tuners
List of currently displayed tuners
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
SIM_PLOT_TYPE GetType() const
wxString m_title
Title displayed in the signal list/plot legend
Class SIM_PLOT_FRAME_BASE.
const BITMAP_OPAQUE directory_browser_xpm[1]
const BITMAP_OPAQUE text_xpm[1]
Definition: text.cpp:27
bool IsGridShown() const
bool GetDottedCurrentPhase() const
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:140
WINDOW_SETTINGS * GetWindowSettings(APP_SETTINGS_BASE *aCfg) override
Returns a pointer to the window settings for this frame.
void menuNewPlot(wxCommandEvent &aEvent) override
void applyTuners()
Applies component values specified using tunder sliders to the current netlist.
const BITMAP_OPAQUE zoom_fit_in_page_xpm[1]
void AddVoltagePlot(const wxString &aNetName)
Adds a voltage plot for a given net name.
void AddCurrentPlot(const wxString &aDeviceName, const wxString &aParam)
Adds a current plot for a particular device.
#define ID_MENU_WHITE_BG
Trace descriptor class
Schematic editor (Eeschema) main window.
wxString CsvFileWildcard()
void onSimUpdate(wxCommandEvent &aEvent)
void menuOpenWorkbook(wxCommandEvent &event) override
void SetDottedCurrentPhase(bool aEnable)
void menuShowGrid(wxCommandEvent &event) override
void menuZoomIn(wxCommandEvent &event) override
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
std::map< SIM_PANEL_BASE *, PLOT_INFO > m_plots
Map of plot panels and associated data
void menuZoomOut(wxCommandEvent &event) override
SIM_THREAD_REPORTER * m_reporter
void OnSimStateChange(SPICE_SIMULATOR *aObject, SIM_STATE aNewState) override
std::shared_ptr< SPICE_SIMULATOR > m_simulator
bool updatePlot(const TRACE_DESC &aDescriptor, SIM_PLOT_PANEL *aPanel)
Updates plot in a particular SIM_PLOT_PANEL.
TRACE * GetTrace(const wxString &aName) const
SIM_PANEL_BASE * m_welcomePanel
Info panel
#define ID_SAVE_AS_CSV
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:122
Field Reference of part, i.e. "IC21".
wxString GetLabelY1() const
wxSplitterWindow * m_splitterTuneValues
static bool IsPlottable(SIM_TYPE aSimType)
static SIM_TYPE CommandToSimType(const wxString &aCmd)
Returns simulation type basing on a simulation command directive.
SIM_PLOT_TYPE GetXAxisType(SIM_TYPE aType) const
Returns X axis for a given simulation type.
void menuSaveCsv(wxCommandEvent &event) override
void onPlotClose(wxAuiNotebookEvent &event) override
void StartSimulation(const wxString &aSimCommand=wxEmptyString)
const wxString & GetParam() const
wxAuiNotebook * m_plotNotebook
SCH_EDIT_FRAME * m_schematicFrame
bool DeleteTrace(const wxString &aName)
void UpdateAll()
Refresh display.
Definition: mathplot.cpp:2820
void EnableCursor(const wxString &aName, bool aEnable)
Toggles cursor for a particular trace.
SIM_STATE
const wxString & GetSimCommand() const
void setSubWindowsSashSize()
const BITMAP_OPAQUE zoom_out_xpm[1]
Definition: zoom_out.cpp:58
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:80
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:68
wxString ToString() const
Returns string value as when converting double to string (e.g.
const BITMAP_OPAQUE sim_add_signal_xpm[1]
SIM_PLOT_PANEL * m_lastSimPlot
Panel that was used as the most recent one for simulations
wxString GetLabelX() const
void AddBitmapToMenuItem(wxMenuItem *aMenu, const wxBitmap &aImage)
Add a bitmap to a menuitem.
Definition: bitmap.cpp:205
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:91
#define NULL
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:342
#define ID_MENU_SHOW_NETLIST
wxString GetLabelY2() const
static TOOL_ACTION simTune
Definition: ee_actions.h:199
Helper class to handle Spice way of expressing values (e.g. 10.5 Meg)
Definition: spice_value.h:32
wxColor GetPlotColor(int aColorId)
wxSplitterWindow * m_splitterLeftRight
void ZoomIn(const wxPoint &centerPoint=wxDefaultPosition)
Zoom into current view and refresh display.
Definition: mathplot.cpp:2243
wxMenuItem * m_runSimulation
#define ID_MENU_TUNE_SIGNALS
void onSimReport(wxCommandEvent &aEvent)
const BITMAP_OPAQUE exit_xpm[1]
Definition: exit.cpp:63
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
SIM_TYPE
Possible simulation types
Definition: sim_types.h:29
std::vector< wxColour > m_colorList
The color list to draw traces, bg, fg, axis...
void onSimFinished(wxCommandEvent &aEvent)
Interface to receive simulation updates from SPICE_SIMULATOR class.
void fillDefaultColorList(bool aWhiteBg)
Fills m_colorList by a default set of colors.
const BITMAP_OPAQUE grid_xpm[1]
Definition: grid.cpp:21
const BITMAP_OPAQUE export_xpm[1]
Definition: export.cpp:75
bool AddTrace(const wxString &aName, int aPoints, const double *aX, const double *aY, SIM_PLOT_TYPE aFlags)
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
KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the s...
Definition: kiway.h:273
wxToolBarToolBase * m_toolAddSignals
Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder.
int m_splitterTuneValuesSashPosition
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Saves common frame parameters to a configuration data file.
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
Creates a simulator instance of particular type (currently only ngspice is handled)
TRACE_DESC(const NETLIST_EXPORTER_PSPICE_SIM &aExporter, const wxString &aName, SIM_PLOT_TYPE aType, const wxString &aParam)
SIM_PANEL_BASE * currentPlotWindow() const
Returns the currently opened plot panel (or NULL if there is none).
const std::string & GetString()
Definition: richio.h:475
void onSignalRClick(wxListEvent &event) override
void ResetScales()
Resets scale ranges to fit the current traces
bool IsSimulationRunning()
#define ID_MENU_SHOW_LEGEND
void menuShowLegend(wxCommandEvent &event) override
void ShowGrid(bool aEnable)
void onTune(wxCommandEvent &event)
wxToolBarToolBase * m_toolSimulate
void menuSaveImage(wxCommandEvent &event) override
#define ID_MENU_SET_SIMUL
const BITMAP_OPAQUE directory_xpm[1]
Definition: directory.cpp:30
wxString PngFileWildcard()
Implementing SIM_PLOT_FRAME_BASE.
bool loadWorkbook(const wxString &aPath)
Loads plot settings from a file.
void SetNetlistExporter(NETLIST_EXPORTER_PSPICE_SIM *aExporter)
static wxString m_savedWorkbooksPath
A string to store the path of saved workbooks during a session
void onCursorUpdate(wxCommandEvent &aEvent)
SCH_FIELD * GetField(int aFieldNdx)
Returns a field in this symbol.
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:1998
const wxString & GetName() const
const wxString What() const
Definition: ki_exception.h:58
const BITMAP_OPAQUE sim_probe_xpm[1]
Definition: sim_probe.cpp:52
#define ID_MENU_ADD_SIGNAL
const BITMAP_OPAQUE sim_stop_xpm[1]
Definition: sim_stop.cpp:20
std::unique_ptr< NETLIST_EXPORTER_PSPICE_SIM > m_exporter
void updateNetlistExporter()
Reloads the current schematic for the netlist exporter.
see class PGM_BASE
void onSimulate(wxCommandEvent &event)
const BITMAP_OPAQUE sim_tune_xpm[1]
Definition: sim_tune.cpp:39
const char * name
Definition: DXF_plotter.cpp:60
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
SIGNAL_CONTEXT_MENU(const wxString &aSignal, SIM_PLOT_FRAME *aPlotFrame)
void onProbe(wxCommandEvent &event)
#define ID_MENU_SHOW_GRID
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
#define _(s)
Definition: 3d_actions.cpp:33
void updateSignalList()
Updates the list of currently plotted signals.
#define ID_MENU_DOTTED
const BITMAP_OPAQUE netlist_xpm[1]
unsigned int m_plotNumber
static wxString GetSpiceField(SPICE_FIELD aField, SCH_COMPONENT *aComponent, unsigned aCtl)
Retrieves either the requested field value or the default value.
Schematic symbol object.
Definition: sch_component.h:88
int m_splitterSignalsSashPosition
const BITMAP_OPAQUE sim_run_xpm[1]
Definition: sim_run.cpp:35
SIM_PLOT_PANEL * CurrentPlot() const
Returns the currently opened plot panel (or NULL if there is none).
std::map< wxString, TRACE_DESC > TRACE_MAP
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:198
const BITMAP_OPAQUE sim_settings_xpm[1]
const NETLIST_EXPORTER_PSPICE_SIM * GetExporter() const
Returns the netlist exporter object used for simulations.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:74
void removePlot(const wxString &aPlotName, bool aErase=true)
Removes a plot with a specific title.
Custom widget to handle quick component values modification and simulation on the fly.
Definition: tuner_slider.h:40
void AddTuner(SCH_COMPONENT *aComponent)
Adds a tuner for a component.
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:3050
const std::map< wxString, TRACE * > & GetTraces() const
wxSplitterWindow * m_splitterPlotAndConsole
void menuShowGridUpdate(wxUpdateUIEvent &event) override
bool HasMessage() const override
Function HasMessage 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:267
STRING_FORMATTER implements OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:445
SIM_PLOT_TYPE
Possible plot types
Definition: sim_types.h:44
#define ID_MENU_RUN_SIM
void addPlot(const wxString &aName, SIM_PLOT_TYPE aType, const wxString &aParam)
Adds a new plot to the current panel.
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:126
void onSettings(wxCommandEvent &event)
void onClose(wxCloseEvent &aEvent)
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.
const BITMAP_OPAQUE delete_xpm[1]
Definition: delete.cpp:62
Special netlist exporter flavor that allows one to override simulation commands.
void updateTuners()
Filters out tuners for components that do not exist anymore.
KI_PARAM_ERROR is a class used to hold a translatable error message and may be used when throwing exc...
Definition: ki_exception.h:45
wxToolBarToolBase * m_toolSettings
SIM_PLOT_FRAME(KIWAY *aKiway, wxWindow *aParent)
Constructor.
const BITMAP_OPAQUE zoom_in_xpm[1]
Definition: zoom_in.cpp:59