//**************************************************************************************************
//                                         PnlAnaBase.cpp                                          *
//                                        ----------------                                         *
// Started     : 2004-04-26                                                                        *
// Last Update : 2016-10-01                                                                        *
// Copyright   : (C) 2004-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.                    *
//                                                                                                 *
//**************************************************************************************************

#include "PnlAnaBase.hpp"

//**************************************************************************************************
// Allocate storage for static data members.

Component  PnlAnaBase::m_oCpntSwpSrc;

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

wxBEGIN_EVENT_TABLE( PnlAnaBase, wxPanel )

  EVT_CHOICE( PnlAnaBase::ID_CHO_SRCNAME, PnlAnaBase::OnSrcName )

wxEND_EVENT_TABLE( )

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

PnlAnaBase::PnlAnaBase( wxWindow * poWin ) : wxPanel( poWin )
{
  m_eAnaType = eCMD_NONE;

  bClear( );
}

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

PnlAnaBase::~PnlAnaBase( )
{
}

//**************************************************************************************************
// Clear the object attributes back to it's initial state.
//
// Return Values :
//   true  - Success
//   false - Failure

bool  PnlAnaBase::bClear( void )
{
  m_osErrMsg.Empty( ); // Clear the error string

  return( true );
}

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

void  PnlAnaBase::CreateBase( void )
{
  wxPanel * poPnl;

  // Create the sweep panel and controls
#ifdef LAYOUT_MNGR
  poPnl = new wxPanel( this );
#else
  poPnl = this;
#endif // LAYOUT_MNGR

  // Create and add sweep parameter labels
#ifdef LAYOUT_MNGR
  m_oPnlStart.bCreate( poPnl, ID_PNL_START, 120 );
  m_oPnlStop .bCreate( poPnl, ID_PNL_STOP,  120 );
  m_oPnlStep .bCreate( poPnl, ID_PNL_STEP,  120 );
#else
  m_oSbxSwpPars.Create( poPnl, ID_UNUSED, wxT(" Sweep Parameters "), wxPoint(  6,  5 ),
                        wxSize( 330, 167 ) );
  m_oPnlStart.bCreate( poPnl, ID_PNL_START, 123, 95, 82,             wxPoint( 22, 26 ) );
  m_oPnlStop .bCreate( poPnl, ID_PNL_STOP,  123, 95, 82,             wxPoint( 22, 56 ) );
  m_oPnlStep .bCreate( poPnl, ID_PNL_STEP,  123, 95, 82,             wxPoint( 22, 86 ) );
#endif // LAYOUT_MNGR

  m_oPnlStart.bSetName( wxT("Start Value") );
  m_oPnlStop .bSetName( wxT("Stop Value") );
  m_oPnlStep .bSetName( wxT("Step Increment") );
  m_oSbxSwpPars.SetOwnFont( FONT_SLANT );

  // Create the parameter (probe) panel and controls
#ifdef LAYOUT_MNGR
  poPnl = new wxPanel( this );
#else
  poPnl = this;
#endif // LAYOUT_MNGR

  // Create and add simulation parameter check boxes
#ifdef LAYOUT_MNGR
  m_oCbxVoltage .Create( poPnl, ID_CBX_VOLT, wxT("Voltage")    );
  m_oCbxCurrent .Create( poPnl, ID_CBX_CURR, wxT("Current")    );
  m_oCbxPower   .Create( poPnl, ID_CBX_PWR,  wxT("Power")      );
  m_oCbxResist  .Create( poPnl, ID_CBX_RES,  wxT("Resistance") );
#else
  m_oSbxCalcPars.Create( poPnl, ID_UNUSED  , wxT(" Parameters "),    wxPoint( 343,   5 ),
                         wxSize( 105, 122 ) );
  m_oCbxVoltage .Create( poPnl, ID_CBX_VOLT, wxT("Voltage"),         wxPoint( 349,  25 ) );
  m_oCbxCurrent .Create( poPnl, ID_CBX_CURR, wxT("Current"),         wxPoint( 349,  50 ) );
  m_oCbxPower   .Create( poPnl, ID_CBX_PWR,  wxT("Power"),           wxPoint( 349,  75 ) );
  m_oCbxResist  .Create( poPnl, ID_CBX_RES,  wxT("Resistance"),      wxPoint( 349, 100 ) );
#endif // LAYOUT_MNGR
  m_oSbxCalcPars.SetOwnFont( FONT_SLANT );

  // Create and add .OPTIONS configuration dialog button
#ifdef LAYOUT_MNGR
  m_oBtnOPTIONS.Create( this, ID_BTN_OPTIONS, wxT(".OPTIONS ...") );
#else
  m_oBtnOPTIONS.Create( this, ID_BTN_OPTIONS, wxT(".OPTIONS ..."),   wxPoint( 343, 135 ),
                        wxSize( 105, -1 ) );
#endif // LAYOUT_MNGR
}

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

