/* -*-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 #include #include #include #include #include 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 > 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 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 bool _coerceAndApply( osg::Object* obj, const std::string& style, const std::string& className ) { T* t = dynamic_cast(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 bool _applyStyles(T* t) { osg::Object* obj = dynamic_cast(t); if(!obj) { warn() << "Cannot call StyleManager::applyStyle with a NULL object or coerce object into osg::Object." << 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