WxValidator

From WxWiki

Jump to: navigation, search

[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;
}
Personal tools