void  PnlAnaBase::CreateScale( void )
{
  wxPanel * poPnl;
  wxString  osScale[]={ wxT("Lin  "), wxT("Log "), wxT("Dec "), wxT("Oct  ") };

  // Create and add the scale radio buttons
  poPnl = (wxPanel *) m_oPnlStart.GetParent( );
  m_oRbxSweep.Create( poPnl, ID_RBX_SCALE, wxT(" Step Scale "), wxPoint( 13, 123 ),
                      wxSize( -1, 41 ), 4, osScale, 4 );
  m_oRbxSweep.SetSelection( eSCALE_LIN );
}

//**************************************************************************************************
// Create the initial conditions display objects.

void  PnlAnaBase::CreateInitC( void )
{
  wxPanel * poPnl;
  wxString  osInitC[]={ wxT("Warm "), wxT("Use ICs"), wxT("Cold  ") };

  // Create and add the initial conditions radio buttons
  poPnl = (wxPanel *) m_oPnlStart.GetParent( );
  m_oRbxSweep.Create( poPnl, ID_UNUSED, wxT(" Initial Conditions "), wxPoint( 13, 123 ),
                      wxSize( -1, 41 ), 3, osInitC, 3 );
  m_oRbxSweep.SetSelection( eINITC_WARM );
}

//**************************************************************************************************
// Create the source component display objects.

void  PnlAnaBase::CreateSigSrc( void )
{
  wxPanel * poPnl;

  // Create the input source panel and controls
#ifdef LAYOUT_MNGR
  poPnl = new wxPanel( this );
#else
  poPnl = this;
#endif // LAYOUT_MNGR

  // Create and add input source
#ifdef LAYOUT_MNGR
  m_oChoSrcName.Create( poPnl, ID_CHO_SRCNAME );
  m_oPnlSrcLvl.bCreate( poPnl, ID_PNL_SRCLVL  );
#else
  m_oSbxSigSrc .Create( poPnl, ID_UNUSED, wxT(" Signal Source "), wxPoint(   6, 178 ),
                        wxSize( 330, 60 ) );
  m_oChoSrcName.Create( poPnl, ID_CHO_SRCNAME,                    wxPoint(  18, 200 ),
                        wxSize( 121, GUI_CTRL_HT ) );
  m_oPnlSrcLvl.bCreate( poPnl, ID_PNL_SRCLVL, -1, 95, 82,         wxPoint( 142, 200 ) );
#endif // LAYOUT_MNGR

  // Set static box font
  m_oSbxSigSrc.SetOwnFont( FONT_SLANT );
}

//**************************************************************************************************
// Create the simulation parameter complex part display objects.

void  PnlAnaBase::CreateCpxPrt( void )
{
  wxPanel * poPnl;

  // Create the parameter (probe) complex part panel and controls
#ifdef LAYOUT_MNGR
  poPnl = new wxPanel( this );
#else
  poPnl = this;
#endif // LAYOUT_MNGR

  // Create and add simulation parameter complex part check boxes
#ifdef LAYOUT_MNGR
  m_oCbxMag   .Create( poPnl, ID_CBX_MAG  , wxT("Magnitude")  );
  m_oCbxPhase .Create( poPnl, ID_CBX_PHASE, wxT("Phase")      );
  m_oCbxReal  .Create( poPnl, ID_CBX_REAL , wxT("Real Part")  );
  m_oCbxImag  .Create( poPnl, ID_CBX_IMAG , wxT("Imag. Part") );
  m_oCbxMagDb .Create( poPnl, ID_CBX_MAGDB, wxT("Mag. in dB") );
#else
  m_oSbxCpxPrt.Create( poPnl, ID_UNUSED,    wxT(" Complex Parts "), wxPoint( 455,   5 ),
                       wxSize( 110, 146 ) );
  m_oCbxMag   .Create( poPnl, ID_CBX_MAG,   wxT("Magnitude"),       wxPoint( 461,  24 ) );
  m_oCbxPhase .Create( poPnl, ID_CBX_PHASE, wxT("Phase"),           wxPoint( 461,  49 ) );
  m_oCbxReal  .Create( poPnl, ID_CBX_REAL,  wxT("Real Part"),       wxPoint( 461,  74 ) );
  m_oCbxImag  .Create( poPnl, ID_CBX_IMAG,  wxT("Imag. Part"),      wxPoint( 461,  99 ) );
  m_oCbxMagDb .Create( poPnl, ID_CBX_MAGDB, wxT("Mag. in dB"),      wxPoint( 461, 124 ) );
#endif // LAYOUT_MNGR

  // Set static box font
  m_oSbxCpxPrt.SetOwnFont( FONT_SLANT );
}

