//**************************************************************************************************
//                                      DlgNgSpiceCfgOPT.cpp                                       *
//                                     ----------------------                                      *
// Started     : 2006-03-03                                                                        *
// Last Update : 2018-10-04                                                                        *
// Copyright   : (C) 2006-2018 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.                    *
//                                                                                                 *
//**************************************************************************************************

#include "DlgNgSpiceCfgOPT.hpp"

//**************************************************************************************************
// Implement an event table.

wxBEGIN_EVENT_TABLE( DlgNgSpiceCfgOPT, wxDialog )

  EVT_BUTTON( DlgNgSpiceCfgOPT::ID_BTN_OK      , DlgNgSpiceCfgOPT::OnBtnOk       )
  EVT_BUTTON( DlgNgSpiceCfgOPT::ID_BTN_DEFAULTS, DlgNgSpiceCfgOPT::OnBtnDefaults )
  EVT_BUTTON( DlgNgSpiceCfgOPT::ID_BTN_CANCEL  , DlgNgSpiceCfgOPT::OnBtnCancel   )

wxEND_EVENT_TABLE( )

//**************************************************************************************************
// Constructor.
//
// Argument List :
//   poWin - A pointer to the dialog parent window

DlgNgSpiceCfgOPT::DlgNgSpiceCfgOPT( wxWindow * poWin ) :
                                    wxDialog( poWin, -1, wxT(""), wxDefaultPosition, wxDefaultSize,
                                              wxDEFAULT_DIALOG_STYLE, wxDialogNameStr )
{
  SetTitle( wxT(" NG-Spice OPTIONS Line Setup") );
  Initialize( );
  bClear( );
}

//**************************************************************************************************
// Destructor.

DlgNgSpiceCfgOPT::~DlgNgSpiceCfgOPT( )
{
}

//**************************************************************************************************
// Initialize object attributes.

void  DlgNgSpiceCfgOPT::Initialize( void )
{
  // Call all the initialization functions
  Create( );
  ToolTips( );

  // Layout the of the display objects
  DoLayout( );
}

//**************************************************************************************************
// Create the display objects.

