Aegisub/aegisub/src/validators.cpp
2010-05-13 18:41:46 +00:00

247 lines
5.5 KiB
C++

// 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/
//
// $Id$
/// @file validators.cpp
/// @brief Various validators for wx
/// @ingroup custom_control utility
///
///////////
// Headers
#include "config.h"
#ifndef AGI_PRE
#include <wx/textctrl.h>
#endif
#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) {
if (isFloat) {
valPtr->ToDouble(&fValue);
}
else {
long tLong;
valPtr->ToLong(&tLong);
iValue = tLong;
}
}
}
/// @brief Copy constructor
/// @param from
///
NumValidator::NumValidator(const NumValidator &from)
: wxValidator()
{
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;
}
/// @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;
}
// 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;
}
// 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;
else {
gotDecimal = true;
return true;
}
}
// Check digit
if (chr < _T('0') || chr > _T('9')) return false;
return true;
}
/// @brief Filter keypresses
/// @param event
/// @return
///
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<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++;
}
bool gotDecimal = decimals > 0;
bool isFirst = from == 0;
bool canSign = signs == 0;
// Check character
if (!CheckCharacter(chr,isFirst,canSign,gotDecimal)) {
if (!wxValidator::IsSilent()) wxBell();
return;
}
// OK
event.Skip();
return;
}
/// @brief Transfer to window
/// @return
///
bool NumValidator::TransferToWindow() {
wxTextCtrl *ctrl = (wxTextCtrl*) GetWindow();
if (isFloat) ctrl->SetValue(wxString::Format(_T("%g"),iValue));
else ctrl->SetValue(wxString::Format(_T("%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;
// Transfer
if (isFloat) {
value.ToDouble(&fValue);
}
else {
long tLong;
value.ToLong(&tLong);
iValue = tLong;
}
return true;
}