//**************************************************************************************************
//                                      DlgGnuCapCfgGEN.cpp                                        *
//                                     ---------------------                                       *
// Started     : 2004-02-27                                                                        *
// Last Update : 2018-11-03                                                                        *
// Copyright   : (C) 2004-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 "DlgGnuCapCfgGEN.hpp"

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

wxBEGIN_EVENT_TABLE( DlgGnuCapCfgGEN, wxDialog )

  EVT_BUTTON( DlgGnuCapCfgGEN::ID_BTN_OK,     DlgGnuCapCfgGEN::OnBtnOk     )
  EVT_BUTTON( DlgGnuCapCfgGEN::ID_BTN_CLEAR,  DlgGnuCapCfgGEN::OnBtnClear  )
  EVT_BUTTON( DlgGnuCapCfgGEN::ID_BTN_CANCEL, DlgGnuCapCfgGEN::OnBtnCancel )

wxEND_EVENT_TABLE( )

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

DlgGnuCapCfgGEN::DlgGnuCapCfgGEN( wxWindow * poWin ) :
                wxDialog( poWin, -1, wxT(""), wxDefaultPosition, wxDefaultSize,
                          wxDEFAULT_DIALOG_STYLE, wxDialogNameStr )
{
  SetTitle( wxT("Generator Setup") );
  Initialize( );
  bClear( );
}

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

DlgGnuCapCfgGEN::~DlgGnuCapCfgGEN( )
{
}

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

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

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

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

void  DlgGnuCapCfgGEN::Create( void )
{
  wxPanel * poPnlOvrAll, * poPnlSine, * poPnlPulse, * poPnlBtns;
  int       iWdName=115, iWdValue=95, iWdUnits=75;

  // Create the various underlying panel objects
  poPnlOvrAll = new wxPanel( this );
  poPnlSine   = new wxPanel( this );
  poPnlPulse  = new wxPanel( this );
  poPnlBtns   = new wxPanel( this );

  // Create the overall panel and controls
  m_oPnlAmplitude.bCreate( poPnlOvrAll, ID_PNL_AMPLITUDE, iWdName, iWdValue, iWdUnits );
  m_oPnlOffset   .bCreate( poPnlOvrAll, ID_PNL_OFFSET,    iWdName, iWdValue, iWdUnits );

  m_oPnlAmplitude.bSetName( wxT("Amplitude") );
  m_oPnlOffset   .bSetName( wxT("DC Offset") );

  m_oPnlAmplitude.bSetUnitsType( eUNITS_VOLT );
  m_oPnlOffset   .bSetUnitsType( eUNITS_VOLT );

  // Create the sine wave panel and controls
  m_oPnlSinFreq .bCreate( poPnlSine, ID_PNL_SIN_FREQ,  iWdName, iWdValue, iWdUnits );
  m_oPnlSinPhase.bCreate( poPnlSine, ID_PNL_SIN_PHASE, iWdName, iWdValue, iWdUnits );

  m_oPnlSinFreq .bSetName( wxT("Frequency")     );
  m_oPnlSinPhase.bSetName( wxT("Initial Phase") );

  m_oPnlSinFreq .bSetUnitsType( eUNITS_FREQ  );
  m_oPnlSinPhase.bSetUnitsType( eUNITS_PHAD );

  m_oPnlSinFreq .bSetSpnRange( 0.0, 1000.0 );
  m_oPnlSinFreq .bSetUnits( wxT("Hz") );

  m_oPnlSinPhase.bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlSinPhase.bSetUnits( wxT("Degree") );

  // Create the pulse panel and controls
  m_oPnlPulInitV .bCreate( poPnlPulse, ID_PNL_PUL_INITV   , iWdName, iWdValue, iWdUnits );
  m_oPnlPulMin   .bCreate( poPnlPulse, ID_PNL_PUL_MIN   , iWdName, iWdValue, iWdUnits );
  m_oPnlPulMax   .bCreate( poPnlPulse, ID_PNL_PUL_MAX   , iWdName, iWdValue, iWdUnits );
  m_oPnlPulDelay .bCreate( poPnlPulse, ID_PNL_PUL_DELAY , iWdName, iWdValue, iWdUnits );
  m_oPnlPulRise  .bCreate( poPnlPulse, ID_PNL_PUL_RISE  , iWdName, iWdValue, iWdUnits );
  m_oPnlPulWidth .bCreate( poPnlPulse, ID_PNL_PUL_WIDTH , iWdName, iWdValue, iWdUnits );
  m_oPnlPulFall  .bCreate( poPnlPulse, ID_PNL_PUL_FALL  , iWdName, iWdValue, iWdUnits );
  m_oPnlPulPeriod.bCreate( poPnlPulse, ID_PNL_PUL_PERIOD, iWdName, iWdValue, iWdUnits );

  m_oPnlPulInitV .bSetName( wxT("Initial Value") );
  m_oPnlPulMin   .bSetName( wxT("Min Level")     );
  m_oPnlPulMax   .bSetName( wxT("Max Level")     );
  m_oPnlPulDelay .bSetName( wxT("Initial Delay") );
  m_oPnlPulRise  .bSetName( wxT("Rise Time")     );
  m_oPnlPulWidth .bSetName( wxT("Pulse Width")   );
  m_oPnlPulFall  .bSetName( wxT("Fall Time")     );
  m_oPnlPulPeriod.bSetName( wxT("Period")        );

  m_oPnlPulInitV .bSetUnitsType( eUNITS_VOLT );
  m_oPnlPulMin   .bSetUnitsType( eUNITS_VOLT );
  m_oPnlPulMax   .bSetUnitsType( eUNITS_VOLT );
  m_oPnlPulDelay .bSetUnitsType( eUNITS_TIME );
  m_oPnlPulRise  .bSetUnitsType( eUNITS_TIME );
  m_oPnlPulWidth .bSetUnitsType( eUNITS_TIME );
  m_oPnlPulFall  .bSetUnitsType( eUNITS_TIME );
  m_oPnlPulPeriod.bSetUnitsType( eUNITS_TIME );

  // Create the buttons panel and the button controls
  m_oBtnOk    .Create( poPnlBtns, ID_BTN_OK    , wxT("OK")     );
  m_oBtnClear .Create( poPnlBtns, ID_BTN_CLEAR , wxT("Clear")  );
  m_oBtnCancel.Create( poPnlBtns, ID_BTN_CANCEL, wxT("Cancel") );
}

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

