OpenSceneGraph/include/osgWidget/StyleManager
Robert Osfield 8ecf508fda From Sergey Leontyev, "1. In StyleManager
when applying styles to a Label element the code below runs in a infinite loop.

The reason for this is that nothing increments the Reader "r" in the case when applying a style to label,

so I advance the reader when no match was found. 

( To replicate the error apply style to any label)

 

replaced this:

                while(!r.eof()) if(_styles[style]->applyStyle(t, r)) inc = true;

 

with this:

                while(!r.eof())

                 {

                                if(_styles[style]->applyStyle(t, r))

                                    inc = true;

                                else

                                    r.advanceOverCurrentFieldOrBlock();

                 }            

 

 

I tested it and it works well for me, I did not find any problems with it.

 

 

2.  Added style support for Canvas element, event though there is no styles to apply yet.

It is usefull for someone who inherits from Canvas class to develop another element.

 If applyStyle(Canvas) does not exist

there is no way to apply style to the  element that inherited from Canvas element.

 

Added virtual

     bool applyStyle(Canvas).

 

and in added call to apply style if the Object is of type Canvas:

StyleManager::_applyStyleToObject(osg::Object* obj, const std::string& style) {

...

 

else if(!std::string("Canvas").compare(c))

return _coerceAndApply<Canvas>(obj,style,c);

 "
2008-08-18 11:21:41 +00:00

210 lines
5.8 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 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.
*/
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: StyleManager 61 2008-06-24 20:24:26Z cubicool $
#ifndef OSGWIDGET_STYLE_MANAGER
#define OSGWIDGET_STYLE_MANAGER
#include <map>
#include <osgDB/FieldReaderIterator>
#include <osgWidget/Box>
#include <osgWidget/Frame>
#include <osgWidget/Input>
#include <osgWidget/Canvas>
namespace osgWidget {
typedef osgDB::FieldReaderIterator& Reader;
class OSGWIDGET_EXPORT Style: public osg::Object
{
public:
META_Object(osgWidget, Style);
// Class and contents...
Style (const std::string& = "", const std::string& = "");
Style (const Style&, const osg::CopyOp&);
virtual bool applyStyle (Widget*, Reader);
virtual bool applyStyle (Label*, Reader);
virtual bool applyStyle (Input*, Reader);
virtual bool applyStyle (Window*, Reader);
virtual bool applyStyle (Window::EmbeddedWindow*, Reader);
virtual bool applyStyle (Box*, Reader);
virtual bool applyStyle (Frame::Corner*, Reader);
virtual bool applyStyle (Frame::Border*, Reader);
virtual bool applyStyle (Canvas*, Reader);
void setStyle(const std::string& style) {
_style = style;
}
std::string& getStyle() {
return _style;
}
const std::string& getStyle() const {
return _style;
}
static Widget::Layer strToLayer (const std::string&);
static Widget::VerticalAlignment strToVAlign (const std::string&);
static Widget::HorizontalAlignment strToHAlign (const std::string&);
static Widget::CoordinateMode strToCoordMode (const std::string&);
static bool strToFill (const std::string&);
protected:
std::string _style;
bool _match(const char* seq, Reader r) {
if(r.matchSequence(seq)) {
++r;
return true;
}
return false;
}
};
class OSGWIDGET_EXPORT StyleManager: public osg::Object
{
public:
typedef std::map<std::string, osg::ref_ptr<Style> > Styles;
typedef Styles::iterator Iterator;
typedef Styles::const_iterator ConstIterator;
META_Object(osgWidget, StyleManager);
StyleManager ();
StyleManager (const StyleManager&, const osg::CopyOp&);
bool addStyle(Style*);
bool applyStyles(Widget* widget) {
return _applyStyles(widget);
}
bool applyStyles(Window* window) {
return _applyStyles(window);
}
private:
Styles _styles;
template<typename T>
bool _applySpecificStyle(T* t, const std::string& style)
{
osgDB::FieldReaderIterator r;
std::istringstream input(_styles[style]->getStyle());
r.attach(&input);
bool inc = false;
while(!r.eof())
{
if(_styles[style]->applyStyle(t, r))
inc = true;
else
r.advanceOverCurrentFieldOrBlock();
}
return inc;
}
template<typename T>
bool _coerceAndApply(
osg::Object* obj,
const std::string& style,
const std::string& className
) {
T* t = dynamic_cast<T*>(obj);
if(!t) {
warn()
<< "An attempt was made to coerce Object [" << obj->getName()
<< "] into a " << className << " but failed." << std::endl
;
return 0;
}
return _applySpecificStyle(t, style);
}
bool _applyStyleToObject(osg::Object*, const std::string&);
// 1. Check and see if the explicit FULL path is available.
// 2. Check and see if each component working backward--minus the last--is available.
// 3. Check to see if just the className() is available.
template<typename T>
bool _applyStyles(T* t)
{
if(!t)
{
warn()
<< "Cannot call StyleManager::applyStyle with a NULL object."
<< std::endl
;
return false;
}
osg::Object* obj = dynamic_cast<osg::Object*>(t);
if(!obj)
{
warn()
<< "Cannot coerce object into osg::Object in StyleManager:::applyStyle"
<< std::endl
;
return false;
}
std::string c = obj->className();
// Case 3; there's no explicit Style set, so see if there's one for the class.
if(t->getStyle().empty())
{
// Couldn't find the className, so we exit.
if(_styles.find(c) == _styles.end()) return false;
return _applyStyleToObject(obj, c);
}
// Case 1...
if(_styles.find(t->getStyle()) != _styles.end()) return _applyStyleToObject(
obj,
t->getStyle()
);
return false;
}
};
}
#endif