void  DlgNgSpiceCfgOPT::Create( void )
{
  wxPanel * poPnlLHS, * poPnlMID, * poPnlRHS, * poPnlRHS1, * poPnlBtns;
  wxSize    oSizeCbx;
  int       iWdName=85, iWdValue=95, iWdUnits=80;

  // Create the necessary panel objects
  poPnlLHS  = new wxPanel( this     );
  poPnlMID  = new wxPanel( this     );
  poPnlRHS  = new wxPanel( this     );
  poPnlRHS1 = new wxPanel( poPnlRHS );
  poPnlBtns = new wxPanel( poPnlRHS );

  // Create the PnlValue controls
  m_oPnlABSTOL  .bCreate( poPnlLHS , ID_PNL_ABSTOL  , iWdName, iWdValue, iWdUnits );
  m_oPnlCHGTOL  .bCreate( poPnlLHS , ID_PNL_CHGTOL  , iWdName, iWdValue, iWdUnits );
  m_oPnlPIVTOL  .bCreate( poPnlLHS , ID_PNL_PIVTOL  , iWdName, iWdValue, iWdUnits );
  m_oPnlRELTOL  .bCreate( poPnlLHS , ID_PNL_RELTOL  , iWdName, iWdValue, iWdUnits );
  m_oPnlTRTOL   .bCreate( poPnlLHS , ID_PNL_TRTOL   , iWdName, iWdValue, iWdUnits );
  m_oPnlVNTOL   .bCreate( poPnlLHS , ID_PNL_VNTOL   , iWdName, iWdValue, iWdUnits );
  m_oPnlPIVREL  .bCreate( poPnlLHS , ID_PNL_PIVREL  , iWdName, iWdValue, iWdUnits );
  m_oPnlDEFL    .bCreate( poPnlLHS , ID_PNL_DEFL    , iWdName, iWdValue, iWdUnits );
  m_oPnlDEFW    .bCreate( poPnlLHS , ID_PNL_DEFW    , iWdName, iWdValue, iWdUnits );
  m_oPnlDEFAD   .bCreate( poPnlLHS , ID_PNL_DEFAD   , iWdName, iWdValue, iWdUnits );
  m_oPnlDEFAS   .bCreate( poPnlLHS , ID_PNL_DEFAS   , iWdName, iWdValue, iWdUnits );
  m_oPnlTEMP    .bCreate( poPnlLHS , ID_PNL_TEMP    , iWdName, iWdValue, iWdUnits );
  m_oPnlTNOM    .bCreate( poPnlLHS , ID_PNL_TNOM    , iWdName, iWdValue, iWdUnits );
  m_oPnlCONVABSS.bCreate( poPnlLHS , ID_PNL_CONVABSS, iWdName, iWdValue, iWdUnits );
  m_oPnlCONVSTEP.bCreate( poPnlMID , ID_PNL_CONVSTEP, iWdName, iWdValue, iWdUnits );
  m_oPnlGMIN    .bCreate( poPnlMID , ID_PNL_GMIN    , iWdName, iWdValue, iWdUnits );
  m_oPnlRSERIES .bCreate( poPnlMID , ID_PNL_RSERIES , iWdName, iWdValue, iWdUnits );
  m_oPnlRSHUNT  .bCreate( poPnlMID , ID_PNL_RSHUNT  , iWdName, iWdValue, iWdUnits );
  m_oPnlRAMPTIME.bCreate( poPnlMID , ID_PNL_RAMPTIME, iWdName, iWdValue, iWdUnits );
  m_oPnlITL1    .bCreate( poPnlMID , ID_PNL_ITL1    , iWdName, iWdValue, iWdUnits );
  m_oPnlITL2    .bCreate( poPnlMID , ID_PNL_ITL2    , iWdName, iWdValue, iWdUnits );
  m_oPnlITL3    .bCreate( poPnlMID , ID_PNL_ITL3    , iWdName, iWdValue, iWdUnits );
  m_oPnlITL4    .bCreate( poPnlMID , ID_PNL_ITL4    , iWdName, iWdValue, iWdUnits );
  m_oPnlITL5    .bCreate( poPnlMID , ID_PNL_ITL5    , iWdName, iWdValue, iWdUnits );
  m_oPnlITL6    .bCreate( poPnlMID , ID_PNL_ITL6    , iWdName, iWdValue, iWdUnits );
  m_oPnlSRCSTEPS.bCreate( poPnlMID , ID_PNL_SRCSTEPS, iWdName, iWdValue, iWdUnits );
  m_oPnlGMINSTEP.bCreate( poPnlMID , ID_PNL_GMINSTEP, iWdName, iWdValue, iWdUnits );
  m_oPnlMAXEVIT .bCreate( poPnlMID , ID_PNL_MAXEVIT , iWdName, iWdValue, iWdUnits );
  m_oPnlMAXOPALT.bCreate( poPnlRHS1, ID_PNL_MAXOPALT, iWdName, iWdValue, iWdUnits );
  m_oPnlMAXORD  .bCreate( poPnlRHS1, ID_PNL_MAXORD  , iWdName, iWdValue, iWdUnits );
  m_oPnlMAXWARNS.bCreate( poPnlRHS1, ID_PNL_MAXWARNS, iWdName, iWdValue, iWdUnits );

  m_oPnlABSTOL  .bSetName( wxT("ABSTOL")   );
  m_oPnlCHGTOL  .bSetName( wxT("CHGTOL")   );
  m_oPnlCONVABSS.bSetName( wxT("CONVABSS") );
  m_oPnlCONVSTEP.bSetName( wxT("CONVSTEP") );
  m_oPnlDEFL    .bSetName( wxT("DEFL")     );
  m_oPnlDEFW    .bSetName( wxT("DEFW")     );
  m_oPnlDEFAD   .bSetName( wxT("DEFAD")    );
  m_oPnlDEFAS   .bSetName( wxT("DEFAS")    );
  m_oPnlGMIN    .bSetName( wxT("GMIN")     );
  m_oPnlGMINSTEP.bSetName( wxT("GMINSTEP") );
  m_oPnlITL1    .bSetName( wxT("ITL1")     );
  m_oPnlITL2    .bSetName( wxT("ITL2")     );
  m_oPnlITL3    .bSetName( wxT("ITL3")     );
  m_oPnlITL4    .bSetName( wxT("ITL4")     );
  m_oPnlITL5    .bSetName( wxT("ITL5")     );
  m_oPnlITL6    .bSetName( wxT("ITL6")     );
  m_oPnlMAXEVIT .bSetName( wxT("MAXEVIT")  );
  m_oPnlMAXOPALT.bSetName( wxT("MAXOPALT") );
  m_oPnlMAXORD  .bSetName( wxT("MAXORD")   );
  m_oPnlMAXWARNS.bSetName( wxT("MAXWARNS") );
  m_oPnlPIVREL  .bSetName( wxT("PIVREL")   );
  m_oPnlPIVTOL  .bSetName( wxT("PIVTOL")   );
  m_oPnlRAMPTIME.bSetName( wxT("RAMPTIME") );
  m_oPnlRELTOL  .bSetName( wxT("RELTOL")   );
  m_oPnlRSERIES .bSetName( wxT("RSERIES")  );
  m_oPnlRSHUNT  .bSetName( wxT("RSHUNT")   );
  m_oPnlSRCSTEPS.bSetName( wxT("SRCSTEPS") );
  m_oPnlTEMP    .bSetName( wxT("TEMP")     );
  m_oPnlTNOM    .bSetName( wxT("TNOM")     );
  m_oPnlTRTOL   .bSetName( wxT("TRTOL")    );
  m_oPnlVNTOL   .bSetName( wxT("VNTOL")    );

  m_oPnlABSTOL  .bSetUnitsType( eUNITS_CURR );
  m_oPnlCHGTOL  .bSetUnitsType( eUNITS_CHRG );
  m_oPnlCONVABSS.bSetUnitsType( eUNITS_EXP  );
  m_oPnlCONVSTEP.bSetUnitsType( eUNITS_EXP  );
  m_oPnlGMIN    .bSetUnitsType( eUNITS_COND );
  m_oPnlPIVTOL  .bSetUnitsType( eUNITS_EXP  );
  m_oPnlRAMPTIME.bSetUnitsType( eUNITS_TIME );
  m_oPnlRSERIES .bSetUnitsType( eUNITS_RES  );
  m_oPnlRSHUNT  .bSetUnitsType( eUNITS_RES  );
  m_oPnlTEMP    .bSetUnitsType( eUNITS_TMPC );
  m_oPnlTNOM    .bSetUnitsType( eUNITS_TMPC );
  m_oPnlVNTOL   .bSetUnitsType( eUNITS_VOLT );

  m_oPnlDEFL    .bSetValueType( eVALUE_FLT );
  m_oPnlDEFW    .bSetValueType( eVALUE_FLT );
  m_oPnlDEFAD   .bSetValueType( eVALUE_SCI );
  m_oPnlDEFAS   .bSetValueType( eVALUE_SCI );
  m_oPnlGMIN    .bSetValueType( eVALUE_FLT );
  m_oPnlGMINSTEP.bSetValueType( eVALUE_INT );
  m_oPnlITL1    .bSetValueType( eVALUE_INT );
  m_oPnlITL2    .bSetValueType( eVALUE_INT );
  m_oPnlITL3    .bSetValueType( eVALUE_INT );
  m_oPnlITL4    .bSetValueType( eVALUE_INT );
  m_oPnlITL5    .bSetValueType( eVALUE_INT );
  m_oPnlITL6    .bSetValueType( eVALUE_INT );
  m_oPnlMAXEVIT .bSetValueType( eVALUE_INT );
  m_oPnlMAXOPALT.bSetValueType( eVALUE_INT );
  m_oPnlMAXORD  .bSetValueType( eVALUE_INT );
  m_oPnlMAXWARNS.bSetValueType( eVALUE_INT );
  m_oPnlPIVREL  .bSetValueType( eVALUE_FLT );
  m_oPnlRELTOL  .bSetValueType( eVALUE_FLT );
  m_oPnlSRCSTEPS.bSetValueType( eVALUE_INT );
  m_oPnlTRTOL   .bSetValueType( eVALUE_FLT );

  m_oPnlDEFL    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlDEFW    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlDEFAD   .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlDEFAS   .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlGMINSTEP.bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlITL1    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlITL2    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlITL3    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlITL4    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlITL5    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlITL6    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlMAXEVIT .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlMAXOPALT.bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlMAXORD  .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlMAXWARNS.bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlPIVREL  .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlRELTOL  .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlSRCSTEPS.bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlTEMP    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlTNOM    .bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlTRTOL   .bShowUnits( PnlValue::eSHOW_LBL );

  m_oPnlDEFL    .bSetUnits( wxT("uMetre") );
  m_oPnlDEFW    .bSetUnits( wxT("uMetre") );
  m_oPnlDEFAD   .bSetUnits( wxT("Metre²") );
  m_oPnlDEFAS   .bSetUnits( wxT("Metre²") );
  m_oPnlPIVREL  .bSetUnits( wxT("%")      );
  m_oPnlRELTOL  .bSetUnits( wxT("%")      );

  m_oPnlDEFAD   .bSetSpnRange( 1.0E-12, 1.0E-06 );
  m_oPnlDEFAS   .bSetSpnRange( 1.0E-12, 1.0E-06 );
  m_oPnlDEFL    .bSetSpnRange( 0.0    , 10000.0 ); m_oPnlDEFL  .bSetSpnIncSz( 1.0 , 1000.0 );
  m_oPnlDEFW    .bSetSpnRange( 0.0    , 10000.0 ); m_oPnlDEFW  .bSetSpnIncSz( 1.0 , 1000.0 );
  m_oPnlTRTOL   .bSetSpnRange( 0.01   ,   100.0 ); m_oPnlTRTOL .bSetSpnIncSz( 0.01,   10.0 );
  m_oPnlPIVREL  .bSetSpnRange( 0.01   ,   100.0 ); m_oPnlPIVREL.bSetSpnIncSz( 0.01,   10.0 );
  m_oPnlRELTOL  .bSetSpnRange( 0.01   ,   100.0 ); m_oPnlRELTOL.bSetSpnIncSz( 0.01,   10.0 );
  m_oPnlITL1    .bSetSpnRange( 0      ,  1000   ); m_oPnlITL1  .bSetSpnIncSz( 1   ,  100   );
  m_oPnlITL2    .bSetSpnRange( 0      ,  1000   ); m_oPnlITL2  .bSetSpnIncSz( 1   ,  100   );
  m_oPnlITL3    .bSetSpnRange( 0      ,  1000   ); m_oPnlITL3  .bSetSpnIncSz( 1   ,  100   );
  m_oPnlITL4    .bSetSpnRange( 0      ,  1000   ); m_oPnlITL4  .bSetSpnIncSz( 1   ,  100   );
  m_oPnlITL5    .bSetSpnRange( 0      , 10000   ); m_oPnlITL5  .bSetSpnIncSz( 1   , 1000   );
  m_oPnlITL6    .bSetSpnRange( 0      ,  1000   ); m_oPnlITL6  .bSetSpnIncSz( 1   ,  100   );

  // Create the choice box control
  m_oChoMETHOD.bCreate( poPnlRHS1, ID_CHO_METHOD, iWdName, iWdValue );
  m_oChoMETHOD.m_oLblName.SetLabel( wxT("METHOD") );
  m_oChoMETHOD.m_oChoice.Append( wxT("Trap") );
  m_oChoMETHOD.m_oChoice.Append( wxT("Gear") );

  // Set height of check box controls according to size of PnlValue object
  oSizeCbx.SetWidth ( 250 );
  oSizeCbx.SetHeight( GUI_CTRL_HT+3 );

  // Create the check box control
  m_oCbxBADMOS3 .Create( poPnlRHS1, ID_CBX_BADMOS3 , wxT("BADMOS3  \t    "), wxDefaultPosition,
                         oSizeCbx, wxALIGN_RIGHT );
  m_oCbxINTERP  .Create( poPnlRHS1, ID_CBX_INTERP  , wxT("INTERP \t\t    "), wxDefaultPosition,
                         oSizeCbx, wxALIGN_RIGHT );
  m_oCbxNOOPAC  .Create( poPnlRHS1, ID_CBX_NOOPAC  , wxT("NOOPAC   \t    "), wxDefaultPosition,
                         oSizeCbx, wxALIGN_RIGHT );
  m_oCbxNOOPALT .Create( poPnlRHS1, ID_CBX_NOOPALT , wxT("NOOPALT  \t    "), wxDefaultPosition,
                         oSizeCbx, wxALIGN_RIGHT );
  m_oCbxOPTS    .Create( poPnlRHS1, ID_CBX_OPTS    , wxT("OPTS   \t\t    "), wxDefaultPosition,
                         oSizeCbx, wxALIGN_RIGHT );
  m_oCbxTRYTOCOM.Create( poPnlRHS1, ID_CBX_TRYTOCOM, wxT("TRYTOCOM \t    "), wxDefaultPosition,
                         oSizeCbx, wxALIGN_RIGHT );
  m_oCbxWARN    .Create( poPnlRHS1, ID_CBX_WARN    , wxT("WARN   \t\t    "), wxDefaultPosition,
                         oSizeCbx, wxALIGN_RIGHT );

  // Create the buttons
  m_oBtnOk      .Create( poPnlBtns, ID_BTN_OK,       wxT("OK")       );
  m_oBtnDefaults.Create( poPnlBtns, ID_BTN_DEFAULTS, wxT("Defaults") );
  m_oBtnCancel  .Create( poPnlBtns, ID_BTN_CANCEL,   wxT("Cancel")   );
}

