Make NumValidator less bizzare

Originally committed to SVN as r5248.
This commit is contained in:
Thomas Goyne 2011-01-20 05:57:30 +00:00
parent a8ebc1e456
commit 5f0d5757be
10 changed files with 93 additions and 217 deletions

View file

@ -104,10 +104,8 @@ DialogProperties::DialogProperties (wxWindow *parent, AssFile *subs)
// Resolution box
wxSizer *ResSizer = new wxStaticBoxSizer(wxHORIZONTAL,this,_("Resolution"));
ResXValue = subs->GetScriptInfo(_T("PlayResX"));
ResYValue = subs->GetScriptInfo(_T("PlayResY"));
ResX = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(50,20),0,NumValidator(&ResXValue));
ResY = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(50,20),0,NumValidator(&ResYValue));
ResX = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(50,20),0,NumValidator(subs->GetScriptInfo("PlayResX")));
ResY = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(50,20),0,NumValidator(subs->GetScriptInfo("PlayResY")));
wxStaticText *ResText = new wxStaticText(this,-1,_T("x"));
wxButton *FromVideo = new wxButton(this,BUTTON_FROM_VIDEO,_("From video"));
if (!VideoContext::Get()->IsLoaded()) FromVideo->Enable(false);

View file

@ -91,12 +91,6 @@ class DialogProperties : public wxDialog {
wxCheckBox *ScaleBorder;
/// DOCME
wxString ResXValue;
/// DOCME
wxString ResYValue;
void OnOK(wxCommandEvent &event);
void OnSetFromVideo(wxCommandEvent &event);
int SetInfoIfDifferent(wxString key,wxString value);

View file

@ -99,10 +99,8 @@ DialogResample::DialogResample(agi::Context *c)
wxSizer *ResSizer = new wxBoxSizer(wxHORIZONTAL);
int sw,sh;
c->ass->GetResolution(sw,sh);
ResXValue = wxString::Format(_T("%i"),sw);
ResYValue = wxString::Format(_T("%i"),sh);
ResX = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(50,-1),0,NumValidator(&ResXValue));
ResY = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(50,-1),0,NumValidator(&ResYValue));
ResX = new wxTextCtrl(this,-1,"",wxDefaultPosition,wxSize(50,-1),0,NumValidator(wxString::Format("%i",sw)));
ResY = new wxTextCtrl(this,-1,"",wxDefaultPosition,wxSize(50,-1),0,NumValidator(wxString::Format("%i",sh)));
wxStaticText *ResText = new wxStaticText(this,-1,_("x"));
wxButton *FromVideo = new wxButton(this,BUTTON_DEST_FROM_VIDEO,_("From video"));
if (!VideoContext::Get()->IsLoaded()) FromVideo->Enable(false);

View file

