291 lines
7.7 KiB
C++
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();
|
|
}
|
|
|