//**************************************************************************************************
// Initialize the tool tips.

void  DlgNgSpiceCfgOPT::ToolTips( void )
{
  // Define tool tips for each control
  m_oPnlABSTOL  .SetToolTip( wxT(" Absolute current error tolerance ") );
  m_oPnlCHGTOL  .SetToolTip( wxT(" Charge tolerance (in Coulomb) ") );
  m_oPnlCONVABSS.SetToolTip( wxT(" Absolute step limit applied to code models ") );
  m_oPnlCONVSTEP.SetToolTip( wxT(" Relative step limit applied to code models ") );
  m_oPnlDEFL    .SetToolTip( wxT(" MOSFET default channel length ") );
  m_oPnlDEFW    .SetToolTip( wxT(" MOSFET default channel width ") );
  m_oPnlDEFAD   .SetToolTip( wxT(" MOSFET default drain diffusion area ") );
  m_oPnlDEFAS   .SetToolTip( wxT(" MOSFET default source diffusion area ") );
  m_oPnlGMIN    .SetToolTip( wxT(" Minimum allowable conductance (in Siemen) ") );
  m_oPnlGMINSTEP.SetToolTip( wxT(" Number of GMIN steps to be attempted ") );
  m_oPnlITL1    .SetToolTip( wxT(" DC iteration limit ") );
  m_oPnlITL2    .SetToolTip( wxT(" DC transfer curve iteration limit ") );
  m_oPnlITL3    .SetToolTip( wxT(" Transient analysis lower iteration limit ") );
  m_oPnlITL4    .SetToolTip( wxT(" Transient analysis timepoint iteration limit ") );
  m_oPnlITL5    .SetToolTip( wxT(" Transient analysis total iteration limit ") );
  m_oPnlITL6    .SetToolTip( wxT(" Source stepping iteration limit (synonym for SRCSTEPS) ") );
  m_oPnlMAXEVIT .SetToolTip( wxT(" Maximum event iterations at an analysis point ") );
  m_oPnlMAXOPALT.SetToolTip( wxT(" Maximum analog/event alternations in OP analysis ") );
  m_oPnlMAXORD  .SetToolTip( wxT(" Maximum order for the numerical integration method ") );
  m_oPnlMAXWARNS.SetToolTip( wxT(" Maximum number of SOA (Safe Operating Area) voltage warning messages ") );
  m_oPnlPIVREL  .SetToolTip( wxT(" Relative ratio between largest column entry and an acceptable pivot value ") );
  m_oPnlPIVTOL  .SetToolTip( wxT(" Absolute minimum value for matrix entry as pivot ") );
  m_oPnlRAMPTIME.SetToolTip( wxT(" Transient analysis supply ramping time ") );
  m_oPnlRELTOL  .SetToolTip( wxT(" Relative error tolerance ") );
  m_oPnlRSERIES .SetToolTip( wxT(" Adds a resistor to each inductor in the circuit ") );
  m_oPnlRSHUNT  .SetToolTip( wxT(" Adds a resistor from each analogue node to ground ") );
  m_oPnlSRCSTEPS.SetToolTip( wxT(" Source stepping iteration limit ") );
  m_oPnlTEMP    .SetToolTip( wxT(" Ambient / operating temperature of the circuit when simulated ") );
  m_oPnlTNOM    .SetToolTip( wxT(" Nominal temperature at which device parameters were measured ") );
  m_oPnlTRTOL   .SetToolTip( wxT(" Transient error tolerance ") );
  m_oPnlVNTOL   .SetToolTip( wxT(" Absolute voltage error tolerance ") );

  m_oCbxBADMOS3 .SetToolTip( wxT(" Use MOS3 model with \"kappa\" discontinuity ") );
  m_oCbxINTERP  .SetToolTip( wxT(" Interpolate output data onto fixed time steps ") );
  m_oCbxNOOPAC  .SetToolTip( wxT(" Don't do an OP analysis before the AC analysis ") );
  m_oCbxNOOPALT .SetToolTip( wxT(" Analog/event alternation in OP analysis ") );
  m_oCbxOPTS    .SetToolTip( wxT(" Enable printing of option values ") );
  m_oCbxTRYTOCOM.SetToolTip( wxT(" Try to condense LTRA model's past history ") );
  m_oCbxWARN    .SetToolTip( wxT(" Enable SOA (Safe Operating Area) voltage warning messages ") );

  m_oChoMETHOD.GetParent( )->SetToolTip( wxT(" Numerical integration method ") );
}

