diff --git a/aegisub/dialog_style_editor.cpp b/aegisub/dialog_style_editor.cpp index f352df318..9ca49eeec 100644 --- a/aegisub/dialog_style_editor.cpp +++ b/aegisub/dialog_style_editor.cpp @@ -125,7 +125,7 @@ DialogStyleEditor::DialogStyleEditor (wxWindow *parent, AssStyle *_style, Subtit performance_timer.Start(); FontName = new wxComboBox(this,TEXT_FONT_NAME,style->font,wxDefaultPosition,wxSize(150,20),0,0,wxCB_DROPDOWN | wxTE_PROCESS_ENTER); wxLogDebug(_T("Time to create font face listbox: %d"), performance_timer.Time()); - FontSize = new wxTextCtrl(this,TEXT_FONT_SIZE,_T(""),wxDefaultPosition,wxSize(50,20),0,wxTextValidator(wxFILTER_NUMERIC,&FontSizeValue)); + FontSize = new wxTextCtrl(this,TEXT_FONT_SIZE,_T(""),wxDefaultPosition,wxSize(50,20),0,NumValidator(&FontSizeValue,true,false)); //wxButton *FontButton = new wxButton(this,BUTTON_STYLE_FONT,_("Choose")); BoxBold = new wxCheckBox(this,CHECKBOX_STYLE_BOLD,_("Bold")); BoxItalic = new wxCheckBox(this,CHECKBOX_STYLE_ITALIC,_("Italic")); @@ -142,13 +142,13 @@ DialogStyleEditor::DialogStyleEditor (wxWindow *parent, AssStyle *_style, Subtit for (int i=0;i<3;i++) margin[i] = new wxSpinCtrl(this,TEXT_MARGIN_L+i,_T(""),wxDefaultPosition,wxSize(60,20),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,wxTextValidator(wxFILTER_NUMERIC,&OutlineValue)); - Shadow = new wxTextCtrl(this,TEXT_SHADOW,_T(""),wxDefaultPosition,wxSize(40,20),0,wxTextValidator(wxFILTER_NUMERIC,&ShadowValue)); + 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,wxTextValidator(wxFILTER_NUMERIC,&ScaleXValue)); - ScaleY = new wxTextCtrl(this,TEXT_SCALE_Y,_T(""),wxDefaultPosition, wxSize(70,20),0,wxTextValidator(wxFILTER_NUMERIC,&ScaleYValue)); - Angle = new wxTextCtrl(this,TEXT_ANGLE,_T(""),wxDefaultPosition, wxSize(40,20),0,wxTextValidator(wxFILTER_NUMERIC,&AngleValue)); - Spacing = new wxTextCtrl(this,TEXT_SPACING,_T(""),wxDefaultPosition,wxSize(40,20),0,wxTextValidator(wxFILTER_NUMERIC,&SpacingValue)); + 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 diff --git a/aegisub/validators.cpp b/aegisub/validators.cpp index d9622d3b0..24cf16e6c 100644 --- a/aegisub/validators.cpp +++ b/aegisub/validators.cpp @@ -37,25 +37,164 @@ /////////// // Headers #include "validators.h" +#include "utils.h" /////////////// // Constructor -NumValidator::NumValidator(wxString* valPtr,bool isfloat,bool issigned) -: wxTextValidator(wxFILTER_INCLUDE_CHAR_LIST,valPtr) -{ - wxArrayString list; - list.Add(_T("0")); - list.Add(_T("1")); - list.Add(_T("2")); - list.Add(_T("3")); - list.Add(_T("4")); - list.Add(_T("5")); - list.Add(_T("6")); - list.Add(_T("7")); - list.Add(_T("8")); - list.Add(_T("9")); - if (isfloat) list.Add(_T(".")); - if (issigned) list.Add(_T("-")); - SetIncludes(list); +NumValidator::NumValidator(wxString* _valPtr,bool isfloat,bool issigned) { + isFloat = isfloat; + isSigned = issigned; + valPtr = _valPtr; + + // Get value + if (valPtr) { + if (isFloat) { + valPtr->ToDouble(&fValue); + } + else { + long tLong; + valPtr->ToLong(&tLong); + iValue = tLong; + } + } +} + + +/////////////// +// Event table +BEGIN_EVENT_TABLE(NumValidator, wxValidator) + EVT_CHAR(NumValidator::OnChar) +END_EVENT_TABLE() + + +///////// +// Clone +wxObject* NumValidator::Clone() const { + NumValidator *clone = new NumValidator(valPtr,isFloat,isSigned); + return clone; +} + + +//////////// +// Validate +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 _T('9')) return false; + return true; +} + + +///////////////////// +// Filter keypresses +void NumValidator::OnChar(wxKeyEvent& event) { + wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow(); + wxString value = ctrl->GetValue(); + int chr = event.GetKeyCode(); + + // Special keys + if (chr < WXK_SPACE || chr == WXK_DELETE || chr > WXK_START) { + event.Skip(); + return; + } + + // Get selection + long from,to; + ctrl->GetSelection(&from,&to); + + // Count decimal points and signs outside selection + int decimals = 0; + int signs = 0; + wxChar curchr; + for (size_t i=0;i= (unsigned)from && i < (unsigned)to) continue; + curchr = value[i]; + if (curchr == _T('.') || curchr == _T(',')) decimals++; + if (curchr == _T('+') || curchr == _T('-')) signs++; + } + bool gotDecimal = decimals > 0; + bool canSign = from == 0 && signs == 0; + + // Check character + if (!CheckCharacter(chr,canSign,gotDecimal)) { + if (!wxValidator::IsSilent()) wxBell(); + return; + } + + // OK + event.Skip(); + return; +} + + +////////////////////// +// Transfer to window +bool NumValidator::TransferToWindow() { + wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow(); + if (isFloat) ctrl->SetValue(PrettyFloatD(fValue)); + else ctrl->SetValue(wxString::Format(_T("%d"),iValue)); + + return true; +} + + +/////////////////////// +// Receive from window +bool NumValidator::TransferFromWindow() { + wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow(); + wxString value = ctrl->GetValue(); + + // Validate + bool ok = Validate(ctrl); + if (!ok) return false; + + // Transfer + if (isFloat) { + value.ToDouble(&fValue); + } + else { + long tLong; + value.ToLong(&tLong); + iValue = tLong; + } + + return true; } diff --git a/aegisub/validators.h b/aegisub/validators.h index 37ba44b7b..3b4ccf052 100644 --- a/aegisub/validators.h +++ b/aegisub/validators.h @@ -45,9 +45,27 @@ ///////////////////// // Numeric validator -class NumValidator : public wxTextValidator { +class NumValidator : public wxValidator { +private: + double fValue; + int iValue; + wxString* valPtr; + + bool isFloat; + bool isSigned; + wxObject* Clone() const; + bool Validate(wxWindow* parent); + bool TransferToWindow(); + bool TransferFromWindow(); + + bool CheckCharacter(int chr,bool isFirst,bool &gotDecimal); + + void OnChar(wxKeyEvent& event); + public: NumValidator(wxString* valPtr = NULL,bool isfloat=false,bool issigned=false); + + DECLARE_EVENT_TABLE(); };