You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.8 KiB
208 lines
5.8 KiB
/* -*-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. |
|
*/ |
|
|
|
// Code by: Jeremy Moles (cubicool) 2007-2008 |
|
|
|
#ifndef OSGWIDGET_STYLE_MANAGER |
|
#define OSGWIDGET_STYLE_MANAGER |
|
|
|
#include <map> |
|
#include <osgDB/Input> |
|
#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
|
|
|