From 85c36885f5bbf2d47276c7702f1b8ccbf22ecc34 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 4 Aug 2008 16:59:55 +0000 Subject: Theme layout parsing. Work in progress. svn-id: r33613 --- gui/ThemeEval.h | 291 +++++++++++++++++++++++++++++++++++++++++++++++++ gui/ThemeParser.cpp | 73 ++++++++++--- gui/ThemeParser.h | 37 +++++-- gui/ThemeRenderer.cpp | 7 +- gui/newgui.cpp | 21 +++- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 115 +++++++++++-------- 7 files changed, 470 insertions(+), 76 deletions(-) (limited to 'gui') diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index c5471bb10d..f53dfe2cd1 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -39,9 +39,233 @@ namespace GUI { +class ThemeLayout { +public: + int16 x, y, w, h; + int paddingTop, paddingBottom, paddingLeft, paddingRight; + int spacing; + Common::Array children; + ThemeLayout *parent; + + uint16 debugcolor; + + enum LayoutType { + kLayoutNone, + kLayoutVertical, + kLayoutHorizontal, + kLayoutWidget + }; + + enum LayoutParsing { + kLayoutParseDefault, + kLayoutParseTop2Bottom, + kLayoutParseBottom2Top, + kLayoutParseLeft2Right, + kLayoutParseRight2Left + } parsingMode; + + virtual LayoutType getLayoutType() { return kLayoutNone; } + virtual void reflowLayout() { + assert(children.size() <= 1); + + if (children.size()) { + children[0]->w = w; + children[0]->h = h; + children[0]->reflowLayout(); + children[0]->setX(0); + children[0]->setY(0); + } + } + + virtual const char *getName() { return "Global Layout"; } + + int16 getParentW() { return parent ? parent->w : g_system->getOverlayWidth(); } + int16 getParentH() { return parent ? parent->w : g_system->getOverlayHeight(); } + int16 getParentX() { return parent ? parent->x : 0; } + int16 getParentY() { return parent ? parent->y : 0; } + + void setX(int newX) { + x += newX; + for (uint i = 0; i < children.size(); ++i) + children[i]->setX(newX); + } + + void setY(int newY) { + y += newY; + for (uint i = 0; i < children.size(); ++i) + children[i]->setY(newY); + } + + ThemeLayout(ThemeLayout *p) : parent(p), x(0), y(0), w(-1), h(-1) { debugcolor = rand() % 0xFFFF; } + + virtual void debugPrintIndent(int indent) { + while (indent--) + printf(" "); + } + + void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { + uint16 color = debugcolor; + font->drawString(screen, getName(), x, y, w, color, Graphics::kTextAlignRight, 0, true); + screen->hLine(x, y, x + w, color); + screen->hLine(x, y + h, x + w, color); + screen->vLine(x, y, y + h, color); + screen->vLine(x + w, y, y + h, color); + + for (uint i = 0; i < children.size(); ++i) + children[i]->debugDraw(screen, font); + } + + virtual void debugPrint(int indent = 0) { + debugPrintIndent(indent); + switch (getLayoutType()) { + case kLayoutNone: + printf("Dialog Layout :: "); + break; + + case kLayoutVertical: + printf("Vertical Layout :: "); + break; + + case kLayoutHorizontal: + printf("Horizontal Layout :: "); + break; + + case kLayoutWidget: + printf("WIDGET (%s) :: ", getName()); + break; + } + + printf("X: %d / Y: %d / W: %d / H: %d\n", x, y, w, h); + + for (uint i = 0; i < children.size(); ++i) + children[i]->debugPrint(indent + 1); + } + + virtual ~ThemeLayout() { + children.clear(); + } +}; + +class ThemeLayoutVertical : public ThemeLayout { +public: + LayoutType getLayoutType() { return kLayoutVertical; } + + ThemeLayoutVertical(ThemeLayout *p) : ThemeLayout(p) {} + + const char *getName() { return "Vertical Layout"; } + + void reflowLayout() { + int curX, curY, mul; + + if (parsingMode == kLayoutParseTop2Bottom) { + curX = paddingLeft; + curY = paddingTop; + mul = 1; + } else { + curX = paddingLeft; + curY = getParentH() - paddingBottom; + mul = -1; + } + + h = paddingTop + paddingBottom; + + for (uint i = 0; i < children.size(); ++i) { + assert(children[i]->getLayoutType() != kLayoutVertical); + + children[i]->reflowLayout(); + + if (i != children.size() - 1) + assert(children[i]->h != -1); + + if (i == 0) + assert(children[i]->w != -1); + + children[i]->setX(curX); + children[i]->setY((parsingMode == kLayoutParseBottom2Top) ? curY - children[i]->h : curY); + + if (children[i]->w == -1) + children[i]->w = w - paddingLeft - paddingRight; + + w = MAX(w, (int16)(children[i]->w + paddingLeft + paddingRight)); + + if (children[i]->h == -1) + children[i]->h = 32; + + h += children[i]->h + spacing; + + curY += (children[i]->h + spacing) * mul; + } + + + } +}; + +class ThemeLayoutHorizontal : public ThemeLayout { +public: + LayoutType getLayoutType() { return kLayoutHorizontal; } + + ThemeLayoutHorizontal(ThemeLayout *p) : ThemeLayout(p) {} + + const char *getName() { return "Horizontal Layout"; } + + void reflowLayout() { + int curX, curY, mul; + + if (parsingMode == kLayoutParseLeft2Right) { + curX = paddingLeft; + curY = paddingTop; + mul = 1; + } else { + curX = getParentW() - paddingRight; + curY = paddingTop; + mul = -1; + } + + w = paddingLeft + paddingRight; + + for (uint i = 0; i < children.size(); ++i) { + assert(children[i]->getLayoutType() != kLayoutHorizontal); + + children[i]->reflowLayout(); + + if (i != children.size() - 1) + assert(children[i]->w != -1); + + if (i == 0) + assert(children[i]->h != -1); + + + children[i]->setX((parsingMode == kLayoutParseRight2Left) ? (curX - children[i]->w) : (curX)); + children[i]->setY(curY); + + if (children[i]->h == -1) + children[i]->h = h - paddingTop - paddingBottom; + + h = MAX(h, (int16)(children[i]->h + paddingTop + paddingBottom)); + + curX += (children[i]->w + spacing) * mul; + w += children[i]->w + spacing; + } + } +}; + +class ThemeLayoutWidget : public ThemeLayout { +public: + LayoutType getLayoutType() { return kLayoutWidget; } + void reflowLayout() { + + } + ThemeLayoutWidget(ThemeLayout *p, const Common::String &name) : ThemeLayout(p), widgetName(name) {} + + const char *getName() { return widgetName.c_str(); } + + Common::String widgetName; +}; + class ThemeEval { typedef Common::HashMap VariablesMap; + typedef Common::HashMap LayoutsMap; public: ThemeEval() {} @@ -64,6 +288,67 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name); } + void addDialog(const Common::String &name) { + ThemeLayout *layout = new ThemeLayout(0); + _layouts[name] = layout; + + layout->x = 0; + layout->y = 0; + layout->w = g_system->getOverlayWidth(); + layout->h = g_system->getOverlayHeight(); + + layout->paddingBottom = getVar("Globals.Padding.Bottom", 0); + layout->paddingTop = getVar("Globals.Padding.Top", 0); + layout->paddingRight = getVar("Globals.Padding.Right", 0); + layout->paddingLeft = getVar("Globals.Padding.Left", 0); + + _curLayout.push(layout); + } + + void addLayout(ThemeLayout::LayoutType type, ThemeLayout::LayoutParsing parsingMode) { + ThemeLayout *layout = 0; + ThemeLayout::LayoutParsing def = ThemeLayout::kLayoutParseDefault; + + if (type == ThemeLayout::kLayoutVertical) { + layout = new ThemeLayoutVertical(_curLayout.top()); + def = ThemeLayout::kLayoutParseTop2Bottom; + } else if (type == ThemeLayout::kLayoutHorizontal) { + layout = new ThemeLayoutHorizontal(_curLayout.top()); + def = ThemeLayout::kLayoutParseLeft2Right; + } + + layout->parsingMode = (parsingMode == ThemeLayout::kLayoutParseDefault) ? def : parsingMode; + layout->paddingBottom = getVar("Globals.Padding.Bottom", 0); + layout->paddingTop = getVar("Globals.Padding.Top", 0); + layout->paddingRight = getVar("Globals.Padding.Right", 0); + layout->paddingLeft = getVar("Globals.Padding.Left", 0); + + layout->spacing = 4; + + _curLayout.top()->children.push_back(layout); + _curLayout.push(layout); + } + + void closeLayout() { + _curLayout.pop(); + } + + void closeDialog() { + _curLayout.top()->reflowLayout(); + printf("DEBUG LAYOUT PRINT:\n"); + + _curLayout.top()->debugPrint(); + } + + void addWidget(const Common::String &name, int w, int h) { + ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name); + + widget->w = w; + widget->h = h; + + _curLayout.top()->children.push_back(widget); + } + void debugPrint() { printf("Debug variable list:\n"); @@ -72,9 +357,15 @@ public: printf(" '%s' = %d\n", i->_key.c_str(), i->_value); } } + + void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { + _curLayout.top()->debugDraw(screen, font); + } private: VariablesMap _vars; + LayoutsMap _layouts; + Common::Stack _curLayout; }; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 310d3d880d..530f613fdb 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -88,7 +88,7 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { step->fillMode = Graphics::VectorRenderer::kFillDisabled; step->scale = (1 << 16); step->shadow = 0; - step->innerShadow = 0; + step->bevel = 0; step->stroke = 0; step->radius = 0xFF; @@ -307,7 +307,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst } __PARSER_ASSIGN_INT(stroke, "stroke", false); - __PARSER_ASSIGN_INT(innerShadow, "inner_shadow", false); + __PARSER_ASSIGN_INT(bevel, "bevel", false); __PARSER_ASSIGN_INT(shadow, "shadow", false); __PARSER_ASSIGN_INT(factor, "gradient_factor", false); @@ -315,6 +315,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst __PARSER_ASSIGN_RGB(bgColor, "bg_color"); __PARSER_ASSIGN_RGB(gradColor1, "gradient_start"); __PARSER_ASSIGN_RGB(gradColor2, "gradient_end"); + __PARSER_ASSIGN_RGB(bevelColor, "bevel_color"); if (functionSpecific) { assert(stepNode->values.contains("func")); @@ -449,16 +450,35 @@ bool ThemeParser::parserCallback_def(ParserNode *node) { bool ThemeParser::parserCallback_widget(ParserNode *node) { Common::String var; - if (getParentNode(node)->name == "globals") + if (getParentNode(node)->name == "globals") { var = "Globals." + node->values["name"] + "."; - else if (getParentNode(node)->name == "dialog") - var = "Dialog." + getParentNode(node)->values["name"] + "." + node->values["name"] + "."; - else - assert(!"Corruption in XML parser."); - - if (!parseCommonLayoutProps(node, var)) - return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); - + if (!parseCommonLayoutProps(node, var)) + return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + } else { + var = node->values["name"]; + int width = -1; + int height = -1; + + if (node->values.contains("width")) { + if (_theme->themeEval()->hasVar(node->values["width"]) == true) + width = _theme->themeEval()->getVar(node->values["width"]); + + else if (!parseIntegerKey(node->values["width"].c_str(), 1, &width)) + return parserError("Corrupted width value in key for %s", var.c_str()); + } + + if (node->values.contains("height")) { + if (_theme->themeEval()->hasVar(node->values["height"]) == true) + height = _theme->themeEval()->getVar(node->values["height"]); + + else if (!parseIntegerKey(node->values["height"].c_str(), 1, &height)) + return parserError("Corrupted height value in key for %s", var.c_str()); + } + + _theme->themeEval()->addWidget(var, width, height); + + } + return true; } @@ -474,8 +494,35 @@ bool ThemeParser::parserCallback_child(ParserNode *node) { bool ThemeParser::parserCallback_dialog(ParserNode *node) { Common::String var = "Dialog." + node->values["name"] + "."; - if (!parseCommonLayoutProps(node, var)) - return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); +// if (!parseCommonLayoutProps(node, var)) +// return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + + _theme->themeEval()->addDialog(var); + + return true; +} + +bool ThemeParser::parserCallback_layout(ParserNode *node) { + + if (!node->values.contains("type")) + return parserError("Layouts need a specific type (vertical or horizontal)."); + + GUI::ThemeLayout::LayoutType type = GUI::ThemeLayout::kLayoutNone; + + if (node->values["type"] == "vertical") + type = GUI::ThemeLayout::kLayoutVertical; + else if (node->values["type"] == "horizontal") + type = GUI::ThemeLayout::kLayoutHorizontal; + + _theme->themeEval()->addLayout(type, GUI::ThemeLayout::kLayoutParseDefault); + return true; +} + +bool ThemeParser::closedKeyCallback(ParserNode *node) { + if (node->name == "layout") + _theme->themeEval()->closeLayout(); + else if (node->name == "dialog") + _theme->themeEval()->closeDialog(); return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index ec7f494735..07bb530894 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -351,12 +351,13 @@ protected: XML_KEY(defaults) XML_PROP(stroke, false) XML_PROP(shadow, false) - XML_PROP(inner_shadow, false) + XML_PROP(bevel, false) XML_PROP(factor, false) XML_PROP(fg_color, false) XML_PROP(bg_color, false) XML_PROP(gradient_start, false) XML_PROP(gradient_end, false) + XML_PROP(bevel_color, false) XML_PROP(gradient_factor, false) XML_PROP(fill, false) KEY_END() @@ -368,12 +369,13 @@ protected: XML_KEY(defaults) XML_PROP(stroke, false) XML_PROP(shadow, false) - XML_PROP(inner_shadow, false) + XML_PROP(bevel, false) XML_PROP(factor, false) XML_PROP(fg_color, false) XML_PROP(bg_color, false) XML_PROP(gradient_start, false) XML_PROP(gradient_end, false) + XML_PROP(bevel_color, false) XML_PROP(gradient_factor, false) XML_PROP(fill, false) KEY_END() @@ -382,13 +384,14 @@ protected: XML_PROP(func, true) XML_PROP(stroke, false) XML_PROP(shadow, false) - XML_PROP(inner_shadow, false) + XML_PROP(bevel, false) XML_PROP(factor, false) XML_PROP(fg_color, false) XML_PROP(bg_color, false) XML_PROP(gradient_start, false) XML_PROP(gradient_end, false) XML_PROP(gradient_factor, false) + XML_PROP(bevel_color, false) XML_PROP(fill, false) XML_PROP(bevel, false) XML_PROP(radius, false) @@ -432,15 +435,21 @@ protected: XML_KEY(dialog) XML_PROP(name, true) - XML_PROP(size, false) - XML_PROP(pos, false) - XML_PROP(resolution, false) - - XML_KEY(widget) - XML_PROP(name, true) - XML_PROP(size, false) - XML_PROP(pos, false) - XML_PROP(padding, false) + XML_KEY(layout) + XML_PROP(type, true) + XML_PROP(align, false) + XML_PROP(direction, false) + XML_KEY(widget) + XML_PROP(name, true) + XML_PROP(width, false) + XML_PROP(height, false) + KEY_END() + + XML_KEY(space) + XML_PROP(size, true) + KEY_END() + + XML_KEY_RECURSIVE(layout) KEY_END() KEY_END() KEY_END() @@ -465,6 +474,10 @@ protected: bool parserCallback_widget(ParserNode *node); bool parserCallback_dialog(ParserNode *node); bool parserCallback_child(ParserNode *node); + bool parserCallback_layout(ParserNode *node); + bool parserCallback_space(ParserNode *node) { return true; } + + bool closedKeyCallback(ParserNode *node); void cleanup(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 9a01b18299..f154f018b9 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -693,8 +693,11 @@ void ThemeRenderer::updateScreen() { _textQueue.clear(); } - renderDirtyScreen(); -// _vectorRenderer->copyWholeFrame(_system); +// renderDirtyScreen(); + + _vectorRenderer->fillSurface(); + themeEval()->debugDraw(_screen, _font); + _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/newgui.cpp b/gui/newgui.cpp index b2e9cf43b0..3c58633923 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -163,6 +163,7 @@ bool NewGui::loadNewTheme(const Common::String &style) { cfg.clear(); */ _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxAntialias16bit); +// _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxStandard16bit); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); @@ -244,6 +245,8 @@ void NewGui::runLoop() { } Common::EventManager *eventMan = _system->getEventManager(); + uint32 lastRedraw = 0; + const uint32 waitTime = 1000 / 45; while (!_dialogStack.empty() && activeDialog == getTopDialog()) { redraw(); @@ -255,9 +258,15 @@ void NewGui::runLoop() { if (_useStdCursor) animateCursor(); - _theme->updateScreen(); - _system->updateScreen(); - +// _theme->updateScreen(); +// _system->updateScreen(); + + if (lastRedraw + waitTime < _system->getMillis()) { + _theme->updateScreen(); + _system->updateScreen(); + lastRedraw = _system->getMillis(); + } + Common::Event event; while (eventMan->pollEvent(event)) { @@ -280,6 +289,12 @@ void NewGui::runLoop() { _redrawStatus = kRedrawFull; redraw(); } + + if (lastRedraw + waitTime < _system->getMillis()) { + _theme->updateScreen(); + _system->updateScreen(); + lastRedraw = _system->getMillis(); + } switch (event.type) { case Common::EVENT_KEYDOWN: diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 20d3e3869f..fb5bd8dcf3 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index dce8495ff8..c26a7856af 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -52,6 +52,9 @@ + @@ -81,7 +84,7 @@ /> - + @@ -314,10 +318,11 @@ radius = '6' stroke = 1 fill = 'gradient' - shadow = 2 - fg_color = 'blandyellow' + shadow = 0 + fg_color = 'shadowcolor' gradient_start = 'brightred' gradient_end = 'darkred' + bevel = 1 /> @@ -329,11 +334,14 @@ @@ -361,7 +369,8 @@ radius = 4 fg_color = 'black' shadow = 0 - inner_shadow = 1 + bevel = 1 + bevel_color = 'shadowcolor' /> @@ -377,8 +386,8 @@ gradient_start = 'brightred' gradient_end = 'darkred' shadow = 0 - stroke = 1 - inner_shadow = 1 + bevel = 1 + bevel_color = 'shadowcolor' /> @@ -392,7 +401,8 @@ radius = 4 fg_color = 'blandyellow' shadow = 0 - inner_shadow = 1 + bevel = 1 + bevel_color = 'shadowcolor' /> @@ -410,9 +420,14 @@ - + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3