2013-10-14 21:11:50 +02:00
|
|
|
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2013-10-14 21:11:50 +02:00
|
|
|
// Permission to use, copy, modify, and distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice appear in all copies.
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2013-10-14 21:11:50 +02:00
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
#include "validators.h"
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
#include "compat.h"
|
|
|
|
|
|
|
|
#include <libaegisub/exception.h>
|
2013-10-14 21:11:50 +02:00
|
|
|
#include <libaegisub/util.h>
|
2013-01-04 16:01:50 +01:00
|
|
|
|
|
|
|
#include <wx/combobox.h>
|
2014-05-01 22:48:46 +02:00
|
|
|
#include <wx/spinctrl.h>
|
2013-01-04 16:01:50 +01:00
|
|
|
#include <wx/textctrl.h>
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
namespace {
|
|
|
|
std::string new_value(wxTextCtrl *ctrl, int chr) {
|
|
|
|
long from, to;
|
|
|
|
ctrl->GetSelection(&from, &to);
|
|
|
|
auto value = ctrl->GetValue();
|
|
|
|
return from_wx(value.substr(0, from) + (wxChar)chr + value.substr(to));
|
2007-06-17 23:12:28 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
wxChar decimal_separator() {
|
|
|
|
auto sep = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);
|
|
|
|
return sep.empty() ? '.' : sep[0];
|
|
|
|
}
|
2011-12-22 22:23:07 +01:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
IntValidator::IntValidator(int val, bool allow_negative)
|
|
|
|
: value(val)
|
|
|
|
, allow_negative(allow_negative)
|
2011-12-22 22:23:07 +01:00
|
|
|
{
|
2013-10-14 21:11:50 +02:00
|
|
|
Bind(wxEVT_CHAR, &IntValidator::OnChar, this);
|
2011-12-22 22:23:07 +01:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
IntValidator::IntValidator(IntValidator const& rgt)
|
2013-10-16 01:02:25 +02:00
|
|
|
: value(rgt.value)
|
|
|
|
, allow_negative(rgt.allow_negative)
|
2008-03-13 19:55:09 +01:00
|
|
|
{
|
2013-10-14 21:11:50 +02:00
|
|
|
SetWindow(rgt.GetWindow());
|
|
|
|
Bind(wxEVT_CHAR, &IntValidator::OnChar, this);
|
2007-06-18 20:20:45 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
bool IntValidator::TransferToWindow() {
|
|
|
|
static_cast<wxTextCtrl *>(GetWindow())->SetValue(std::to_wstring(value));
|
|
|
|
return true;
|
2007-06-17 23:12:28 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
void IntValidator::OnChar(wxKeyEvent& event) {
|
|
|
|
int chr = event.GetKeyCode();
|
|
|
|
if (chr < WXK_SPACE || chr == WXK_DELETE || chr > WXK_START) {
|
|
|
|
event.Skip();
|
|
|
|
return;
|
2007-06-17 23:12:28 +02:00
|
|
|
}
|
2013-10-14 21:11:50 +02:00
|
|
|
|
|
|
|
auto ctrl = static_cast<wxTextCtrl *>(GetWindow());
|
|
|
|
auto str = new_value(ctrl, chr);
|
|
|
|
int parsed;
|
|
|
|
if (allow_negative && str == '-')
|
|
|
|
event.Skip();
|
|
|
|
else if (agi::util::try_parse(str, &parsed) && (allow_negative || parsed >= 0))
|
|
|
|
event.Skip();
|
|
|
|
else if (!wxValidator::IsSilent())
|
|
|
|
wxBell();
|
2007-06-17 23:12:28 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
DoubleValidator::DoubleValidator(double *val, bool allow_negative)
|
|
|
|
: value(val)
|
|
|
|
, min(allow_negative ? std::numeric_limits<double>::lowest() : 0)
|
|
|
|
, max(std::numeric_limits<double>::max())
|
|
|
|
, decimal_sep(decimal_separator())
|
|
|
|
{
|
|
|
|
Bind(wxEVT_CHAR, &DoubleValidator::OnChar, this);
|
|
|
|
}
|
2007-06-17 23:12:28 +02:00
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
DoubleValidator::DoubleValidator(double *val, double min, double max)
|
|
|
|
: value(val)
|
|
|
|
, min(min)
|
|
|
|
, max(max)
|
|
|
|
, decimal_sep(decimal_separator())
|
|
|
|
{
|
|
|
|
Bind(wxEVT_CHAR, &DoubleValidator::OnChar, this);
|
|
|
|
}
|
2007-06-17 23:12:28 +02:00
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
DoubleValidator::DoubleValidator(DoubleValidator const& rgt)
|
|
|
|
: value(rgt.value)
|
|
|
|
, min(rgt.min)
|
|
|
|
, max(rgt.max)
|
|
|
|
, decimal_sep(rgt.decimal_sep)
|
|
|
|
{
|
|
|
|
Bind(wxEVT_CHAR, &DoubleValidator::OnChar, this);
|
|
|
|
SetWindow(rgt.GetWindow());
|
2007-06-17 23:12:28 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
void DoubleValidator::OnChar(wxKeyEvent& event) {
|
2007-06-17 23:12:28 +02:00
|
|
|
int chr = event.GetKeyCode();
|
|
|
|
if (chr < WXK_SPACE || chr == WXK_DELETE || chr > WXK_START) {
|
|
|
|
event.Skip();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
if (chr == decimal_sep)
|
|
|
|
chr = '.';
|
2007-06-17 23:12:28 +02:00
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
auto str = new_value(static_cast<wxTextCtrl *>(GetWindow()), chr);
|
|
|
|
if (decimal_sep != '.')
|
|
|
|
replace(begin(str), end(str), (char)decimal_sep, '.');
|
2007-06-17 23:12:28 +02:00
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
double parsed;
|
|
|
|
bool can_parse = agi::util::try_parse(str, &parsed);
|
|
|
|
if ((min < 0 && str == '-') || str == '.')
|
|
|
|
event.Skip();
|
|
|
|
else if (can_parse && parsed >= min && parsed <= max)
|
|
|
|
event.Skip();
|
|
|
|
else if (can_parse && min < 0 && chr == '-') // allow negating an existing value even if it results in being out of range
|
|
|
|
event.Skip();
|
|
|
|
else if (!wxValidator::IsSilent())
|
|
|
|
wxBell();
|
2007-06-17 23:12:28 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
bool DoubleValidator::TransferToWindow() {
|
2014-05-29 17:28:37 +02:00
|
|
|
auto str = std::to_wstring(*value);
|
2013-10-14 21:11:50 +02:00
|
|
|
if (decimal_sep != '.')
|
2014-05-29 17:28:37 +02:00
|
|
|
std::replace(str.begin(), str.end(), L'.', decimal_sep);
|
2013-10-14 21:11:50 +02:00
|
|
|
if (str.find(decimal_sep) != str.npos) {
|
2014-05-29 17:28:37 +02:00
|
|
|
while (str.back() == '0')
|
|
|
|
str.pop_back();
|
2013-10-14 21:11:50 +02:00
|
|
|
}
|
|
|
|
static_cast<wxTextCtrl *>(GetWindow())->SetValue(str);
|
2007-06-17 23:12:28 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-10-14 21:11:50 +02:00
|
|
|
bool DoubleValidator::TransferFromWindow() {
|
|
|
|
auto ctrl = static_cast<wxTextCtrl *>(GetWindow());
|
2011-01-20 06:57:30 +01:00
|
|
|
if (!Validate(ctrl)) return false;
|
2013-10-14 21:11:50 +02:00
|
|
|
auto str = from_wx(ctrl->GetValue());
|
|
|
|
if (decimal_sep != '.')
|
|
|
|
replace(begin(str), end(str), (char)decimal_sep, '.');
|
|
|
|
agi::util::try_parse(str, value);
|
2007-06-17 23:12:28 +02:00
|
|
|
return true;
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
2013-01-04 16:01:50 +01:00
|
|
|
|
2014-04-28 16:07:07 +02:00
|
|
|
bool DoubleSpinValidator::TransferToWindow() {
|
|
|
|
static_cast<wxSpinCtrlDouble*>(GetWindow())->SetValue(*value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DoubleSpinValidator::TransferFromWindow() {
|
|
|
|
auto ctrl = static_cast<wxSpinCtrlDouble*>(GetWindow());
|
|
|
|
#ifndef wxHAS_NATIVE_SPINCTRLDOUBLE
|
|
|
|
wxFocusEvent evt;
|
|
|
|
ctrl->OnTextLostFocus(evt);
|
|
|
|
#endif
|
|
|
|
*value = ctrl->GetValue();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
bool StringBinder::TransferFromWindow() {
|
|
|
|
wxWindow *window = GetWindow();
|
|
|
|
if (wxTextCtrl *ctrl = dynamic_cast<wxTextCtrl*>(window))
|
|
|
|
*value = from_wx(ctrl->GetValue());
|
|
|
|
else if (wxComboBox *ctrl = dynamic_cast<wxComboBox*>(window))
|
|
|
|
*value = from_wx(ctrl->GetValue());
|
|
|
|
else
|
2014-05-29 14:57:27 +02:00
|
|
|
throw agi::InternalError("Unsupported control type");
|
2013-01-04 16:01:50 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StringBinder::TransferToWindow() {
|
|
|
|
wxWindow *window = GetWindow();
|
|
|
|
if (wxTextCtrl *ctrl = dynamic_cast<wxTextCtrl*>(window))
|
|
|
|
ctrl->SetValue(to_wx(*value));
|
|
|
|
else if (wxComboBox *ctrl = dynamic_cast<wxComboBox*>(window))
|
|
|
|
ctrl->SetValue(to_wx(*value));
|
|
|
|
else
|
2014-05-29 14:57:27 +02:00
|
|
|
throw agi::InternalError("Unsupported control type");
|
2013-01-04 16:01:50 +01:00
|
|
|
return true;
|
|
|
|
}
|