//**************************************************************************************************
// Layout the dialog display objects.

void  DlgNgSpiceCfgOPT::DoLayout( void )
{
  wxBoxSizer  * poSzrDlg;
  wxPanel     * poPnlLHS, * poPnlMID, * poPnlRHS, * poPnlRHS1, * poPnlBtns;
  wxBoxSizer  * poSzrLHS, * poSzrMID, * poSzrRHS, * poSzrRHS1, * poSzrBtns;
  wxSizerFlags  oFlags;

  // Get pointers to the various panels
  poPnlLHS  = (wxPanel *) m_oPnlABSTOL  .GetParent( );
  poPnlMID  = (wxPanel *) m_oPnlRSERIES .GetParent( );
  poPnlRHS1 = (wxPanel *) m_oPnlMAXWARNS.GetParent( );
  poPnlBtns = (wxPanel *) m_oBtnOk      .GetParent( );
  poPnlRHS  = (wxPanel *) poPnlBtns    ->GetParent( );

  // Create sizers to associate with the panels
  poSzrDlg  = new wxBoxSizer      ( wxHORIZONTAL );
  poSzrLHS  = new wxStaticBoxSizer( wxVERTICAL, poPnlLHS  );
  poSzrMID  = new wxStaticBoxSizer( wxVERTICAL, poPnlMID  );
  poSzrRHS1 = new wxStaticBoxSizer( wxVERTICAL, poPnlRHS1 );
  poSzrBtns = new wxBoxSizer      ( wxHORIZONTAL );
  poSzrRHS  = new wxBoxSizer      ( wxVERTICAL );

  // Set the sizers to the panels
             SetSizer( poSzrDlg  );
  poPnlLHS ->SetSizer( poSzrLHS  );
  poPnlMID ->SetSizer( poSzrMID );
  poPnlRHS ->SetSizer( poSzrRHS  );
  poPnlRHS1->SetSizer( poSzrRHS1 );
  poPnlBtns->SetSizer( poSzrBtns );

  // Layout the left hand panel
  oFlags.Align( wxALIGN_LEFT );
  oFlags.Border( wxTOP | wxLEFT | wxRIGHT, 10 );
  poSzrLHS->Add(  &m_oPnlABSTOL  , oFlags );
  oFlags.Border( wxLEFT                  , 10 );
  poSzrLHS->Add(  &m_oPnlCHGTOL  , oFlags );
  poSzrLHS->Add(  &m_oPnlPIVTOL  , oFlags );
  poSzrLHS->Add(  &m_oPnlRELTOL  , oFlags );
  poSzrLHS->Add(  &m_oPnlTRTOL   , oFlags );
  poSzrLHS->Add(  &m_oPnlVNTOL   , oFlags );
  poSzrLHS->Add(  &m_oPnlPIVREL  , oFlags );
  poSzrLHS->Add(  &m_oPnlDEFL    , oFlags );
  poSzrLHS->Add(  &m_oPnlDEFW    , oFlags );
  poSzrLHS->Add(  &m_oPnlDEFAD   , oFlags );
  poSzrLHS->Add(  &m_oPnlDEFAS   , oFlags );
  poSzrLHS->Add(  &m_oPnlTEMP    , oFlags );
  poSzrLHS->Add(  &m_oPnlTNOM    , oFlags );
  oFlags.Border( wxLEFT | wxBOTTOM       , 10 );
  poSzrLHS->Add(  &m_oPnlCONVABSS, oFlags );

  // Layout the middle panel
  oFlags.Border( wxTOP | wxLEFT | wxRIGHT, 10 );
  poSzrMID->Add(  &m_oPnlCONVSTEP, oFlags );
  oFlags.Border( wxLEFT                  , 10 );
  poSzrMID->Add(  &m_oPnlGMIN    , oFlags );
  poSzrMID->Add(  &m_oPnlRSERIES , oFlags );
  poSzrMID->Add(  &m_oPnlRSHUNT  , oFlags );
  poSzrMID->Add(  &m_oPnlRAMPTIME, oFlags );
  poSzrMID->Add(  &m_oPnlITL1    , oFlags );
  poSzrMID->Add(  &m_oPnlITL2    , oFlags );
  poSzrMID->Add(  &m_oPnlITL3    , oFlags );
  poSzrMID->Add(  &m_oPnlITL4    , oFlags );
  poSzrMID->Add(  &m_oPnlITL5    , oFlags );
  poSzrMID->Add(  &m_oPnlITL6    , oFlags );
  poSzrMID->Add(  &m_oPnlSRCSTEPS, oFlags );
  poSzrMID->Add(  &m_oPnlGMINSTEP, oFlags );
  oFlags.Border( wxLEFT | wxBOTTOM       , 10 );
  poSzrMID->Add(  &m_oPnlMAXEVIT , oFlags );

  // Layout the right hand options panel
  oFlags.Border( wxTOP | wxLEFT | wxRIGHT, 10 );
  poSzrRHS1->Add( &m_oPnlMAXOPALT, oFlags );
  oFlags.Border( wxLEFT                  , 10 );
  poSzrRHS1->Add( &m_oPnlMAXORD  , oFlags );
  poSzrRHS1->Add( &m_oPnlMAXWARNS, oFlags );
  poSzrRHS1->Add( &m_oChoMETHOD  , oFlags );
  oFlags.Border( wxLEFT                  ,  7 );
  poSzrRHS1->Add( &m_oCbxBADMOS3 , oFlags );
  poSzrRHS1->Add( &m_oCbxINTERP  , oFlags );
  poSzrRHS1->Add( &m_oCbxNOOPAC  , oFlags );
  poSzrRHS1->Add( &m_oCbxNOOPALT , oFlags );
  poSzrRHS1->Add( &m_oCbxOPTS    , oFlags );
  poSzrRHS1->Add( &m_oCbxTRYTOCOM, oFlags );
  oFlags.Border( wxLEFT | wxBOTTOM       ,  7 );
  poSzrRHS1->Add( &m_oCbxWARN    , oFlags );

  // Layout the buttons panel
  oFlags.Align( wxALIGN_RIGHT  );
  oFlags.Border( wxTOP | wxBOTTOM        , 12 );
  poSzrBtns->Add( &m_oBtnOk      , oFlags );
  poSzrBtns->AddSpacer( 10 );
  oFlags.Align( wxALIGN_CENTER );
  poSzrBtns->Add( &m_oBtnDefaults, oFlags );
  poSzrBtns->AddSpacer( 10 );
  oFlags.Align( wxALIGN_LEFT   );
  poSzrBtns->Add( &m_oBtnCancel  , oFlags );

  // Layout the right hand panel
  oFlags.Align( wxALIGN_CENTER );
  oFlags.Border( wxALL                   ,  0 );
  poSzrRHS->Add( poPnlRHS1       , oFlags );
  oFlags.Border( wxTOP                   , 43 );
  poSzrRHS->Add( poPnlBtns, oFlags );

  // Layout the overall dialog
  oFlags.Border( wxALL                   , 15 );
  poSzrDlg->Add( poPnlLHS        , oFlags );
  oFlags.Border( wxTOP | wxBOTTOM        , 15 );
  poSzrDlg->Add( poPnlMID        , oFlags );
  oFlags.Border( wxALL                   , 15 );
  poSzrDlg->Add( poPnlRHS        , oFlags );

  // Set dialogues minimum size and initial size as calculated by the sizer
  poSzrLHS ->SetSizeHints( poPnlLHS  );
  poSzrMID ->SetSizeHints( poPnlMID  );
  poSzrRHS1->SetSizeHints( poPnlRHS1 );
  poSzrBtns->SetSizeHints( poPnlBtns );
  poSzrRHS ->SetSizeHints( poPnlRHS  );
  poSzrDlg ->SetSizeHints( this      );
}