//**************************************************************************************************
// Create the analysis temperature display objects.

void  PnlAnaBase::CreateTemp( void )
{
  wxPanel * poPnl;

  // Create the temperature panel and controls
#ifdef LAYOUT_MNGR
  poPnl = new wxPanel( this );
#else
  poPnl = this;
#endif // LAYOUT_MNGR

  // Create and add analysis temperature
#ifdef LAYOUT_MNGR
  m_oPnlTemp.bCreate( poPnl, ID_PNL_TEMP );
#else
  m_oSbxTemp. Create( poPnl, ID_UNUSED, wxT(" Temperature "), wxPoint( 343, 178 ),
                      wxSize( 156, 60 ) );
  m_oPnlTemp.bCreate( poPnl, ID_PNL_TEMP, 0, 95, 40,          wxPoint( 353, 200 ) );
#endif // LAYOUT_MNGR

  // Set static box font
  m_oSbxTemp.SetOwnFont( FONT_SLANT );

  // Set PnlValue parameters
  m_oPnlTemp.bShowUnits( PnlValue::eSHOW_LBL );
  m_oPnlTemp.bSetUnitsType( eUNITS_TMPC );
  m_oPnlTemp.Layout( );
}

//**************************************************************************************************
// Layout the panel display objects.

void  PnlAnaBase::DoLayout( void )
{
#ifndef LAYOUT_MNGR
  return;
#endif

  wxWindow       * poWin;
  wxSizer        * poSzr;
  wxGridBagSizer * poSzrGB;
  wxSizerFlags     oFlags;
  wxGBPosition     oGBPosn;
  wxGBSpan         oGBSpan;
  int              iFlags;
  int              iBorder;

  //---------------------------------------------------------------------------
  // Create and set the sizer for the sweep panel
  poWin = m_oPnlStart.GetParent( );
  poSzr = new wxStaticBoxSizer( wxVERTICAL, poWin, wxT(" Sweep Parameters ") );
  poWin->SetSizer( poSzr );

  // Layout the sweep panel
  oFlags.Align( wxALIGN_LEFT );
  oFlags.Border( wxALL & ~wxBOTTOM, 3 );
  poSzr->Add( &m_oPnlStart, oFlags );
  poSzr->Add( &m_oPnlStop , oFlags );
  poSzr->Add( &m_oPnlStep , oFlags );
  poSzr->AddSpacer( 3 );
  poSzr->Add( &m_oRbxSweep, oFlags );

  //---------------------------------------------------------------------------
  // If required create the signal source panel
  poWin = m_oChoSrcName.GetParent( );
  if( poWin != NULL )
  {
    // Create and set the sizer for the signal source panel
    poSzr = new wxStaticBoxSizer( wxHORIZONTAL, poWin, wxT(" Signal Source ") );
    poWin->SetSizer( poSzr );

    // Layout the signal source panel
    oFlags.Align( wxALIGN_LEFT );
    oFlags.Border( wxALL, 3 );
    poSzr->Add( &m_oChoSrcName, oFlags );
    poSzr->Add( &m_oPnlSrcLvl , oFlags );
  }

  //---------------------------------------------------------------------------
  // Create and set the sizer for the parameter (probe) panel
  poWin = m_oCbxVoltage.GetParent( );
  poSzr = new wxStaticBoxSizer( wxVERTICAL, poWin, wxT(" Parameters ") );
  poWin->SetSizer( poSzr );

  // Layout the parameter (probe) panel
  oFlags.Align( wxALIGN_LEFT );
  oFlags.Border( wxALL & ~wxBOTTOM, 3 );
  poSzr->Add( &m_oCbxVoltage, oFlags );
  poSzr->Add( &m_oCbxCurrent, oFlags );
  poSzr->Add( &m_oCbxPower  , oFlags );
  poSzr->Add( &m_oCbxResist , oFlags );
  poSzr->AddSpacer( 3 );

  //---------------------------------------------------------------------------
  // If required create the complex parts panel
  poWin = m_oCbxMag.GetParent( );
  if( poWin != NULL )
  {
    // Create and set the sizer for the complex part panel
    poSzr = new wxStaticBoxSizer( wxVERTICAL, poWin, wxT(" Complex Parts ") );
    poWin->SetSizer( poSzr );

    // Layout the complex part panel
    oFlags.Align( wxALIGN_LEFT );
    oFlags.Border( wxALL & ~wxBOTTOM, 3 );
    poSzr->Add( &m_oCbxMag  , oFlags );
    poSzr->Add( &m_oCbxPhase, oFlags );
    poSzr->Add( &m_oCbxReal , oFlags );
    poSzr->Add( &m_oCbxImag , oFlags );
    poSzr->Add( &m_oCbxMagDb, oFlags );
    poSzr->AddSpacer( 3 );
  }

  //---------------------------------------------------------------------------
  // If required create the analysis temperature panel
  poWin = m_oPnlTemp.GetParent( );
  if( poWin != NULL )
  {
    // Create and set the sizer for the analysis temperature panel
    poSzr = new wxStaticBoxSizer( wxVERTICAL, poWin, wxT(" Temperature ") );
    poWin->SetSizer( poSzr );

    // Layout the complex part panel
    oFlags.Align( wxALIGN_LEFT );
    oFlags.Border( wxALL, 3 );
    poSzr->Add( &m_oPnlTemp, oFlags );
  }

  //---------------------------------------------------------------------------
  // Create and set the underlying panel's sizer
  poSzrGB = new wxGridBagSizer( 1, 1 );
  SetSizer( poSzrGB );

  // Add the sweep panel
  poWin = m_oPnlStart.GetParent( );
  oGBPosn.SetCol( 0 );     oGBPosn.SetRow( 0 );
  oGBSpan.SetColspan( 3 ); oGBSpan.SetRowspan( 4 );
  iFlags  = wxALL | wxALIGN_CENTER;
  iBorder = 5;
  poSzrGB->Add( poWin, oGBPosn, oGBSpan, iFlags, iBorder );

  poWin = m_oChoSrcName.GetParent( );
  if( poWin != NULL )
  {
    // Add the signal source panel
    oGBPosn.SetCol( 0 );     oGBPosn.SetRow( 4 );
    oGBSpan.SetColspan( 3 ); oGBSpan.SetRowspan( 1 );
    iFlags = wxALL | wxALIGN_LEFT;
    poSzrGB->Add( poWin, oGBPosn, oGBSpan, iFlags, iBorder );
  }

  // Add the parameter (probe) panel
  poWin = m_oCbxVoltage.GetParent( );
  oGBPosn.SetCol( 3 );     oGBPosn.SetRow( 0 );
  oGBSpan.SetColspan( 1 ); oGBSpan.SetRowspan( 3 );
  poSzrGB->Add( poWin, oGBPosn, oGBSpan, iFlags, iBorder );

  // Add the options button
  oGBPosn.SetCol( 3 );     oGBPosn.SetRow( 3 );
  oGBSpan.SetColspan( 1 ); oGBSpan.SetRowspan( 1 );
  iFlags = wxALL | wxALIGN_CENTER;
  poSzrGB->Add( &m_oBtnOPTIONS, oGBPosn, oGBSpan, iFlags, iBorder );

  poWin = m_oCbxMag.GetParent( );
  if( poWin != NULL )
  {
    // Add the complex parts panel
    oGBPosn.SetCol( 4 );     oGBPosn.SetRow( 0 );
    oGBSpan.SetColspan( 1 ); oGBSpan.SetRowspan( 4 );
    poSzrGB->Add( poWin, oGBPosn, oGBSpan, iFlags, iBorder );
  }

  poWin = m_oPnlTemp.GetParent( );
  if( poWin != NULL )
  {
    // Add the temperature panel
    oGBPosn.SetCol( 3 );     oGBPosn.SetRow( 4 );
    oGBSpan.SetColspan( 2 ); oGBSpan.SetRowspan( 1 );
    poSzrGB->Add( poWin, oGBPosn, oGBSpan, iFlags, iBorder );
  }
}