@ -54,11 +54,6 @@ class AssOverrideParameter;
class DialogResample : public wxDialog {
agi::Context *c;
/// DOCME
/// DOCME
wxString ResXValue,ResYValue;
/// DOCME
wxTextCtrl *ResX;

View file

@ -108,14 +108,14 @@ DialogStyleEditor::DialogStyleEditor (wxWindow *parent, AssStyle *style, agi::Co
SetIcon(BitmapToIcon(GETIMAGE(style_toolbutton_24)));
// Prepare control values
FontSizeValue = AegiFloatToString(style->fontsize);
OutlineValue = AegiFloatToString(style->outline_w);
ShadowValue = AegiFloatToString(style->shadow_w);
ScaleXValue = AegiFloatToString(style->scalex);
ScaleYValue = AegiFloatToString(style->scaley);
AngleValue = AegiFloatToString(style->angle);
EncodingValue = AegiIntegerToString(style->encoding);
SpacingValue = AegiFloatToString(style->spacing);
wxString FontSizeValue = AegiFloatToString(style->fontsize);
wxString OutlineValue = AegiFloatToString(style->outline_w);
wxString ShadowValue = AegiFloatToString(style->shadow_w);
wxString ScaleXValue = AegiFloatToString(style->scalex);
wxString ScaleYValue = AegiFloatToString(style->scaley);
wxString AngleValue = AegiFloatToString(style->angle);
wxString EncodingValue = AegiIntegerToString(style->encoding);
wxString SpacingValue = AegiFloatToString(style->spacing);
wxString alignValues[9] = { _T("7"),_T("8"),_T("9"),_T("4"),_T("5"),_T("6"),_T("1"),_T("2"),_T("3") };
wxArrayString fontList = wxFontEnumerator::GetFacenames();
fontList.Sort();
@ -136,7 +136,7 @@ DialogStyleEditor::DialogStyleEditor (wxWindow *parent, AssStyle *style, agi::Co
// Create controls
StyleName = new wxTextCtrl(this,-1,style->name);
FontName = new wxComboBox(this,TEXT_FONT_NAME,style->font,wxDefaultPosition,wxSize(150,-1),0,0,wxCB_DROPDOWN);
FontSize = new wxTextCtrl(this,TEXT_FONT_SIZE,_T(""),wxDefaultPosition,wxSize(50,-1),0,NumValidator(&FontSizeValue,true,false));
FontSize = new wxTextCtrl(this,TEXT_FONT_SIZE,_T(""),wxDefaultPosition,wxSize(50,-1),0,NumValidator(FontSizeValue,true,false));
BoxBold = new wxCheckBox(this,CHECKBOX_STYLE_BOLD,_("Bold"));
BoxItalic = new wxCheckBox(this,CHECKBOX_STYLE_ITALIC,_("Italic"));
BoxUnderline = new wxCheckBox(this,CHECKBOX_STYLE_UNDERLINE,_("Underline"));
@ -152,13 +152,13 @@ DialogStyleEditor::DialogStyleEditor (wxWindow *parent, AssStyle *style, agi::Co
for (int i=0;i<3;i++) margin[i] = new wxSpinCtrl(this,TEXT_MARGIN_L+i,AegiFloatToString(style->Margin[i]),wxDefaultPosition,wxSize(60,-1),wxSP_ARROW_KEYS,0,9999,style->Margin[i]);
margin[3] = 0;
Alignment = new wxRadioBox(this, RADIO_ALIGNMENT, _("Alignment"), wxDefaultPosition, wxDefaultSize, 9, alignValues, 3, wxRA_SPECIFY_COLS);
Outline = new wxTextCtrl(this,TEXT_OUTLINE,_T(""),wxDefaultPosition,wxSize(40,20),0,NumValidator(&OutlineValue,true,false));
Shadow = new wxTextCtrl(this,TEXT_SHADOW,_T(""),wxDefaultPosition,wxSize(40,20),0,NumValidator(&ShadowValue,true,false));
Outline = new wxTextCtrl(this,TEXT_OUTLINE,_T(""),wxDefaultPosition,wxSize(40,20),0,NumValidator(OutlineValue,true,false));
Shadow = new wxTextCtrl(this,TEXT_SHADOW,_T(""),wxDefaultPosition,wxSize(40,20),0,NumValidator(ShadowValue,true,false));
OutlineType = new wxCheckBox(this,CHECKBOX_OUTLINE,_("Opaque box"));
ScaleX = new wxTextCtrl(this,TEXT_SCALE_X,_T(""),wxDefaultPosition, wxSize(70,20),0,NumValidator(&ScaleXValue,true,false));
ScaleY = new wxTextCtrl(this,TEXT_SCALE_Y,_T(""),wxDefaultPosition, wxSize(70,20),0,NumValidator(&ScaleYValue,true,false));
Angle = new wxTextCtrl(this,TEXT_ANGLE,_T(""),wxDefaultPosition, wxSize(40,20),0,NumValidator(&AngleValue,true,true));
Spacing = new wxTextCtrl(this,TEXT_SPACING,_T(""),wxDefaultPosition,wxSize(40,20),0,NumValidator(&SpacingValue,true,true));
ScaleX = new wxTextCtrl(this,TEXT_SCALE_X,_T(""),wxDefaultPosition, wxSize(70,20),0,NumValidator(ScaleXValue,true,false));
ScaleY = new wxTextCtrl(this,TEXT_SCALE_Y,_T(""),wxDefaultPosition, wxSize(70,20),0,NumValidator(ScaleYValue,true,false));
Angle = new wxTextCtrl(this,TEXT_ANGLE,_T(""),wxDefaultPosition, wxSize(40,20),0,NumValidator(AngleValue,true,true));
Spacing = new wxTextCtrl(this,TEXT_SPACING,_T(""),wxDefaultPosition,wxSize(40,20),0,NumValidator(SpacingValue,true,true));
Encoding = new wxComboBox(this,COMBO_ENCODING,_T(""),wxDefaultPosition, wxDefaultSize, encodingStrings,wxCB_READONLY);
// Set control tooltips

View file

@ -74,35 +74,6 @@ class DialogStyleEditor : public wxDialog {
/// DOCME
AssStyleStorage *store;
/// DOCME
wxString FontSizeValue;
/// DOCME
wxString AlignmentValue;
/// DOCME
wxString OutlineValue;
/// DOCME
wxString ShadowValue;
/// DOCME
wxString ScaleXValue;
/// DOCME
wxString ScaleYValue;
/// DOCME
wxString AngleValue;
/// DOCME
wxString EncodingValue;
/// DOCME
wxString SpacingValue;
/// DOCME
wxTextCtrl *StyleName;

View file

@ -70,17 +70,17 @@ enum {
DialogTimingProcessor::DialogTimingProcessor(agi::Context *c)
: wxDialog(c->parent,-1,_("Timing Post-Processor"),wxDefaultPosition,wxSize(400,250),wxDEFAULT_DIALOG_STYLE)
, c(c)
, leadInTime(wxString::Format("%d", OPT_GET("Audio/Lead/IN")->GetInt()))
, leadOutTime(wxString::Format("%d", OPT_GET("Audio/Lead/OUT")->GetInt()))
, thresStartBefore(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key Start Before")->GetInt()))
, thresStartAfter(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key Start After")->GetInt()))
, thresEndBefore(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key End Before")->GetInt()))
, thresEndAfter(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key End After")->GetInt()))
, adjsThresTime(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Adjacent")->GetInt()))
{
SetIcon(BitmapToIcon(GETIMAGE(timing_processor_toolbutton_24)));
// Set variables
wxString leadInTime(wxString::Format("%d", OPT_GET("Audio/Lead/IN")->GetInt()));
wxString leadOutTime(wxString::Format("%d", OPT_GET("Audio/Lead/OUT")->GetInt()));
wxString thresStartBefore(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key Start Before")->GetInt()));
wxString thresStartAfter(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key Start After")->GetInt()));
wxString thresEndBefore(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key End Before")->GetInt()));
wxString thresEndAfter(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Key End After")->GetInt()));
wxString adjsThresTime(wxString::Format("%d", OPT_GET("Tool/Timing Post Processor/Threshold/Adjacent")->GetInt()));
// Styles box
wxSizer *LeftSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Apply to styles"));
@ -103,12 +103,12 @@ DialogTimingProcessor::DialogTimingProcessor(agi::Context *c)
hasLeadIn = new wxCheckBox(this,CHECK_ENABLE_LEADIN,_("Add lead in:"));
hasLeadIn->SetToolTip(_("Enable adding of lead-ins to lines."));
hasLeadIn->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Lead/IN")->GetBool());
leadIn = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(80,-1),0,NumValidator(&leadInTime));
leadIn = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(80,-1),0,NumValidator(leadInTime));
leadIn->SetToolTip(_("Lead in to be added, in milliseconds."));
hasLeadOut = new wxCheckBox(this,CHECK_ENABLE_LEADOUT,_("Add lead out:"));
hasLeadOut->SetToolTip(_("Enable adding of lead-outs to lines."));
hasLeadOut->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Lead/OUT")->GetBool());
leadOut = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(80,-1),0,NumValidator(&leadOutTime));
leadOut = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(80,-1),0,NumValidator(leadOutTime));
leadOut->SetToolTip(_("Lead out to be added, in milliseconds."));
LeadSizer->Add(hasLeadIn,0,wxRIGHT|wxEXPAND,5);
LeadSizer->Add(leadIn,0,wxRIGHT|wxEXPAND,5);
@ -122,7 +122,7 @@ DialogTimingProcessor::DialogTimingProcessor(agi::Context *c)
adjsEnable->SetToolTip(_("Enable snapping of subtitles together if they are within a certain distance of each other."));
adjsEnable->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Adjacent")->GetBool());
wxStaticText *adjsThresText = new wxStaticText(this,-1,_("Threshold:"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTRE);
adjacentThres = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(&adjsThresTime));
adjacentThres = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(adjsThresTime));
adjacentThres->SetToolTip(_("Maximum difference between start and end time for two subtitles to be made continuous, in milliseconds."));
adjacentBias = new wxSlider(this,-1,mid(0,int(OPT_GET("Tool/Timing Post Processor/Adjacent Bias")->GetDouble()*100),100),0,100,wxDefaultPosition,wxSize(-1,20));
adjacentBias->SetToolTip(_("Sets how to set the adjoining of lines. If set totally to left, it will extend start time of the second line; if totally to right, it will extend the end time of the first line."));
@ -140,16 +140,16 @@ DialogTimingProcessor::DialogTimingProcessor(agi::Context *c)
keysEnable->SetToolTip(_("Enable snapping of subtitles to nearest keyframe, if distance is within threshold."));
keysEnable->SetValue(OPT_GET("Tool/Timing Post Processor/Enable/Keyframe")->GetBool());
wxStaticText *textStartBefore = new wxStaticText(this,-1,_("Starts before thres.:"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTRE);
keysStartBefore = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(&thresStartBefore));
keysStartBefore = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(thresStartBefore));
keysStartBefore->SetToolTip(_("Threshold for 'before start' distance, that is, how many frames a subtitle must start before a keyframe to snap to it."));
wxStaticText *textStartAfter = new wxStaticText(this,-1,_("Starts after thres.:"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTRE);
keysStartAfter = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(&thresStartAfter));
keysStartAfter = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(thresStartAfter));
keysStartAfter->SetToolTip(_("Threshold for 'after start' distance, that is, how many frames a subtitle must start after a keyframe to snap to it."));
wxStaticText *textEndBefore = new wxStaticText(this,-1,_("Ends before thres.:"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTRE);
keysEndBefore = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(&thresEndBefore));
keysEndBefore = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(thresEndBefore));
keysEndBefore->SetToolTip(_("Threshold for 'before end' distance, that is, how many frames a subtitle must end before a keyframe to snap to it."));
wxStaticText *textEndAfter = new wxStaticText(this,-1,_("Ends after thres.:"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTRE);
keysEndAfter = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(&thresEndAfter));
keysEndAfter = new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(60,-1),0,NumValidator(thresEndAfter));
keysEndAfter->SetToolTip(_("Threshold for 'after end' distance, that is, how many frames a subtitle must end after a keyframe to snap to it."));
KeyframesFlexSizer->Add(keysEnable,0,wxRIGHT|wxEXPAND,10);
KeyframesFlexSizer->Add(textStartBefore,0,wxRIGHT|wxALIGN_CENTER,5);

View file

@ -106,21 +106,6 @@ class DialogTimingProcessor : public wxDialog {
/// DOCME
wxButton *ApplyButton;
/// DOCME
/// DOCME
/// DOCME
/// DOCME
/// DOCME
/// DOCME
/// DOCME
wxString leadInTime,leadOutTime,thresStartBefore,thresStartAfter,thresEndBefore,thresEndAfter,adjsThresTime;
/// DOCME
std::vector<int> KeyFrames;

View file

@ -34,9 +34,6 @@
/// @ingroup custom_control utility
///
///////////
// Headers
#include "config.h"
#ifndef AGI_PRE
@ -46,109 +43,67 @@
#include "utils.h"
#include "validators.h"
/// @brief Constructor
/// @param _valPtr
/// @param isfloat
/// @param issigned
///
NumValidator::NumValidator(wxString* _valPtr,bool isfloat,bool issigned) {
isFloat = isfloat;
isSigned = issigned;
valPtr = _valPtr;
// Get value
if (valPtr) {
NumValidator::NumValidator(wxString val, bool isfloat, bool issigned)
: isFloat(isfloat)
, isSigned(issigned)
{
if (isFloat) {
valPtr->ToDouble(&fValue);
val.ToDouble(&fValue);
}
else {
long tLong;
valPtr->ToLong(&tLong);
val.ToLong(&tLong);
iValue = tLong;
}
}
}
/// @brief Copy constructor
/// @param from
///
NumValidator::NumValidator(const NumValidator &from)
: wxValidator()
, fValue(from.fValue)
, iValue(from.iValue)
, isFloat(from.isFloat)
, isSigned(from.isSigned)
{
valPtr = from.valPtr;
isFloat = from.isFloat;
isSigned = from.isSigned;
SetWindow(from.GetWindow());
}
///////////////
// Event table
BEGIN_EVENT_TABLE(NumValidator, wxValidator)
EVT_CHAR(NumValidator::OnChar)
END_EVENT_TABLE()
/// @brief Clone
/// @return
///
wxObject* NumValidator::Clone() const {
NumValidator *clone = new NumValidator(valPtr,isFloat,isSigned);
return clone;
return new NumValidator(*this);
}
/// @brief Validate
/// @param parent
/// @return
///
bool NumValidator::Validate(wxWindow* parent) {
wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow();
wxString value = ctrl->GetValue();
// Is the control enabled?
if (!ctrl->IsEnabled()) return true;
// Check length
if (value.Length() < 1) return false;
// Check each character
bool gotDecimal = false;
for (size_t i = 0; i < value.Length(); i++) {
if (!CheckCharacter(value[i],i==0,true,gotDecimal)) return false;
if (!CheckCharacter(value[i], !i, true, gotDecimal))
return false;
}
// All clear
return true;
}
/// @brief Check if a given character is valid
/// @param chr
/// @param isFirst
/// @param canSign
/// @param gotDecimal
/// @return
///
bool NumValidator::CheckCharacter(int chr, bool isFirst, bool canSign, bool &gotDecimal) {
// Check sign
if (chr == _T('-') || chr == _T('+')) {
if (!isFirst || !canSign || !isSigned) return false;
else return true;
if (chr == '-' || chr == '+') {
return isFirst && canSign && isSigned;
}
// Don't allow anything before a sign
if (isFirst && !canSign) return false;
// Check decimal point
if (chr == _T('.') || chr == _T(',')) {
if (!isFloat || gotDecimal) return false;
if (chr == '.' || chr == ',') {
if (!isFloat || gotDecimal)
return false;
else {
gotDecimal = true;
return true;
@ -156,16 +111,9 @@ bool NumValidator::CheckCharacter(int chr,bool isFirst,bool canSign,bool &gotDec
}
// Check digit
if (chr < _T('0') || chr > _T('9')) return false;
return true;
return chr >= '0' && chr <= '9';
}
/// @brief Filter keypresses
/// @param event
/// @return
///
void NumValidator::OnChar(wxKeyEvent& event) {
wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow();
wxString value = ctrl->GetValue();
@ -188,15 +136,13 @@ void NumValidator::OnChar(wxKeyEvent& event) {
for (size_t i=0;i<value.Length();i++) {
if (i >= (unsigned)from && i < (unsigned)to) continue;
curchr = value[i];
if (curchr == _T('.') || curchr == _T(',')) decimals++;
if (curchr == _T('+') || curchr == _T('-')) signs++;
if (curchr == '.' || curchr == ',') decimals++;
if (curchr == '+' || curchr == '-') signs++;
}
bool gotDecimal = decimals > 0;
bool isFirst = from == 0;
bool canSign = signs == 0;
// Check character
if (!CheckCharacter(chr,isFirst,canSign,gotDecimal)) {
if (!CheckCharacter(chr,!from,!signs,gotDecimal)) {
if (!wxValidator::IsSilent()) wxBell();
return;
}
@ -206,30 +152,21 @@ void NumValidator::OnChar(wxKeyEvent& event) {
return;
}
/// @brief Transfer to window
/// @return
///
bool NumValidator::TransferToWindow() {
wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow();
if (isFloat) ctrl->SetValue(wxString::Format(_T("%g"),fValue));
else ctrl->SetValue(wxString::Format(_T("%d"),iValue));
if (isFloat)
ctrl->SetValue(wxString::Format("%g",fValue));
else
ctrl->SetValue(wxString::Format("%d",iValue));
return true;
}
/// @brief Receive from window
///
bool NumValidator::TransferFromWindow() {
wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow();
wxString value = ctrl->GetValue();
// Validate
bool ok = Validate(ctrl);
if (!ok) return false;
if (!Validate(ctrl)) return false;
// Transfer
if (isFloat) {
@ -243,5 +180,3 @@ bool NumValidator::TransferFromWindow() {
return true;
}

View file

@ -34,11 +34,6 @@
/// @ingroup custom_control utility
///
///////////
// Headers
#ifndef AGI_PRE
#include <wx/validate.h>
#endif
@ -46,38 +41,43 @@
/// DOCME
/// @class NumValidator
/// @brief DOCME
/// @brief wx validator that only allows valid numbers
///
/// DOCME
class NumValidator : public wxValidator {
private:
double fValue; ///< Value if isFloat is true
int iValue; ///< Value if isFloat is false
bool isFloat; ///< Should decimals be allowed?
bool isSigned; ///< Can the number be negative?
/// DOCME
double fValue;
/// DOCME
int iValue;
/// DOCME
wxString* valPtr;
/// DOCME
bool isFloat;
/// DOCME
bool isSigned;
/// Polymorphic copy
wxObject* Clone() const;
/// Check if the value in the passed window is valid
bool Validate(wxWindow* parent);
/// Copy the currently stored value to the associated window
bool TransferToWindow();
/// Read the value in the associated window and validate it
bool TransferFromWindow();
/// Check a single character
/// @param chr Character to check
/// @param isFirst Is this the first character in the string?
/// @param canSign Can this character be a sign?
/// @param gotDecimal[in,out] Has a decimal been found? Set to true if a chr is a decimal
/// @return Is this character valid?
bool CheckCharacter(int chr,bool isFirst,bool canSign,bool &gotDecimal);
/// wx character event handler
void OnChar(wxKeyEvent& event);
public:
NumValidator(wxString* valPtr = NULL,bool isfloat=false,bool issigned=false);
/// Constructor
/// @param val Initial value to set the associated control to
/// @param isfloat Allow floats, or just ints?
/// @param issigned Allow negative numbers?
NumValidator(wxString val = "", bool isfloat=false, bool issigned=false);
/// Copy constructor
NumValidator(const NumValidator& from);
DECLARE_EVENT_TABLE();