//**************************************************************************************************
// Get a pointer to a value panel associated with a control ID number.
//
// Argument List :
//   iPnlID - The control ID number
//
// Return Values :
//   Success - A pointer to the value panel
//   Failure - NULL

PnlValue * DlgNgSpiceCfgOPT::poGetPanel( int iPnlID )
{
  switch( iPnlID )
  {
    case ID_PNL_ABSTOL   : return( &m_oPnlABSTOL   );
    case ID_PNL_CHGTOL   : return( &m_oPnlCHGTOL   );
    case ID_PNL_CONVABSS : return( &m_oPnlCONVABSS );
    case ID_PNL_CONVSTEP : return( &m_oPnlCONVSTEP );
    case ID_PNL_DEFL     : return( &m_oPnlDEFL     );
    case ID_PNL_DEFW     : return( &m_oPnlDEFW     );
    case ID_PNL_DEFAD    : return( &m_oPnlDEFAD    );
    case ID_PNL_DEFAS    : return( &m_oPnlDEFAS    );
    case ID_PNL_GMIN     : return( &m_oPnlGMIN     );
    case ID_PNL_GMINSTEP : return( &m_oPnlGMINSTEP );
    case ID_PNL_ITL1     : return( &m_oPnlITL1     );
    case ID_PNL_ITL2     : return( &m_oPnlITL2     );
    case ID_PNL_ITL3     : return( &m_oPnlITL3     );
    case ID_PNL_ITL4     : return( &m_oPnlITL4     );
    case ID_PNL_ITL5     : return( &m_oPnlITL5     );
    case ID_PNL_ITL6     : return( &m_oPnlITL6     );
    case ID_PNL_MAXEVIT  : return( &m_oPnlMAXEVIT  );
    case ID_PNL_MAXOPALT : return( &m_oPnlMAXOPALT );
    case ID_PNL_MAXORD   : return( &m_oPnlMAXORD   );
    case ID_PNL_MAXWARNS : return( &m_oPnlMAXWARNS );
    case ID_PNL_PIVREL   : return( &m_oPnlPIVREL   );
    case ID_PNL_PIVTOL   : return( &m_oPnlPIVTOL   );
    case ID_PNL_RAMPTIME : return( &m_oPnlRAMPTIME );
    case ID_PNL_RELTOL   : return( &m_oPnlRELTOL   );
    case ID_PNL_RSERIES  : return( &m_oPnlRSERIES  );
    case ID_PNL_RSHUNT   : return( &m_oPnlRSHUNT   );
    case ID_PNL_SRCSTEPS : return( &m_oPnlSRCSTEPS );
    case ID_PNL_TEMP     : return( &m_oPnlTEMP     );
    case ID_PNL_TNOM     : return( &m_oPnlTNOM     );
    case ID_PNL_TRTOL    : return( &m_oPnlTRTOL    );
    case ID_PNL_VNTOL    : return( &m_oPnlVNTOL    );

    default              : return( NULL );
  }
}