void  DlgGnuCapCfgGEN::ToolTips( void )
{
  m_oPnlAmplitude.SetToolTip( wxT("The overall amplitude of the sine wave and the pulse train") );
  m_oPnlOffset   .SetToolTip( wxT("The DC offset applied to the entire signal") );

  m_oPnlSinFreq  .SetToolTip( wxT("The frequency of the sine wave generator for a Transient analysis") );
  m_oPnlSinPhase .SetToolTip( wxT("The phase of the sine wave at startup") );

  m_oPnlPulInitV .SetToolTip( wxT("The initial value of the source") );
  m_oPnlPulMin   .SetToolTip( wxT("The 'OFF' value for the pulse train") );
  m_oPnlPulMax   .SetToolTip( wxT("The 'ON' value for the pulse train") );
  m_oPnlPulDelay .SetToolTip( wxT("The time until the first pulse") );
  m_oPnlPulRise  .SetToolTip( wxT("The time taken to go from 0 to the pulsed value") );
  m_oPnlPulWidth .SetToolTip( wxT("The width of each pulse") );
  m_oPnlPulFall  .SetToolTip( wxT("The time taken to go from the pulsed value to 0") );
  m_oPnlPulPeriod.SetToolTip( wxT("The period of the pulse train") );
}

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

void  DlgGnuCapCfgGEN::DoLayout( void )
{
  wxPanel          * poPnlOvrAll, * poPnlSine, * poPnlPulse, * poPnlBtns;
  wxBoxSizer       * poSzrDlg, * poSzrBtns;
  wxStaticBoxSizer * poSzrOvrAll, * poSzrSine, * poSzrPulse;
  wxSizerFlags       oFlags;
  wxFont             oFont;

  // Get pointers to the various panels
  poPnlOvrAll = (wxPanel *) m_oPnlAmplitude.GetParent( );
  poPnlSine   = (wxPanel *) m_oPnlSinFreq  .GetParent( );
  poPnlPulse  = (wxPanel *) m_oPnlPulInitV .GetParent( );
  poPnlBtns   = (wxPanel *) m_oBtnOk       .GetParent( );

  // Create sizers to associate with the panels
  poSzrDlg    = new wxBoxSizer      ( wxVERTICAL   );
  poSzrOvrAll = new wxStaticBoxSizer( wxVERTICAL, poPnlOvrAll, wxT(" Overall ")  );
  poSzrSine   = new wxStaticBoxSizer( wxVERTICAL, poPnlSine  , wxT(" Sinusoid ") );
  poSzrPulse  = new wxStaticBoxSizer( wxVERTICAL, poPnlPulse , wxT(" Pulse ")    );
  poSzrBtns   = new wxBoxSizer      ( wxHORIZONTAL );

  // Set the font of the static box labels
  oFont = poSzrOvrAll->GetStaticBox( )->GetFont( );
  oFont.SetStyle( wxFONTSTYLE_ITALIC );
  poSzrOvrAll->GetStaticBox( )->SetFont( oFont );
  poSzrSine  ->GetStaticBox( )->SetFont( oFont );
  poSzrPulse ->GetStaticBox( )->SetFont( oFont );

  // Set the sizers to the panels
               SetSizer( poSzrDlg    );
  poPnlOvrAll->SetSizer( poSzrOvrAll );
  poPnlSine  ->SetSizer( poSzrSine   );
  poPnlPulse ->SetSizer( poSzrPulse  );
  poPnlBtns  ->SetSizer( poSzrBtns   );

  // Layout the Overall panel
  oFlags.Align( wxALIGN_LEFT );
  oFlags.Border( wxTOP | wxLEFT | wxRIGHT, 10 );
  poSzrOvrAll->Add( &m_oPnlAmplitude, oFlags );
  oFlags.Border( wxLEFT | wxBOTTOM       , 10 );
  poSzrOvrAll->Add( &m_oPnlOffset   , oFlags );

  // Layout the Sinusoid panel
  oFlags.Border( wxTOP | wxLEFT | wxRIGHT, 10 );
  poSzrSine->Add( &m_oPnlSinFreq , oFlags );
  oFlags.Border( wxLEFT | wxBOTTOM       , 10 );
  poSzrSine->Add( &m_oPnlSinPhase, oFlags );

  // Layout the Pulse panel
  oFlags.Border( wxTOP | wxLEFT | wxRIGHT, 10 );
  poSzrPulse->Add( &m_oPnlPulInitV , oFlags );
  oFlags.Border( wxLEFT | wxRIGHT        , 10 );
  poSzrPulse->Add( &m_oPnlPulMin   , oFlags );
  poSzrPulse->Add( &m_oPnlPulMax   , oFlags );
  poSzrPulse->Add( &m_oPnlPulDelay , oFlags );
  poSzrPulse->Add( &m_oPnlPulRise  , oFlags );
  poSzrPulse->Add( &m_oPnlPulWidth , oFlags );
  poSzrPulse->Add( &m_oPnlPulFall  , oFlags );
  oFlags.Border( wxLEFT | wxBOTTOM       , 10 );
  poSzrPulse->Add( &m_oPnlPulPeriod, oFlags );

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

  // Layout the underlying dialog
  oFlags.Align( wxALIGN_CENTER );
  oFlags.Border( wxTOP | wxLEFT | wxRIGHT, 15 );
  poSzrDlg->Add( poPnlOvrAll, oFlags );
  poSzrDlg->Add( poPnlSine  , oFlags );
  oFlags.Border( wxALL                   , 15 );
  poSzrDlg->Add( poPnlPulse , oFlags );
  oFlags.Border( wxBOTTOM                , 15 );
  poSzrDlg->Add( poPnlBtns  , oFlags );

  // Set dialogues minimum size and initial size as calculated by the sizer
  poSzrOvrAll->SetSizeHints( poPnlOvrAll );
  poSzrSine  ->SetSizeHints( poPnlSine   );
  poSzrPulse ->SetSizeHints( poPnlPulse  );
  poSzrBtns  ->SetSizeHints( poPnlBtns   );
  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 * DlgGnuCapCfgGEN::poGetPanel( int iPnlID )
{
  switch( iPnlID )
  {
    case ID_PNL_AMPLITUDE  : return( &m_oPnlAmplitude );
    case ID_PNL_OFFSET     : return( &m_oPnlOffset    );
    case ID_PNL_SIN_FREQ   : return( &m_oPnlSinFreq   );
    case ID_PNL_SIN_PHASE  : return( &m_oPnlSinPhase  );
    case ID_PNL_PUL_INITV  : return( &m_oPnlPulInitV  );
    case ID_PNL_PUL_MIN    : return( &m_oPnlPulMin    );
    case ID_PNL_PUL_MAX    : return( &m_oPnlPulMax    );
    case ID_PNL_PUL_DELAY  : return( &m_oPnlPulDelay  );
    case ID_PNL_PUL_RISE   : return( &m_oPnlPulRise   );
    case ID_PNL_PUL_WIDTH  : return( &m_oPnlPulWidth  );
    case ID_PNL_PUL_FALL   : return( &m_oPnlPulFall   );
    case ID_PNL_PUL_PERIOD : return( &m_oPnlPulPeriod );

    default                : return( NULL );
  }
}

//**************************************************************************************************
// Set the values in the value panel controls.
//
// Argument List :
//   roCmdGEN - A reference to a GENERATOR command object

void  DlgGnuCapCfgGEN::SetValues( CmdGnuCapGEN & roCmdGEN )
{
  SetEvtHandlerEnabled( false );

  m_oPnlAmplitude.bSetValue( roCmdGEN.m_osAmplitude );
  m_oPnlOffset   .bSetValue( roCmdGEN.m_osOffset    );

  m_oPnlSinFreq  .bSetValue( roCmdGEN.m_osSinFreq   );
  m_oPnlSinPhase .bSetValue( roCmdGEN.m_osSinPhase  );

  m_oPnlPulInitV .bSetValue( roCmdGEN.m_osPulInitV  );
  m_oPnlPulMin   .bSetValue( roCmdGEN.m_osPulMin    );
  m_oPnlPulMax   .bSetValue( roCmdGEN.m_osPulMax    );
  m_oPnlPulDelay .bSetValue( roCmdGEN.m_osPulDelay  );
  m_oPnlPulRise  .bSetValue( roCmdGEN.m_osPulRise   );
  m_oPnlPulWidth .bSetValue( roCmdGEN.m_osPulWidth  );
  m_oPnlPulFall  .bSetValue( roCmdGEN.m_osPulFall   );
  m_oPnlPulPeriod.bSetValue( roCmdGEN.m_osPulPeriod );

  SetEvtHandlerEnabled( true );
}

//**************************************************************************************************
// Get the values from the value panel controls.
//
// Argument List :
//   roCmdGEN - A reference to a GENERATOR command object

void  DlgGnuCapCfgGEN::GetValues( CmdGnuCapGEN & roCmdGEN )
{
  SetEvtHandlerEnabled( false );

  roCmdGEN.m_osAmplitude = m_oPnlAmplitude.rosGetValue( );
  roCmdGEN.m_osOffset    = m_oPnlOffset   .rosGetValue( );

  roCmdGEN.m_osSinFreq   = m_oPnlSinFreq  .rosGetValue( );
  roCmdGEN.m_osSinPhase  = m_oPnlSinPhase .rosGetValue( );

  roCmdGEN.m_osPulInitV  = m_oPnlPulInitV .rosGetValue( );
  roCmdGEN.m_osPulMin    = m_oPnlPulMin   .rosGetValue( );
  roCmdGEN.m_osPulMax    = m_oPnlPulMax   .rosGetValue( );
  roCmdGEN.m_osPulDelay  = m_oPnlPulDelay .rosGetValue( );
  roCmdGEN.m_osPulRise   = m_oPnlPulRise  .rosGetValue( );
  roCmdGEN.m_osPulWidth  = m_oPnlPulWidth .rosGetValue( );
  roCmdGEN.m_osPulFall   = m_oPnlPulFall  .rosGetValue( );
  roCmdGEN.m_osPulPeriod = m_oPnlPulPeriod.rosGetValue( );

  roCmdGEN.bFormat( );

  SetEvtHandlerEnabled( true );
}

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

bool  DlgGnuCapCfgGEN::bClear( void )
{
  m_oCmdGEN.bSetDefaults( );

  SetValues( m_oCmdGEN );

  return( true );
}

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

bool  DlgGnuCapCfgGEN::bSetValues( CmdGnuCapGEN & roCmdGEN )
{
  SetValues( roCmdGEN );
  m_oCmdGEN = roCmdGEN;

  return( true );
}

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

bool  DlgGnuCapCfgGEN::bGetValues( CmdGnuCapGEN & roCmdGEN )
{
  GetValues( roCmdGEN );

  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 & DlgGnuCapCfgGEN::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  DlgGnuCapCfgGEN::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 GENERATOR command object
  GetValues( m_oCmdGEN );

  return( true );
}

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

void  DlgGnuCapCfgGEN::OnBtnOk( wxCommandEvent & roEvtCmd )
{
  GetValues( m_oCmdGEN );
  EndModal( wxID_OK );
}

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

void  DlgGnuCapCfgGEN::OnBtnClear( wxCommandEvent & roEvtCmd )
{
  CmdGnuCapGEN  oCmdGEN;

  oCmdGEN.bSetDefaults( );
  SetValues( oCmdGEN );
}

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

void  DlgGnuCapCfgGEN::OnBtnCancel( wxCommandEvent & roEvtCmd )
{
  SetValues( m_oCmdGEN );
  EndModal( wxID_CANCEL );
}

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