Implemented osgUI::Validator, IntValidator and DoubleValidator classes that manage validation/specialization of LineEdit widgets to work with just integer or double values.
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14398 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
@@ -21,6 +21,7 @@ SET(TARGET_H
|
||||
${HEADER_PATH}/AlignmentSettings
|
||||
${HEADER_PATH}/FrameSettings
|
||||
${HEADER_PATH}/TextSettings
|
||||
${HEADER_PATH}/Validator
|
||||
)
|
||||
|
||||
SET(TARGET_SRC
|
||||
@@ -36,6 +37,7 @@ SET(TARGET_SRC
|
||||
AlignmentSettings.cpp
|
||||
FrameSettings.cpp
|
||||
TextSettings.cpp
|
||||
Validator.cpp
|
||||
${OPENSCENEGRAPH_VERSIONINFO_RC}
|
||||
)
|
||||
|
||||
|
||||
@@ -58,6 +58,17 @@ bool LineEdit::handleImplementation(osgGA::EventVisitor* ev, osgGA::Event* event
|
||||
}
|
||||
else if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Return )
|
||||
{
|
||||
if (_validator.valid())
|
||||
{
|
||||
std::string text_copy(_text);
|
||||
int cursorpos;
|
||||
if (_validator->validate(text_copy, cursorpos)==Validator::INTERMEDIATE)
|
||||
{
|
||||
_validator->fixup(text_copy);
|
||||
}
|
||||
if (text_copy!=_text) setText(text_copy);
|
||||
}
|
||||
|
||||
returnPressed();
|
||||
return true;
|
||||
}
|
||||
@@ -74,10 +85,17 @@ bool LineEdit::handleImplementation(osgGA::EventVisitor* ev, osgGA::Event* event
|
||||
|
||||
void LineEdit::setText(const std::string& text)
|
||||
{
|
||||
if (!validate(text)) return;
|
||||
if (_text==text) return;
|
||||
|
||||
_text = text;
|
||||
std::string text_copy(text);
|
||||
if (_validator.valid())
|
||||
{
|
||||
int cursorpos = 0;
|
||||
Validator::State state = _validator->validate(text_copy, cursorpos);
|
||||
if (state==Validator::INVALID) return;
|
||||
}
|
||||
|
||||
_text = text_copy;
|
||||
|
||||
textChanged(_text);
|
||||
|
||||
@@ -97,36 +115,6 @@ void LineEdit::leaveImplementation()
|
||||
if (_backgroundSwitch.valid()) _backgroundSwitch->setSingleChildOn(0);
|
||||
}
|
||||
|
||||
bool LineEdit::validate(const std::string& text)
|
||||
{
|
||||
osg::CallbackObject* co = getCallbackObject(this, "validate");
|
||||
if (co)
|
||||
{
|
||||
osg::Parameters inputParameters, outputParameters;
|
||||
inputParameters.push_back(new osg::StringValueObject("text",text));
|
||||
if (co->run(this, inputParameters, outputParameters))
|
||||
{
|
||||
if (outputParameters.size()>=1)
|
||||
{
|
||||
osg::Object* object = outputParameters[0].get();
|
||||
osg::BoolValueObject* bvo = dynamic_cast<osg::BoolValueObject*>(object);
|
||||
if (bvo)
|
||||
{
|
||||
OSG_NOTICE<<"Have bool return value from validate "<<bvo->getValue()<<std::endl;
|
||||
return bvo->getValue();
|
||||
}
|
||||
OSG_NOTICE<<"Called validate CallbackObject but didn't get bool return value."<<object->className()<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return validateImplementation(text);
|
||||
}
|
||||
|
||||
bool LineEdit::validateImplementation(const std::string& text)
|
||||
{
|
||||
OSG_NOTICE<<"LineEdit::validateImplemetation("<<text<<")"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LineEdit::textChanged(const std::string& text)
|
||||
{
|
||||
|
||||
290
src/osgUI/Validator.cpp
Normal file
290
src/osgUI/Validator.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
/* -*-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();
|
||||
}
|
||||
|
||||
17
src/osgWrappers/serializers/osgUI/DoubleValidator.cpp
Normal file
17
src/osgWrappers/serializers/osgUI/DoubleValidator.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <osgUI/Validator>
|
||||
#include <osg/ValueObject>
|
||||
#include <osgDB/ObjectWrapper>
|
||||
#include <osgDB/InputStream>
|
||||
#include <osgDB/OutputStream>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
REGISTER_OBJECT_WRAPPER( DoubleValidator,
|
||||
new osgUI::DoubleValidator,
|
||||
osgUI::DoubleValidator,
|
||||
"osg::Object osgUI::Validator osgUI::DoubleValidator" )
|
||||
{
|
||||
ADD_INT_SERIALIZER(Decimals, -1);
|
||||
ADD_DOUBLE_SERIALIZER(Bottom, -DBL_MAX);
|
||||
ADD_DOUBLE_SERIALIZER(Top, DBL_MAX);
|
||||
}
|
||||
16
src/osgWrappers/serializers/osgUI/IntValidator.cpp
Normal file
16
src/osgWrappers/serializers/osgUI/IntValidator.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <osgUI/Validator>
|
||||
#include <osg/ValueObject>
|
||||
#include <osgDB/ObjectWrapper>
|
||||
#include <osgDB/InputStream>
|
||||
#include <osgDB/OutputStream>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
REGISTER_OBJECT_WRAPPER( IntValidator,
|
||||
new osgUI::IntValidator,
|
||||
osgUI::IntValidator,
|
||||
"osg::Object osgUI::Validator osgUI::IntValidator" )
|
||||
{
|
||||
ADD_INT_SERIALIZER(Bottom, -INT_MAX);
|
||||
ADD_INT_SERIALIZER(Top, INT_MAX);
|
||||
}
|
||||
@@ -10,5 +10,6 @@ REGISTER_OBJECT_WRAPPER( LineEdit,
|
||||
osgUI::LineEdit,
|
||||
"osg::Object osg::Node osg::Group osgUI::Widget osgUI::LineEdit" )
|
||||
{
|
||||
ADD_OBJECT_SERIALIZER( Validator, osgUI::Validator, NULL);
|
||||
ADD_STRING_SERIALIZER( Text, std::string());
|
||||
}
|
||||
|
||||
13
src/osgWrappers/serializers/osgUI/Validator.cpp
Normal file
13
src/osgWrappers/serializers/osgUI/Validator.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <osgUI/Validator>
|
||||
#include <osg/ValueObject>
|
||||
#include <osgDB/ObjectWrapper>
|
||||
#include <osgDB/InputStream>
|
||||
#include <osgDB/OutputStream>
|
||||
|
||||
|
||||
REGISTER_OBJECT_WRAPPER( Validator,
|
||||
new osgUI::Validator,
|
||||
osgUI::Validator,
|
||||
"osg::Object osgUI::Validator" )
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user