//**************************************************************************************************
// This file is part of SACAMOS, cable models for EMI simulations in SPICE. *
// It was developed by the University of Nottingham and the Netherlands Aerospace *
// Centre (NLR) for ESA under contract number 4000112765/14/NL/HK. *
// Copyright (C) 2015-2017 University of Nottingham *
// *
// SACAMOS is free software: you can redistribute it and/or modify it under the *
// terms of the GNU General Public License as published by the Free Software *
// Foundation, either version 3 of the License, or (at your option) any later *
// version. *
// *
// SACAMOS is distributed in the hope that it will be useful, but *
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
// for more details. *
// *
// A copy of the GNU General Public License version 3 can be found in the *
// file GNU_GPL_v3 in the root or at . *
// *
// The University of Nottingham can be contacted at ggiemr@nottingham.ac.uk *
// *
// This file is a minor modification of gSpiceUI to allow the library of spice cable models (MOD) *
// to be accessed via a GUI *
//**************************************************************************************************
//**************************************************************************************************
// FrmMain.cpp *
// ------------- *
// Started : 2003-08-18 *
// Last Update : 2016-11-05 *
// Copyright : (C) 2003-2016 MSWaters *
//**************************************************************************************************
//**************************************************************************************************
// *
// This program is free software; you can redistribute it and/or modify it under the *
// terms of the GNU General Public License as published by the Free Software Foundation; *
// either version 3 of the License, or (at your option) any later version. *
// *
//**************************************************************************************************
//#define DEBUG 0
#include "FrmMain.hpp"
// The application icons
#include "icons/gspiceui-32x32.xpm"
#include "icons/file-open.xpm"
#include "icons/file-import.xpm"
#include "icons/file-reload.xpm"
#include "icons/file-close.xpm"
#include "icons/sim-create.xpm"
#include "icons/sim-run.xpm"
#include "icons/sim-stop.xpm"
#include "icons/sim-edit.xpm"
#include "icons/sim-plot.xpm"
#include "icons/help.xpm"
//**************************************************************************************************
// Implement an event table in which the events are routed to their respective handler functions in
// the class. If -1 is given as the ID, the given handler will be invoked for any event of the
// specified type.
wxBEGIN_EVENT_TABLE( FrmMain, wxFrame )
EVT_MENU( FrmMain::ID_MNU_OPEN , FrmMain::OnOpen )
EVT_MENU( FrmMain::ID_MNU_IMPORT , FrmMain::OnImport )
EVT_MENU( FrmMain::ID_MNU_RELOAD , FrmMain::OnReload )
EVT_MENU( FrmMain::ID_MNU_CLOSE , FrmMain::OnClose )
EVT_MENU( FrmMain::ID_MNU_QUIT , FrmMain::OnQuit )
EVT_MENU( FrmMain::ID_MNU_CREATE , FrmMain::OnSimCreate )
EVT_MENU( FrmMain::ID_MNU_RUN , FrmMain::OnSimRun )
EVT_MENU( FrmMain::ID_MNU_STOP , FrmMain::OnSimStop )
EVT_MENU( FrmMain::ID_MNU_SCHEM , FrmMain::OnSchematic )
EVT_MENU( FrmMain::ID_MNU_VIEWER , FrmMain::OnViewData )
// BEGIN: EVENT_TABLE addition for vSACAMOS
EVT_MENU( FrmMain::ID_MNU_GUPSYM , FrmMain::OngUpSym )
EVT_MENU( FrmMain::ID_MNU_GSCHEM , FrmMain::Ongschem )
EVT_MENU( FrmMain::ID_MNU_GNETLIST, FrmMain::Ongnetlist )
EVT_MENU( FrmMain::ID_MNU_SRESULTS, FrmMain::OnSResults )
// END: EVENT_TABLE addition for vSACAMOS
EVT_MENU( FrmMain::ID_MNU_NGSPICE , FrmMain::OnSelSimEng )
EVT_MENU( FrmMain::ID_MNU_GNUCAP , FrmMain::OnSelSimEng )
EVT_MENU( FrmMain::ID_MNU_PREFS , FrmMain::OnPrefs )
EVT_MENU( FrmMain::ID_MNU_MAN_USER, FrmMain::OnManualUser )
EVT_MENU( FrmMain::ID_MNU_MAN_NGSP, FrmMain::OnManualNGSP )
EVT_MENU( FrmMain::ID_MNU_MAN_GCAP, FrmMain::OnManualGCAP )
EVT_MENU( FrmMain::ID_MNU_ABOUT , FrmMain::OnAbout )
EVT_TOOL( FrmMain::ID_TBR_OPEN , FrmMain::OnOpen )
EVT_TOOL( FrmMain::ID_TBR_IMPORT , FrmMain::OnImport )
EVT_TOOL( FrmMain::ID_TBR_RELOAD , FrmMain::OnReload )
EVT_TOOL( FrmMain::ID_TBR_CLOSE , FrmMain::OnClose )
EVT_TOOL( FrmMain::ID_TBR_CREATE , FrmMain::OnSimCreate )
EVT_TOOL( FrmMain::ID_TBR_RUN , FrmMain::OnSimRun )
EVT_TOOL( FrmMain::ID_TBR_STOP , FrmMain::OnSimStop )
EVT_TOOL( FrmMain::ID_TBR_SCHEM , FrmMain::OnSchematic )
EVT_TOOL( FrmMain::ID_TBR_VIEWER , FrmMain::OnViewData )
// BEGIN: EVENT_TABLE addition for vSACAMOS
EVT_TOOL( FrmMain::ID_TBR_GUPSYM , FrmMain::OngUpSym )
EVT_TOOL( FrmMain::ID_TBR_GSCHEM , FrmMain::Ongschem )
EVT_TOOL( FrmMain::ID_TBR_GNETLIST, FrmMain::Ongnetlist )
EVT_TOOL( FrmMain::ID_TBR_SRESULTS ,FrmMain::OnSResults )
// END: EVENT_TABLE addition for vSACAMOS
EVT_TOOL( FrmMain::ID_TBR_HELP , FrmMain::OnManualUser )
EVT_TOOL_ENTER( -1 , FrmMain::OnToolEnter )
EVT_CLOSE( FrmMain::OnSysExit )
wxEND_EVENT_TABLE( )
//**************************************************************************************************
// Constructor.
//
// Argument List :
// poApp - A pointer to the class that created this object
FrmMain::FrmMain( const wxApp * poApp ) :
wxFrame( (wxFrame *) NULL, -1, wxT(""), wxDefaultPosition, wxDefaultSize,
wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX ),
m_oFileTasks( this ), m_oHelpTasks( this ), m_oSimnNgSp( ), m_oSimnGCap( ),
m_oPrc_gschem( ), m_oPrc_gaw( ), m_oPrc_gwave( )
{
wxString os1;
// Indicate that the main frame is open
m_bIsOpen = true;
// Initialize pointers
m_poSimn = NULL;
m_poPrcSimEng = NULL;
m_poNbkSimEng = NULL;
// Create everything
Initialize( );
// Set status bar text
os1 << APP_NAME << wxT(" version ") << APP_VERSION << wxT(" (") << APP_DATE << wxT(")");
SetStatusText( wxT(" Welcome to ") + os1, ePANE_MESAGE );
}
//**************************************************************************************************
// Destructor.
FrmMain::~FrmMain( )
{
if( m_poNbkSimEng != NULL ) { delete m_poNbkSimEng; m_poNbkSimEng = NULL; }
if( m_poPrcSimEng != NULL ) { delete m_poPrcSimEng; m_poPrcSimEng = NULL; }
}
//**************************************************************************************************
// Initialize the main frame.
void FrmMain::Initialize( void )
{
// Set the frame icon, font and title
SetIcon( wxICON( gspiceui32x32 ) );
SetFont( FONT_NORM );
m_oFileTasks.bSetTitle( );
// Automatically update the frame layout when it is resized
SetAutoLayout( true );
// Set the main frame layout
m_uiFrmLayout = g_oConfig.uiGetFrmLayout( );
// Call the initialization functions
InitMenuBar ( );
InitToolBar ( );
InitLstBoxs ( );
InitNbkTCtls( );
InitStatBar ( );
InitToolTips( );
InitSimEng ( );
DoLayout( );
InitPosnSize( );
// Display desired analysis page
m_poNbkSimEng->bSetPage( g_oConfig.eGetAnalysis( ) );
// Initialize the FileTasks object (eg. load schematic or netlist file/s) and set log file name
m_oFileTasks.Initialize( );
InitLogFiles( ); // The log files can't be configured until m_oFileTsks.Initialize( ) is called
// If necessary load the simulation or netlist
if( ! m_oNetLst.bIsEmpty( ) ) bSimnLoad( );
// Display the appropriate text control page
if( ! m_oNbkTxtCtls.poGetPage( NbkTxtCtls::ePAGE_SIMULTN )->bIsEmpty( ) )
m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_SIMULTN );
else if( ! m_oNbkTxtCtls.poGetPage( NbkTxtCtls::ePAGE_NETLIST )->bIsEmpty( ) )
m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_NETLIST );
else
m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_CONSOLE );
}
//**************************************************************************************************
// Initialize the menu bar.
void FrmMain::InitMenuBar( void )
{
// Create the menu bar and menus
wxMenuBar * poMenuBar = new wxMenuBar;
wxMenu * poMenuFile = new wxMenu;
wxMenu * poMenuSimu = new wxMenu;
wxMenu * poMenuSACAMOS = new wxMenu; // Menu for vSACAMOS
wxMenu * poMenuSets = new wxMenu;
wxMenu * poMenuHelp = new wxMenu;
// Set the tool bar font
poMenuBar->SetFont( FONT_NORM );
// Load the menus with items
poMenuFile->Append( ID_MNU_OPEN , wxT(" &Open ... ") );
poMenuFile->Append( ID_MNU_IMPORT, wxT(" &Import ... ") );
poMenuFile->Append( ID_MNU_RELOAD, wxT(" &Reload ") );
poMenuFile->Append( ID_MNU_CLOSE , wxT(" &Close ") );
poMenuFile->AppendSeparator( );
poMenuFile->Append( ID_MNU_QUIT , wxT(" &Quit ") );
poMenuSimu->Append( ID_MNU_CREATE, wxT(" &Create ") );
poMenuSimu->Append( ID_MNU_RUN , wxT(" &Run ") );
poMenuSimu->Append( ID_MNU_STOP , wxT(" &Stop ") );
poMenuSimu->AppendSeparator( );
poMenuSimu->Append( ID_MNU_SCHEM , wxT(" Sc&hematic ... ") );
poMenuSimu->Append( ID_MNU_VIEWER, wxT(" R&esults ... ") );
// BEGIN: Menu additions for vSACAMOS
poMenuSACAMOS->Append( ID_MNU_GUPSYM , wxT(" &Import MOD ") );
poMenuSACAMOS->AppendSeparator( );
poMenuSACAMOS->Append( ID_MNU_GSCHEM , wxT(" &gschem ") );
poMenuSACAMOS->Append( ID_MNU_GNETLIST , wxT(" &gnetlist ") );
poMenuSACAMOS->AppendSeparator( );
poMenuSACAMOS->Append( ID_MNU_SRESULTS, wxT(" View Results") );
// END: Menu additions for vSACAMOS
poMenuSets->Append( ID_MNU_PREFS, wxT(" &Preferences ... ") );
poMenuSets->AppendSeparator( );
poMenuSets->AppendRadioItem( ID_MNU_NGSPICE, wxT(" &NG-Spice ") );
poMenuSets->AppendRadioItem( ID_MNU_GNUCAP , wxT(" &GNU-Cap ") );
poMenuHelp->Append( ID_MNU_MAN_USER, wxT(" &User Manual ... ") );
// poMenuHelp->Append( ID_MNU_MAN_NGSP, wxT(" &NG-Spice Manual ... ") );
// poMenuHelp->Append( ID_MNU_MAN_GCAP, wxT(" &GNU-Cap Manual ... ") );
// poMenuHelp->AppendSeparator( );
poMenuHelp->Append( ID_MNU_ABOUT , wxT(" &About ... ") );
// Load the menubar with menus
poMenuBar->Append( poMenuFile, wxT(" &File ") );
poMenuBar->Append( poMenuSimu, wxT(" &Simulate ") );
poMenuBar->Append( poMenuSACAMOS, wxT(" SACAMOS ") ); // vSACAMOS
poMenuBar->Append( poMenuSets, wxT(" S&ettings ") );
poMenuBar->Append( poMenuHelp, wxT(" &Help ") );
// Check the appropriate simulation engine menu item
if( g_oConfig.eGetSimEng( ) == eSIMR_NGSPICE ) poMenuSets->Check( ID_MNU_NGSPICE, true );
else poMenuSets->Check( ID_MNU_GNUCAP , true );
// Attach the menu bar to the frame
SetMenuBar( poMenuBar );
}
//**************************************************************************************************
// Initialize the tool bar.
void FrmMain::InitToolBar( void )
{
wxToolBar * poToolBar;
wxBitmap * poPixMap[ 10 ];
// Create the tool bar
poToolBar = CreateToolBar( wxHORIZONTAL | wxTB_FLAT );
poToolBar->SetToolSeparation( 10 );
// Create the bitmaps for the tools
poPixMap[ 0 ] = new wxBitmap( file_open_xpm );
poPixMap[ 1 ] = new wxBitmap( file_import_xpm );
poPixMap[ 2 ] = new wxBitmap( file_reload_xpm );
poPixMap[ 3 ] = new wxBitmap( file_close_xpm );
poPixMap[ 4 ] = new wxBitmap( sim_create_xpm );
poPixMap[ 5 ] = new wxBitmap( sim_run_xpm );
poPixMap[ 6 ] = new wxBitmap( sim_stop_xpm );
poPixMap[ 7 ] = new wxBitmap( sim_edit_xpm );
poPixMap[ 8 ] = new wxBitmap( sim_plot_xpm );
poPixMap[ 9 ] = new wxBitmap( help_xpm );
// Add the tools to the toolbar
poToolBar->AddTool( ID_TBR_OPEN, wxT(""), *(poPixMap[ 0 ]), wxT("Open a netlist file") );
poToolBar->AddTool( ID_TBR_IMPORT, wxT(""), *(poPixMap[ 1 ]), wxT("Import a schematic file") );
poToolBar->AddTool( ID_TBR_RELOAD, wxT(""), *(poPixMap[ 2 ]), wxT("Reload a netlist / schematic file") );
poToolBar->AddTool( ID_TBR_CLOSE, wxT(""), *(poPixMap[ 3 ]), wxT("Close a netlist / schematic file") );
poToolBar->AddSeparator( );
poToolBar->AddTool( ID_TBR_CREATE, wxT(""), *(poPixMap[ 4 ]), wxT("Create a netlist file including simulation instructions") );
poToolBar->AddTool( ID_TBR_RUN, wxT(""), *(poPixMap[ 5 ]), wxT("Run the simulation") );
poToolBar->AddTool( ID_TBR_STOP, wxT(""), *(poPixMap[ 6 ]), wxT("Stop the simulation") );
poToolBar->AddSeparator( );
poToolBar->AddTool( ID_TBR_SCHEM, wxT(""), *(poPixMap[ 7 ]), wxT("Edit / view a schematic") );
poToolBar->AddTool( ID_TBR_VIEWER, wxT(""), *(poPixMap[ 8 ]), wxT("View simulation results") );
poToolBar->AddSeparator( );
poToolBar->AddTool( ID_TBR_HELP, wxT(""), *(poPixMap[ 9 ]), wxT("View the user manual") );
// Realize the toolbar
poToolBar->Realize( );
// Delete the bitmaps
for( int i1=0; i1<10; i1++ ) delete poPixMap[ i1 ];
}
//**************************************************************************************************
// Initialize the test node and component list boxes.
void FrmMain::InitLstBoxs( void )
{
long lStyle;
// Create the node and component list labels
lStyle = wxALIGN_CENTER;
m_oLblNodes.Create( this, ID_UNUSED, wxT("Nodes"), wxDefaultPosition, wxDefaultSize, lStyle );
m_oLblCpnts.Create( this, ID_UNUSED, wxT("Components"), wxDefaultPosition, wxDefaultSize, lStyle );
// Create the node and component list boxes
lStyle = wxLB_EXTENDED | wxLB_NEEDED_SB;
m_oLbxNodes.Create( this, ID_LBX_NODES, wxDefaultPosition, wxSize( 100, -1 ), 0, NULL, lStyle );
m_oLbxCpnts.Create( this, ID_LBX_CPNTS, wxDefaultPosition, wxSize( 100, -1 ), 0, NULL, lStyle );
}
//**************************************************************************************************
// Initialize the console notebook.
void FrmMain::InitNbkTCtls( void )
{
uint ui1;
// Create the text control notebook
m_oNbkTxtCtls.bCreate( this, ID_NBK_TXTCTRLS );
// Set the text control maximum lines
ui1 = g_oConfig.uiGetNbkMaxLns( );
m_oNbkTxtCtls.bSetLinesMax( ui1 );
// Set the precision of the results data
ui1 = g_oConfig.uiGetPrecision( );
CnvtType::bSetFltRes( ui1 );
}
//**************************************************************************************************
// Initialize the status bar.
//
// Note : The first field in the status bar has benn effectively disable by setting it's width to
// near zero. It is not used since the frame insists on writing text into this field as the
// user moves the mouse over display controls.
void FrmMain::InitStatBar( void )
{
wxStatusBar * poStatusBar = new wxStatusBar;
long liStyle;
int iaPaneWidths[ ePANE_LAST+1 ];
#if wxCHECK_VERSION( 3,0,0 )
int iaPaneStyles[ ePANE_LAST+1 ];
#endif
wxString os1;
// Set the style bits
#if wxCHECK_VERSION( 3,0,0 )
liStyle = wxSTB_SHOW_TIPS | wxSTB_ELLIPSIZE_END | wxFULL_REPAINT_ON_RESIZE;
#else
liStyle = wxFULL_REPAINT_ON_RESIZE;
#endif
// Create the status bar
poStatusBar->Create( this, wxID_ANY, liStyle );
poStatusBar->SetFieldsCount( ePANE_LAST+1 );
poStatusBar->SetMinHeight( 25 );
// Set the status bar pane widths
iaPaneWidths[ ePANE_MESAGE ] = -1; // Variable width
iaPaneWidths[ ePANE_SIMENG ] = 144; // Fixed width
iaPaneWidths[ ePANE_VIEWER ] = 110; // Fixed width
poStatusBar->SetStatusWidths( ePANE_LAST+1, iaPaneWidths );
// Set the status bar pane styles
#if wxCHECK_VERSION( 3,0,0 )
iaPaneStyles[ ePANE_MESAGE ] = wxSB_SUNKEN;
iaPaneStyles[ ePANE_SIMENG ] = wxSB_SUNKEN;
iaPaneStyles[ ePANE_VIEWER ] = wxSB_SUNKEN;
poStatusBar->SetStatusStyles( ePANE_LAST+1, iaPaneStyles );
#endif
// Get the viewer application name from the configuration object
os1 = g_oConfig.rosGetDataViewer( );
// Set status bar text
poStatusBar->SetStatusText( wxT(" Welcome message") , ePANE_MESAGE );
poStatusBar->SetStatusText( wxT(" Simulator : None"), ePANE_SIMENG );
poStatusBar->SetStatusText( wxT(" Viewer : ") + os1 , ePANE_VIEWER );
// Set the main frame status bar
SetStatusBar( poStatusBar );
// Disable the status bar pane used to display menu and toolbar help
SetStatusBarPane( -1 );
}
//**************************************************************************************************
// Initialize the tool tips.
void FrmMain::InitToolTips( void )
{
// Define tool tips for each control
m_oLbxNodes.SetToolTip( wxT(" Test Nodes ") );
m_oLbxCpnts.SetToolTip( wxT(" Test Components ") );
// Set global tool tip attributes
wxToolTip::Enable( g_oConfig.bGetToolTips( ) );
wxToolTip::SetDelay( g_oConfig.uiGetToolTipDly( ) );
}
//**************************************************************************************************
// Set the electronic circuit simulator engine to use.
void FrmMain::InitSimEng( void )
{
// Delete any existing simulation engine notebook object
if( m_poNbkSimEng != NULL )
{
GetSizer( )->Detach( m_poNbkSimEng );
delete m_poNbkSimEng;
m_poNbkSimEng = NULL;
}
// Delete any existing simulation engine process object
if( m_poPrcSimEng != NULL )
{
delete m_poPrcSimEng;
m_poPrcSimEng = NULL;
}
// Create the new simulation engine objects and update the status text
if( GetMenuBar( )->IsChecked( ID_MNU_NGSPICE ) )
{
m_poNbkSimEng = new NbkNgSpice( this, ID_NBK_ANALYSIS );
m_poPrcSimEng = new PrcNgSpice( );
m_poSimn = &m_oSimnNgSp;
SetStatusText( wxT(" Simulator : NG-Spice"), ePANE_SIMENG );
}
else
{
m_poNbkSimEng = new NbkGnuCap( this, ID_NBK_ANALYSIS );
m_poPrcSimEng = new PrcGnuCap( );
m_poSimn = &m_oSimnGCap;
SetStatusText( wxT(" Simulator : GNU-Cap"), ePANE_SIMENG );
}
}
//**************************************************************************************************
// Initialize the log file names in the process objects.
void FrmMain::InitLogFiles( void )
{
wxFileName ofn1;
wxString os1;
// Check that a netlist file has been defined
ofn1 = m_oFileTasks.rosGetNetLstFile( );
if( ! ofn1.IsOk( ) ) return;
if( ! ofn1.FileExists( ) ) return;
// Get the path to the schematic or netlist file
os1 = ofn1.GetPath( ) + wxT("/gspiceui.log");
// Set the log file path for the gNetList process object
m_oFileTasks.bSetLogFile( os1 );
// Set the log file path for the simulation process object
if( m_poPrcSimEng != NULL ) m_poPrcSimEng->bSetLogFile( os1 );
}
//**************************************************************************************************
// Initialize the frames position amd size.
void FrmMain::InitPosnSize( void )
{
int iPosnX, iPosnY, iSizeW, iSizeH;
// Get the position and size from the configuration object
iPosnX = g_oConfig.iGetMainPosnX( );
iPosnY = g_oConfig.iGetMainPosnY( );
iSizeW = g_oConfig.iGetMainSizeW( );
iSizeH = g_oConfig.iGetMainSizeH( );
// Set the position and size
if( iPosnX>=0 && iPosnY>=0 ) Move( iPosnX, iPosnY );
if( iSizeW> 0 && iSizeH> 0 ) SetClientSize( iSizeW, iSizeH );
}
//**************************************************************************************************
// Layout the main frame display objects.
void FrmMain::DoLayout( void )
{
wxGridBagSizer * poSzr;
wxGBPosition oGBPosn;
wxGBSpan oGBSpan;
int iFlags;
int iBorder;
size_t sz1;
if( GetSizer( ) == NULL )
{
// Create and set the frame's sizer (at startup)
poSzr = new wxGridBagSizer( 1, 1 );
SetSizer( poSzr );
// Specify how the sizer will grow when resized
poSzr->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
poSzr->SetCols( 3 );
poSzr->AddGrowableCol( 0 );
poSzr->AddGrowableCol( 1 );
for( sz1=13; sz1<20; sz1++ ) poSzr->AddGrowableRow( sz1 );
}
else
{
// Detach the display objects from the sizer
poSzr = (wxGridBagSizer *) GetSizer( );
poSzr->Detach( &m_oLblNodes );
poSzr->Detach( &m_oLbxNodes );
poSzr->Detach( &m_oLblCpnts );
poSzr->Detach( &m_oLbxCpnts );
poSzr->Detach( m_poNbkSimEng );
poSzr->Detach( &m_oNbkTxtCtls );
poSzr->Clear( );
}
iFlags = wxTOP | wxALIGN_CENTER_HORIZONTAL | wxALIGN_TOP;
iBorder = 11;
// Add the nodes list box label
oGBPosn.SetCol( 0 ); oGBPosn.SetRow( 0 );
oGBSpan.SetColspan( 1 ); oGBSpan.SetRowspan( 1 );
poSzr->Add( &m_oLblNodes, oGBPosn, oGBSpan, iFlags, iBorder );
// Add the components list box label
oGBPosn.SetCol( 1 ); oGBPosn.SetRow( 0 );
oGBSpan.SetColspan( 1 ); oGBSpan.SetRowspan( 1 );
poSzr->Add( &m_oLblCpnts, oGBPosn, oGBSpan, iFlags, iBorder );
iFlags = (wxALL & ~wxRIGHT) | wxALIGN_CENTER | wxEXPAND;
iBorder = 5;
// Add the nodes list box
oGBPosn.SetCol( 0 ); oGBPosn.SetRow( 1 ); oGBSpan.SetColspan( 1 );
if( m_uiFrmLayout == 0 ) oGBSpan.SetRowspan( 19 );
else oGBSpan.SetRowspan( 12 );
poSzr->Add( &m_oLbxNodes, oGBPosn, oGBSpan, iFlags, iBorder );
// Add the components list box
oGBPosn.SetCol( 1 ); oGBPosn.SetRow( 1 ); oGBSpan.SetColspan( 1 );
if( m_uiFrmLayout == 0 ) oGBSpan.SetRowspan( 19 );
else oGBSpan.SetRowspan( 12 );
poSzr->Add( &m_oLbxCpnts, oGBPosn, oGBSpan, iFlags, iBorder );
iFlags = wxALL | wxALIGN_CENTER | wxEXPAND;
iBorder = 5;
// Add the simulator notebook
oGBPosn.SetCol( 2 ); oGBPosn.SetRow( 0 );
oGBSpan.SetColspan( 1 ); oGBSpan.SetRowspan( 13 );
poSzr->Add( m_poNbkSimEng, oGBPosn, oGBSpan, iFlags, iBorder );
#ifndef LAYOUT_MNGR
poSzr->SetItemMinSize( m_poNbkSimEng, NBKSIMENG_WIDTH, NBKSIMENG_HEIGHT );
#endif // LAYOUT_MNGR
iFlags = (wxALL & ~wxTOP) | wxALIGN_CENTER | wxEXPAND;
iBorder = 5;
// Add the console notebook
oGBPosn.SetRow( 13 ); oGBSpan.SetRowspan( 7 );
if( m_uiFrmLayout == 0 )
{ oGBPosn.SetCol( 2 ); oGBSpan.SetColspan( 1 ); }
else { oGBPosn.SetCol( 0 ); oGBSpan.SetColspan( 3 ); }
poSzr->Add( &m_oNbkTxtCtls, oGBPosn, oGBSpan, iFlags, iBorder );
#ifndef LAYOUT_MNGR
poSzr->SetItemMinSize( &m_oNbkTxtCtls, NBKTXTCTLS_WIDTH, NBKTXTCTLS_HEIGHT );
#endif // LAYOUT_MNGR
// Set minimum and initial sizes as calculated by the frame's sizer
poSzr->SetSizeHints( this );
}
//**************************************************************************************************
// Load information from the Simulation object (FrmMain::m_poSimn) into the various display
// controls.
//
// Return Values :
// true - Success
// false - Failure
bool FrmMain::bSimnLoad( void )
{
TextCtrl * poTxtCtl;
wxArrayString osa1;
size_t sz1;
// Load all the nodes (except ground) into the "Nodes" list box
for( sz1=0; sz1m_osaNodeLbls.GetCount( ); sz1++ )
m_oLbxNodes.Append( m_poSimn->m_osaNodeLbls.Item( sz1 ) );
// Select the test nodes (if any have been specified)
for( sz1=0; sz1rosaGetTstNodes( ).GetCount( ); sz1++ )
m_oLbxNodes.SetStringSelection( m_poSimn->rosaGetTstNodes( ).Item( sz1 ) );
// Load all 2-port components into the "Components" list box
for( sz1=0; sz1m_oaCpnts.GetCount( ); sz1++ )
{
Component & roCpnt = m_poSimn->m_oaCpnts.Item( sz1 );
switch( roCpnt.eGetType( ) ) // Only collect two terminal components
{
case eCPNT_CAP : // Capacitor
case eCPNT_RES : // Resistor
case eCPNT_IND : // Inductor
case eCPNT_CIND : // Coupled (Mutual) Inductors
case eCPNT_DIODE : // Diode
case eCPNT_VCVS : // Voltage Controlled Voltage Source
case eCPNT_CCCS : // Current Controlled Current Source
case eCPNT_VCCS : // Voltage Controlled Current Source
case eCPNT_CCVS : // Current Controlled Voltage Source
case eCPNT_IVS : // Independent Voltage Source
case eCPNT_ICS : // Independent Current Source
case eCPNT_NLDS : // Non-Linear Dependent Source
case eCPNT_NLDCS : // Non-Linear Dependent Current Source
case eCPNT_NLDVS : // Non-Linear Dependent Voltage Source
case eCPNT_STJ : // Super-conducting Tunnel Junction
osa1.Add( roCpnt.rosGetName( ) );
break;
default : // Do nothing
break;
}
}
osa1.Sort( &iStrCmpCpnt ); // Function iStrCmpCpnt( ) is defined in utility/StrUtils.hpp
if( ! osa1.IsEmpty( ) ) m_oLbxCpnts.InsertItems( osa1, 0 );
// Select the test components (if any have been specified)
const wxArrayString & rosa1 = m_poSimn->rosaGetTstCpnts( );
for( sz1=0; sz1bClear( );
for( sz1=0; sz1bAppendLine( m_oNetLst.m_osaNetLst.Item( sz1 ) );
m_oNbkTxtCtls.bSetPosn( 0 );
}
// Load the analysis notebook with simulation information
if( ! m_poNbkSimEng->bLoad( *m_poSimn ) ) return( false );
// Load the circuit description into the Simulation text control
m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_SIMULTN );
poTxtCtl = m_oNbkTxtCtls.poGetPage( );
poTxtCtl->bClear( );
for( sz1=0; sz1bAppendLine( m_oNetLst.m_osaNetLst.Item( sz1 ) );
m_oNbkTxtCtls.bSetPosn( 0 );
poTxtCtl->SetEditable( true );
return( true );
}
//**************************************************************************************************
// Reload information from the Simulation object (FrmMain::m_poSimn) into the various display
// controls.
//
// Return Values :
// true - Success
// false - Failure
bool FrmMain::bSimnReload( void )
{
wxArrayString osaTstNodes;
wxArrayString osaTstCpnts;
size_t sz1;
int i1;
// Record the nodes that are currently selected
#if wxCHECK_VERSION( 2,8,0 )
for( sz1=0; sz1bClrCmds( );
// Get an array of indicies to the currently selected test points
m_oLbxNodes.GetSelections( oaiSelNodes );
m_oLbxCpnts.GetSelections( oaiSelCpnts );
// Load the test nodes into the simulation object
for( sz1=0; sz1bAddTstNode( osSel );
}
// Load the test components into the simulation object
for( sz1=0; sz1bAddTstCpnt( osSel );
}
// Transfer the simulation parameters into the simulation object
if( ! m_poNbkSimEng->bSave( *m_poSimn ) ) return( false );
// Create the simulation information and save it to file
if( ! m_poSimn->bSave( ) ) return( false );
if( ! m_poSimn->bSaveFile( ) ) return( false );
return( true );
}
//**************************************************************************************************
// Check that the electronic circuit simulator engine is present and accounted for, if not display
// an error message.
//
// Argument List :
// poPrcSimEng - The utility object to be tested
//
// Return Values :
// true - Success
// false - Failure
bool FrmMain::bIsOkSimEng( PrcBase * poPrcSimEng )
{
wxString os1;
// Check that gnetlist exists and is accessible
if( ! poPrcSimEng->bBinExists( ) )
{
os1 << wxT("Can't find the binary file required to run simulation :\n")
<< poPrcSimEng->roGetBinFile( ).GetFullName( )
<< wxT("\nThere is no path to the binary or it hasn't been installed.")
<< wxT("\n\n");
DlgErrMsg( wxT("ERROR"), os1 );
return( false );
}
return( true );
}
//**************************************************************************************************
// Check that the waveform viewer utility is present and accounted for, if not display an error
// message.
//
// Argument List :
// poPrcViewer - The utility object to be tested
//
// Return Values :
// true - Success
// false - Failure
bool FrmMain::bIsOkViewer( PrcBase * poPrcViewer )
{
wxString os1;
// Check that the waveform viewer utility exists and is accessible
if( ! poPrcViewer->bBinExists( ) )
{
os1 << wxT("Can't find the binary file required to plot the simulation ")
<< wxT("results :\n")
<< poPrcViewer->roGetBinFile( ).GetFullName( )
<< wxT("\nThere is no path to the binary or it hasn't been installed.")
<< wxT("\n\n");
DlgErrMsg( wxT("ERROR"), os1 );
return( false );
}
return( true );
}
//**************************************************************************************************
// Check that a required binary file is present and accounted for, if not display an error message.
//
// Argument List :
// poProcess - The process object to test
// rosPurpose - What is the binary needed to do?
//
// Return Values :
// true - Success
// false - Failure
bool FrmMain::bIsOkBinary( PrcBase * poProcess, const wxString & rosPurpose )
{
wxString os1;
// Check that the waveform viewer utility exists and is accessible
if( ! poProcess->bBinExists( ) )
{
os1 << wxT("Can't find the binary file required to ")
<< rosPurpose << wxT(" :\n")
<< poProcess->roGetBinFile( ).GetFullName( )
<< wxT("\nThere is no path to the binary or it hasn't been installed.")
<< wxT("\n\n");
DlgErrMsg( wxT("ERROR"), os1 );
return( false );
}
return( true );
}
//**************************************************************************************************
// Lock GUI controls.
//
// Argument List :
// bEnable - Enable or disable lock GUI mode
void FrmMain::LockGUI( bool bEnable )
{
size_t sz1;
GetMenuBar( )->Enable( ! bEnable ); // Set the menu bar state
m_poNbkSimEng->Enable( ! bEnable ); // Set the simulator notebook state
m_oLbxNodes .Enable( ! bEnable ); // Set the node label list box state
m_oLbxCpnts .Enable( ! bEnable ); // Set the component label list box state
// Set the individual state of each tool in the tool bar
for( sz1=ID_TBR_FST; sz1<=ID_TBR_LST; sz1++ ) GetToolBar( )->EnableTool( sz1, ! bEnable );
if( bEnable ) ::wxBeginBusyCursor( ); // Change the cursor to the wait symbol
else ::wxEndBusyCursor( ); // Change the cursor to the default
}
//**************************************************************************************************
// Clear the object attributes.
bool FrmMain::bClear( void )
{
bool bRtn = true;
// Clear all previously selected test points
m_oLbxNodes.Clear( );
m_oLbxCpnts.Clear( );
// Clear simulation object attributes
m_oSimnGCap.bClear( );
m_oSimnNgSp.bClear( );
// Clear the simulation object and the analysis panels
if( m_poNbkSimEng != NULL )
if( ! m_poNbkSimEng->bClear( ) ) bRtn = false;
// Clear the text controls
if( ! m_oNbkTxtCtls.bClear( ) ) bRtn = false;
m_oNbkTxtCtls.bInitialize( );
// Terminate any simulation process
if( m_poPrcSimEng != NULL )
if( ! m_poPrcSimEng->bKill( ) ) bRtn = false;
// Terminate any schematic editor process
if( ! m_oPrc_gschem.bKill( ) ) bRtn = false;
// Terminate any waveform viewer process
if( g_oConfig.eGetDataViewer( ) == eVIEW_GAW )
{ if( ! m_oPrc_gaw .bKill( ) ) bRtn = false; }
else { if( ! m_oPrc_gwave.bKill( ) ) bRtn = false; }
return( bRtn );
}
//**************************************************************************************************
// Display a dialog box containing an error message.
//
// Note : At start-up the first error message is held over until the the main GUI is created and
// displayed; to display this message call this function with no arguments.
//
// Argument List :
// rosTitle - The dialogue box title
// rosMsg - The error message
void FrmMain::DlgErrMsg( const wxString & rosTitle, const wxString & rosMsg )
{
static wxMessageDialog * poDlgMsg=NULL;
wxStringTokenizer ostk1;
wxString os1, os2, os3;
if( poDlgMsg == NULL )
{
if( rosTitle.IsEmpty( ) || rosMsg.IsEmpty( ) ) return;
// Tokenize the message into lines
ostk1.SetString( rosMsg, wxT(" \n\r"), wxTOKEN_STRTOK );
// Use the first complete sentence as the status bar message
os1 << wxT(" ERROR :");
while( ostk1.HasMoreTokens( ) )
{
// Get the next line
os2 = ostk1.GetNextToken( ).Strip( wxString::both );
// Remove the path from file names
if( os2.Freq( wxT('/') ) > 1 )
{
os3 << os2.AfterLast( wxT('/') ) << wxT(',');
os2 = os3;
}
// Look for the end of the sentence
if( os2==wxT('.') || os2==wxT(':') ) break;
// Append the line to the message
os1 << wxT(' ') << os2;
}
// If debug mode is enabled send the error message to the console
if( g_bDebug ) std::cerr << "DEBUG : " << rosStrToLine( os1 ).mb_str( ) << "\n\n";
// Set the status line message
SetStatusText( os1, ePANE_MESAGE );
// Create the error message dialog
os1 = wxT('\n') + rosMsg;
poDlgMsg = new wxMessageDialog( this, os1, rosTitle, wxOK | wxICON_ERROR );
}
if( ! IsShown( ) ) return;
// Display the error message dialog
poDlgMsg->ShowModal( );
// Delete the error message dialog
delete poDlgMsg;
poDlgMsg = NULL;
}
//**************************************************************************************************
// Event Handlers *
//**************************************************************************************************
// Open a circuit description file.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnOpen( wxCommandEvent & roEvtCmd )
{
if( ! m_oFileTasks.bDlgOpen( ) ) return; // Attempt to get a netlist file name from the user
LockGUI( true ); // Lock the GUI controls
bClear( ); // Clear the main frame object attributes
m_oFileTasks.bOpen( ); // Attempt to open and read the netlist file
bSimnLoad( ); // Load the simulation information
InitLogFiles( ); // Initialize the process log files
LockGUI( false ); // Unlock the GUI controls
}
//**************************************************************************************************
// Import a schematic file using gnetlist to convert the schematic to a circuit description.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnImport( wxCommandEvent & roEvtCmd )
{
if( ! m_oFileTasks.bDlgImport( ) ) return; // Attempt to get the schematic file name/s from user
LockGUI( true ); // Lock the GUI controls
bClear( ); // Clear the main frame object attributes
m_oFileTasks.bImport( ); // Attempt to import schematic/s and read netlist file
bSimnLoad( ); // Load the simulation information
InitLogFiles( ); // Initialize the process log files
LockGUI( false ); // Unlock the GUI controls
}
//**************************************************************************************************
// Reload the schematic or netlist file.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnReload( wxCommandEvent & roEvtCmd )
{
LockGUI( true ); // Lock the GUI controls
m_oFileTasks.bReload( ); // Reload schematic file/s and/or the netlist file
bSimnReload( ); // Reload the simulation information
LockGUI( false ); // Unlock the GUI controls
}
//**************************************************************************************************
// Close the circuit description file.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnClose( wxCommandEvent & roEvtCmd )
{
m_oFileTasks.bClose( ); // Delete temporary files
bClear( ); // Clear the object attributes
m_oFileTasks.bSetTitle( ); // Set the frame title
m_poNbkSimEng->bSetPage( (eTypeCmd) 0 ); // Display first analysis panel
}
//**************************************************************************************************
// Exit the application.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnQuit( wxCommandEvent & roEvtCmd )
{
Close( true ); // Generates a wxCloseEvent which is handled by OnSysExit( )
}
//**************************************************************************************************
// Create the simulation.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnSimCreate( wxCommandEvent & roEvtCmd )
{
TextCtrl * poTxtCtl;
wxString osErrMsg;
// If a simulation is currently running do nothing
if( m_poPrcSimEng->bIsExec( ) ) return;
LockGUI( true ); // Lock the GUI controls
if( ! m_oNetLst.m_osaNetLst.IsEmpty( ) )
{ // Save the simulation info. in the simulation object
if( bSimnSave( ) )
{
// Print the simulation to the simulation text control
m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_SIMULTN );
poTxtCtl = m_oNbkTxtCtls.poGetPage( NbkTxtCtls::ePAGE_SIMULTN );
poTxtCtl->bLoadFile( m_poSimn->roGetSaveFile( ).GetFullPath( ) );
poTxtCtl->SetEditable( true );
}
else
{
if( ! m_poNbkSimEng->bIsOk( ) ) osErrMsg = m_poNbkSimEng->rosGetErrMsg( );
else if( ! m_poSimn->bIsValid( ) ) osErrMsg = m_poSimn ->rosGetErrMsg( );
else osErrMsg = wxT("Unknown error.");
}
}
else osErrMsg = wxT("There's no schematic or netlist file loaded.");
// Display exit status message
if( ! osErrMsg.IsEmpty( ) )
DlgErrMsg( wxT("Create Simulation Error"), osErrMsg );
else SetStatusText( wxT(" Simulation ran successfully"), ePANE_MESAGE );
LockGUI( false ); // Unlock the GUI controls
}
//**************************************************************************************************
// Run the simulation.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnSimRun( wxCommandEvent & roEvtCmd )
{
TextCtrl * poTxtCtl;
NbkTxtCtls::ePageType ePage;
wxFileName ofn1;
wxString osErrMsg, os1;
//------------------------------------------------------------------------------------------------
// Prepare to run the simulation
LockGUI( true ); // Lock the GUI controls
GetToolBar( )->EnableTool( ID_TBR_STOP, true );
SetStatusText( wxT(" Running the simulation ..."), ePANE_MESAGE );
//------------------------------------------------------------------------------------------------
// Check if a schematic or netlist file is currently open
ofn1 = m_oFileTasks.rosGetNetLstFile( );
if( ofn1.GetFullPath( ).IsEmpty( ) )
{ osErrMsg = wxT("There's no schematic or netlist file loaded."); goto OnSimRun_Exit; }
//------------------------------------------------------------------------------------------------
// Prepare to run the simulation (and update the Simulation text page)
poTxtCtl = m_oNbkTxtCtls.poGetPage( NbkTxtCtls::ePAGE_SIMULTN );
if( poTxtCtl->IsModified( ) )
{ // Save the simulation in the text page to file, the user has modified it
poTxtCtl->SaveFile( m_poSimn->roGetSaveFile( ).GetFullPath( ) );
}
else if( bSimnSave( ) )
{ // Load the simulation on file into the Simulation text page
poTxtCtl->bLoadFile( m_poSimn->roGetSaveFile( ).GetFullPath( ) );
poTxtCtl->DiscardEdits( ); // Reset modified flag as if changes had been saved
poTxtCtl->SetEditable( true ); // Make the text control editable
}
else
{ // There's been an error, report it to the user and return
if( ! m_poNbkSimEng->bIsOk( ) ) osErrMsg = m_poNbkSimEng->rosGetErrMsg( );
else if( ! m_poSimn->bIsValid( ) ) osErrMsg = m_poSimn ->rosGetErrMsg( );
else osErrMsg = wxT("Unknown error."); goto OnSimRun_Exit;
}
m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_SIMULTN );
//------------------------------------------------------------------------------------------------
// Run the simulation (and update the Console text page)
if( ! m_poPrcSimEng->bMakeArgLst( *m_poSimn ) )
{ osErrMsg = m_poPrcSimEng->rosGetErrMsg( ); goto OnSimRun_Exit; }
if( ! m_poPrcSimEng->bExec( ) ) { osErrMsg = m_poPrcSimEng->rosGetErrMsg( ); goto OnSimRun_Exit; }
m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_CONSOLE );
poTxtCtl = m_oNbkTxtCtls.poGetPage( NbkTxtCtls::ePAGE_CONSOLE );
poTxtCtl->bClear( ); // Clear the Console text page
m_poPrcSimEng->PrintCmd( *poTxtCtl ); // Print simulator cmd to Console page
// Return immediately if the user aborted the simulation
if( GetStatusBar( )->GetStatusText( 1 ).Contains( wxT("aborted") ) ) goto OnSimRun_Exit;
GetToolBar( )->EnableTool( ID_TBR_STOP, false );
m_poPrcSimEng->PrintRsp( *poTxtCtl ); // Print simulator output to Console page
//------------------------------------------------------------------------------------------------
// Format the simulation results (and update the Results text page)
SetStatusText( wxT(" Formatting the simulation results ..."), ePANE_MESAGE );
wxTheApp->Yield( true ); // Allow the display to update
if( ! m_poPrcSimEng->bFmtResults( ) )
{ osErrMsg = m_poPrcSimEng->rosGetErrMsg( ); goto OnSimRun_Exit; }
if( m_poNbkSimEng->eGetSimEng( ) == eSIMR_GNUCAP ) ePage = NbkTxtCtls::ePAGE_GNUCAP;
else ePage = NbkTxtCtls::ePAGE_NGSPICE;
poTxtCtl = m_oNbkTxtCtls.poGetPage( ePage );
os1 = m_poPrcSimEng->roGetResultsFile( ).GetFullPath( );
// Load the simulation output into the results text page
if( ! poTxtCtl->bLoadFile( os1 ) )
{ osErrMsg = wxT("Couldn't load the results file : \n\n") + os1; goto OnSimRun_Exit; }
m_oNbkTxtCtls.bSetPage( ePage ); // Change to the appropriate results page
//------------------------------------------------------------------------------------------------
// Display status and any errors messages and return
OnSimRun_Exit:
// Display exit status message
if( ! osErrMsg.IsEmpty( ) )
DlgErrMsg( wxT("Run Simulation Error"), osErrMsg );
else SetStatusText( wxT(" Simulation ran successfully"), ePANE_MESAGE );
LockGUI( false ); // Unlock the GUI controls
}
//**************************************************************************************************
// Stop the simulation.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnSimStop( wxCommandEvent & roEvtCmd )
{
if( m_poPrcSimEng->bIsExec( ) )
{ // A simulation is currently running, abort it
m_poPrcSimEng->bKill( );
SetStatusText( wxT(" Simulation aborted by the user"), ePANE_MESAGE );
}
else
{ // No simulation is currently running, display an error message dialogue
DlgErrMsg( wxT("Stop Simulation Error"), wxT("There's no simulation running.") );
}
}
//**************************************************************************************************
// Edit / view the schematic file.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnSchematic( wxCommandEvent & roEvtCmd )
{
wxString osErrHdr = wxT("Schematic Editor Error");
wxString osErrMsg;
// Check if the schematic editor process is already running
if( m_oPrc_gschem.bIsExec( ) )
{
osErrMsg = wxT("The schematic editor process is already running.");
DlgErrMsg( osErrHdr, osErrMsg );
return;
}
// Check if a schematic file is currently set
m_oPrc_gschem.bSetSchemFiles( m_oFileTasks.rosaGetSchemFiles( ) );
if( m_oPrc_gschem.rosGetSchemFiles( ).IsEmpty( ) )
{
osErrMsg = wxT("There's no schematic loaded or the netlist has no associated schematic file.");
DlgErrMsg( osErrHdr, osErrMsg );
return;
}
// Execute the schematic editor process
if( ! m_oPrc_gschem.bExec( ) )
{ // Something went wrong, display an error message
osErrMsg = m_oPrc_gschem.rosGetErrMsg( );
DlgErrMsg( osErrHdr, osErrMsg );
}
}
//**************************************************************************************************
// View the simulation results.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnViewData( wxCommandEvent & roEvtCmd )
{
wxFileName ofn1;
wxString osErrHdr = wxT("Plot Results Error");
wxString os1;
// Check if the waveform viewer process is already running
if( m_oPrc_gaw.bIsExec( ) || m_oPrc_gwave.bIsExec( ) )
{
DlgErrMsg( osErrHdr, wxT("The waveform viewer process is already running.") );
return;
}
// Check if a schematic or netlist file is currently open
ofn1 = m_oFileTasks.rosGetNetLstFile( );
if( ofn1.GetFullPath( ).IsEmpty( ) )
{
DlgErrMsg( osErrHdr, wxT("There's no schematic or netlist file loaded.") );
return;
}
// Create the appropriate name for the results file
os1 = ofn1.GetName( );
switch( m_poNbkSimEng->eGetSimEng( ) )
{
case eSIMR_GNUCAP :
if( m_oNbkTxtCtls.eGetPage( ) == NbkTxtCtls::ePAGE_NGSPICE )
os1 << wxT(".ngspice");
else os1 << wxT(".gnucap");
break;
case eSIMR_NGSPICE :
if( m_oNbkTxtCtls.eGetPage( ) == NbkTxtCtls::ePAGE_GNUCAP )
os1 << wxT(".gnucap");
else os1 << wxT(".ngspice");
break;
default :
return;
}
ofn1.SetName( os1 );
ofn1.SetExt( m_poNbkSimEng->rosGetPage( ) );
// Set the results file in the waveform viewer process
if( ! ofn1.FileExists( ) )
{
os1.Empty( );
os1 << wxT("The simulation results file :\n\n") << ofn1.GetFullPath( )
<< wxT("\n\nhasn't yet been generated.");
DlgErrMsg( osErrHdr, os1 );
return;
}
m_oPrc_gaw .bSetResultsFile( ofn1.GetFullPath( ) );
m_oPrc_gwave.bSetResultsFile( ofn1.GetFullPath( ) );
// Execute the waveform viewer process
if( g_oConfig.eGetDataViewer( ) == eVIEW_GAW )
{ if( ! m_oPrc_gaw .bExec( ) ) DlgErrMsg( osErrHdr, m_oPrc_gaw .rosGetErrMsg( ) ); }
else { if( ! m_oPrc_gwave.bExec( ) ) DlgErrMsg( osErrHdr, m_oPrc_gwave.rosGetErrMsg( ) ); }
}
//**************************************************************************************************
// Select which simulator to use.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnSelSimEng( wxCommandEvent & roEvtCmd )
{
int iw, ih;
// Temporarily store the current main frame size
GetClientSize( &iw, &ih );
// Change cursor to the wait symbol and hide the GUI while re-constructing it
::wxBeginBusyCursor( );
Show( false );
// Create and display a progress dialog
wxProgressDialog oDlgProgress( wxT(" GNU Spice GUI"),
wxT("Changing simulation engines ..."), 100, this,
wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_SMOOTH );
oDlgProgress.CenterOnParent( );
oDlgProgress.Update( 5 ); ::wxMilliSleep( 250 );
// Record the simulation engine change in the configuration file
if( GetMenuBar( )->IsChecked( ID_MNU_NGSPICE ) ) g_oConfig.bSetSimEng( eSIMR_NGSPICE );
else g_oConfig.bSetSimEng( eSIMR_GNUCAP );
g_oConfig.bFlush( ); // Write changes to the configuration file
// Update the progress dialog
oDlgProgress.Update( 20 );
// Change the simulator
InitSimEng( );
// Update the progress dialog
oDlgProgress.Update( 50 ); ::wxMilliSleep( 150 );
// Set the simulator process log file name
InitLogFiles( );
// Update the progress dialog
oDlgProgress.Update( 60 ); ::wxMilliSleep( 150 );
// Update the GUI components
DoLayout( );
// Update the progress dialog
oDlgProgress.Update( 70 ); ::wxMilliSleep( 150 );
// Transfer info. from one simulation object to the other
if( ! m_oNetLst.bIsEmpty( ) )
{
if( GetMenuBar( )->IsChecked( ID_MNU_GNUCAP ) ) m_oSimnGCap = m_oSimnNgSp;
else m_oSimnNgSp = m_oSimnGCap;
}
// Update the progress dialog
oDlgProgress.Update( 80 ); ::wxMilliSleep( 150 );
// Load the analysis notebook with the simulation values
m_poNbkSimEng->bLoad( *m_poSimn );
// Update the progress dialog
oDlgProgress.Update( 90 ); ::wxMilliSleep( 150 );
// Restore the frame's original size
SetClientSize( iw, ih );
// Update the progress dialog
oDlgProgress.Update( 99 ); ::wxMilliSleep( 150 );
oDlgProgress.Update( 100 ); // Kill the progress dialog
// Show the GUI again and change the cursor to the default
Show( true );
::wxEndBusyCursor( );
}
//**************************************************************************************************
// Show the application preferences dialog.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnPrefs( wxCommandEvent & roEvtCmd )
{
uint ui1;
DlgPrefs oDlgPrefs( this );
oDlgPrefs.CenterOnParent( );
oDlgPrefs.ShowModal( );
if( oDlgPrefs.GetReturnCode( ) == wxID_OK )
{
// Set the schematic capture / editor program binary
// m_oPrc_gschem.bSetBinFile( g_oConfig.rosGetSchemEdit( ) );
// Set the waveform viewer
SetStatusText( wxString( wxT(" Viewer : ") ) + g_oConfig.rosGetDataViewer( ), ePANE_VIEWER );
// Set the precision of the results values
CnvtType::bSetFltRes( g_oConfig.uiGetPrecision( ) );
// Set the gnetlist Guile procedure to use for the backend processing
m_oFileTasks.bSetGuileProc( g_oConfig.rosGetGuileProc( ) );
// Set the text control maximum lines
m_oNbkTxtCtls.bSetLinesMax( g_oConfig.uiGetNbkMaxLns( ) );
// Set the spin control update rate
PnlTxtSpn::bSetSpnPeriod( g_oConfig.uiGetSpnPeriod( ) );
// Set the state of tooltips
wxToolTip::Enable( g_oConfig.bGetToolTips( ) );
wxToolTip::SetDelay( g_oConfig.uiGetToolTipDly( ) );
// Set the main frame layout to be used
ui1 = g_oConfig.uiGetFrmLayout( );
if( m_uiFrmLayout != ui1 )
{
m_uiFrmLayout = ui1;
DoLayout( );
InitPosnSize( );
}
}
}
//**************************************************************************************************
// Display the gSpiceUI user manual.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnManualUser( wxCommandEvent & roEvtCmd )
{
m_oHelpTasks.ManualUser( );
}
//**************************************************************************************************
// Display about message dialog.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnAbout( wxCommandEvent & roEvtCmd )
{
m_oHelpTasks.About( );
}
//**************************************************************************************************
// Change the cursor when a simulation is running and the mouse is over the stop button.
//
// Argument List :
// roEvtCmd - The event to be processed
void FrmMain::OnToolEnter( wxCommandEvent & roEvtCmd )
{
if( roEvtCmd.GetSelection( ) == ID_TBR_STOP )
{
if( m_poPrcSimEng->bIsExec( ) && ::wxIsBusy( ) )
{
::wxEndBusyCursor( ); // Change the cursor to the default
wxTheApp->Yield( true ); // Allow the display to update
}
}
else
{
if( m_poPrcSimEng->bIsExec( ) && !::wxIsBusy( ) )
{
::wxBeginBusyCursor( ); // Change the cursor to the hour glass
wxTheApp->Yield( true ); // Allow the display to update
}
}
}
//**************************************************************************************************
// Event handler for system close.
//
// Argument List :
// roEvtClose - The event to be processed
void FrmMain::OnSysExit( wxCloseEvent & roEvtClose )
{
int iPosnX, iPosnY, iSizeW, iSizeH;
bClear( ); // Kill any processes currently running
m_oFileTasks.bExit( ); // Delete temporary files
Hide( ); // Hide the main frame while exiting
// Save the frame size and position
GetPosition( &iPosnX, &iPosnY );
GetClientSize( &iSizeW, &iSizeH );
g_oConfig.bSetMainPosnX( iPosnX );
g_oConfig.bSetMainPosnY( iPosnY );
g_oConfig.bSetMainSizeW( iSizeW );
g_oConfig.bSetMainSizeH( iSizeH );
// Record the simulation engine currently selected
g_oConfig.bSetSimEng( m_poPrcSimEng->eGetSimEng( ) );
// Record the analysis type last used
g_oConfig.bSetAnalysis( m_poNbkSimEng->eGetPage( ) );
g_oConfig.bFlush( ); // Write changes to the configuration file
m_bIsOpen = false; // Indicate that the main frame has been closed
Destroy( ); // Destroys the window safely (used instead of the delete operator)
}
//**************************************************************************************************
//Below Added by SG 05_17 for gSpiceUI vSACAMOS
void FrmMain::OngUpSym( wxCommandEvent & roEvtCmd )
{
wxString defaultPath = wxT("/");
wxDirDialog dialog(this, wxT("Directory picker"), defaultPath, wxDD_NEW_DIR_BUTTON);
if (dialog.ShowModal() == wxID_OK)
{
wxString path = dialog.GetPath();
wxDir symbolFolder(path);
if ( !symbolFolder.IsOpened() )
{
// deal with the error here - wxDir would already log an error message
// explaining the exact reason of the failure
return;
}
wxString filename;
bool cont = symbolFolder.GetFirst(&filename, wxEmptyString, wxDIR_FILES );
while ( cont )
{
wxString source = path;
source = source + "\\" + filename;
// Copy to \geda\local - assumes gEDA is installed to root of C: drive
// Windows permissions prevent writing to program file directories
wxString dest = "C:\\gEDA\\gEDA\\share\\gEDA\\sym\\local\\" ;
dest = dest + filename;
if ( wxCopyFile(source , dest))
{
wxMessageBox("Import Succesful", source);
}
else
{
///wxMessageBox( wxT("Failed"));
}
cont = symbolFolder.GetNext(&filename);
}
}
}
void FrmMain::Ongschem ( wxCommandEvent & roEvtCmd )
{
wxExecute(wxT("gschem"), wxEXEC_SYNC);
}
void FrmMain::Ongnetlist( wxCommandEvent & roEvtCmd )
{
wxString outputFile, filePath, gnetlistCL;
wxArrayString output, errors;
wxString myString1, myString2;
// Open file browser and filter on .sch
wxFileDialog* OpenDialog = new wxFileDialog( this, _("Choose a file to open"), wxEmptyString, wxEmptyString, _("Schematic Files (*.sch)|*.sch"), wxFD_OPEN, wxDefaultPosition);
if (OpenDialog->ShowModal() == wxID_OK)
{
filePath = OpenDialog->GetPath();
inputFile = OpenDialog->GetFilename();
filePath.Replace("\\","/",true);
// Truncate at file extension
outputFile = filePath.BeforeLast('.');
// Construct name of file holding results
resultsFile = outputFile + ".ngspice.ac";
outputFile += ".net";
gnetlistCL = "gnetlist -g spice-sdb -o " ;
gnetlistCL += outputFile ;
gnetlistCL += " " ;
gnetlistCL += filePath ;
wxExecute(gnetlistCL, output, errors, wxEXEC_SYNC);
wxString myString;
for(size_t i = 0; i < output.size(); i++) myString += " " + output[i];
wxMessageBox(myString,"gnetlist report");
}
OpenDialog->Destroy();
}
void FrmMain::OnSResults( wxCommandEvent & roEvtCmd )
{
#ifdef DEBUG
wxMessageBox(resultsFile,_("File to plot"));
#endif
wxFileInputStream input(resultsFile);
wxTextInputStream text(input, wxT("\x09"), wxConvUTF8 );
wxString plotHeader=text.ReadLine();
//wxString t_plotHeader = plotHeader;
// Reduce multiple white spaces to single space
while ( plotHeader.Replace(" "," "));
// Replace single SPACE with UNDERSCORE and count occurences, add one = number of columns
int Cols = plotHeader.Replace(" ","_") + 1;
wxString tmpCols;
tmpCols << Cols;
#ifdef DEBUG
wxMessageBox(tmpCols,_("Number of columns"));
#endif
// Revert back
while ( plotHeader.Replace("_"," "))
; // NULL
#ifdef DEBUG
wxMessageBox(plotHeader,_("Plot Header"));
#endif
std::ofstream plotFile;
inputFile = inputFile.BeforeLast('.');
wxString gnuplotFile = inputFile + ".plt";
plotFile.open (gnuplotFile);
#ifdef DEBUG
wxMessageBox(gnuplotFile,_("Plot Header"));
#endif
plotFile << "set title '" << inputFile << "'" << "\t# Plot Title\n";
plotFile << "set xlabel 'frequency (Hz)' \n";
plotFile << "plot ";
for (int i = 1; i