//**************************************************************************************************
// Set the state of the step scale radio box.
//
// Argument List :
//   eScale - The enumerated scale specifier
//
// Return Values :
//   Success - true
//   Failure - false

bool  PnlAnaBase::bSetScale( eTypeScale eScale )
{
  if( eScale == eSCALE_NONE )                       return( false );
#if wxCHECK_VERSION( 2,8,0 )
  if( m_oRbxSweep.GetCount( ) < (uint) eScale + 1 ) return( false );
#else
  if( m_oRbxSweep.GetCount( ) < (int)  eScale + 1 ) return( false );
#endif

  m_oRbxSweep.SetSelection( (int) eScale );

  InitScale( );

  return( true );
}

//**************************************************************************************************
// Set the state of the initial conditions radio box.
//
// Argument List :
//   eInitC - The enumerated initial conditions specifier
//
// Return Values :
//   Success - true
//   Failure - false

bool  PnlAnaBase::bSetInitC( eTypeInitC eInitC )
{
  if( eInitC == eINITC_NONE )                       return( false );
#if wxCHECK_VERSION( 2,8,0 )
  if( m_oRbxSweep.GetCount( ) < (uint) eInitC + 1 ) return( false );
#else
  if( m_oRbxSweep.GetCount( ) < (int)  eInitC + 1 ) return( false );
#endif

  m_oRbxSweep.SetSelection( (int) eInitC );

  return( true );
}

