WxValidator
From WxWiki
[edit] Hint
For those trying to write their own validators, when doing TransferToWindow() you should use the undocumented m_validatorWindow variable to know which control you should validate.
[edit] A Validator for float
- Tries to mimic the functionality of MFC floating point DDV/DDX functions, where upper and lower bounds can be set on a text control expecting numeric input.
- Works with single and double precision floating point values by using an overloaded constructor and a union type within the class for storing the value.
- Note that the Clone() method in the code shown below must be const.
- The overloading function's signature must match the overloaded signature exactly. For example, overloading wxValidate as Validate(wxWindow* parent, showErrorWindow=true) will not work even though it allows a call to Validate(wxWindow* parent).
class CfloatValidator : public wxValidator { public: CfloatValidator(float *pval, float lBound=FLT_MIN, float hBound=FLT_MAX); CfloatValidator(double *pval, double lBound=DBL_MIN, double hBound=DBL_MAX); CfloatValidator( const CfloatValidator& v ); wxObject *Clone() const; bool TransferFromWindow(); bool TransferToWindow(); bool Validate(wxWindow* parent); private: union fpt_union { double *d; float *s; } val; double m_lBound,m_hBound; enum { doubleType, singleType } m_type; CfloatValidator& operator=(const CfloatValidator&); };
CfloatValidator::CfloatValidator(float *pval, float lBound, float hBound) { val.s = pval; m_type = singleType; m_lBound = (double)lBound; m_hBound = (double)hBound; } CfloatValidator::CfloatValidator(double *pval, double lBound, double hBound) { val.d = pval; m_type = doubleType; m_lBound = lBound; m_hBound = hBound; } CfloatValidator::CfloatValidator( const CfloatValidator& v ) : wxValidator() { m_type = v.m_type; m_lBound = v.m_lBound; m_hBound = v.m_hBound; if (v.m_type == singleType) val.s = v.val.s; else val.d = v.val.d; } // Note the 'const' here wxObject *CfloatValidator::Clone() const { if (m_type == singleType) return new CfloatValidator(val.s, (float)m_lBound, (float)m_hBound); else return new CfloatValidator(val.d, m_lBound, m_hBound); } bool CfloatValidator::TransferFromWindow() { wxString s=((wxTextCtrl*)m_validatorWindow)->GetValue(); fpt_union t; int r; if (m_type == singleType) r=sscanf(s.fn_str()," %f",t.s); else r=sscanf(s.fn_str()," %g",t.d); if (r==1) { if (m_type == singleType) *val.s=*t.s; else *val.d=*t.d; return true; } return false; } bool CfloatValidator::TransferToWindow() { wxString buf; if (m_type == singleType) buf=wxString::Format(wxT("%g"),*val.s); else buf=wxString::Format(wxT("%g"),*val.d); ((wxTextCtrl*)m_validatorWindow)->SetValue(buf); return true; } bool CfloatValidator::Validate(wxWindow* parent) { wxString s=((wxTextCtrl*)m_validatorWindow)->GetValue(); fpt_union t; bool ret; if (m_type == singleType) { int r = sscanf(s.fn_str()," %f",t.s); ret = ( (r==1) && ( *t.s > m_lBound ) && ( *t.s < m_hBound ) ); } else { int r = sscanf(s.fn_str()," %g",t.d); ret = ( (r==1) && ( *t.d > m_lBound ) && ( *t.d < m_hBound ) ); } if (!ret) { wxString errmsg = wxString::Format(wxT("You must enter a number between %g and %g!"), m_lBound, m_hBound); wxMessageDialog dlg(parent,errmsg,wxT("Bad input"),wxOK); dlg.ShowModal(); } return ret; }
