Files
OpenSceneGraph/src/osgUI/Validator.cpp
2016-06-08 09:05:34 +01:00

291 lines
7.7 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgUI/Validator>
#include <osg/ValueObject>
#include <osg/Callback>
#include <sstream>
#include <limits.h>
using namespace osgUI;
Validator::Validator()
{
}
Validator::Validator(const osgUI::Validator& validator, const osg::CopyOp& copyop):
osg::Object(validator, copyop)
{
}
Validator::State Validator::validate(std::string& text, int& cursorpos) const
{
const osg::CallbackObject* co = getCallbackObject(this, "validate");
if (co)
{
osg::ref_ptr<osg::StringValueObject> textInput = new osg::StringValueObject("text",text);
osg::ref_ptr<osg::IntValueObject> cursorposInput = new osg::IntValueObject("cursorpos",cursorpos);
osg::Parameters inputParameters, outputParameters;
inputParameters.push_back(textInput.get());
inputParameters.push_back(cursorposInput.get());
if (co->run(const_cast<Validator*>(this), inputParameters, outputParameters))
{
if (textInput->getValue()!=text)
{
OSG_NOTICE<<"Updating text in CallbackObject "<<textInput->getValue()<<std::endl;
text = textInput->getValue();
}
if (cursorposInput->getValue()!=cursorpos)
{
OSG_NOTICE<<"Updating cursor pos in CallbackObject "<<cursorposInput->getValue()<<std::endl;
cursorpos = cursorposInput->getValue();
}
if (outputParameters.size()>=1)
{
osg::Object* object = outputParameters[0].get();
osg::StringValueObject* svo = dynamic_cast<osg::StringValueObject*>(object);
if (svo)
{
OSG_NOTICE<<"Have string return value from validate "<<svo->getValue()<<std::endl;
std::string returnString = svo->getValue();
if (returnString=="INVALID") return INVALID;
else if (returnString=="INTERMEDITATE") return INTERMEDIATE;
else if (returnString=="ACCEPTABLE") return ACCEPTABLE;
}
OSG_NOTICE<<"Called validate CallbackObject but didn't get string return value."<<object->className()<<std::endl;
}
}
}
return validateImplementation(text, cursorpos);
}
Validator::State Validator::validateImplementation(std::string& text, int& cursorpos) const
{
OSG_NOTICE<<"Validator::validateImplemetation("<<text<<", "<<cursorpos<<")"<<std::endl;
return ACCEPTABLE;
}
void Validator::fixup(std::string& text) const
{
const osg::CallbackObject* co = getCallbackObject(this, "fixup");
if (co)
{
osg::ref_ptr<osg::StringValueObject> textInput = new osg::StringValueObject("text",text);
osg::Parameters inputParameters, outputParameters;
inputParameters.push_back(textInput.get());
if (co->run(const_cast<Validator*>(this), inputParameters, outputParameters))
{
if (textInput->getValue()!=text)
{
OSG_NOTICE<<"Updating text in CallbackObject "<<textInput->getValue()<<std::endl;
text = textInput->getValue();
}
}
}
return fixupImplementation(text);
}
void Validator::fixupImplementation(std::string& text) const
{
OSG_NOTICE<<"Validator::fixupImplemetation("<<text<<")"<<std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// IntValidator
//
IntValidator::IntValidator():
_bottom(-INT_MAX),
_top(-INT_MAX)
{
}
IntValidator::IntValidator(const IntValidator& validator, const osg::CopyOp& copyop):
Validator(validator, copyop),
_bottom(validator._bottom),
_top(validator._top)
{
}
IntValidator::State IntValidator::validateImplementation(std::string& str, int& /*cursorpos*/) const
{
std::string newstring;
bool canBeNegative = _bottom<0.0;
int numNegative = 0;
for(std::size_t pos = 0; pos<str.size(); ++pos)
{
char c = str[pos];
bool validChar = false;
if (c>='0' && c<='9')
{
validChar = true;
}
else if (c=='-')
{
if (canBeNegative)
{
if (numNegative==0) validChar = true;
++numNegative;
}
}
if (validChar) newstring.push_back(c);
}
str = newstring;
if (str.empty()) return INTERMEDIATE;
int v = static_cast<int>(osg::asciiToDouble(str.c_str()));
if (v<_bottom)
{
return INTERMEDIATE;
}
if (v>_top)
{
return INTERMEDIATE;
}
return ACCEPTABLE;
}
void IntValidator::fixupImplementation(std::string& str) const
{
if (str.empty()) return;
int v = static_cast<int>(osg::asciiToDouble(str.c_str()));
if (v<_bottom)
{
v = _bottom;
}
if (v>_top)
{
v = _top;
}
std::stringstream buffer;
buffer<<v<<std::endl;
str = buffer.str();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DoubleValidator
//
DoubleValidator::DoubleValidator():
_decimals(-1),
_bottom(-DBL_MAX),
_top(DBL_MAX)
{
}
DoubleValidator::DoubleValidator(const DoubleValidator& validator, const osg::CopyOp& copyop):
Validator(validator, copyop),
_decimals(validator._decimals),
_bottom(validator._bottom),
_top(validator._top)
{
}
DoubleValidator::State DoubleValidator::validateImplementation(std::string& str, int& /*cursorpos*/) const
{
std::string newstring;
bool canBeNegative = _bottom<0.0;
int maxNumDecimalPlaces = _decimals>=0 ? _decimals : str.size();
int numPlacesAfterDecimal = 0;
int numNegative = 0;
bool hasDecimal = false;
for(std::size_t pos = 0; pos<str.size(); ++pos)
{
char c = str[pos];
bool validChar = false;
if (c>='0' && c<='9')
{
if (hasDecimal)
{
++numPlacesAfterDecimal;
if (numPlacesAfterDecimal<=maxNumDecimalPlaces) validChar = true;
}
else
{
validChar = true;
}
}
else if (c=='-')
{
if (canBeNegative)
{
if (numNegative==0) validChar = true;
++numNegative;
}
}
else if (c=='.')
{
if (!hasDecimal)
{
validChar = true;
hasDecimal = true;
}
}
if (validChar) newstring.push_back(c);
}
str = newstring;
if (str.empty()) return INTERMEDIATE;
double v = osg::asciiToDouble(str.c_str());
if (v<_bottom)
{
return INTERMEDIATE;
}
if (v>_top)
{
return INTERMEDIATE;
}
return ACCEPTABLE;
}
void DoubleValidator::fixupImplementation(std::string& str) const
{
if (str.empty()) return;
double v = osg::asciiToDouble(str.c_str());
if (v<_bottom)
{
v = _bottom;
}
if (v>_top)
{
v = _top;
}
std::stringstream buffer;
buffer<<v<<std::endl;
str = buffer.str();
}