void SIM_PLOT_FRAME::onClose( wxCloseEvent& aEvent )
{
    if( IsSimulationRunning() )
        m_simulator->Stop();

    Destroy();
}
void SIM_PLOT_FRAME::onSimulate( wxCommandEvent& event )
{
    if( IsSimulationRunning() )
        StopSimulation();
    else
        StartSimulation();
}
void SIM_PLOT_FRAME::onClose( wxCloseEvent& aEvent )
{
    SaveSettings( config() );

    if( IsSimulationRunning() )
        m_simulator->Stop();

    Destroy();
}
bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath )
{
    m_plots.clear();
    m_plotNotebook->DeleteAllPages();

    wxTextFile file( aPath );

    if( !file.Open() )
        return false;

    long plotsCount;

    if( !file.GetFirstLine().ToLong( &plotsCount ) )        // GetFirstLine instead of GetNextLine
        return false;

    for( long i = 0; i < plotsCount; ++i )
    {
        long plotType, tracesCount;

        if( !file.GetNextLine().ToLong( &plotType ) )
            return false;

        SIM_PLOT_PANEL* plotPanel = NewPlotPanel( (SIM_TYPE) plotType );
        m_plots[plotPanel].m_simCommand = file.GetNextLine();
        StartSimulation();

        // Perform simulation, so plots can be added with values
        do
        {
            wxThread::This()->Sleep( 50 );
        }
        while( IsSimulationRunning() );

        if( !file.GetNextLine().ToLong( &tracesCount ) )
            return false;

        for( long j = 0; j < tracesCount; ++j )
        {
            long traceType;
            wxString name, param;

            if( !file.GetNextLine().ToLong( &traceType ) )
                return false;

            name = file.GetNextLine();
            param = file.GetNextLine();

            if( name.IsEmpty() || param.IsEmpty() )
                return false;

            addPlot( name, (SIM_PLOT_TYPE) traceType, param );
        }
    }

    return true;
}
void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
{
    m_toolBar->SetToolNormalBitmap( ID_SIM_RUN, KiBitmap( sim_run_xpm ) );
    SetCursor( wxCURSOR_ARROW );

    SIM_TYPE simType = m_exporter->GetSimType();

    if( simType == ST_UNKNOWN )
        return;

    SIM_PLOT_PANEL* plotPanel = CurrentPlot();

    if( !plotPanel || plotPanel->GetType() != simType )
        plotPanel = NewPlotPanel( simType );

    if( IsSimulationRunning() )
        return;

    // If there are any signals plotted, update them
    if( SIM_PLOT_PANEL::IsPlottable( simType ) )
    {
        TRACE_MAP& traceMap = m_plots[plotPanel].m_traces;

        for( auto it = traceMap.begin(); it != traceMap.end(); /* iteration occurs in the loop */)
        {
            if( !updatePlot( it->second, plotPanel ) )
            {
                removePlot( it->first, false );
                it = traceMap.erase( it );       // remove a plot that does not exist anymore
            }
            else
            {
                ++it;
            }
        }

        updateSignalList();
        plotPanel->UpdateAll();
        plotPanel->ResetScales();
    }
    else
    {
        /// @todo do not make it hardcoded for ngspice
        for( const auto& net : m_exporter->GetNetIndexMap() )
        {
            int node = net.second;

            if( node > 0 )
                m_simulator->Command( wxString::Format( "print v(%d)", node ).ToStdString() );
        }
    }
}
void SIM_PLOT_FRAME::onSimUpdate( wxCommandEvent& aEvent )
{
    if( IsSimulationRunning() )
        StopSimulation();

    if( CurrentPlot() != m_lastSimPlot )
    {
        // We need to rerun simulation, as the simulator currently stores
        // results for another plot
        StartSimulation();
    }
    else
    {
        // Incremental update
        m_simConsole->Clear();
        // Do not export netlist, it is already stored in the simulator
        applyTuners();
        m_simulator->Run();
    }
}