Hi Robert,
Recently I've been having some trouble with osgWidget::StyleManager
(I'll omit osgWidget namespace from now on). It seems to me that there
are some inconsistency in the code. In Style there are multiple
applyStyle method overloads, applying style for different
widgets/windows built-in in osgWidget. Plus you can do overrides. It's
good so far.
The problem lies in StyleManager::_applyStyleToObject (which calls
_coearceAndApply, which calls _applySpecificStyle, which calls
Style::applyStyle). With current implementation Style::applyStyle
variants for Input, Window, Frame::Corner, Frame::Border,
Window::EmbeddedWindow are never called, because their classes' names
are omitted in methods' if/else if block, making it impossible to use
styles with most than half of built-in widget/window types.
My fix simply adds couple else if blocks, making each
Style::applyStyle variant callable. By the way, I think that next
update should add Style::applyStyle overload for Table class and add
proper className overloads for Input and Window.
--
Best regards,
Piotr Gwiazdowski
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
#include <sstream>
#include <osg/io_utils>
#include <osgWidget/StyleManager>
namespace osgWidget {
Style::Style(const std::string& name, const std::string& style):
_style(style) {
setName(name);
}
Style::Style(const Style& style, const osg::CopyOp& co):
osg::Object (style, co),
_style (style._style) {
}
bool Style::applyStyle(Widget* widget, Reader r) {
std::string str;
osg::Vec2 vec2;
osg::Vec3 vec3;
osg::Vec4 vec4;
float f;
if(_match("pos %i %i", r) || _match("pos %f %f", r)) {
r.readSequence(vec2);
widget->setOrigin(vec2);
}
else if(_match("pos-x %i", r) || _match("pos-x %f", r)) {
r.readSequence(f);
widget->setX(f);
}
else if(_match("pos-y %i", r) || _match("pos-y %f", r)) {
r.readSequence(f);
widget->setY(f);
}
else if(_match("size %i %i", r) || _match("size %f %f", r)) {
r.readSequence(vec2);
widget->setSize(vec2);
}
else if(_match("width %i", r) || _match("width %f", r)) {
r.readSequence(f);
widget->setWidth(f);
}
else if(_match("height %i", r) || _match("height %f", r)) {
r.readSequence(f);
widget->setHeight(f);
}
// Color using 4x 0-255 integers.
else if(_match("color %i %i %i %i", r)) {
r.readSequence(vec4);
widget->setColor(vec4 / 255.0f);
}
// Color using 3x 0-255 integers with a default alpha of 255.
else if(_match("color %i %i %i", r)) {
r.readSequence(vec3);
widget->setColor(osg::Vec4(vec3[0], vec3[1], vec3[2], 255.0f) / 255.0f);
}
// Color using 4x 0.0f-1.0f floats.
else if(_match("color %f %f %f %f", r)) {
r.readSequence(vec4);
widget->setColor(vec4);
}
// Color using 3x 0.0f-1.0f floats with a default alpha of 1.0f.
else if(_match("color %f %f %f", r)) {
r.readSequence(vec3);
widget->setColor(osg::Vec4(vec3[0], vec3[1], vec3[2], 1.0f));
}
// Set padding uniformly.
else if(_match("padding %i", r)) {
r.readSequence(f);
widget->setPadding(f);
}
// Set left padding.
else if(_match("padding-left %i", r)) {
r.readSequence(f);
widget->setPadLeft(f);
}
// Set right padding.
else if(_match("padding-right %i", r)) {
r.readSequence(f);
widget->setPadRight(f);
}
// Set top padding.
else if(_match("padding-top %i", r)) {
r.readSequence(f);
widget->setPadTop(f);
}
// Set bottom padding.
else if(_match("padding-bottom %i", r)) {
r.readSequence(f);
widget->setPadBottom(f);
}
else if(_match("layer %w", r)) {
r.readSequence(str);
widget->setLayer(strToLayer(str));
}
else if(_match("valign %w", r)) {
r.readSequence(str);
widget->setAlignVertical(strToVAlign(str));
}
else if(_match("halign %w", r)) {
r.readSequence(str);
widget->setAlignHorizontal(strToHAlign(str));
}
else if(_match("coordmode %w", r)) {
r.readSequence(str);
widget->setCoordinateMode(strToCoordMode(str));
}
else if(_match("fill %w", r)) {
r.readSequence(str);
widget->setCanFill(strToFill(str));
}
else if(_match("image %s", r)) {
r.readSequence(str);
widget->setImage(str, true);
}
// Otherwise, increment the stream pointer.
else return false;
return true;
}
bool Style::applyStyle(Label* label, Reader r) {
return false;
}
bool Style::applyStyle(Input* input, Reader r) {
return false;
}
bool Style::applyStyle(Window* window, Reader r) {
osg::Vec2 vec2;
float f;
if(_match("pos %i %i", r) || _match("pos %f %f", r)) {
r.readSequence(vec2);
window->setOrigin(vec2.x(), vec2.y());
}
else if(_match("pos-x %i", r) || _match("pos-x %f", r)) {
r.readSequence(f);
window->setX(f);
}
else if(_match("pos-y %i", r) || _match("pos-y %f", r)) {
r.readSequence(f);
window->setY(f);
}
else if(_match("size %i %i", r) || _match("size %f %f", r)) {
r.readSequence(vec2);
window->resize(vec2.x(), vec2.y());
}
else if(_match("width %i", r) || _match("width %f", r)) {
r.readSequence(f);
window->resize(f);
}
else if(_match("height %i", r) || _match("height %f", r)) {
r.readSequence(f);
window->resize(0.0f, f);
}
else return false;
return true;
}
bool Style::applyStyle(Canvas* label, Reader r) {
return false;
}
bool Style::applyStyle(Window::EmbeddedWindow*, Reader r) {
return false;
}
bool Style::applyStyle(Box* box, Reader r) {
if(applyStyle(static_cast<Window*>(box), r)) return true;
return false;
}
bool Style::applyStyle(Frame::Corner*, Reader r) {
return false;
}
bool Style::applyStyle(Frame::Border*, Reader r) {
return false;
}
Widget::Layer Style::strToLayer(const std::string& layer)
{
std::string l = lowerCase(layer);
if(l == "top") return Widget::LAYER_TOP;
else if(l == "high") return Widget::LAYER_HIGH;
else if(l == "middle") return Widget::LAYER_MIDDLE;
else if(l == "low") return Widget::LAYER_LOW;
else if(l == "bg") return Widget::LAYER_BG;
else {
warn() << "Unkown Layer name [" << layer << "]; using LAYER_MIDDLE." << std::endl;
return Widget::LAYER_MIDDLE;
}
}
Widget::VerticalAlignment Style::strToVAlign(const std::string& valign) {
std::string va = lowerCase(valign);
if(va == "center") return Widget::VA_CENTER;
else if(va == "top") return Widget::VA_TOP;
else if(va == "bottom") return Widget::VA_BOTTOM;
else {
warn() << "Unkown VAlign name [" << valign << "]; using VA_CENTER." << std::endl;
return Widget::VA_CENTER;
}
}
Widget::HorizontalAlignment Style::strToHAlign(const std::string& halign) {
std::string ha = lowerCase(halign);
if(ha == "center") return Widget::HA_CENTER;
else if(ha == "left") return Widget::HA_LEFT;
else if(ha == "right") return Widget::HA_RIGHT;
else {
warn() << "Unkown HAlign name [" << halign << "]; using HA_CENTER." << std::endl;
return Widget::HA_CENTER;
}
}
Widget::CoordinateMode Style::strToCoordMode(const std::string& coordmode) {
std::string cm = lowerCase(coordmode);
if(cm == "absolute") return Widget::CM_ABSOLUTE;
else if(cm == "relative") return Widget::CM_RELATIVE;
else {
warn()
<< "Unkown CoordMode name [" << coordmode
<< "]; using CM_ABSOLUTE." << std::endl
;
return Widget::CM_ABSOLUTE;
}
}
bool Style::strToFill(const std::string& fill) {
std::string cm = lowerCase(fill);
if(cm == "true") return true;
else if(cm == "false") return false;
else {
warn()
<< "Unkown Fill name [" << fill
<< "]; using false." << std::endl
;
return false;
}
}
StyleManager::StyleManager() {
}
StyleManager::StyleManager(const StyleManager& manager, const osg::CopyOp& co):
osg::Object(manager, co) {
for(ConstIterator i = _styles.begin(); i != _styles.end(); i++) if(i->second.valid()) {
_styles[i->first] = new Style(*i->second.get(), osg::CopyOp::DEEP_COPY_ALL);
}
}
bool StyleManager::_applyStyleToObject(osg::Object* obj, const std::string& style) {
std::string c = obj->className();
if(!std::string("Widget").compare(c)) return _coerceAndApply<Widget>(
obj,
style,
c
);
else if(!std::string("Label").compare(c)) return _coerceAndApply<Label>(
obj,
style,
c
);
else if(!std::string("Box").compare(c)) return _coerceAndApply<Box>(
obj,
style,
c
);
else if(!std::string("Canvas").compare(c)) return _coerceAndApply<Canvas>(
obj,
style,
c
);
else if(!std::string("Window").compare(c)) return _coerceAndApply<Window>(
obj,
style,
c
);
else if(!std::string("Input").compare(c)) return _coerceAndApply<Input>(
obj,
style,
c
);
else if(!std::string("Corner").compare(c)) return _coerceAndApply<Frame::Corner>(
obj,
style,
c
);
else if(!std::string("Border").compare(c)) return _coerceAndApply<Frame::Border>(
obj,
style,
c
);
else if(!std::string("EmbeddedWindow").compare(c)) return _coerceAndApply<Window::EmbeddedWindow>(
obj,
style,
c
);
else warn()
<< "StyleManager does not support coercion of objects of type "
<< c << "." << std::endl
;
return false;
}
bool StyleManager::addStyle(Style* style) {
if(!style || style->getName().empty()) {
warn() << "Cannot add a NULL or nameless Style object." << std::endl;
return false;
}
_styles[style->getName()] = style;
return true;
}
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org