Added dynamic color support + text display item

This commit is contained in:
Borna Rajković 2022-06-12 16:02:24 +02:00
parent e6bbaabde4
commit 09991904e9
13 changed files with 265 additions and 36 deletions

View File

@ -37,5 +37,5 @@ add_executable(SchemeEditor
comdel/parser/comdel_lexer.cpp comdel/parser/comdel_lexer.cpp
main.cpp main.cpp
mainwindow.ui mainwindow.ui
comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h application.cpp application.h comdel/display/single_automatic_dialog.cpp comdel/display/single_automatic_dialog.h) comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h application.cpp application.h comdel/display/single_automatic_dialog.cpp comdel/display/single_automatic_dialog.h comdel/parser/color.cpp comdel/parser/color.h)
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)

View File

@ -19,7 +19,7 @@ namespace display {
Component::Component(const std::shared_ptr<domain::ComponentInstance> &instance): instance(instance) { Component::Component(const std::shared_ptr<domain::ComponentInstance> &instance): instance(instance) {
setFlag(ItemSendsGeometryChanges, true); setFlag(ItemSendsGeometryChanges, true);
setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getName())); setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getName()));
instance->component.getDisplay().render(this); instance->component.getDisplay().render(this, domain::ui::DisplayContext(instance.get()));
} }
void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {

View File

@ -20,13 +20,13 @@ display::NameDialog::NameDialog(std::string currentName, std::set<std::string> &
auto buttonLayout = new QHBoxLayout(this); auto buttonLayout = new QHBoxLayout(this);
auto okButton = new QPushButton("Ažuriraj"); button = new QPushButton("Ažuriraj");
auto cancelButton = new QPushButton("Odustani", this); auto cancelButton = new QPushButton("Odustani", this);
connect(okButton, &QPushButton::clicked, this, &NameDialog::onNameChange); connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); }); connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
buttonLayout->addWidget(okButton); buttonLayout->addWidget(button);
buttonLayout->addWidget(cancelButton); buttonLayout->addWidget(cancelButton);
layout->addLayout(buttonLayout); layout->addLayout(buttonLayout);

View File