//**************************************************************************************************
// Set the values in the value panel controls.
//
// Argument List :
//   rosCmdOPT - A reference to an OPTION command object

void  DlgNgSpiceCfgOPT::SetValues( CmdNgSpiceOPT & roCmdOPT )
{
  wxString  os1;
  uint      ui1;

  SetEvtHandlerEnabled( false );

  m_oPnlABSTOL  .bSetValue( roCmdOPT.m_osABSTOL   );
  m_oPnlCHGTOL  .bSetValue( roCmdOPT.m_osCHGTOL   );
  m_oPnlCONVABSS.bSetValue( roCmdOPT.m_osCONVABSS );
  m_oPnlCONVSTEP.bSetValue( roCmdOPT.m_osCONVSTEP );
  m_oPnlDEFL    .bSetValue( roCmdOPT.m_osDEFL     );
  m_oPnlDEFW    .bSetValue( roCmdOPT.m_osDEFW     );
  m_oPnlDEFAD   .bSetValue( roCmdOPT.m_osDEFAD    );
  m_oPnlDEFAS   .bSetValue( roCmdOPT.m_osDEFAS    );
  m_oPnlGMIN    .bSetValue( roCmdOPT.m_osGMIN     );
  m_oPnlGMINSTEP.bSetValue( roCmdOPT.m_osGMINSTEP );
  m_oPnlITL1    .bSetValue( roCmdOPT.m_osITL1     );
  m_oPnlITL2    .bSetValue( roCmdOPT.m_osITL2     );
  m_oPnlITL3    .bSetValue( roCmdOPT.m_osITL3     );
  m_oPnlITL4    .bSetValue( roCmdOPT.m_osITL4     );
  m_oPnlITL5    .bSetValue( roCmdOPT.m_osITL5     );
  m_oPnlITL6    .bSetValue( roCmdOPT.m_osITL6     );
  m_oPnlMAXEVIT .bSetValue( roCmdOPT.m_osMAXEVIT  );
  m_oPnlMAXOPALT.bSetValue( roCmdOPT.m_osMAXOPALT );
  m_oPnlMAXORD  .bSetValue( roCmdOPT.m_osMAXORD   );
  m_oPnlMAXWARNS.bSetValue( roCmdOPT.m_osMAXWARNS );
  m_oPnlPIVREL  .bSetValue( roCmdOPT.m_osPIVREL   );
  m_oPnlPIVTOL  .bSetValue( roCmdOPT.m_osPIVTOL   );
  m_oPnlRAMPTIME.bSetValue( roCmdOPT.m_osRAMPTIME );
  m_oPnlRELTOL  .bSetValue( roCmdOPT.m_osRELTOL   );
  m_oPnlRSERIES .bSetValue( roCmdOPT.m_osRSERIES  );
  m_oPnlRSHUNT  .bSetValue( roCmdOPT.m_osRSHUNT   );
  m_oPnlSRCSTEPS.bSetValue( roCmdOPT.m_osSRCSTEPS );
  m_oPnlTEMP    .bSetValue( roCmdOPT.m_osTEMP     );
  m_oPnlTNOM    .bSetValue( roCmdOPT.m_osTNOM     );
  m_oPnlTRTOL   .bSetValue( roCmdOPT.m_osTRTOL    );
  m_oPnlVNTOL   .bSetValue( roCmdOPT.m_osVNTOL    );

  m_oCbxBADMOS3 .SetValue(  roCmdOPT.m_bBADMOS3   );
  m_oCbxINTERP  .SetValue(  roCmdOPT.m_bINTERP    );
  m_oCbxNOOPAC  .SetValue(  roCmdOPT.m_bNOOPAC    );
  m_oCbxNOOPALT .SetValue(  roCmdOPT.m_bNOOPALT   );
  m_oCbxOPTS    .SetValue(  roCmdOPT.m_bOPTS      );
  m_oCbxTRYTOCOM.SetValue(  roCmdOPT.m_bTRYTOCOM  );
  m_oCbxWARN    .SetValue(  roCmdOPT.m_bWARN      );

  for( ui1=0; ui1<m_oChoMETHOD.m_oChoice.GetCount( ); ui1++ )
  {
    os1 = m_oChoMETHOD.m_oChoice.GetString( ui1 );
    if( os1.IsSameAs( roCmdOPT.m_osMETHOD, false ) )
      { m_oChoMETHOD.m_oChoice.SetSelection( ui1 ); break; }
  }

  SetEvtHandlerEnabled( true );
}

