//************************************************************************************************** // PnlValue.cpp * // -------------- * // Started : 2004-09-14 * // Last Update : 2015-08-10 * // 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 "PnlValue.hpp" //************************************************************************************************** // Implement an event table. wxBEGIN_EVENT_TABLE( PnlValue, wxPanel ) EVT_SPIN_UP ( PnlTxtSpn::ID_SPINBTN , PnlValue::OnSpnScroll ) EVT_SPIN_DOWN( PnlTxtSpn::ID_SPINBTN , PnlValue::OnSpnScroll ) EVT_CHOICE ( PnlValue ::ID_CHO_UNITS, PnlValue::OnChoUnits ) wxEND_EVENT_TABLE( ) //************************************************************************************************** // Constructor. PnlValue::PnlValue( void ) : wxPanel( ) { bClear( ); } //************************************************************************************************** // Destructor. PnlValue::~PnlValue( ) { } //************************************************************************************************** // Layout the display objects. void PnlValue::DoLayout( void ) { wxBoxSizer * poSzr; wxSizerFlags oFlags; // Create and set the sizer for the panel poSzr = new wxBoxSizer( wxHORIZONTAL ); SetSizer( poSzr ); // Add the value label oFlags.Proportion( 1 ); // The next 3 lines vertically center the wxLabel oFlags.Border( wxTOP, 6 ); poSzr->Add( &m_oLblName, oFlags ); // Add the value itself oFlags.Proportion( 0 ); oFlags.Border( wxTOP, 0 ); poSzr->Add( &m_oSpnValue, oFlags ); // Add units for the value poSzr->AddSpacer( 4 ); poSzr->Add( &m_oChoUnits, oFlags ); poSzr->AddSpacer( 3 ); oFlags.Border( wxTOP, 6 ); poSzr->Add( &m_oLblUnits, oFlags ); // Set the panel sizer and the min. & init. sizes as calculated by the sizer poSzr->SetSizeHints( this ); } //************************************************************************************************** // Create an instance of this object. // // Argument List : // poWin - The parent window // oWinID - The window identifier // iNameWd - The width of the name label in pixels // iValueWd - The width of the value control // iUnitsWd - The width of the units control // roPosn - The position // eShowUnits - Flag indicating if units should be accommodated // // Return Values : // true - Success // false - Failure bool PnlValue::bCreate( wxWindow * poWin, wxWindowID oWinID, int iNameWd, int iValueWd, int iUnitsWd, const wxPoint & roPosn, eTypeShow eShowUnits ) { bool bRtn=true; if( bIsCreated( ) ) return( true ); // Create the base class (wxPanel) if( ! wxPanel::Create( poWin, oWinID, roPosn ) ) return( false ); // Create the variable name label if( ! m_oLblName.Create( this, ID_UNUSED, wxT(""), wxDefaultPosition, wxSize( iNameWd, GUI_CTRL_HT-2 ), wxALIGN_LEFT ) ) bRtn = false; // Create the value spin control if( ! m_oSpnValue.bCreate( this, ID_SPN_VALUE, iValueWd ) ) bRtn = false; // Create the units choice box if( ! m_oChoUnits.bCreate( this, ID_CHO_UNITS, iUnitsWd ) ) bRtn = false; // Create the units static label if( ! m_oLblUnits.bCreate( this, ID_LBL_UNITS, iUnitsWd ) ) bRtn = false; // Specify how units should be displayed bShowUnits( eShowUnits ); // Layout the display objects DoLayout( ); return( bRtn ); } //************************************************************************************************** // Clear the spin and choice values. // // Return Values : // Success - true // Failure - false bool PnlValue::bClear( void ) { bool bRtn=true; m_eShowUnits = eSHOW_CHO; if( ! m_oSpnValue.bClear( ) ) bRtn = false; if( ! m_oChoUnits.bClear( ) ) bRtn = false; if( ! m_oLblUnits.bClear( ) ) bRtn = false; return( bRtn ); } //************************************************************************************************** // Set the name label. // // Argument List : // rosName - The name of the variable // // Return Values : // Success - true // Failure - false bool PnlValue::bSetName( const wxString & rosName ) { if( ! bIsCreated( ) ) return( false ); if( rosName.IsEmpty( ) ) return( false ); m_oLblName.SetLabel( rosName ); return( true ); } //************************************************************************************************** // Set the variable type for the spin control to display. // // Argument List : // eVType - The variable type // // Return Values : // Success - true // Failure - false bool PnlValue::bSetValueType( eTypeValue eVType ) { if( ! bIsCreated( ) ) return( false ); return( m_oSpnValue.bSetValType( eVType ) ); } //************************************************************************************************** // Set the type of units to be displayed in the choice control. // // Argument List : // eUType - The units specifier // // Return Values : // Success - true // Failure - false bool PnlValue::bSetUnitsType( eTypeUnits eUType ) { if( ! bIsCreated( ) ) return( false ); switch( m_eShowUnits ) { //---------------------------------------------------------------------------------------------- case eSHOW_CHO : if( m_oChoUnits.eGetUnitsType( ) == eUType ) return( true ); if( ! m_oChoUnits.bSetUnitsType( eUType ) ) return( false ); // Automatically set the spin control parameters switch( eUType ) { case eUNITS_CAP : // Capacitance bSetDefValue( 100.0 ); bSetSpnRange( 0.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_IND : // Inductance bSetDefValue( 100.0 ); bSetSpnRange( 0.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_RES : // Resistance bSetDefValue( 100.0 ); bSetSpnRange( 0.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_COND : // Conductance bSetDefValue( 100.0 ); bSetSpnRange( 0.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_VOLT : // Voltage bSetDefValue( 1.0 ); bSetSpnRange( -10000.0 , 10000.0 ); bSetSpnIncSz( 1.0, 1000.0 ); break; case eUNITS_CURR : // Current bSetDefValue( 1.0 ); bSetSpnRange( -1001.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_TIME : // Time bSetDefValue( 1.0 ); bSetSpnRange( 0.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_FREQ : // Frequency bSetDefValue( 100.0 ); bSetSpnRange( 0.01, 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_CHRG : // Charge bSetDefValue( 100.0 ); bSetSpnRange( 0.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; case eUNITS_PHAD : // Phase / angle in Degree bSetDefValue( 0.0 ); bSetSpnRange( -200.0 , 200.0 ); bSetSpnIncSz( 1.0, 10.0 ); break; case eUNITS_PHAR : // Phase / angle in Radian bSetDefValue( 0.0 ); bSetSpnRange( -3.2 , 3.2 ); bSetSpnIncSz( 0.1, 0.5 ); break; case eUNITS_TMPC : // Temperature in Celcius bSetDefValue( 27.0 ); bSetSpnRange( -273.15, 300.0 ); bSetSpnIncSz( 1.0, 10.0 ); break; case eUNITS_TMPF : // Temperature in Fahrenheit bSetDefValue( 80.0 ); bSetSpnRange( -459.7 , 500.0 ); bSetSpnIncSz( 1.0, 10.0 ); break; case eUNITS_EXP : // Exponent (dimensionless) bSetDefValue( 1.0 ); bSetSpnRange( -1001.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; default : bSetDefValue( 100.0 ); bSetSpnRange( -1001.0 , 1001.0 ); bSetSpnIncSz( 1.0, 100.0 ); break; } //---------------------------------------------------------------------------------------------- case eSHOW_LBL : if( m_oLblUnits.eGetUnitsType( ) == eUType ) return( true ); if( ! m_oLblUnits.bSetUnitsType( eUType ) ) return( false ); break; //---------------------------------------------------------------------------------------------- case eSHOW_NONE : return( false ); } return( true ); } //************************************************************************************************** // Set the spin control range. // // Argument List : // dfMinValue - The spin control minimum value // dfMaxValue - The spin control maximum value // // Return Values : // Success - true // Failure - false bool PnlValue::bSetSpnRange( double dfMinValue, double dfMaxValue ) { if( ! bIsCreated( ) ) return( false ); return( m_oSpnValue.bSetRange( dfMinValue, dfMaxValue ) ); } //************************************************************************************************** // Set the increment sizes of the spin control. // // This spin control can be incremented using two different approaches, constant or variable step // sizes. A constant step size means that the spin control is incremented by the same amount // throughout it's range. A variable step size means that the spin control is incremented by an // amount dependent on it's current value. // // Argument List : // dfMinIncSz - The minimum spin control increment size // dfMaxIncSz - The maximum spin control increment size // // Return Values : // true - Success // false - Failure bool PnlValue::bSetSpnIncSz( double dfMinIncSz, double dfMaxIncSz ) { if( ! bIsCreated( ) ) return( false ); return( m_oSpnValue.bSetIncSz( dfMinIncSz, dfMaxIncSz ) ); } //************************************************************************************************** // Set the value from a long integer. // // Argument List : // liValue - The long integer value // uiExp - An optional exponent, specifies the units if it is a multiple of 3 // // Return Values : // Success - true // Failure - false bool PnlValue::bSetValue( long liValue, uint uiExp ) { long liMan; uint ui1; int i1; if( ! bIsCreated( ) ) return( false ); // Combine the value with the exponent function argument if specified liMan = liValue; if( uiExp != NOVAL_UINT ) for( ui1=uiExp; ui1>0; ui1-- ) liMan *= 10; // Set the value. Do different things depending on the units control on display switch( m_eShowUnits ) { case eSHOW_CHO : // Parse the value passed to the function for( ui1=0; liMan>1000; ui1++ ) { liMan += 5; liMan /= 10; } // Note : rounding could occur here // Restore values if the exponent is a multiple of 3 if( uiExp != NOVAL_UINT ) { if( uiExp % 3 == 0 ) { liMan = liValue; ui1 = uiExp; } } // Set the units choice control values if( ! m_oChoUnits.bSetUnits( (int) ui1 ) ) return( false ); break; case eSHOW_LBL : // Combine the value with it's units i1 = m_oLblUnits.iGetUnits( ); for( ; i1>0; i1-- ) { liMan += 5; liMan /= 10; } // Note : rounding could occur here for( ; i1<0; i1++ ) { liMan *= 10; } break; case eSHOW_NONE : break; } // Set the spin control value if( ! m_oSpnValue.bSetValue( liMan ) ) return( false ); return( true ); } //************************************************************************************************** // Set the value from a double float. // // Argument List : // dfValue - The double float value // iExp - An optional exponent, specifies the units if it is a multiple of 3 // // Return Values : // Success - true // Failure - false bool PnlValue::bSetValue( double dfValue, int iExp ) { double dfMan; int i1; if( ! bIsCreated( ) ) return( false ); // Combine the value with the exponent function argument if specified if( iExp != NOVAL_INT ) dfMan = dfValue * EXP10( (double) iExp ); else dfMan = dfValue; // Set the value. Do different things depending on the units control on display switch( m_eShowUnits ) { case eSHOW_CHO : // Restore mantissa and exponent if the exponent is a multiple of 3 if( iExp!=NOVAL_INT && iExp%3==0 ) { dfMan = dfValue; i1 = iExp; } else { // Parse the value passed to the function if( ! CnvtType::bParseDbl( dfValue, &dfMan, &i1 ) ) return( false ); // Determine the spin control value and the units choice selection if( dfMan != 0.0 ) for( ; i1%3!=0; i1-- ) dfMan *= 10.0; } // Set the units choice control values if( ! m_oChoUnits.bSetUnits( i1 ) ) return( false ); break; case eSHOW_LBL : // Determine the spin control value combined with it's units i1 = m_oLblUnits.iGetUnits( ); if( i1 != 0 ) dfMan /= EXP10( (double) i1 ); break; case eSHOW_NONE : dfMan = dfValue; break; } // Set the spin control value if( ! m_oSpnValue.bSetValue( dfMan ) ) return( false ); return( true ); } //************************************************************************************************** // Set the value from a string. // // Notes : 1. If the arguments numeric component is zero but units have been specified the units // will still be set, eg. "0.00mVolt". // 2. If the units type specified differ from the currently set units type then the // operation fails. // 3. This function will cope with arguments which contain both an exponent and a units // specifier, eg. 12.3E-7mF will be set as 1.23nF. // // Argument List : // rosValue - The string value // // Return Values : // Success - true // Failure - false bool PnlValue::bSetValue( const wxString & rosValue ) { eTypeUnits eUType=eUNITS_NONE; double dfValue; int iPfx; size_t sz1; // Don't continue unless the panel has been created if( ! bIsCreated( ) ) return( false ); // Check that the string represents a numeric value if( ! CnvtType::bStrToFlt( rosValue, &dfValue ) ) return( false ); // If there is a units specifier check that it matches the object's units type if( UnitsBase::bGetUnitsType( rosValue, &eUType ) ) if( eUType!=eGetUnitsType( ) && eUType!=eUNITS_NONE ) return( false ); // Set the value. Do different things depending on the units control on display switch( m_eShowUnits ) { case eSHOW_CHO : // Look for a units prefix and attempt to set the units accordingly sz1 = rosValue.find_first_not_of( wxT(" .-+0123456789Ee") ); if( sz1 != std::string::npos ) if( CnvtType::bUnitPfxToExp( rosValue[ sz1 ], &iPfx ) ) if( bSetValue( dfValue / EXP10( (double) iPfx ), iPfx ) ) break; // See if the value can be set without units if( bSetValue( dfValue, 0 ) ) if( dfValue == dfGetValue( ) ) break; // Set the value and allow the choice control to select an appropriate units prefix if( ! bSetValue( dfValue ) ) return( false ); break; case eSHOW_LBL : if( ! bSetValue( dfValue ) ) return( false ); break; case eSHOW_NONE : if( ! m_oSpnValue.bSetValue( rosValue ) ) return( false ); break; } return( true ); } //************************************************************************************************** // Set the units to be displayed in the choice control or static label. // // Argument List : // rosUnits - The units to be displayed // // Return Values : // Success - true // Failure - false bool PnlValue::bSetUnits( const wxString & rosUnits ) { if( ! bIsCreated( ) ) return( false ); switch( m_eShowUnits ) { case eSHOW_CHO : if( ! m_oChoUnits.bSetUnits( rosUnits ) ) return( false ); break; case eSHOW_LBL : if( ! m_oLblUnits.bSetUnits( rosUnits ) ) return( false ); break; case eSHOW_NONE : return( false ); } return( true ); } //************************************************************************************************** // Specify if and how units should be displayed. // // The units can be hidden or displayed in either a choice control or a static label. A choice // control allowes the user to specify the units. A label simply displays the units. // // Argument List : // eShow - Enumerated show (units) specifier // // Return Values : // Success - true // Failure - false bool PnlValue::bShowUnits( eTypeShow eShow ) { if( ! bIsCreated( ) ) return( false ); switch( eShow ) { case eSHOW_CHO : m_oChoUnits.Show( true ); m_oLblUnits.Show( false ); break; case eSHOW_LBL : m_oChoUnits.Show( false ); m_oLblUnits.Show( true ); break; case eSHOW_NONE : m_oChoUnits.Show( false ); m_oLblUnits.Show( false ); break; } m_eShowUnits = eShow; return( true ); } //************************************************************************************************** // Get the variable name. // // Return Values : // Success - The variable name as a string // Failure - An empty string const wxString & PnlValue::rosGetName( void ) { static wxString osName; osName.Empty( ); if( ! bIsCreated( ) ) return( osName ); osName = m_oLblName.GetLabel( ); return( osName ); } //************************************************************************************************** // Get the spin control value including units as an integer. // // Return Values : // Success - The value as a long integer // Failure - NOVAL_LNG long PnlValue::liGetValue( void ) { double df1; long li1=0; // Has the control been created? if( ! bIsCreated( ) ) return( NOVAL_LNG ); // Get the spin control as a float and check it can be converted to a long df1 = m_oSpnValue.dfGetValue( ); if( df1LONG_MAX ) return( NOVAL_LNG ); // Get the value combining it with any units switch( m_eShowUnits ) { case eSHOW_CHO : li1 = m_oChoUnits.liGetValue( df1 ); break; case eSHOW_LBL : li1 = m_oLblUnits.liGetValue( df1 ); break; case eSHOW_NONE : li1 = m_oSpnValue.liGetValue( ); break; } return( li1 ); } //************************************************************************************************** // Get the spin control value including units as a float. // // Return Values : // Success - The value as a double precision float // Failure - NOVAL_DBL double PnlValue::dfGetValue( void ) { double df1; // Has the control been created? if( ! bIsCreated( ) ) return( NOVAL_DBL ); // Get the spin control value df1 = m_oSpnValue.dfGetValue( ); if( df1 == NOVAL_DBL ) return( NOVAL_DBL ); // Combine the spin control value with any units switch( m_eShowUnits ) { case eSHOW_CHO : df1 = m_oChoUnits.dfGetValue( df1 ); break; case eSHOW_LBL : df1 = m_oLblUnits.dfGetValue( df1 ); break; case eSHOW_NONE : break; } return( df1 ); } //************************************************************************************************** // Get the spin control value including units as a string. // // Return Values : // Success - The value as a string // Failure - An empty string const wxString & PnlValue::rosGetValue( void ) { static wxString osValue; double df1; osValue.Empty( ); // Has the control been created? if( ! bIsCreated( ) ) return( osValue ); // Test the spin control value df1 = m_oSpnValue.dfGetValue( ); if( df1 == NOVAL_DBL ) return( osValue ); // Combine the spin control value with any units osValue = m_oSpnValue.rosGetValue( ); switch( m_eShowUnits ) { case eSHOW_CHO : if( m_oChoUnits.iGetUnits( ) != 0 ) osValue = m_oChoUnits.rosGetValue( df1 ); break; case eSHOW_LBL : if( m_oLblUnits.iGetUnits( ) != 0 ) osValue = m_oLblUnits.rosGetValue( df1 ); break; case eSHOW_NONE : break; } return( osValue ); } //************************************************************************************************** // Get the units type. // // Return Values : // Enumerated units type specifier eTypeUnits PnlValue::eGetUnitsType( void ) { eTypeUnits eUType=eUNITS_NONE; switch( m_eShowUnits ) { case eSHOW_CHO : eUType = m_oChoUnits.eGetUnitsType( ); break; case eSHOW_LBL : eUType = m_oLblUnits.eGetUnitsType( ); break; case eSHOW_NONE : eUType = eUNITS_NONE; break; } return( eUType ); } //************************************************************************************************** // Get the units. // // Return Values : // Success - The currently selected units // Failure - An empty string const wxString & PnlValue::rosGetUnits( void ) { static wxString osUnits; osUnits.Empty( ); if( ! bIsCreated( ) ) return( osUnits ); switch( m_eShowUnits ) { case eSHOW_CHO : osUnits = m_oChoUnits.rosGetUnits( ); case eSHOW_LBL : osUnits = m_oLblUnits.rosGetUnits( ); case eSHOW_NONE : break; } return( osUnits ); } //************************************************************************************************** // Print the object attributes. // // Argument List : // rosPrefix - A prefix to every line displayed (usually just spaces) void PnlValue::Print( const wxString & rosPrefix ) { m_oSpnValue.Print( rosPrefix + wxT("m_oSpnValue.") ); m_oChoUnits.Print( rosPrefix + wxT("m_oChoUnits.") ); m_oLblUnits.Print( rosPrefix + wxT("m_oLblUnits.") ); } //************************************************************************************************** // Event Handlers * //************************************************************************************************** // Spin button scroll event handler. // // Combine the spin control value and the choice control units // // Argument List : // roEvtSpn - An object holding information about the event void PnlValue::OnSpnScroll( wxSpinEvent & roEvtSpn ) { double dfMan, df1; int iExp; // If there's no units or the units are fixed then skip this event handler if( m_eShowUnits != eSHOW_CHO ) return; switch( m_oChoUnits.eGetUnitsType( ) ) { case eUNITS_TMPC : case eUNITS_TMPF : case eUNITS_PHAD : case eUNITS_PHAR : return; default : break; } // Get the current values for the value and it's units dfMan = m_oSpnValue.dfGetValue( ); iExp = m_oChoUnits.iGetUnits( ); df1 = dfMan; // Determine the event type and act accordingly if( roEvtSpn.GetEventType( ) == wxEVT_SCROLL_LINEUP ) { // Increment the value if( dfMan > 0.0 ) { // Positive numbers if( dfMan <= 1000.0 ) return; df1 = 1.0; iExp += 3; } else { // Negative numbers if( dfMan <= -1.0 ) return; df1 = -1000.0; iExp -= 3; } } else if( roEvtSpn.GetEventType( ) == wxEVT_SCROLL_LINEDOWN ) { // Decrement the value if( dfMan < 0.0 ) { // Negative numbers if( dfMan >= -1000.0 ) return; df1 = -1.0; iExp += 3; } else { // Positive numbers if( dfMan >= 1.0 ) return; df1 = 1000.0; iExp -= 3; } } else return; // Set the new spin control and choice control values if( m_oChoUnits.bSetUnits( iExp ) ) dfMan = df1; m_oSpnValue.bSetValue( dfMan ); } //************************************************************************************************** // Units choice box event handler. // // Argument List : // roEvtCmd - An object holding information about the event void PnlValue::OnChoUnits( wxCommandEvent & roEvtCmd ) { eTypeUnits eUType; eUType = m_oChoUnits.eGetUnitsType( ); if( eUType==eUNITS_TMPC || eUType==eUNITS_TMPF ) { if( m_oChoUnits.rosGetUnits( ).IsSameAs( wxT("Deg.C") ) ) bSetUnitsType( eUNITS_TMPC ); else if( m_oChoUnits.rosGetUnits( ).IsSameAs( wxT("Deg.F") ) ) bSetUnitsType( eUNITS_TMPF ); } else if( eUType==eUNITS_PHAD || eUType==eUNITS_PHAR ) { if( m_oChoUnits.rosGetUnits( ).IsSameAs( wxT("Degree") ) ) bSetUnitsType( eUNITS_PHAD ); else if( m_oChoUnits.rosGetUnits( ).IsSameAs( wxT("Radian") ) ) bSetUnitsType( eUNITS_PHAR ); } } //**************************************************************************************************