//**************************************************************************************************
// Load the source choice box with the components names which may be chosen as
// a source.
//
// Argument List :
//   roSimn   - A reference to an array on Component objects
//   osPrefix - A string containing the first letter of the desired components

void  PnlAnaBase::LoadSrcNames( ArrayComponent & roaCpnts, wxString osPrefixes )
{
  wxArrayString  oasSrcs;
  wxString       osTmpSrc;
  wxString       os1;
  wxChar         oc1;
  uint           ui1;

  // Temporarily record the current selection
  osTmpSrc = m_oChoSrcName.GetStringSelection( );

  // Clear the signal source choice box
  m_oChoSrcName.Clear( );
  m_oChoSrcName.Append( wxT("None") );

  // Load selected components into string array, sort and put them in the signal source choice box
  for( ui1=0; ui1<roaCpnts.GetCount( ); ui1++ )
  {
    os1 = roaCpnts.Item( ui1 ).rosGetName( );
    if( os1.IsEmpty( ) )                        continue;

    oc1 = os1.GetChar( 0 );
    if( osPrefixes.Find( oc1 ) == wxNOT_FOUND ) continue;

    oasSrcs.Add( os1 );                        // Add the component label to the the string array
    m_oaCpntSrcs.Add( roaCpnts.Item( ui1 ) );  // Add the component to the source component array
  }
  oasSrcs.Sort( iStrCmpSrc );
  m_oChoSrcName.Append( oasSrcs );

  // Restore the original selection if possible
  if( ! m_oChoSrcName.SetStringSelection( osTmpSrc ) )
    m_oChoSrcName.SetStringSelection( wxT("None") );
}

//**************************************************************************************************
// Set the source component.
//
// Argument List :
//   roCpnt - A component object
//
// Return Values :
//   true  - Success
//   false - Failure

bool  PnlAnaBase::bSetSrcCpnt( Component & roCpnt )
{
  // If the components isn't valid set default values
  if( ! roCpnt.bIsValid( ) )
  {
    m_oChoSrcName.SetStringSelection( wxT("None") );
    if( m_oPnlSrcLvl.GetParent( ) != NULL )
    {
      m_oPnlSrcLvl.bSetUnitsType( eUNITS_NONE );
      m_oPnlSrcLvl.bSetValue( (float) 0.0 );
    }
    return( false );
  }

  // Set the source component label, value and units
  if( ! m_oChoSrcName.SetStringSelection( roCpnt.rosGetName( ) ) ) return( false );
  if( m_oPnlSrcLvl.GetParent( ) != NULL )
  {
    if( ! m_oPnlSrcLvl.bSetUnitsType( roCpnt.eGetUnitsType( ) ) )  return( false );
    if( ! m_oPnlSrcLvl.bSetValue( roCpnt.rosGetNumValue( ) ) )     return( false );
  }

  return( true );
}

//**************************************************************************************************
// Select the analysis to be performed.
//
// Argument List :
//   eAnalysis - The analysis type
//
// Return Values :
//   true  - Success
//   false - Failure

bool  PnlAnaBase::bSetAnalysType( eTypeCmd eAnaType )
{
  if( eAnaType == eCMD_NONE ) return( false );

  m_eAnaType = eAnaType;

  return( true );
}

//**************************************************************************************************
//                                         Event Handlers                                          *
//**************************************************************************************************
// Source component choice box event handler.
//
// Argument List :
//   roEvtCmd - An object holding information about the event

void  PnlAnaBase::OnSrcName( wxCommandEvent & roEvtCmd )
{
  // Set the sweep source component
  if( m_oChoSrcName.GetSelection( ) > 0 )
       m_oCpntSwpSrc.bSetName( m_oChoSrcName.GetStringSelection( ) );
  else m_oCpntSwpSrc.bClear( );
}

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