//**************************************************************************************************
// Get the values from the value panel controls.
//
// Argument List :
//   rosCmdOPT - A reference to an OPTION command object

void  DlgNgSpiceCfgOPT::GetValues( CmdNgSpiceOPT & roCmdOPT )
{
  SetEvtHandlerEnabled( false );

  roCmdOPT.m_osABSTOL   = m_oPnlABSTOL  .rosGetValue( );
  roCmdOPT.m_osCHGTOL   = m_oPnlCHGTOL  .rosGetValue( );
  roCmdOPT.m_osCONVABSS = m_oPnlCONVABSS.rosGetValue( );
  roCmdOPT.m_osCONVSTEP = m_oPnlCONVSTEP.rosGetValue( );
  roCmdOPT.m_osDEFL     = m_oPnlDEFL    .rosGetValue( );
  roCmdOPT.m_osDEFW     = m_oPnlDEFW    .rosGetValue( );
  roCmdOPT.m_osDEFAD    = m_oPnlDEFAD   .rosGetValue( );
  roCmdOPT.m_osDEFAS    = m_oPnlDEFAS   .rosGetValue( );
  roCmdOPT.m_osGMIN     = m_oPnlGMIN    .rosGetValue( );
  roCmdOPT.m_osGMINSTEP = m_oPnlGMINSTEP.rosGetValue( );
  roCmdOPT.m_osITL1     = m_oPnlITL1    .rosGetValue( );
  roCmdOPT.m_osITL2     = m_oPnlITL2    .rosGetValue( );
  roCmdOPT.m_osITL3     = m_oPnlITL3    .rosGetValue( );
  roCmdOPT.m_osITL4     = m_oPnlITL4    .rosGetValue( );
  roCmdOPT.m_osITL5     = m_oPnlITL5    .rosGetValue( );
  roCmdOPT.m_osITL6     = m_oPnlITL6    .rosGetValue( );
  roCmdOPT.m_osMAXEVIT  = m_oPnlMAXEVIT .rosGetValue( );
  roCmdOPT.m_osMAXOPALT = m_oPnlMAXOPALT.rosGetValue( );
  roCmdOPT.m_osMAXORD   = m_oPnlMAXORD  .rosGetValue( );
  roCmdOPT.m_osMAXWARNS = m_oPnlMAXWARNS.rosGetValue( );
  roCmdOPT.m_osPIVREL   = m_oPnlPIVREL  .rosGetValue( );
  roCmdOPT.m_osPIVTOL   = m_oPnlPIVTOL  .rosGetValue( );
  roCmdOPT.m_osRAMPTIME = m_oPnlRAMPTIME.rosGetValue( );
  roCmdOPT.m_osRELTOL   = m_oPnlRELTOL  .rosGetValue( );
  roCmdOPT.m_osRSERIES  = m_oPnlRSERIES .rosGetValue( );
  roCmdOPT.m_osRSHUNT   = m_oPnlRSHUNT  .rosGetValue( );
  roCmdOPT.m_osSRCSTEPS = m_oPnlSRCSTEPS.rosGetValue( );
  roCmdOPT.m_osTEMP     = m_oPnlTEMP    .rosGetValue( );
  roCmdOPT.m_osTNOM     = m_oPnlTNOM    .rosGetValue( );
  roCmdOPT.m_osTRTOL    = m_oPnlTRTOL   .rosGetValue( );
  roCmdOPT.m_osVNTOL    = m_oPnlVNTOL   .rosGetValue( );

  roCmdOPT.m_bBADMOS3  = m_oCbxBADMOS3  .GetValue( );
  roCmdOPT.m_bINTERP   = m_oCbxINTERP   .GetValue( );
  roCmdOPT.m_bNOOPAC   = m_oCbxNOOPAC   .GetValue( );
  roCmdOPT.m_bNOOPALT  = m_oCbxNOOPALT  .GetValue( );
  roCmdOPT.m_bOPTS     = m_oCbxOPTS     .GetValue( );
  roCmdOPT.m_bTRYTOCOM = m_oCbxTRYTOCOM .GetValue( );
  roCmdOPT.m_bWARN     = m_oCbxWARN     .GetValue( );

  roCmdOPT.m_osMETHOD  = m_oChoMETHOD.m_oChoice.GetStringSelection( ).Upper( );

  if( g_oConfig.eGetPhaseUnits( ) == eUNITS_PHAD ) roCmdOPT.m_osUNITS = wxT("DEGREES");
  else                                             roCmdOPT.m_osUNITS = wxT("RADIANS");

  roCmdOPT.bFormat( );

  SetEvtHandlerEnabled( true );
}