@ -2,17 +2,17 @@
#include <QBrush> #include <QBrush>
#include <QPen> #include <QPen>
#include <QFont>
#include "comdel/domain/instance.h"
namespace domain { namespace domain {
QBrush busBrush(QColor::fromRgb(200, 200, 200));
QPen busPen(QColor::fromRgb(200, 200, 200));
Display::Display(std::vector<ui::Item> items) : items(items) {} Display::Display(std::vector<ui::Item> items) : items(items) {}
void Display::render(QGraphicsItemGroup *group) { void Display::render(QGraphicsItemGroup *group, ui::DisplayContext context) {
for (auto &item: items) { for (auto &item: items) {
item.render(group); item.render(group, context);
} }
} }
@ -22,8 +22,26 @@ namespace domain {
} }
} }
void ui::Text::render(QGraphicsItemGroup *group, ui::DisplayContext context) {
auto formattedText = context.populateMessage(text);
auto content = new QGraphicsTextItem(QString::fromStdString(formattedText));
content->setDefaultTextColor(color);
content->setPos(x, y);
content->setFont(QFont("arial", 8));
group->addToGroup(content);
}
void ui::Text::comdel(std::ostream &buffer, int x, int y) {
// TODO
}
void ui::Rect::render(QGraphicsItemGroup *group) { void ui::Rect::render(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsRectItem(x, y, w, h)); auto rect = new QGraphicsRectItem(x, y, w, h);
rect->setPen(QPen(config.lineColor));
rect->setBrush(QBrush(config.fillColor));
group->addToGroup(rect);
} }
void ui::Rect::comdel(std::ostream &buffer, int x, int y) { void ui::Rect::comdel(std::ostream &buffer, int x, int y) {
@ -34,7 +52,9 @@ namespace domain {
} }
void ui::Line::render(QGraphicsItemGroup *group) { void ui::Line::render(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsLineItem(x1, y1, x2, y2)); auto line = new QGraphicsLineItem(x1, y1, x2, y2);
line->setPen(QPen(config.lineColor));
group->addToGroup(line);
} }
void ui::Line::comdel(std::ostream &buffer, int x, int y) { void ui::Line::comdel(std::ostream &buffer, int x, int y) {
@ -52,8 +72,8 @@ namespace domain {
_h = size; _h = size;
} }
auto rect = new QGraphicsRectItem(x, y, _w, _h); auto rect = new QGraphicsRectItem(x, y, _w, _h);
rect->setBrush(busBrush); rect->setBrush(QBrush(config.fillColor));
rect->setPen(busPen); rect->setPen(QPen(config.lineColor));
group->addToGroup(rect); group->addToGroup(rect);
} }
@ -97,7 +117,11 @@ namespace domain {
<< QPoint(x + w / 2, y + h / 2) << QPoint(x + w, y); << QPoint(x + w / 2, y + h / 2) << QPoint(x + w, y);
break; break;
} }
group->addToGroup(new QGraphicsPolygonItem(polygon)); auto item = new QGraphicsPolygonItem(polygon);
item->setFillRule(Qt::OddEvenFill);
item->setBrush(QBrush(config.fillColor));
item->setPen(QPen(config.lineColor));
group->addToGroup(item);
} }
void ui::Pin::renderOut(QGraphicsItemGroup *group) { void ui::Pin::renderOut(QGraphicsItemGroup *group) {
@ -121,11 +145,18 @@ namespace domain {
<< QPoint(x + w, y + h / 2) << QPoint(x + w / 2, y); << QPoint(x + w, y + h / 2) << QPoint(x + w / 2, y);
break; break;
} }
group->addToGroup(new QGraphicsPolygonItem(polygon)); auto item = new QGraphicsPolygonItem(polygon);
item->setFillRule(Qt::OddEvenFill);
item->setBrush(QBrush(config.fillColor));
item->setPen(QPen(config.lineColor));
group->addToGroup(item);
} }
void ui::Pin::renderInOut(QGraphicsItemGroup *group) { void ui::Pin::renderInOut(QGraphicsItemGroup *group) {
group->addToGroup(new QGraphicsRectItem(x, y, w, h)); auto rect = new QGraphicsRectItem(x, y, w, h);
rect->setBrush(QBrush(config.fillColor));
rect->setPen(QPen(config.lineColor));
group->addToGroup(rect);
} }
void ui::Pin::render(QGraphicsItemGroup *group) { void ui::Pin::render(QGraphicsItemGroup *group) {
@ -168,11 +199,12 @@ namespace domain {
return 0; return 0;
} }
void ui::Item::render(QGraphicsItemGroup *group, int size) { void ui::Item::render(QGraphicsItemGroup *group, ui::DisplayContext context, int size) {
if (rect) rect->render(group); if (rect) rect->render(group);
if (line) line->render(group); if (line) line->render(group);
if (pin) pin->render(group); if (pin) pin->render(group);
if (bus) bus->render(group, size); if (bus) bus->render(group, size);
if (text) text->render(group, context);
} }
void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) { void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) {
@ -180,5 +212,32 @@ namespace domain {
if (line) line->comdel(buffer, x, y); if (line) line->comdel(buffer, x, y);
// pins aren't exported // pins aren't exported
if (bus) bus->comdel(buffer, x, y, size); if (bus) bus->comdel(buffer, x, y, size);
// text currently isn't exported TODO
}
ui::DisplayContext::DisplayContext(ComponentInstance *instance) {
for(auto attr: instance->attributes) {
this->values[attr.name] = attr.value;
}
this->values["instanceName"] = Value::fromString(instance->name);
}
string replacePlaceholder(string source, string key, Value value) {
key = "{" + key + "}";
auto placeholderValue = value.string();
auto found = source.find(key);
while (found != string::npos) {
source.replace(found, key.length(), placeholderValue);
found = source.find(key);
}
return source;
}
std::string ui::DisplayContext::populateMessage(std::string source) {
for (auto &[key, value]: values) {
source = replacePlaceholder(source, key, value);
}
return source;
} }
} // namespace domain } // namespace domain

