From af671d109fbcb1a69354c0929c474d37782aefcb Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 18 Jan 2024 16:23:12 +0200 Subject: [PATCH] Made graphical primitive-based UI more configurable --- client/CMakeLists.txt | 2 + client/adventureMap/TurnTimerWidget.cpp | 2 +- client/battle/BattleInterfaceClasses.cpp | 2 +- client/globalLobby/GlobalLobbyLoginWindow.cpp | 1 + client/globalLobby/GlobalLobbyWidget.cpp | 1 + client/gui/InterfaceObjectConfigurable.cpp | 23 ++++- client/gui/InterfaceObjectConfigurable.h | 1 + client/lobby/CSelectionBase.cpp | 2 +- client/mainmenu/CHighScoreScreen.cpp | 2 +- client/widgets/GraphicalPrimitiveCanvas.cpp | 85 ++++++++++++++++ client/widgets/GraphicalPrimitiveCanvas.h | 54 +++++++++++ client/widgets/MiscWidgets.cpp | 60 +++--------- client/widgets/MiscWidgets.h | 30 +----- client/windows/CHeroOverview.cpp | 4 +- client/windows/CSpellWindow.cpp | 2 +- config/widgets/turnOptionsTab.json | 96 ++++++++++++------- 16 files changed, 247 insertions(+), 120 deletions(-) create mode 100644 client/widgets/GraphicalPrimitiveCanvas.cpp create mode 100644 client/widgets/GraphicalPrimitiveCanvas.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 545faa4f5..561dd0201 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -108,6 +108,7 @@ set(client_SRCS widgets/CGarrisonInt.cpp widgets/CreatureCostBox.cpp widgets/ComboBox.cpp + widgets/GraphicalPrimitiveCanvas.cpp widgets/Images.cpp widgets/MiscWidgets.cpp widgets/ObjectLists.cpp @@ -291,6 +292,7 @@ set(client_HEADERS widgets/CGarrisonInt.h widgets/CreatureCostBox.h widgets/ComboBox.h + widgets/GraphicalPrimitiveCanvas.h widgets/Images.h widgets/MiscWidgets.h widgets/ObjectLists.h diff --git a/client/adventureMap/TurnTimerWidget.cpp b/client/adventureMap/TurnTimerWidget.cpp index 95effa225..c97d67f94 100644 --- a/client/adventureMap/TurnTimerWidget.cpp +++ b/client/adventureMap/TurnTimerWidget.cpp @@ -18,7 +18,7 @@ #include "../gui/CGuiHandler.h" #include "../render/Graphics.h" #include "../widgets/Images.h" -#include "../widgets/MiscWidgets.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/TextControls.h" #include "../../CCallback.h" diff --git a/client/battle/BattleInterfaceClasses.cpp b/client/battle/BattleInterfaceClasses.cpp index e2cd006c1..eb97fdcab 100644 --- a/client/battle/BattleInterfaceClasses.cpp +++ b/client/battle/BattleInterfaceClasses.cpp @@ -34,7 +34,7 @@ #include "../widgets/Buttons.h" #include "../widgets/Images.h" #include "../widgets/TextControls.h" -#include "../widgets/MiscWidgets.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../windows/CMessage.h" #include "../windows/CCreatureWindow.h" #include "../windows/CSpellWindow.h" diff --git a/client/globalLobby/GlobalLobbyLoginWindow.cpp b/client/globalLobby/GlobalLobbyLoginWindow.cpp index 673941c9f..bf5c68224 100644 --- a/client/globalLobby/GlobalLobbyLoginWindow.cpp +++ b/client/globalLobby/GlobalLobbyLoginWindow.cpp @@ -20,6 +20,7 @@ #include "../gui/WindowHandler.h" #include "../widgets/Buttons.h" #include "../widgets/Images.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/MiscWidgets.h" #include "../widgets/TextControls.h" diff --git a/client/globalLobby/GlobalLobbyWidget.cpp b/client/globalLobby/GlobalLobbyWidget.cpp index 2be6b21e8..0ffe23254 100644 --- a/client/globalLobby/GlobalLobbyWidget.cpp +++ b/client/globalLobby/GlobalLobbyWidget.cpp @@ -18,6 +18,7 @@ #include "../gui/CGuiHandler.h" #include "../gui/WindowHandler.h" #include "../widgets/Buttons.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/MiscWidgets.h" #include "../widgets/ObjectLists.h" #include "../widgets/TextControls.h" diff --git a/client/gui/InterfaceObjectConfigurable.cpp b/client/gui/InterfaceObjectConfigurable.cpp index 38ad05cad..50d6eedbc 100644 --- a/client/gui/InterfaceObjectConfigurable.cpp +++ b/client/gui/InterfaceObjectConfigurable.cpp @@ -22,7 +22,7 @@ #include "../widgets/CComponent.h" #include "../widgets/ComboBox.h" #include "../widgets/Buttons.h" -#include "../widgets/MiscWidgets.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/ObjectLists.h" #include "../widgets/Slider.h" #include "../widgets/TextControls.h" @@ -57,6 +57,7 @@ InterfaceObjectConfigurable::InterfaceObjectConfigurable(int used, Point offset) REGISTER_BUILDER("layout", &InterfaceObjectConfigurable::buildLayout); REGISTER_BUILDER("comboBox", &InterfaceObjectConfigurable::buildComboBox); REGISTER_BUILDER("textInput", &InterfaceObjectConfigurable::buildTextInput); + REGISTER_BUILDER("graphicalPrimitive", &InterfaceObjectConfigurable::buildGraphicalPrimitive); REGISTER_BUILDER("transparentFilledRectangle", &InterfaceObjectConfigurable::buildTransparentFilledRectangle); REGISTER_BUILDER("textBox", &InterfaceObjectConfigurable::buildTextBox); } @@ -707,6 +708,26 @@ std::shared_ptr InterfaceObjectConfigurable::buildAnimation(const return anim; } +std::shared_ptr InterfaceObjectConfigurable::buildGraphicalPrimitive(const JsonNode & config) const +{ + logGlobal->debug("Building widget GraphicalPrimitiveCanvas"); + + auto rect = readRect(config["rect"]); + auto widget = std::make_shared(rect); + + for (auto const & entry : config["primitives"].Vector()) + { + auto color = readColor(entry["color"]); + //auto typeString = entry["type"]; + auto pointA = readPosition(entry["a"]); + auto pointB = readPosition(entry["b"]); + + widget->addLine(pointA, pointB, color); + } + + return widget; +} + std::shared_ptr InterfaceObjectConfigurable::buildTransparentFilledRectangle(const JsonNode & config) const { logGlobal->debug("Building widget TransparentFilledRectangle"); diff --git a/client/gui/InterfaceObjectConfigurable.h b/client/gui/InterfaceObjectConfigurable.h index b1ce32b67..b1bbbde93 100644 --- a/client/gui/InterfaceObjectConfigurable.h +++ b/client/gui/InterfaceObjectConfigurable.h @@ -108,6 +108,7 @@ protected: std::shared_ptr buildComboBox(const JsonNode &); std::shared_ptr buildTextInput(const JsonNode &) const; std::shared_ptr buildTransparentFilledRectangle(const JsonNode & config) const; + std::shared_ptr buildGraphicalPrimitive(const JsonNode & config) const; std::shared_ptr buildTextBox(const JsonNode & config) const; //composite widgets diff --git a/client/lobby/CSelectionBase.cpp b/client/lobby/CSelectionBase.cpp index 86bb6ed26..df251d4f9 100644 --- a/client/lobby/CSelectionBase.cpp +++ b/client/lobby/CSelectionBase.cpp @@ -29,7 +29,7 @@ #include "../mainmenu/CMainMenu.h" #include "../widgets/Buttons.h" #include "../widgets/CComponent.h" -#include "../widgets/MiscWidgets.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/ObjectLists.h" #include "../widgets/Slider.h" #include "../widgets/TextControls.h" diff --git a/client/mainmenu/CHighScoreScreen.cpp b/client/mainmenu/CHighScoreScreen.cpp index 4abcc712b..4d18d4c04 100644 --- a/client/mainmenu/CHighScoreScreen.cpp +++ b/client/mainmenu/CHighScoreScreen.cpp @@ -17,7 +17,7 @@ #include "../widgets/TextControls.h" #include "../widgets/Buttons.h" #include "../widgets/Images.h" -#include "../widgets/MiscWidgets.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../windows/InfoWindows.h" #include "../render/Canvas.h" diff --git a/client/widgets/GraphicalPrimitiveCanvas.cpp b/client/widgets/GraphicalPrimitiveCanvas.cpp new file mode 100644 index 000000000..e7734edde --- /dev/null +++ b/client/widgets/GraphicalPrimitiveCanvas.cpp @@ -0,0 +1,85 @@ +/* + * MiscWidgets.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "GraphicalPrimitiveCanvas.h" + +#include "../render/Canvas.h" + +GraphicalPrimitiveCanvas::GraphicalPrimitiveCanvas(Rect dimensions) +{ + pos = dimensions + pos.topLeft(); +} + +void GraphicalPrimitiveCanvas::showAll(Canvas & to) +{ + auto const & translatePoint = [this](const Point & input){ + int x = input.x < 0 ? pos.w + input.x : input.x; + int y = input.y < 0 ? pos.h + input.y : input.y; + + return Point(x,y); + }; + + for (auto const & entry : primitives) + { + switch (entry.type) + { + case PrimitiveType::LINE: + { + to.drawLine(pos.topLeft() + translatePoint(entry.a), pos.topLeft() + translatePoint(entry.b), entry.color, entry.color); + break; + } + case PrimitiveType::FILLED_BOX: + { + to.drawColorBlended(Rect(pos.topLeft() + translatePoint(entry.a), translatePoint(entry.b)), entry.color); + break; + } + case PrimitiveType::RECTANGLE: + { + to.drawBorder(Rect(pos.topLeft() + translatePoint(entry.a), translatePoint(entry.b)), entry.color); + break; + } + } + } +} + +void GraphicalPrimitiveCanvas::addLine(const Point & from, const Point & to, const ColorRGBA & color) +{ + primitives.push_back({color, from, to, PrimitiveType::LINE}); +} + +void GraphicalPrimitiveCanvas::addBox(const Point & topLeft, const Point & size, const ColorRGBA & color) +{ + primitives.push_back({color, topLeft, size, PrimitiveType::FILLED_BOX}); +} + +void GraphicalPrimitiveCanvas::addRectangle(const Point & topLeft, const Point & size, const ColorRGBA & color) +{ + primitives.push_back({color, topLeft, size, PrimitiveType::RECTANGLE}); +} + +TransparentFilledRectangle::TransparentFilledRectangle(Rect position, ColorRGBA color) : + GraphicalPrimitiveCanvas(position) +{ + addBox(Point(0,0), Point(-1, -1), color); +} + +TransparentFilledRectangle::TransparentFilledRectangle(Rect position, ColorRGBA color, ColorRGBA colorLine, int width) : + GraphicalPrimitiveCanvas(position) +{ + addBox(Point(0,0), Point(-1, -1), color); + for (int i = 0; i < width; ++i) + addRectangle(Point(i,i), Point(-1-i, -1-i), colorLine); +} + +SimpleLine::SimpleLine(Point pos1, Point pos2, ColorRGBA color) : + GraphicalPrimitiveCanvas(Rect(pos1, pos2 - pos1)) +{ + addLine(Point(0,0), Point(-1, -1), color); +} diff --git a/client/widgets/GraphicalPrimitiveCanvas.h b/client/widgets/GraphicalPrimitiveCanvas.h new file mode 100644 index 000000000..2cf508b94 --- /dev/null +++ b/client/widgets/GraphicalPrimitiveCanvas.h @@ -0,0 +1,54 @@ +/* + * GraphicalPrimitiveCanvas.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "../gui/CIntObject.h" + +class GraphicalPrimitiveCanvas : public CIntObject +{ + enum class PrimitiveType + { + LINE, + RECTANGLE, + FILLED_BOX + }; + + struct PrimitiveEntry + { + ColorRGBA color; + Point a; + Point b; + PrimitiveType type; + }; + + std::vector primitives; + + void showAll(Canvas & to) override; + +public: + GraphicalPrimitiveCanvas(Rect position); + + void addLine(const Point & from, const Point & to, const ColorRGBA & color); + void addBox(const Point & topLeft, const Point & size, const ColorRGBA & color); + void addRectangle(const Point & topLeft, const Point & size, const ColorRGBA & color); +}; + +class TransparentFilledRectangle : public GraphicalPrimitiveCanvas +{ +public: + TransparentFilledRectangle(Rect position, ColorRGBA color); + TransparentFilledRectangle(Rect position, ColorRGBA color, ColorRGBA colorLine, int width = 1); +}; + +class SimpleLine : public GraphicalPrimitiveCanvas +{ +public: + SimpleLine(Point pos1, Point pos2, ColorRGBA color); +}; diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index c44bc288c..584392267 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -21,8 +21,9 @@ #include "../gui/WindowHandler.h" #include "../eventsSDL/InputHandler.h" #include "../windows/CTradeWindow.h" -#include "../widgets/TextControls.h" #include "../widgets/CGarrisonInt.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" +#include "../widgets/TextControls.h" #include "../windows/CCastleInterface.h" #include "../windows/InfoWindows.h" #include "../render/Canvas.h" @@ -663,54 +664,13 @@ void CCreaturePic::setAmount(int newAmount) amount->setText(""); } -TransparentFilledRectangle::TransparentFilledRectangle(Rect position, ColorRGBA color) : - color(color), colorLine(ColorRGBA()), drawLine(false), lineWidth(0) -{ - pos = position + pos.topLeft(); -} - -TransparentFilledRectangle::TransparentFilledRectangle(Rect position, ColorRGBA color, ColorRGBA colorLine, int width) : - color(color), colorLine(colorLine), drawLine(true), lineWidth(width) -{ - pos = position + pos.topLeft(); -} - -void TransparentFilledRectangle::setDrawBorder(bool on) -{ - drawLine = on; -} - -bool TransparentFilledRectangle::getDrawBorder() -{ - return drawLine; -} - -void TransparentFilledRectangle::setBorderWidth(int width) -{ - lineWidth = width; -} - -void TransparentFilledRectangle::showAll(Canvas & to) -{ - to.drawColorBlended(pos, color); - if(drawLine) - to.drawBorder(pos, colorLine, lineWidth); -} - -SimpleLine::SimpleLine(Point pos1, Point pos2, ColorRGBA color) : - pos1(pos1), pos2(pos2), color(color) -{} - -void SimpleLine::showAll(Canvas & to) -{ - to.drawLine(pos1 + pos.topLeft(), pos2 + pos.topLeft(), color, color); -} - SelectableSlot::SelectableSlot(Rect area, Point oversize, const int width) : LRClickableAreaWTextComp(area) + , selected(false) { - selection = std::make_unique( - Rect(area.topLeft() - oversize, area.dimensions() + oversize * 2), Colors::TRANSPARENCY, Colors::YELLOW, width); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + selection = std::make_shared( Rect(-oversize, area.dimensions() + oversize * 2), Colors::TRANSPARENCY, Colors::YELLOW, width); selectSlot(false); } @@ -726,15 +686,17 @@ SelectableSlot::SelectableSlot(Rect area, const int width) void SelectableSlot::selectSlot(bool on) { - selection->setDrawBorder(on); + selection->setEnabled(on); + selected = on; } bool SelectableSlot::isSelected() const { - return selection->getDrawBorder(); + return selected; } void SelectableSlot::setSelectionWidth(int width) { - selection->setBorderWidth(width); + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + selection = std::make_shared( selection->pos - pos.topLeft(), Colors::TRANSPARENCY, Colors::YELLOW, width); } diff --git a/client/widgets/MiscWidgets.h b/client/widgets/MiscWidgets.h index acdfcd2dd..36a741755 100644 --- a/client/widgets/MiscWidgets.h +++ b/client/widgets/MiscWidgets.h @@ -33,6 +33,7 @@ class CCreatureAnim; class CComponent; class CAnimImage; class LRClickableArea; +class TransparentFilledRectangle; /// Shows a text by moving the mouse cursor over the object class CHoverableArea: public virtual CIntObject @@ -248,35 +249,10 @@ public: MoraleLuckBox(bool Morale, const Rect &r, bool Small=false); }; -class TransparentFilledRectangle : public CIntObject -{ - ColorRGBA color; - ColorRGBA colorLine; - bool drawLine; - int lineWidth; - -public: - TransparentFilledRectangle(Rect position, ColorRGBA color); - TransparentFilledRectangle(Rect position, ColorRGBA color, ColorRGBA colorLine, int width = 1); - void setDrawBorder(bool on); - bool getDrawBorder(); - void setBorderWidth(int width); - void showAll(Canvas & to) override; -}; - -class SimpleLine : public CIntObject -{ - Point pos1; - Point pos2; - ColorRGBA color; -public: - SimpleLine(Point pos1, Point pos2, ColorRGBA color); - void showAll(Canvas & to) override; -}; - class SelectableSlot : public LRClickableAreaWTextComp { - std::unique_ptr selection; + std::shared_ptr selection; + bool selected; public: SelectableSlot(Rect area, Point oversize, const int width); diff --git a/client/windows/CHeroOverview.cpp b/client/windows/CHeroOverview.cpp index 00b522cc2..2a5412dc1 100644 --- a/client/windows/CHeroOverview.cpp +++ b/client/windows/CHeroOverview.cpp @@ -20,7 +20,7 @@ #include "../widgets/CComponent.h" #include "../widgets/Images.h" #include "../widgets/TextControls.h" -#include "../widgets/MiscWidgets.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../../lib/GameSettings.h" #include "../../lib/CGeneralTextHandler.h" @@ -234,4 +234,4 @@ void CHeroOverview::genControls() labelSpellsNames.push_back(std::make_shared(302 + (292 / 2) + 3 * borderOffset + 32 + borderOffset, 8 * borderOffset + yOffset + 186 + i * (32 + borderOffset) + 3, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, (*CGI->spellh)[spell]->getNameTranslated())); i++; } -} \ No newline at end of file +} diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index 2ecc9acf4..8c3ab46e9 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -25,7 +25,7 @@ #include "../gui/CGuiHandler.h" #include "../gui/Shortcut.h" #include "../gui/WindowHandler.h" -#include "../widgets/MiscWidgets.h" +#include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/CComponent.h" #include "../widgets/TextControls.h" #include "../adventureMap/AdventureMapInterface.h" diff --git a/config/widgets/turnOptionsTab.json b/config/widgets/turnOptionsTab.json index d31b26b79..65ff54687 100644 --- a/config/widgets/turnOptionsTab.json +++ b/config/widgets/turnOptionsTab.json @@ -66,15 +66,7 @@ "rect": {"x": 60, "y": 48, "w": 320, "h": 0}, "adoptHeight": true }, - -// { -// "type": "label", -// "font": "medium", -// "alignment": "center", -// "color": "yellow", -// "text": "vcmi.optionsTab.selectPreset", -// "position": {"x": 105, "y": 100} -// }, + { "type" : "dropDownTimers", "name": "timerPresetSelector", @@ -94,36 +86,68 @@ "color" : "blue", "rect": {"x" : 64, "y" : 394, "w": 316, "h": 124} }, + { - "type": "transparentFilledRectangle", + "type": "graphicalPrimitive", "rect": {"x" : 64, "y" : 394, "w": 316, "h": 124}, - "color": [0, 0, 0, 0], - "colorLine": [64, 80, 128, 128] - }, - { - "type": "transparentFilledRectangle", - "rect": {"x" : 65, "y" : 416, "w": 314, "h": 1}, - "color": [0, 0, 0, 0], - "colorLine": [80, 96, 160, 128] - }, - { - "type": "transparentFilledRectangle", - "rect": {"x" : 65, "y" : 417, "w": 314, "h": 1}, - "color": [0, 0, 0, 0], - "colorLine": [32, 40, 128, 128] - }, - { - "type": "transparentFilledRectangle", - "rect": {"x" : 65, "y" : 466, "w": 314, "h": 1}, - "color": [0, 0, 0, 0], - "colorLine": [80, 96, 160, 128] - }, - { - "type": "transparentFilledRectangle", - "rect": {"x" : 65, "y" : 467, "w": 314, "h": 1}, - "color": [0, 0, 0, 0], - "colorLine": [32, 40, 128, 128] + "primitives" : [ + // Top line + { "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : -1, "y" : 0}, "color" : [ 255, 255, 255, 32 ] }, + { "type" : "line", "a" : { "x" : 0, "y" : 1}, "b" : { "x" : -1, "y" : 1}, "color" : [ 0, 0, 0, 48 ] } + + // Left line + { "type" : "line", "a" : { "x" : 0, "y" : 1}, "b" : { "x" : 0, "y" : -2}, "color" : [ 255, 255, 255, 32 ] }, + { "type" : "line", "a" : { "x" : 1, "y" : 2}, "b" : { "x" : 1, "y" : -2}, "color" : [ 0, 0, 0, 48 ] } + + // Right line + { "type" : "line", "a" : { "x" : -2, "y" : 2}, "b" : { "x" : -2, "y" : -3}, "color" : [ 255, 255, 255, 24 ] }, + { "type" : "line", "a" : { "x" : -1, "y" : 1}, "b" : { "x" : -1, "y" : -2}, "color" : [ 255, 255, 255, 48 ] }, + + // Central separator + { "type" : "line", "a" : { "x" : 1, "y" : 22}, "b" : { "x" : -2, "y" : 22}, "color" : [ 255, 255, 255, 64 ] }, + { "type" : "line", "a" : { "x" : 1, "y" : 23}, "b" : { "x" : -2, "y" : 23}, "color" : [ 0, 0, 0, 64 ] }, + + // 2nd Central separator + { "type" : "line", "a" : { "x" : 1, "y" : 72}, "b" : { "x" : -2, "y" : 72}, "color" : [ 255, 255, 255, 64 ] }, + { "type" : "line", "a" : { "x" : 1, "y" : 73}, "b" : { "x" : -2, "y" : 73}, "color" : [ 0, 0, 0, 64 ] }, + + // Bottom line + { "type" : "line", "a" : { "x" : 1, "y" : -2}, "b" : { "x" : -1, "y" : -2}, "color" : [ 255, 255, 255, 24 ] }, + { "type" : "line", "a" : { "x" : 0, "y" : -1}, "b" : { "x" : -1, "y" : -1}, "color" : [ 255, 255, 255, 48 ] }, + ] }, + + +// { +// "type": "transparentFilledRectangle", +// "rect": {"x" : 64, "y" : 394, "w": 316, "h": 124}, +// "color": [0, 0, 0, 0], +// "colorLine": [64, 80, 128, 128] +// }, +// { +// "type": "transparentFilledRectangle", +// "rect": {"x" : 65, "y" : 416, "w": 314, "h": 1}, +// "color": [0, 0, 0, 0], +// "colorLine": [80, 96, 160, 128] +// }, +// { +// "type": "transparentFilledRectangle", +// "rect": {"x" : 65, "y" : 417, "w": 314, "h": 1}, +// "color": [0, 0, 0, 0], +// "colorLine": [32, 40, 128, 128] +// }, +// { +// "type": "transparentFilledRectangle", +// "rect": {"x" : 65, "y" : 466, "w": 314, "h": 1}, +// "color": [0, 0, 0, 0], +// "colorLine": [80, 96, 160, 128] +// }, +// { +// "type": "transparentFilledRectangle", +// "rect": {"x" : 65, "y" : 467, "w": 314, "h": 1}, +// "color": [0, 0, 0, 0], +// "colorLine": [32, 40, 128, 128] +// }, { "type" : "verticalLayout66", "customType" : "labelTitle",