UNIT_BINDER: better support of DEGREES units (and some fixes).

Especially, add a way to define the number of digits in mantissa.
base_units.cpp: set number of digits in mantissa to 3 instead of 1 for DEGREES
This commit is contained in:
jean-pierre charras 2020-12-10 15:46:20 +01:00
parent d1fe4a0c98
commit f26a1a32e0
3 changed files with 108 additions and 41 deletions

View File

@ -187,7 +187,8 @@ wxString MessageTextFromValue( EDA_UNITS aUnits, double aValue, bool aAddUnitLab
break; break;
case EDA_UNITS::DEGREES: case EDA_UNITS::DEGREES:
format = wxT( "%.1f" ); // 3 digits in mantissa should be good for rotation in degree
format = wxT( "%.3f" );
break; break;
case EDA_UNITS::UNSCALED: case EDA_UNITS::UNSCALED:

View File

@ -35,11 +35,11 @@
wxDEFINE_EVENT( DELAY_FOCUS, wxCommandEvent ); wxDEFINE_EVENT( DELAY_FOCUS, wxCommandEvent );
UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindow* aValue, UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindow* aValueCtrl,
wxStaticText* aUnitLabel, bool allowEval ) : wxStaticText* aUnitLabel, bool allowEval ) :
m_frame( aParent ), m_frame( aParent ),
m_label( aLabel ), m_label( aLabel ),
m_value( aValue ), m_valueCtrl( aValueCtrl ),
m_unitLabel( aUnitLabel ), m_unitLabel( aUnitLabel ),
m_eval( aParent->GetUserUnits() ), m_eval( aParent->GetUserUnits() ),
m_originTransforms( aParent->GetOriginTransforms() ), m_originTransforms( aParent->GetOriginTransforms() ),
@ -47,12 +47,13 @@ UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindo
{ {
m_units = aParent->GetUserUnits(); m_units = aParent->GetUserUnits();
m_dataType = EDA_DATA_TYPE::DISTANCE; m_dataType = EDA_DATA_TYPE::DISTANCE;
m_allowEval = allowEval && dynamic_cast<wxTextEntry*>( m_value ); m_precision = 0;
m_allowEval = allowEval && dynamic_cast<wxTextEntry*>( m_valueCtrl );
m_needsEval = false; m_needsEval = false;
m_selStart = 0; m_selStart = 0;
m_selEnd = 0; m_selEnd = 0;
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( textEntry ) if( textEntry )
{ {
@ -60,10 +61,11 @@ UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindo
textEntry->ChangeValue( wxT( "0" ) ); textEntry->ChangeValue( wxT( "0" ) );
} }
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) ); if( m_unitLabel )
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) );
m_value->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), NULL, this ); m_valueCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), NULL, this );
m_value->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this ); m_valueCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this );
Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), NULL, this ); Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), NULL, this );
m_frame->Connect( UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ), nullptr, this ); m_frame->Connect( UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ), nullptr, this );
@ -79,14 +81,24 @@ UNIT_BINDER::~UNIT_BINDER()
void UNIT_BINDER::SetUnits( EDA_UNITS aUnits ) void UNIT_BINDER::SetUnits( EDA_UNITS aUnits )
{ {
m_units = aUnits; m_units = aUnits;
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) );
if( m_unitLabel )
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) );
}
void UNIT_BINDER::SetPrecision( int aLength )
{
m_precision = std::min( aLength, 6 );
} }
void UNIT_BINDER::SetDataType( EDA_DATA_TYPE aDataType ) void UNIT_BINDER::SetDataType( EDA_DATA_TYPE aDataType )
{ {
m_dataType = aDataType; m_dataType = aDataType;
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) );
if( m_unitLabel )
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) );
} }
@ -104,7 +116,7 @@ void UNIT_BINDER::onUnitsChanged( wxCommandEvent& aEvent )
void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent ) void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( m_allowEval && textEntry ) if( m_allowEval && textEntry )
{ {
@ -125,7 +137,7 @@ void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent ) void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( m_allowEval && textEntry ) if( m_allowEval && textEntry )
{ {
@ -168,16 +180,16 @@ wxString valueDescriptionFromLabel( wxStaticText* aLabel )
void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& ) void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
{ {
if( !m_errorMessage.IsEmpty() ) if( !m_errorMessage.IsEmpty() )
DisplayError( m_value->GetParent(), m_errorMessage ); DisplayError( m_valueCtrl->GetParent(), m_errorMessage );
m_errorMessage = wxEmptyString; m_errorMessage = wxEmptyString;
m_value->SetFocus(); m_valueCtrl->SetFocus();
} }
bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits ) bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits )
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( !textEntry if( !textEntry
|| textEntry->GetValue() == INDETERMINATE_ACTION || textEntry->GetValue() == INDETERMINATE_ACTION
@ -231,14 +243,15 @@ void UNIT_BINDER::SetValue( int aValue )
void UNIT_BINDER::SetDoubleValue( double aValue ) void UNIT_BINDER::SetDoubleValue( double aValue )
{ {
double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType ); double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
displayValue = setPrecision( displayValue, false );
SetValue( StringFromValue( m_units, displayValue, false, m_dataType ) ); SetValue( StringFromValue( m_units, displayValue, false, m_dataType ) );
} }
void UNIT_BINDER::SetValue( wxString aValue ) void UNIT_BINDER::SetValue( wxString aValue )
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value ); wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
if( textEntry ) if( textEntry )
textEntry->SetValue( aValue ); textEntry->SetValue( aValue );
@ -248,7 +261,8 @@ void UNIT_BINDER::SetValue( wxString aValue )
if( m_allowEval ) if( m_allowEval )
m_eval.Clear(); m_eval.Clear();
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) ); if( m_unitLabel )
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) );
} }
@ -262,8 +276,8 @@ void UNIT_BINDER::ChangeValue( int aValue )
void UNIT_BINDER::ChangeValue( const wxString& aValue ) void UNIT_BINDER::ChangeValue( const wxString& aValue )
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value ); wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
if( textEntry ) if( textEntry )
textEntry->ChangeValue( aValue ); textEntry->ChangeValue( aValue );
@ -273,14 +287,15 @@ void UNIT_BINDER::ChangeValue( const wxString& aValue )
if( m_allowEval ) if( m_allowEval )
m_eval.Clear(); m_eval.Clear();
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) ); if( m_unitLabel )
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_dataType ) );
} }
long long int UNIT_BINDER::GetValue() long long int UNIT_BINDER::GetValue()
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value ); wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
wxString value; wxString value;
if( textEntry ) if( textEntry )
@ -300,10 +315,26 @@ long long int UNIT_BINDER::GetValue()
} }
double UNIT_BINDER::setPrecision( double aValue, bool aValueUsesUserUnits )
{
if( m_precision > 1 )
{
int scale = pow( 10, m_precision );
long long tmp = aValueUsesUserUnits ? aValue : To_User_Unit( m_units, aValue ) * scale;
aValue = static_cast<double>( tmp ) / scale;
if( !aValueUsesUserUnits )
aValue = From_User_Unit( m_units, aValue );
}
return aValue;
}
double UNIT_BINDER::GetDoubleValue() double UNIT_BINDER::GetDoubleValue()
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value ); wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
wxString value; wxString value;
if( textEntry ) if( textEntry )
@ -323,13 +354,15 @@ double UNIT_BINDER::GetDoubleValue()
} }
double displayValue = DoubleValueFromString( m_units, value, m_dataType ); double displayValue = DoubleValueFromString( m_units, value, m_dataType );
displayValue = setPrecision( displayValue, false );
return m_originTransforms.FromDisplay( displayValue, m_coordType ); return m_originTransforms.FromDisplay( displayValue, m_coordType );
} }
bool UNIT_BINDER::IsIndeterminate() const bool UNIT_BINDER::IsIndeterminate() const
{ {
wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( te ) if( te )
return te->GetValue() == INDETERMINATE_STATE || te->GetValue() == INDETERMINATE_ACTION; return te->GetValue() == INDETERMINATE_STATE || te->GetValue() == INDETERMINATE_ACTION;
@ -340,8 +373,8 @@ bool UNIT_BINDER::IsIndeterminate() const
wxString UNIT_BINDER::GetOriginalText() const wxString UNIT_BINDER::GetOriginalText() const
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value ); wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
if( m_allowEval ) if( m_allowEval )
return m_eval.OriginalText(); return m_eval.OriginalText();
@ -363,30 +396,38 @@ void UNIT_BINDER::SetLabel( const wxString& aLabel )
void UNIT_BINDER::Enable( bool aEnable ) void UNIT_BINDER::Enable( bool aEnable )
{ {
m_label->Enable( aEnable ); m_label->Enable( aEnable );
m_value->Enable( aEnable ); m_valueCtrl->Enable( aEnable );
m_unitLabel->Enable( aEnable );
if( m_unitLabel )
m_unitLabel->Enable( aEnable );
} }
void UNIT_BINDER::Show( bool aShow, bool aResize ) void UNIT_BINDER::Show( bool aShow, bool aResize )
{ {
m_label->Show( aShow ); m_label->Show( aShow );
m_value->Show( aShow ); m_valueCtrl->Show( aShow );
m_unitLabel->Show( aShow );
if( m_unitLabel )
m_unitLabel->Show( aShow );
if( aResize ) if( aResize )
{ {
if( aShow ) if( aShow )
{ {
m_label->SetSize( -1, -1 ); m_label->SetSize( -1, -1 );
m_value->SetSize( -1, -1 ); m_valueCtrl->SetSize( -1, -1 );
m_unitLabel->SetSize( -1, -1 );
if( m_unitLabel )
m_unitLabel->SetSize( -1, -1 );
} }
else else
{ {
m_label->SetSize( 0, 0 ); m_label->SetSize( 0, 0 );
m_value->SetSize( 0, 0 ); m_valueCtrl->SetSize( 0, 0 );
m_unitLabel->SetSize( 0, 0 );
if( m_unitLabel )
m_unitLabel->SetSize( 0, 0 );
} }
} }
} }

View File

@ -47,24 +47,33 @@ public:
* @param aParent is the parent EDA_DRAW_FRAME. * @param aParent is the parent EDA_DRAW_FRAME.
* @param aLabel is the static text used to label the text input widget (note: the label * @param aLabel is the static text used to label the text input widget (note: the label
* text, trimmed of its colon, will also be used in error messages) * text, trimmed of its colon, will also be used in error messages)
* @param aValue is the control used to edit or display the given value (wxTextCtrl, * @param aValueCtrl is the control used to edit or display the given value (wxTextCtrl,
* wxComboBox, wxStaticText, etc.). * wxComboBox, wxStaticText, etc.).
* @param aUnitLabel is the units label displayed after the text input widget * @param aUnitLabel is the units label displayed after the text input widget
* Can be nullptr.
* @param aAllowEval indicates \a aTextInput's content should be eval'ed before storing * @param aAllowEval indicates \a aTextInput's content should be eval'ed before storing
*/ */
UNIT_BINDER( EDA_DRAW_FRAME* aParent, UNIT_BINDER( EDA_DRAW_FRAME* aParent,
wxStaticText* aLabel, wxWindow* aValue, wxStaticText* aUnitLabel, wxStaticText* aLabel, wxWindow* aValueCtrl, wxStaticText* aUnitLabel,
bool aAllowEval = true ); bool aAllowEval = true );
~UNIT_BINDER() override; ~UNIT_BINDER() override;
/** /**
* Function SetUnits
* Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be * Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be
* used to set to DEGREES for angular controls. * used to set to DEGREES for angular controls.
*/ */
virtual void SetUnits( EDA_UNITS aUnits ); virtual void SetUnits( EDA_UNITS aUnits );
/**
* Normally not needed, but can be used to set the precision when using
* internal units that are floats (not integers) like DEGREES or PERCENT.
* Not used for integer values in IU
* @param aLength is the number of digits for mantissa (0 = no truncation)
* must be <= 6
*/
virtual void SetPrecision( int aLength );
/** /**
* Used to override the datatype of the displayed property (default is DISTANCE) * Used to override the datatype of the displayed property (default is DISTANCE)
* @param aDataType is the datatype to use for the units text display * @param aDataType is the datatype to use for the units text display
@ -84,6 +93,8 @@ public:
* Function SetDoubleValue * Function SetDoubleValue
* Sets new value (in Internal Units) for the text field, taking care of units conversion. * Sets new value (in Internal Units) for the text field, taking care of units conversion.
* @param aValue is the new value. * @param aValue is the new value.
* the initialized value will be truncated according to the precision set by SetPrecision()
* (if not <= 0)
*/ */
virtual void SetDoubleValue( double aValue ); virtual void SetDoubleValue( double aValue );
@ -106,6 +117,8 @@ public:
/** /**
* Function GetValue * Function GetValue
* Returns the current value in Internal Units. * Returns the current value in Internal Units.
* the returned value will be truncated according to the precision set by
* SetPrecision() (if not <= 0)
*/ */
virtual double GetDoubleValue(); virtual double GetDoubleValue();
@ -178,16 +191,28 @@ protected:
void onUnitsChanged( wxCommandEvent& aEvent ); void onUnitsChanged( wxCommandEvent& aEvent );
/** When m_precision > 0 truncate the value aValue to show only
* m_precision digits in mantissa.
* used in GetDoubleValue to return a rounded value.
* Mainly for units set to DEGREES.
* @param aValue is the value to modify.
* @param aValueUsesUserUnits must be set to true if aValue is a user value,
* and set to false if aValue is a internal unit value.
* @return the "rounded" value.
*/
double setPrecision( double aValue, bool aValueUsesUserUnits );
EDA_DRAW_FRAME* m_frame; EDA_DRAW_FRAME* m_frame;
///> The bound widgets ///> The bound widgets
wxStaticText* m_label; wxStaticText* m_label;
wxWindow* m_value; wxWindow* m_valueCtrl;
wxStaticText* m_unitLabel; wxStaticText* m_unitLabel; // Can be nullptr
///> Currently used units. ///> Currently used units.
EDA_UNITS m_units; EDA_UNITS m_units;
EDA_DATA_TYPE m_dataType; EDA_DATA_TYPE m_dataType;
int m_precision; // 0 to 6
///> Validation support. ///> Validation support.
wxString m_errorMessage; wxString m_errorMessage;