View File

@ -5,16 +5,52 @@
#include <optional> #include <optional>
#include <ostream> #include <ostream>
#include "comdel/parser/color.h"
#include "value.h"
namespace domain { namespace domain {
namespace ui { namespace ui {
class DisplayContext {
std::map<std::string, domain::Value> values;
public:
explicit DisplayContext(ComponentInstance *instance);
std::string populateMessage(std::string message);
};
struct DisplayConfig {
QColor lineColor;
QColor fillColor;
DisplayConfig(Color lineColor, Color fillColor) {
this->lineColor = QColor::fromRgb(lineColor.r, lineColor.g, lineColor.b, lineColor.a);
this->fillColor = QColor::fromRgb(fillColor.r, fillColor.g, fillColor.b, fillColor.a);
}
};
class Text {
public:
int x, y, w, h;
QColor color;
std::string text;
Text(int x, int y, int w, int h, std::string text, Color color) : x(x), y(y), w(w), h(h), text(text),
color(QColor::fromRgb(color.r, color.g, color.b, color.a)) {}
void render(QGraphicsItemGroup *group, ui::DisplayContext context);
void comdel(std::ostream &buffer, int x, int y);
};
class Rect { class Rect {
public: public:
int x, y, w, h; int x, y, w, h;
DisplayConfig config;
Rect(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {} Rect(int x, int y, int w, int h, DisplayConfig config) : x(x), y(y), w(w), h(h), config(config) {}
void render(QGraphicsItemGroup *group); void render(QGraphicsItemGroup *group);
@ -25,8 +61,9 @@ namespace domain {
class Line { class Line {
public: public:
int x1, y1, x2, y2; int x1, y1, x2, y2;
DisplayConfig config;
Line(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) {} Line(int x1, int y1, int x2, int y2, DisplayConfig config) : x1(x1), y1(y1), x2(x2), y2(y2), config(config) {}
void render(QGraphicsItemGroup *group); void render(QGraphicsItemGroup *group);
@ -47,9 +84,11 @@ namespace domain {
public: public:
int x, y, w, h; int x, y, w, h;
BusOrientation orientation; BusOrientation orientation;
DisplayConfig config;
Bus(int x, int y, int w, int h, BusOrientation orientation) : x(x), y(y), w(w), h(h), Bus(int x, int y, int w, int h, BusOrientation orientation, DisplayConfig config) : x(x), y(y), w(w), h(h),
orientation(orientation) {} orientation(orientation),
config(config) {}
void render(QGraphicsItemGroup *group, int size); void render(QGraphicsItemGroup *group, int size);
@ -64,10 +103,10 @@ namespace domain {
PinOrientation orientation; PinOrientation orientation;
PinType pinType; PinType pinType;
int x, y, w, h; int x, y, w, h;
DisplayConfig config;
Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType) : x(x), y(y), w(w), h(h), Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType, DisplayConfig config)
orientation(orientation), : x(x), y(y), w(w), h(h), orientation(orientation), pinType(pinType), config(config) {}
pinType(pinType) {}
public: public:
void render(QGraphicsItemGroup *group); void render(QGraphicsItemGroup *group);
@ -90,8 +129,9 @@ namespace domain {
std::optional<Line> line = std::nullopt; std::optional<Line> line = std::nullopt;
std::optional<Pin> pin = std::nullopt; std::optional<Pin> pin = std::nullopt;
std::optional<Bus> bus = std::nullopt; std::optional<Bus> bus = std::nullopt;
std::optional<Text> text = std::nullopt;
void render(QGraphicsItemGroup *group, int size = 0); void render(QGraphicsItemGroup *group, ui::DisplayContext context, int size = 0);
void comdel(std::ostream &buffer, int x, int y, int size = 0); void comdel(std::ostream &buffer, int x, int y, int size = 0);
}; };
@ -102,7 +142,7 @@ namespace domain {
Display(std::vector<ui::Item> items); Display(std::vector<ui::Item> items);
void render(QGraphicsItemGroup *group); void render(QGraphicsItemGroup *group, ui::DisplayContext context);
void comdel(std::ostream &buffer, int x, int y, int size = 0); void comdel(std::ostream &buffer, int x, int y, int size = 0);

View File

@ -615,20 +615,34 @@ namespace domain {
for (auto &item: node.items) { for (auto &item: node.items) {
ui::Item displayItem; ui::Item displayItem;
std::string type = item.type.value; std::string type = item.type.value;
if (type == "rect") {
auto fillColor = item.asColor(&errors, "fillColor", Color(255, 255, 255, 255));
auto lineColor = item.asColor(&errors, "lineColor", Color(0, 0, 0, 255));
if (type == "text") {
long long int x, y, w, h;
std::string text;
auto color = item.asColor(&errors, "color", Color(0, 0, 0, 255));
x = item.asInt(&errors, "x");
y = item.asInt(&errors, "y");
w = item.asInt(&errors, "w");
h = item.asInt(&errors, "h");
text = item.asString(&errors, "text");
displayItem.text = ui::Text(x, y, w, h, text, color);
} else if (type == "rect") {
long long int x, y, w, h; long long int x, y, w, h;
x = item.asInt(&errors, "x"); x = item.asInt(&errors, "x");
y = item.asInt(&errors, "y"); y = item.asInt(&errors, "y");
w = item.asInt(&errors, "w"); w = item.asInt(&errors, "w");
h = item.asInt(&errors, "h"); h = item.asInt(&errors, "h");
displayItem.rect = ui::Rect(x, y, w, h); displayItem.rect = ui::Rect(x, y, w, h, {lineColor, fillColor});
} else if (type == "line") { } else if (type == "line") {
long long int x1, y1, x2, y2; long long int x1, y1, x2, y2;
x1 = item.asInt(&errors, "x1"); x1 = item.asInt(&errors, "x1");
y1 = item.asInt(&errors, "y1"); y1 = item.asInt(&errors, "y1");
x2 = item.asInt(&errors, "x2"); x2 = item.asInt(&errors, "x2");
y2 = item.asInt(&errors, "y2"); y2 = item.asInt(&errors, "y2");
displayItem.line = ui::Line(x1, y1, x2, y2); displayItem.line = ui::Line(x1, y1, x2, y2, {lineColor, fillColor});
} else if (type == "pin") { } else if (type == "pin") {
long long int x, y, w, h; long long int x, y, w, h;
x = item.asInt(&errors, "x"); x = item.asInt(&errors, "x");
@ -662,7 +676,7 @@ namespace domain {
errors.emplace_back(item.span, "unknown pin type '" + _pinType + "'"); errors.emplace_back(item.span, "unknown pin type '" + _pinType + "'");
} }
displayItem.pin = ui::Pin(x, y, w, h, orientation, pinType); displayItem.pin = ui::Pin(x, y, w, h, orientation, pinType, {lineColor, fillColor});
} else if (type == "bus") { } else if (type == "bus") {
long long int x, y, w, h; long long int x, y, w, h;
x = item.asInt(&errors, "x"); x = item.asInt(&errors, "x");
@ -680,7 +694,7 @@ namespace domain {
errors.emplace_back(item.span, "unknown bus orientation type '" + _orientation + "'"); errors.emplace_back(item.span, "unknown bus orientation type '" + _orientation + "'");
} }
displayItem.bus = ui::Bus(x, y, w, h, orientation); displayItem.bus = ui::Bus(x, y, w, h, orientation, {lineColor, fillColor});
} else { } else {
errors.emplace_back(item.type.span, "unsupported display type"); errors.emplace_back(item.type.span, "unsupported display type");
} }

View File

@ -20,6 +20,19 @@ NumberNode::NumberNode(const std::string &expression) {
} }
} }
/*************************** COLOR NODE *********************************/
ColorNode::ColorNode(const std::string &expression) {
auto value = expression.substr(1);
color.r = std::stoul(value.substr(0, 2), nullptr, 16);
color.g = std::stoul(value.substr(2, 4), nullptr, 16);
color.b = std::stoul(value.substr(4, 6), nullptr, 16);
color.a = 255;
if(value.length() == 8) {
color.a = std::stoul(value.substr(6,8), nullptr, 16);
}
}
/*************************** STRING NODE ********************************/ /*************************** STRING NODE ********************************/
std::string StringNode::asString() { std::string StringNode::asString() {
@ -49,6 +62,14 @@ std::string ValueNode::asIdentifier() {
return ""; return "";
} }
Color ValueNode::asColor() {
if (is(COLOR)) {
return colorValue.value();
}
return {};
}
bool ValueNode::asBool() { bool ValueNode::asBool() {
if (is(BOOL)) { if (is(BOOL)) {
return boolValue.value(); return boolValue.value();
@ -94,6 +115,13 @@ ValueNode ValueNode::ofNull() {
return value; return value;
} }
ValueNode ValueNode::ofColor(Color color) {
ValueNode value;
value.type = EnumNode(COLOR);
value.colorValue = color;
return value;
}
ValueNode ValueNode::ofWire(std::optional<std::string> _value) { ValueNode ValueNode::ofWire(std::optional<std::string> _value) {
ValueNode value; ValueNode value;
value.type = EnumNode(WIRE); value.type = EnumNode(WIRE);

View File

@ -2,6 +2,7 @@
#define AST_NODE_H #define AST_NODE_H
#include "token.h" #include "token.h"
#include "color.h"
#include "source_error.h" #include "source_error.h"
#include <optional> #include <optional>
#include <utility> #include <utility>
@ -56,6 +57,14 @@ struct NumberNode : public AstNode {
NumberNode() : value(0) {} NumberNode() : value(0) {}
}; };
struct ColorNode : public AstNode {
Color color;
explicit ColorNode(const std::string &expression);
ColorNode() {}
};
struct CountNode : public AstNode { struct CountNode : public AstNode {
NumberNode first; NumberNode first;
@ -83,6 +92,7 @@ public:
IDENTIFIER, IDENTIFIER,
MEMORY, MEMORY,
NIL, NIL,
COLOR,
}; };
private: private:
@ -91,6 +101,7 @@ private:
std::optional<std::string> stringValue; std::optional<std::string> stringValue;
std::optional<bool> boolValue; std::optional<bool> boolValue;
std::optional<std::string> identifierValue; std::optional<std::string> identifierValue;
std::optional<Color> colorValue;
public: public:
ValueNode() = default; ValueNode() = default;
@ -105,6 +116,8 @@ public:
std::string asIdentifier(); std::string asIdentifier();
Color asColor();
bool asBool(); bool asBool();
bool is(ValueType valueType); bool is(ValueType valueType);
@ -121,7 +134,10 @@ public:
static ValueNode ofNull(); static ValueNode ofNull();
static ValueNode ofColor(Color color);
static ValueNode ofWire(std::optional<std::string> _value); static ValueNode ofWire(std::optional<std::string> _value);
}; };
struct ConditionNode { struct ConditionNode {
@ -196,6 +212,21 @@ struct DisplayItemNode : public AstNode {
return _default; return _default;
} }
Color asColor(std::vector<SourceError> *errors, const std::string &property, Color _default = Color(0, 0, 0)) {
for (auto &prop: values) {
if (prop.key.value == property) {
if (prop.value.is(ValueNode::COLOR)) {
return prop.value.asColor();
} else {
if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected number");
}
}
}
}
return _default;
}
std::string asIdentifier(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") { std::string asIdentifier(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
for (auto &prop: values) { for (auto &prop: values) {
if (prop.key.value == property) { if (prop.key.value == property) {

5
comdel/parser/color.cpp Normal file
View File

@ -0,0 +1,5 @@
//
// Created by bbr on 12.06.22..
//
#include "color.h"

21
comdel/parser/color.h Normal file
View File

@ -0,0 +1,21 @@
//
// Created by bbr on 12.06.22..
//
#ifndef SCHEMEEDITOR_COLOR_H
#define SCHEMEEDITOR_COLOR_H
struct Color {
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
Color(): r(0), g(0), b(0), a(0) {}
Color(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 0): r(r), g(g), b(b), a(a) {}
};
#endif //SCHEMEEDITOR_COLOR_H

View File

@ -259,9 +259,7 @@ std::optional<LibraryNode> ComdelParser::parseLibrary() {
TokenType::RBRACE, TokenType::RBRACE,
std::nullopt, std::nullopt,
false, false,
[this] { return parseProperty( [this] { return parseProperty(TokenType::STRING);
std::optional<TokenType>(
TokenType::STRING));
} }
)); ));
if (!err.has_value()) { if (!err.has_value()) {
@ -302,6 +300,23 @@ PResult<StringNode> ComdelParser::parseString() {
} }
/****************************************************************************
*
* ColorNode := #RRGGBB[AA]
*
****************************************************************************/
PResult<ColorNode> ComdelParser::parseColor() {
auto spanner = getSpanner();
if (check(TokenType::COLOR)) {
ColorNode node{current().text};
node.span = current().span;
bump();
return spanner(node);
}
return unexpected();
}
/**************************************************************************** /****************************************************************************
* *
* IdentifierNode := IDENTIFIER * IdentifierNode := IDENTIFIER
@ -1144,6 +1159,8 @@ PResult<ValueNode> ComdelParser::parseValue() {
} else if (check(TokenType::NIL)) { } else if (check(TokenType::NIL)) {
bump(); bump();
value = ValueNode::ofNull(); value = ValueNode::ofNull();
} else if(check(TokenType::COLOR)) {
value = ValueNode::ofColor(parseColor()->color);
} else { } else {
return unexpected(); return unexpected();
} }

View File

@ -66,6 +66,8 @@ private:
// used to parse library and schema // used to parse library and schema
PResult<StringNode> parseString(); PResult<StringNode> parseString();
PResult<ColorNode> parseColor();
PResult<IdentifierNode> parseIdentifier(); PResult<IdentifierNode> parseIdentifier();
PResult<NumberNode> parseNumber(); PResult<NumberNode> parseNumber();

View File

@ -49,6 +49,14 @@
rect { rect {
x: 0; y:0; w:100; h:100; x: 0; y:0; w:100; h:100;
} }
text {
x: 0; y: 0; w: 100; h: 100;
text: "FRISC";
}
text {
x: 0; y: 16; w: 100; h: 100;
text: "{instanceName}";
}
} }
@pin glavniPin in { @pin glavniPin in {
@tooltip "pin za spajanje na glavnu sabirnicu" @tooltip "pin za spajanje na glavnu sabirnicu"
@ -283,6 +291,7 @@
*/ */
pin { pin {
x: 100; y: 30; w: 16; h: 16; x: 100; y: 30; w: 16; h: 16;
orientation: "right";
} }
} }
} }
@ -293,6 +302,7 @@
@display { @display {
pin { pin {
x: 100; y: 7; w: 16; h: 16; x: 100; y: 7; w: 16; h: 16;
orientation: "right";
} }
} }
@wires { 0, 0, null, null} @wires { 0, 0, null, null}
@ -317,6 +327,8 @@
h: 20; w: 100; h: 20; w: 100;
orientation: "horizontal"; orientation: "horizontal";
resizable: true; resizable: true;
lineColor: #bbbbbb;
fillColor: #bbbbbb;
} }
} }
@wires { @wires {