Improve robustness of numeric evaluation.
It would appear that some platforms process the KILL_FOCUS event after running TransferDataFromWindow(). This change makes sure that the evaluation is done no matter the order. Fixes: lp:1793911 * https://bugs.launchpad.net/kicad/+bug/1793911
This commit is contained in:
parent
90df7a8b22
commit
3024ded91e
|
@ -136,6 +136,12 @@ bool NUMERIC_EVALUATOR::Process( const wxString& aString )
|
||||||
m_parseFinished = false;
|
m_parseFinished = false;
|
||||||
Token tok;
|
Token tok;
|
||||||
|
|
||||||
|
if( aString.IsEmpty() )
|
||||||
|
{
|
||||||
|
m_parseFinished = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
tok = getToken();
|
tok = getToken();
|
||||||
|
|
|
@ -76,9 +76,6 @@ void TEXT_CTRL_EVAL::onTextEnter( wxCommandEvent& aEvent )
|
||||||
|
|
||||||
void TEXT_CTRL_EVAL::evaluate()
|
void TEXT_CTRL_EVAL::evaluate()
|
||||||
{
|
{
|
||||||
if( GetValue().IsEmpty() )
|
|
||||||
wxTextCtrl::SetValue( "0" );
|
|
||||||
|
|
||||||
if( m_eval.Process( GetValue() ) )
|
if( m_eval.Process( GetValue() ) )
|
||||||
SetValue( m_eval.Result() );
|
SetValue( m_eval.Result() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent,
|
||||||
m_min = aMin;
|
m_min = aMin;
|
||||||
m_max = aMax;
|
m_max = aMax;
|
||||||
m_allowEval = allowEval && dynamic_cast<wxTextEntry*>( m_value );
|
m_allowEval = allowEval && dynamic_cast<wxTextEntry*>( m_value );
|
||||||
|
m_needsEval = false;
|
||||||
|
|
||||||
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
||||||
if( textEntry )
|
if( textEntry )
|
||||||
|
@ -58,13 +59,6 @@ UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent,
|
||||||
|
|
||||||
m_value->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), NULL, this );
|
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_value->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this );
|
||||||
|
|
||||||
// Connect wxEVT_TEXT_ENTER when (and *only when*) m_value has the wxTE_PROCESS_ENTER style
|
|
||||||
// because if this style does not exist:
|
|
||||||
// 1 - Connect wxEVT_TEXT_ENTER is useless
|
|
||||||
// 2 - it generates wxWidgets assert
|
|
||||||
if( m_value->HasFlag( wxTE_PROCESS_ENTER ) )
|
|
||||||
m_value->Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( UNIT_BINDER::onTextEnter ), NULL, this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +80,8 @@ void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
|
||||||
|
|
||||||
if( oldStr.length() )
|
if( oldStr.length() )
|
||||||
textEntry->SetValue( oldStr );
|
textEntry->SetValue( oldStr );
|
||||||
|
|
||||||
|
m_needsEval = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
aEvent.Skip();
|
aEvent.Skip();
|
||||||
|
@ -94,8 +90,15 @@ void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
|
||||||
|
|
||||||
void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
|
void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
|
||||||
{
|
{
|
||||||
if( m_allowEval )
|
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
||||||
evaluate();
|
|
||||||
|
if( m_allowEval && textEntry )
|
||||||
|
{
|
||||||
|
if( m_eval.Process( textEntry->GetValue() ) )
|
||||||
|
textEntry->ChangeValue( m_eval.Result() );
|
||||||
|
|
||||||
|
m_needsEval = false;
|
||||||
|
}
|
||||||
|
|
||||||
Validate( true );
|
Validate( true );
|
||||||
|
|
||||||
|
@ -103,32 +106,6 @@ void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UNIT_BINDER::onTextEnter( wxCommandEvent& aEvent )
|
|
||||||
{
|
|
||||||
if( m_allowEval )
|
|
||||||
evaluate();
|
|
||||||
|
|
||||||
// Send an OK event to the parent dialog
|
|
||||||
wxCommandEvent event( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK );
|
|
||||||
wxPostEvent( m_value->GetParent(), event );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void UNIT_BINDER::evaluate()
|
|
||||||
{
|
|
||||||
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
|
||||||
|
|
||||||
if( !textEntry )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( textEntry->GetValue().IsEmpty() )
|
|
||||||
textEntry->ChangeValue( "0" );
|
|
||||||
|
|
||||||
if( m_eval.Process( textEntry->GetValue() ) )
|
|
||||||
textEntry->ChangeValue( m_eval.Result() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wxString valueDescriptionFromLabel( wxStaticText* aLabel )
|
wxString valueDescriptionFromLabel( wxStaticText* aLabel )
|
||||||
{
|
{
|
||||||
wxString desc = aLabel->GetLabel();
|
wxString desc = aLabel->GetLabel();
|
||||||
|
@ -208,10 +185,13 @@ void UNIT_BINDER::SetValue( int aValue )
|
||||||
|
|
||||||
void UNIT_BINDER::SetValue( wxString aValue )
|
void UNIT_BINDER::SetValue( wxString aValue )
|
||||||
{
|
{
|
||||||
if( dynamic_cast<wxTextEntry*>( m_value ) )
|
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
||||||
dynamic_cast<wxTextEntry*>( m_value )->SetValue( aValue );
|
auto staticText = dynamic_cast<wxStaticText*>( m_value );
|
||||||
else if( dynamic_cast<wxStaticText*>( m_value ) )
|
|
||||||
dynamic_cast<wxStaticText*>( m_value )->SetLabel( aValue );
|
if( textEntry )
|
||||||
|
textEntry->SetValue( aValue );
|
||||||
|
else if( staticText )
|
||||||
|
staticText->SetLabel( aValue );
|
||||||
|
|
||||||
if( m_allowEval )
|
if( m_allowEval )
|
||||||
m_eval.Clear();
|
m_eval.Clear();
|
||||||
|
@ -228,10 +208,13 @@ void UNIT_BINDER::ChangeValue( int aValue )
|
||||||
|
|
||||||
void UNIT_BINDER::ChangeValue( wxString aValue )
|
void UNIT_BINDER::ChangeValue( wxString aValue )
|
||||||
{
|
{
|
||||||
if( dynamic_cast<wxTextEntry*>( m_value ) )
|
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
||||||
dynamic_cast<wxTextEntry*>( m_value )->ChangeValue( aValue );
|
auto staticText = dynamic_cast<wxStaticText*>( m_value );
|
||||||
else if( dynamic_cast<wxStaticText*>( m_value ) )
|
|
||||||
dynamic_cast<wxStaticText*>( m_value )->SetLabel( aValue );
|
if( textEntry )
|
||||||
|
textEntry->ChangeValue( aValue );
|
||||||
|
else if( staticText )
|
||||||
|
staticText->SetLabel( aValue );
|
||||||
|
|
||||||
if( m_allowEval )
|
if( m_allowEval )
|
||||||
m_eval.Clear();
|
m_eval.Clear();
|
||||||
|
@ -240,23 +223,34 @@ void UNIT_BINDER::ChangeValue( wxString aValue )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int UNIT_BINDER::GetValue() const
|
int UNIT_BINDER::GetValue()
|
||||||
{
|
{
|
||||||
wxString s;
|
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
||||||
|
auto staticText = dynamic_cast<wxStaticText*>( m_value );
|
||||||
|
|
||||||
if( dynamic_cast<wxTextEntry*>( m_value ) )
|
if( m_needsEval && textEntry )
|
||||||
s = dynamic_cast<wxTextEntry*>( m_value )->GetValue();
|
{
|
||||||
else if( dynamic_cast<wxStaticText*>( m_value ) )
|
if( m_eval.Process( textEntry->GetValue() ) )
|
||||||
s = dynamic_cast<wxStaticText*>( m_value )->GetLabel();
|
textEntry->ChangeValue( m_eval.Result() );
|
||||||
|
|
||||||
return ValueFromString( m_units, s, m_useMils );
|
m_needsEval = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( textEntry )
|
||||||
|
return ValueFromString( m_units, textEntry->GetValue(), m_useMils );
|
||||||
|
else if( staticText )
|
||||||
|
return ValueFromString( m_units, staticText->GetLabel(), m_useMils );
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool UNIT_BINDER::IsIndeterminate() const
|
bool UNIT_BINDER::IsIndeterminate() const
|
||||||
{
|
{
|
||||||
if( dynamic_cast<wxTextEntry*>( m_value ) )
|
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
|
||||||
return dynamic_cast<wxTextEntry*>( m_value )->GetValue() == INDETERMINATE;
|
|
||||||
|
if( textEntry )
|
||||||
|
return textEntry->GetValue() == INDETERMINATE;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ public:
|
||||||
* Function GetValue
|
* Function GetValue
|
||||||
* Returns the current value in Internal Units.
|
* Returns the current value in Internal Units.
|
||||||
*/
|
*/
|
||||||
virtual int GetValue() const;
|
virtual int GetValue();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function IsIndeterminate
|
* Function IsIndeterminate
|
||||||
|
@ -125,11 +125,8 @@ protected:
|
||||||
|
|
||||||
void onSetFocus( wxFocusEvent& aEvent );
|
void onSetFocus( wxFocusEvent& aEvent );
|
||||||
void onKillFocus( wxFocusEvent& aEvent );
|
void onKillFocus( wxFocusEvent& aEvent );
|
||||||
void onTextEnter( wxCommandEvent& aEvent );
|
|
||||||
void delayedFocusHandler( wxIdleEvent& aEvent );
|
void delayedFocusHandler( wxIdleEvent& aEvent );
|
||||||
|
|
||||||
void evaluate();
|
|
||||||
|
|
||||||
///> The bound widgets
|
///> The bound widgets
|
||||||
wxStaticText* m_label;
|
wxStaticText* m_label;
|
||||||
wxWindow* m_value;
|
wxWindow* m_value;
|
||||||
|
@ -147,6 +144,7 @@ protected:
|
||||||
///> Evaluator
|
///> Evaluator
|
||||||
NUMERIC_EVALUATOR m_eval;
|
NUMERIC_EVALUATOR m_eval;
|
||||||
bool m_allowEval;
|
bool m_allowEval;
|
||||||
|
bool m_needsEval;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __UNIT_BINDER_H_ */
|
#endif /* __UNIT_BINDER_H_ */
|
||||||
|
|
Loading…
Reference in New Issue