//**************************************************************************************************
// Set the values in the value panel controls.
//
// Argument List :
//   roCmdOPT - A reference to an OPTION command object
//
// Return Values :
//   true  - Success
//   false - Failure

bool  DlgNgSpiceCfgOPT::bSetValues( CmdNgSpiceOPT & roCmdOPT )
{
  SetValues( roCmdOPT );
  m_oCmdOPT = roCmdOPT;

  return( true );
}

//**************************************************************************************************
// Get the values from the value panel controls.
//
// Argument List :
//   roCmdOPT - A reference to an OPTION command object
//
// Return Values :
//   true  - Success
//   false - Failure

bool  DlgNgSpiceCfgOPT::bGetValues( CmdNgSpiceOPT & roCmdOPT )
{
  GetValues( roCmdOPT );

  return( true );
}

//**************************************************************************************************
// Reset all dialog settings to defaults.
//
// Return Values :
//   true  - Success
//   false - Failure

bool  DlgNgSpiceCfgOPT::bClear( void )
{
  m_oCmdOPT.bSetDefaults( );

  SetValues( m_oCmdOPT );

  return( true );
}

//**************************************************************************************************
// Get a value panel control's value.
//
// Argument List :
//   iPnlID - Value panel control identifier
//
// Return Values :
//   Success - The panel value
//   Failure - An empty string

const wxString & DlgNgSpiceCfgOPT::rosGetValue( int iPnlID )
{
  static  wxString   osEmpty;
          PnlValue * poPnlValue;

  poPnlValue = poGetPanel( iPnlID );
  if( poPnlValue == NULL ) return( osEmpty );

  return( poPnlValue->rosGetValue( ) );
}

//**************************************************************************************************
// Set a value panel control's value.
//
// Argument List :
//   iPnlID   - Value panel control identifier
//   rosValue - The value to set
//
// Return Values :
//   true  - Success
//   false - Failure

bool  DlgNgSpiceCfgOPT::bSetValue( int iPnlID, const wxString & rosValue )
{
  PnlValue * poPnlValue;

  // Get a pointer to the appropriate value panel
  poPnlValue = poGetPanel( iPnlID );
  if( poPnlValue == NULL )                  return( false );

  // Set the panel value
  if( ! poPnlValue->bSetValue( rosValue ) ) return( false );

  // Update the OPTIONS command object
  GetValues( m_oCmdOPT );

  return( true );
}

//**************************************************************************************************
//                                         Event Handlers                                          *
//**************************************************************************************************
// Ok button event handler.
//
// Argument List :
//   roEvtCmd - An object holding information about the event (not used)

void  DlgNgSpiceCfgOPT::OnBtnOk( wxCommandEvent & roEvtCmd )
{
  GetValues( m_oCmdOPT );
  EndModal( wxID_OK );
}

//**************************************************************************************************
// Defaults button event handler.
//
// Argument List :
//   roEvtCmd - An object holding information about the event (not used)

void  DlgNgSpiceCfgOPT::OnBtnDefaults( wxCommandEvent & roEvtCmd )
{
  CmdNgSpiceOPT  oCmdOPT;

  oCmdOPT.bSetDefaults( );
  SetValues( oCmdOPT );
}

//**************************************************************************************************
// Cancel button event handler.
//
// Argument List :
//   roEvtCmd - An object holding information about the event (not used)

void  DlgNgSpiceCfgOPT::OnBtnCancel( wxCommandEvent & roEvtCmd )
{
  SetValues( m_oCmdOPT );
  EndModal( wxID_CANCEL );
}

//**************************************************************************************************
