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;
case EDA_UNITS::DEGREES:
format = wxT( "%.1f" );
// 3 digits in mantissa should be good for rotation in degree
format = wxT( "%.3f" );
break;
case EDA_UNITS::UNSCALED:

View File

@ -35,11 +35,11 @@
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 ) :
m_frame( aParent ),
m_label( aLabel ),
m_value( aValue ),
m_valueCtrl( aValueCtrl ),
m_unitLabel( aUnitLabel ),
m_eval( aParent->GetUserUnits() ),
m_originTransforms( aParent->GetOriginTransforms() ),
@ -47,12 +47,13 @@ UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindo
{
m_units = aParent->GetUserUnits();
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_selStart = 0;
m_selEnd = 0;
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value );
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( textEntry )
{
@ -60,10 +61,11 @@ UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindo
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_value->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this );
m_valueCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), NULL, this );
m_valueCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this );
Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), NULL, 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 )
{
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 )
{
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 )
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value );
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( m_allowEval && textEntry )
{
@ -125,7 +137,7 @@ void UNIT_BINDER::onSetFocus( 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 )
{
@ -168,16 +180,16 @@ wxString valueDescriptionFromLabel( wxStaticText* aLabel )
void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
{
if( !m_errorMessage.IsEmpty() )
DisplayError( m_value->GetParent(), m_errorMessage );
DisplayError( m_valueCtrl->GetParent(), m_errorMessage );
m_errorMessage = wxEmptyString;
m_value->SetFocus();
m_valueCtrl->SetFocus();
}
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
|| textEntry->GetValue() == INDETERMINATE_ACTION
@ -231,14 +243,15 @@ void UNIT_BINDER::SetValue( int aValue )
void UNIT_BINDER::SetDoubleValue( double aValue )
{
double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
displayValue = setPrecision( displayValue, false );
SetValue( StringFromValue( m_units, displayValue, false, m_dataType ) );
}
void UNIT_BINDER::SetValue( wxString aValue )
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value );
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
if( textEntry )
textEntry->SetValue( aValue );
@ -248,7 +261,8 @@ void UNIT_BINDER::SetValue( wxString aValue )
if( m_allowEval )
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 )
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value );
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
if( textEntry )
textEntry->ChangeValue( aValue );
@ -273,14 +287,15 @@ void UNIT_BINDER::ChangeValue( const wxString& aValue )
if( m_allowEval )
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()
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value );
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
wxString value;
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()
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value );
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
wxString value;
if( textEntry )
@ -323,13 +354,15 @@ double UNIT_BINDER::GetDoubleValue()
}
double displayValue = DoubleValueFromString( m_units, value, m_dataType );
displayValue = setPrecision( displayValue, false );
return m_originTransforms.FromDisplay( displayValue, m_coordType );
}
bool UNIT_BINDER::IsIndeterminate() const
{
wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_value );
wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl );
if( te )
return te->GetValue() == INDETERMINATE_STATE || te->GetValue() == INDETERMINATE_ACTION;
@ -340,8 +373,8 @@ bool UNIT_BINDER::IsIndeterminate() const
wxString UNIT_BINDER::GetOriginalText() const
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_value );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_value );
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
if( m_allowEval )
return m_eval.OriginalText();
@ -363,30 +396,38 @@ void UNIT_BINDER::SetLabel( const wxString& aLabel )
void UNIT_BINDER::Enable( bool aEnable )
{
m_label->Enable( aEnable );
m_value->Enable( aEnable );
m_unitLabel->Enable( aEnable );
m_valueCtrl->Enable( aEnable );
if( m_unitLabel )
m_unitLabel->Enable( aEnable );
}
void UNIT_BINDER::Show( bool aShow, bool aResize )
{
m_label->Show( aShow );
m_value->Show( aShow );
m_unitLabel->Show( aShow );
m_valueCtrl->Show( aShow );
if( m_unitLabel )
m_unitLabel->Show( aShow );
if( aResize )
{
if( aShow )
{
m_label->SetSize( -1, -1 );
m_value->SetSize( -1, -1 );
m_unitLabel->SetSize( -1, -1 );
m_valueCtrl->SetSize( -1, -1 );
if( m_unitLabel )
m_unitLabel->SetSize( -1, -1 );
}
else
{
m_label->SetSize( 0, 0 );
m_value->SetSize( 0, 0 );
m_unitLabel->SetSize( 0, 0 );
m_valueCtrl->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 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)
* @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.).
* @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
*/
UNIT_BINDER( EDA_DRAW_FRAME* aParent,
wxStaticText* aLabel, wxWindow* aValue, wxStaticText* aUnitLabel,
wxStaticText* aLabel, wxWindow* aValueCtrl, wxStaticText* aUnitLabel,
bool aAllowEval = true );
~UNIT_BINDER() override;
/**
* Function SetUnits
* Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be
* used to set to DEGREES for angular controls.
*/
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)
* @param aDataType is the datatype to use for the units text display
@ -84,6 +93,8 @@ public:
* Function SetDoubleValue
* Sets new value (in Internal Units) for the text field, taking care of units conversion.
* @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 );
@ -106,6 +117,8 @@ public:
/**
* Function GetValue
* 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();
@ -178,16 +191,28 @@ protected:
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;
///> The bound widgets
wxStaticText* m_label;
wxWindow* m_value;
wxStaticText* m_unitLabel;
wxWindow* m_valueCtrl;
wxStaticText* m_unitLabel; // Can be nullptr
///> Currently used units.
EDA_UNITS m_units;
EDA_DATA_TYPE m_dataType;
int m_precision; // 0 to 6
///> Validation support.
wxString m_errorMessage;