// Copyright (c) 2005, Rodrigo Braz Monteiro // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of the Aegisub Group nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // Aegisub Project http://www.aegisub.org/ /// @file validators.cpp /// @brief Various validators for wx /// @ingroup custom_control utility /// #include "config.h" #include "validators.h" #include "compat.h" #include "utils.h" #include #include #include NumValidator::NumValidator(wxString val, bool isfloat, bool issigned) : fValue(0) , iValue(0) , isFloat(isfloat) , isSigned(issigned) { if (isFloat) { val.ToDouble(&fValue); } else { long tLong = 0; val.ToLong(&tLong); iValue = tLong; } } NumValidator::NumValidator(int val, bool issigned) : fValue(0) , iValue(val) , isFloat(false) , isSigned(issigned) { } NumValidator::NumValidator(int64_t val, bool issigned) : fValue(0) , iValue((int)val) , isFloat(false) , isSigned(issigned) { } NumValidator::NumValidator(double val, bool issigned) : fValue(val) , iValue(0) , isFloat(true) , isSigned(issigned) { } NumValidator::NumValidator(const NumValidator &from) : wxValidator() , fValue(from.fValue) , iValue(from.iValue) , isFloat(from.isFloat) , isSigned(from.isSigned) { SetWindow(from.GetWindow()); } BEGIN_EVENT_TABLE(NumValidator, wxValidator) EVT_CHAR(NumValidator::OnChar) END_EVENT_TABLE() wxObject* NumValidator::Clone() const { return new NumValidator(*this); } bool NumValidator::Validate(wxWindow*) { wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow(); wxString value = ctrl->GetValue(); if (!ctrl->IsEnabled()) return true; if (value.Length() < 1) return false; bool gotDecimal = false; for (size_t i = 0; i < value.Length(); i++) { if (!CheckCharacter(value[i], !i, true, gotDecimal)) return false; } return true; } bool NumValidator::CheckCharacter(int chr, bool isFirst, bool canSign, bool &gotDecimal) { // Check sign if (chr == '-' || chr == '+') { return isFirst && canSign && isSigned; } // Don't allow anything before a sign if (isFirst && !canSign) return false; // Check decimal point if (chr == '.' || chr == ',') { if (!isFloat || gotDecimal) return false; else { gotDecimal = true; return true; } } // Check digit return chr >= '0' && chr <= '9'; } 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 == '.' || curchr == ',') decimals++; if (curchr == '+' || curchr == '-') signs++; } bool gotDecimal = decimals > 0; // Check character if (!CheckCharacter(chr,!from,!signs,gotDecimal)) { if (!wxValidator::IsSilent()) wxBell(); return; } // OK event.Skip(); return; } bool NumValidator::TransferToWindow() { wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow(); if (isFloat) ctrl->SetValue(wxString::Format("%g",fValue)); else ctrl->SetValue(wxString::Format("%d",iValue)); return true; } bool NumValidator::TransferFromWindow() { wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow(); wxString value = ctrl->GetValue(); if (!Validate(ctrl)) return false; // Transfer if (isFloat) { value.ToDouble(&fValue); } else { long tLong; value.ToLong(&tLong); iValue = tLong; } return true; } bool StringBinder::TransferFromWindow() { wxWindow *window = GetWindow(); if (wxTextCtrl *ctrl = dynamic_cast(window)) *value = from_wx(ctrl->GetValue()); else if (wxComboBox *ctrl = dynamic_cast(window)) *value = from_wx(ctrl->GetValue()); else throw agi::InternalError("Unsupported control type", 0); return true; } bool StringBinder::TransferToWindow() { wxWindow *window = GetWindow(); if (wxTextCtrl *ctrl = dynamic_cast(window)) ctrl->SetValue(to_wx(*value)); else if (wxComboBox *ctrl = dynamic_cast(window)) ctrl->SetValue(to_wx(*value)); else throw agi::InternalError("Unsupported control type", 0); return true; }