//**************************************************************************************************
//                                         PnlAnaBase.cpp                                          *
//                                        ----------------                                         *
// Started     : 2004-04-26                                                                        *
// Last Update : 2018-11-04                                                                        *
// 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 "PnlAnaBase.hpp"

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

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

//**************************************************************************************************
// 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, 123, 95, 82 );
  m_oPnlStop  .bCreate( poPnl, ID_PNL_STOP,  123, 95, 82 );
  m_oPnlStep  .bCreate( poPnl, ID_PNL_STEP,  123, 95, 82 );
#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 ) );

  // Set static box font
  m_oSbxSwpPars.SetOwnFont( FONT_SLANT );
#endif // LAYOUT_MNGR

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

  // 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 ) );

  // Set static box font
  m_oSbxCalcPars.SetOwnFont( FONT_SLANT );
#endif // LAYOUT_MNGR

  // Create and add .OPTIONS configuration dialog button
#ifdef LAYOUT_MNGR
  m_oBtnOPTIONS.Create( this, ID_BTN_OPTIONS, wxT(".OPTIONS ...") );
  m_oBtnOPTIONS.SetMinSize( wxSize( 105, GUI_CTRL_HT+4 ) );
#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_oChoSrcName.SetMinSize( wxSize( 121, GUI_CTRL_HT ) );
#else
  m_oSbxSigSrc .Create( poPnl, ID_UNUSED, wxT(" Signal Source "), wxPoint(   6, 178 ),
                        wxSize( 145, 60 ) );
  m_oChoSrcName.Create( poPnl, ID_CHO_SRCNAME,                    wxPoint(  18, 200 ),
                        wxSize( 121, GUI_CTRL_HT ) );

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

//**************************************************************************************************
// 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 ) );

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

//**************************************************************************************************
// 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, 0, 85, 20 );
#else
  m_oSbxTemp. Create( poPnl, ID_UNUSED, wxT(" Temperature "), wxPoint( 343, 178 ),
                      wxSize( 156, 60 ) );
  m_oPnlTemp.bCreate( poPnl, ID_PNL_TEMP, 0, 85, 20,          wxPoint( 353, 200 ) );

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

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

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

#ifdef LAYOUT_MNGR

void  PnlAnaBase::DoLayout( void )
{
  wxWindow         * poWin;
  wxStaticBoxSizer * poSzrSB;
  wxGridBagSizer   * poSzrGB;
  wxSizerFlags       oFlags;
  wxGBPosition       oGBPosn;
  wxGBSpan           oGBSpan;
  wxFont             oFont;
  int                iFlags;
  int                iBorder;

  //---------------------------------------------------------------------------
  // Create and set the sizer for the sweep panel

  poWin = m_oPnlStart.GetParent( );
  poSzrSB = new wxStaticBoxSizer( wxVERTICAL, poWin, wxT(" Sweep Parameters ") );
  poWin->SetSizer( poSzrSB );

  // Set the font for the static box label
  oFont = poSzrSB->GetStaticBox( )->GetFont( );
  oFont.SetStyle( wxFONTSTYLE_ITALIC );
  poSzrSB->GetStaticBox( )->SetFont( oFont );

  // Layout the sweep panel
  oFlags.Align( wxALIGN_LEFT );
  oFlags.Border( wxLEFT | wxRIGHT, 8 );
  poSzrSB->AddSpacer( 7 );
  poSzrSB->Add( &m_oPnlStart, oFlags );
  poSzrSB->Add( &m_oPnlStop , oFlags );
  poSzrSB->Add( &m_oPnlStep , oFlags );
  poSzrSB->AddSpacer( 6 );
  oFlags.Border( wxLEFT          , 6 );
  poSzrSB->Add( &m_oRbxSweep, oFlags );
  poSzrSB->AddSpacer( 6 );

  //---------------------------------------------------------------------------
  // If required create the signal source panel

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

    // Set the font for the static box label
    poSzrSB->GetStaticBox( )->SetFont( oFont );

    // Layout the signal source panel
    oFlags.Align( wxALIGN_LEFT );
    oFlags.Border( wxTOP | wxBOTTOM, 6 );
    poSzrSB->AddSpacer( 8 );
    poSzrSB->Add( &m_oChoSrcName, oFlags );
    poSzrSB->AddSpacer( 3 );
    if( m_oPnlSrcLvl.GetParent( ) != NULL ) poSzrSB->Add( &m_oPnlSrcLvl, oFlags );
    if( m_oBtnSetup .GetParent( ) != NULL ) poSzrSB->Add( &m_oBtnSetup , oFlags );
    poSzrSB->AddSpacer( 6 );
  }

  //---------------------------------------------------------------------------
  // Create the parameter (probe) panel

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

  // Set the font for the static box label
  poSzrSB->GetStaticBox( )->SetFont( oFont );

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

  //---------------------------------------------------------------------------
  // If required create the complex parts panel

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

    // Set the font for the static box label
    poSzrSB->GetStaticBox( )->SetFont( oFont );

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

  //---------------------------------------------------------------------------
  // If required create the analysis temperature panel

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

    // Set the font for the static box label
    poSzrSB->GetStaticBox( )->SetFont( oFont );

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

  //---------------------------------------------------------------------------
  // Create the sizer for the whole analysis panel

  // Create and set the analysis panel sizer
  poSzrGB = new wxGridBagSizer( );
  SetSizer( poSzrGB );

  // Set horizontal & vertical gaps between cells and the border on the cell out edges
  poSzrGB->SetHGap( 8 );
  poSzrGB->SetVGap( 8 );
  iBorder = 9;

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

  // Add the signal source panel
  poWin = m_oChoSrcName.GetParent( );
  if( poWin != NULL )
  {
    oGBPosn.SetCol( 0 );     oGBPosn.SetRow( 4 );
    oGBSpan.SetColspan( 3 ); oGBSpan.SetRowspan( 1 );
    iFlags = wxLEFT;
    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 );
  iFlags = wxTOP;
  poSzrGB->Add( poWin, oGBPosn, oGBSpan, iFlags, iBorder );

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

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

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

#endif // LAYOUT_MNGR

//**************************************************************************************************
// 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 );
}

//**************************************************************************************************
// Set the static box label for the sweep parameters.
//
// Argument List :
//   rosLabel - The new label string
//
// Return Values :
//   true  - Success
//   false - Failure

#ifdef LAYOUT_MNGR

bool  PnlAnaBase::bSetSwpParsLbl( const wxString & rosLabel )
{
  wxWindow    * poWin;
  wxSizer     * poSzr;
  wxStaticBox * poSBx;
  wxString      os1;

  poWin = m_oPnlStart.GetParent( );
  if( poWin != NULL )
  {
    poSzr = poWin->GetSizer( );
    if( poSzr != NULL )
    {
      poSBx = static_cast< wxStaticBoxSizer * >( poSzr )->GetStaticBox( );
      if( poSBx != NULL )
      {
#if wxCHECK_VERSION( 3,0,0 )
        os1 = wxString( wxT(" <i>") ) + rosLabel + wxT("</i> ");
        poSBx->SetLabelMarkup( os1 );
#else
        os1 = rosLabel;
        poSBx->SetLabel( os1 );
#endif
        return( true );
      }
    }
  }

  return( false );
}

#endif // LAYOUT_MNGR

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