diff --git a/CMakeLists.txt b/CMakeLists.txt index dd5aebcb..4ac88877 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ set(CPP_SOURCE_FILES src/NodeState.cpp src/NodeStyle.cpp src/Properties.cpp - src/StyleCollection.cpp + src/StyleImport.cpp ) # If we want to give the option to build a static library, diff --git a/examples/calculator/main.cpp b/examples/calculator/main.cpp index 28708cd5..0332ff5a 100644 --- a/examples/calculator/main.cpp +++ b/examples/calculator/main.cpp @@ -60,27 +60,24 @@ registerDataModels() static -void -setStyle() +auto +connectionStyle() { - ConnectionStyle::setConnectionStyle( - R"( - { - "ConnectionStyle": { - "ConstructionColor": "gray", - "NormalColor": "black", - "SelectedColor": "gray", - "SelectedHaloColor": "deepskyblue", - "HoveredColor": "deepskyblue", - - "LineWidth": 3.0, - "ConstructionLineWidth": 2.0, - "PointDiameter": 10.0, - - "UseDataDefinedColors": true - } - } - )"); + auto style = ConnectionStyle::defaultStyle(); + + style.setConstructionColor(QColor("gray")); + style.setNormalColor(QColor("black")); + style.setSelectedColor(QColor("gray")); + style.setSelectedHaloColor(QColor("deepskyblue")); + style.setHoveredColor(QColor("deepskyblue")); + + style.setLineWidth(3.0); + style.setConstructionLineWidth(2.0); + style.setPointDiameter(10.0); + + style.useDataDefinedColors(true); + + return style; } @@ -89,8 +86,6 @@ main(int argc, char *argv[]) { QApplication app(argc, argv); - setStyle(); - QWidget mainWidget; auto menuBar = new QMenuBar(); @@ -101,6 +96,7 @@ main(int argc, char *argv[]) l->addWidget(menuBar); auto scene = new FlowScene(registerDataModels(), &mainWidget); + scene->setConnectionStyle(connectionStyle()); l->addWidget(new FlowView(scene)); l->setContentsMargins(0, 0, 0, 0); l->setSpacing(0); diff --git a/examples/connection_colors/main.cpp b/examples/connection_colors/main.cpp index a9aeb826..008616d3 100644 --- a/examples/connection_colors/main.cpp +++ b/examples/connection_colors/main.cpp @@ -33,21 +33,6 @@ registerDataModels() } -static -void -setStyle() -{ - ConnectionStyle::setConnectionStyle( - R"( - { - "ConnectionStyle": { - "UseDataDefinedColors": true - } - } - )"); -} - - //------------------------------------------------------------------------------ int @@ -55,9 +40,11 @@ main(int argc, char* argv[]) { QApplication app(argc, argv); - setStyle(); + auto connectionStyle = ConnectionStyle::defaultStyle(); + connectionStyle.useDataDefinedColors(true); FlowScene scene(registerDataModels()); + scene.setConnectionStyle(std::move(connectionStyle)); FlowView view(&scene); diff --git a/examples/styles/main.cpp b/examples/styles/main.cpp index 1b1e3c8d..6802a3bf 100644 --- a/examples/styles/main.cpp +++ b/examples/styles/main.cpp @@ -30,9 +30,9 @@ registerDataModels() static void -setStyle() +setStyle(FlowScene& scene, FlowView& view) { - FlowViewStyle::setStyle( + view.setStyle(FlowViewStyle::fromJson( R"( { "FlowViewStyle": { @@ -41,9 +41,9 @@ setStyle() "CoarseGridColor": [235, 235, 220] } } - )"); + )")); - NodeStyle::setNodeStyle( + scene.setNodeStyle(NodeStyle::fromJson( R"( { "NodeStyle": { @@ -63,9 +63,9 @@ setStyle() "Opacity": 1.0 } } - )"); + )")); - ConnectionStyle::setConnectionStyle( + scene.setConnectionStyle(ConnectionStyle::fromJson( R"( { "ConnectionStyle": { @@ -82,7 +82,7 @@ setStyle() "UseDataDefinedColors": false } } - )"); + )")); } @@ -93,11 +93,9 @@ main(int argc, char* argv[]) { QApplication app(argc, argv); - setStyle(); - FlowScene scene(registerDataModels()); - FlowView view(&scene); + setStyle(scene, view); view.setWindowTitle("Style example"); view.resize(800, 600); diff --git a/include/nodes/internal/Connection.hpp b/include/nodes/internal/Connection.hpp index afe80a48..0a3d24e2 100644 --- a/include/nodes/internal/Connection.hpp +++ b/include/nodes/internal/Connection.hpp @@ -23,6 +23,7 @@ namespace QtNodes class Node; class NodeData; class ConnectionGraphicsObject; +class ConnectionStyle; /// class NODE_EDITOR_PUBLIC Connection @@ -36,15 +37,17 @@ class NODE_EDITOR_PUBLIC Connection /// New Connection is attached to the port of the given Node. /// The port has parameters (portType, portIndex). - /// The opposite connection end will require anothre port. + /// The opposite connection end will require another port. Connection(PortType portType, Node& node, - PortIndex portIndex); + PortIndex portIndex, + ConnectionStyle const &style); Connection(Node& nodeIn, PortIndex portIndexIn, Node& nodeOut, PortIndex portIndexOut, + ConnectionStyle const &style, TypeConverter converter = TypeConverter{}); @@ -118,6 +121,9 @@ class NODE_EDITOR_PUBLIC Connection void setTypeConverter(TypeConverter converter); + ConnectionStyle const & + connectionStyle() const; + public: // data propagation void @@ -139,10 +145,11 @@ class NODE_EDITOR_PUBLIC Connection PortIndex _inPortIndex; private: - ConnectionState _connectionState; ConnectionGeometry _connectionGeometry; + ConnectionStyle const &_connectionStyle; + std::unique_ptr_connectionGraphicsObject; TypeConverter _converter; diff --git a/include/nodes/internal/ConnectionGeometry.hpp b/include/nodes/internal/ConnectionGeometry.hpp index 870c3559..86965c7a 100644 --- a/include/nodes/internal/ConnectionGeometry.hpp +++ b/include/nodes/internal/ConnectionGeometry.hpp @@ -10,11 +10,12 @@ namespace QtNodes { +class ConnectionStyle; + class ConnectionGeometry { public: - - ConnectionGeometry(); + ConnectionGeometry(ConnectionStyle const &style); public: @@ -56,5 +57,7 @@ class ConnectionGeometry double _lineWidth; bool _hovered; + + ConnectionStyle const* _style; }; } diff --git a/include/nodes/internal/ConnectionStyle.hpp b/include/nodes/internal/ConnectionStyle.hpp index e37feb03..48242512 100644 --- a/include/nodes/internal/ConnectionStyle.hpp +++ b/include/nodes/internal/ConnectionStyle.hpp @@ -2,37 +2,27 @@ #include +#include +#include + #include "Export.hpp" -#include "Style.hpp" namespace QtNodes { -class NODE_EDITOR_PUBLIC ConnectionStyle : public Style +class NODE_EDITOR_PUBLIC ConnectionStyle { public: - ConnectionStyle(); - ConnectionStyle(QString jsonText); - -public: - - static void setConnectionStyle(QString jsonText); - -private: - - void loadJsonText(QString jsonText) override; + static ConnectionStyle const& + defaultStyle(); - void loadJsonFile(QString fileName) override; - - void loadJsonFromByteArray(QByteArray const &byteArray) override; - -public: + static ConnectionStyle + fromJson(QString const& jsonText); QColor constructionColor() const; QColor normalColor() const; - QColor normalColor(QString typeId) const; QColor selectedColor() const; QColor selectedHaloColor() const; QColor hoveredColor() const; @@ -43,18 +33,35 @@ class NODE_EDITOR_PUBLIC ConnectionStyle : public Style bool useDataDefinedColors() const; + void setConstructionColor(QColor); + void setNormalColor(QColor); + void setSelectedColor(QColor); + void setSelectedHaloColor(QColor); + void setHoveredColor(QColor); + + void setLineWidth(float); + void setConstructionLineWidth(float); + void setPointDiameter(float); + + void useDataDefinedColors(bool); + + static QColor + computeNormalColor(QString const& typeId); + private: + ConnectionStyle(QByteArray const& jsonBytes); + void loadJson(QByteArray const& jsonBytes); - QColor ConstructionColor; - QColor NormalColor; - QColor SelectedColor; - QColor SelectedHaloColor; - QColor HoveredColor; + QColor _constructionColor; + QColor _normalColor; + QColor _selectedColor; + QColor _selectedHaloColor; + QColor _hoveredColor; - float LineWidth; - float ConstructionLineWidth; - float PointDiameter; + float _lineWidth; + float _constructionLineWidth; + float _pointDiameter; - bool UseDataDefinedColors; + bool _useDataDefinedColors; }; } diff --git a/include/nodes/internal/FlowScene.hpp b/include/nodes/internal/FlowScene.hpp index 5bcfa411..990044ef 100644 --- a/include/nodes/internal/FlowScene.hpp +++ b/include/nodes/internal/FlowScene.hpp @@ -13,6 +13,9 @@ #include "TypeConverter.hpp" #include "memory.hpp" +#include "ConnectionStyle.hpp" +#include "NodeStyle.hpp" + namespace QtNodes { @@ -22,7 +25,6 @@ class Node; class NodeGraphicsObject; class Connection; class ConnectionGraphicsObject; -class NodeStyle; /// Scene holds connections and nodes. class NODE_EDITOR_PUBLIC FlowScene @@ -97,6 +99,12 @@ class NODE_EDITOR_PUBLIC FlowScene void loadFromMemory(const QByteArray& data); + ConnectionStyle const& connectionStyle() const; + NodeStyle const& nodeStyle() const; + + void setConnectionStyle(ConnectionStyle style); + void setNodeStyle(NodeStyle style); + signals: void nodeCreated(Node &n); @@ -125,6 +133,10 @@ class NODE_EDITOR_PUBLIC FlowScene using SharedConnection = std::shared_ptr; using UniqueNode = std::unique_ptr; + // styles MUST come before _connections and _nodes, so that the styles outlive them + ConnectionStyle _connectionStyle; + NodeStyle _nodeStyle; + std::unordered_map _connections; std::unordered_map _nodes; std::shared_ptr _registry; diff --git a/include/nodes/internal/FlowView.hpp b/include/nodes/internal/FlowView.hpp index 378ff2e6..bc04a3f2 100644 --- a/include/nodes/internal/FlowView.hpp +++ b/include/nodes/internal/FlowView.hpp @@ -3,6 +3,7 @@ #include #include "Export.hpp" +#include "FlowViewStyle.hpp" namespace QtNodes { @@ -16,7 +17,9 @@ class NODE_EDITOR_PUBLIC FlowView public: FlowView(QWidget *parent = Q_NULLPTR); + FlowView(FlowViewStyle style, QWidget *parent = Q_NULLPTR); FlowView(FlowScene *scene, QWidget *parent = Q_NULLPTR); + FlowView(FlowScene *scene, FlowViewStyle style, QWidget *parent = Q_NULLPTR); FlowView(const FlowView&) = delete; FlowView operator=(const FlowView&) = delete; @@ -27,6 +30,8 @@ class NODE_EDITOR_PUBLIC FlowView void setScene(FlowScene *scene); + void setStyle(FlowViewStyle style); + public slots: void scaleUp(); @@ -65,5 +70,7 @@ public slots: QPointF _clickPos; FlowScene* _scene; + + FlowViewStyle _style; }; } diff --git a/include/nodes/internal/FlowViewStyle.hpp b/include/nodes/internal/FlowViewStyle.hpp index aebdb4b4..1567933b 100644 --- a/include/nodes/internal/FlowViewStyle.hpp +++ b/include/nodes/internal/FlowViewStyle.hpp @@ -2,36 +2,66 @@ #include +#include +#include + #include "Export.hpp" -#include "Style.hpp" namespace QtNodes { -class NODE_EDITOR_PUBLIC FlowViewStyle : public Style +class NODE_EDITOR_PUBLIC FlowViewStyle { public: - FlowViewStyle(); - FlowViewStyle(QString jsonText); + static FlowViewStyle const& + defaultStyle(); -public: + static FlowViewStyle + fromJson(QString const& jsonText); - static void setStyle(QString jsonText); + QColor const & + backgroundColor() const + { + return _backgroundColor; + } -private: + QColor const & + fineGridColor() const + { + return _fineGridColor; + } - void loadJsonText(QString jsonText) override; + QColor const & + coarseGridColor() const + { + return _coarseGridColor; + } - void loadJsonFile(QString fileName) override; + void + setBackgroundColor(QColor backgroundColor) + { + _backgroundColor = backgroundColor; + } - void loadJsonFromByteArray(QByteArray const &byteArray) override; + void + setFineGridColor(QColor fineGridColor) + { + _fineGridColor = fineGridColor; + } -public: + void + setCoarseGridColor(QColor coarseGridColor) + { + _coarseGridColor = coarseGridColor; + } + +private: + FlowViewStyle(QByteArray const& jsonBytes); - QColor BackgroundColor; - QColor FineGridColor; - QColor CoarseGridColor; + QColor _backgroundColor; + QColor _fineGridColor; + QColor _coarseGridColor; }; } diff --git a/include/nodes/internal/Node.hpp b/include/nodes/internal/Node.hpp index 739c5cf9..28e8da05 100644 --- a/include/nodes/internal/Node.hpp +++ b/include/nodes/internal/Node.hpp @@ -10,6 +10,7 @@ #include "Export.hpp" #include "NodeState.hpp" +#include "NodeStyle.hpp" #include "NodeGeometry.hpp" #include "NodeData.hpp" #include "NodeGraphicsObject.hpp" @@ -34,7 +35,7 @@ class NODE_EDITOR_PUBLIC Node public: /// NodeDataModel should be an rvalue and is moved into the Node - Node(std::unique_ptr && dataModel); + Node(std::unique_ptr && dataModel, NodeStyle const& defaultStyle); virtual ~Node(); @@ -82,6 +83,9 @@ class NODE_EDITOR_PUBLIC Node NodeState & nodeState(); + NodeStyle const & + nodeStyle() const; + NodeDataModel* nodeDataModel() const; @@ -111,6 +115,9 @@ public slots: // data propagation // painting + // _nodeStyle must come before _nodeGeometry + NodeStyle const &_nodeStyle; + NodeGeometry _nodeGeometry; std::unique_ptr _nodeGraphicsObject; diff --git a/include/nodes/internal/NodeDataModel.hpp b/include/nodes/internal/NodeDataModel.hpp index e3d895b6..489d52bd 100644 --- a/include/nodes/internal/NodeDataModel.hpp +++ b/include/nodes/internal/NodeDataModel.hpp @@ -1,6 +1,5 @@ #pragma once - #include #include "PortType.hpp" @@ -85,11 +84,7 @@ class NODE_EDITOR_PUBLIC NodeDataModel return ConnectionPolicy::Many; } - NodeStyle const& - nodeStyle() const; - - void - setNodeStyle(NodeStyle const& style); + virtual NodeStyle const* nodeStyle() const { return nullptr; } public: @@ -135,9 +130,5 @@ class NODE_EDITOR_PUBLIC NodeDataModel void computingFinished(); - -private: - - NodeStyle _nodeStyle; }; } diff --git a/include/nodes/internal/NodeGeometry.hpp b/include/nodes/internal/NodeGeometry.hpp index cc1f0e8a..ff761f77 100644 --- a/include/nodes/internal/NodeGeometry.hpp +++ b/include/nodes/internal/NodeGeometry.hpp @@ -15,12 +15,13 @@ namespace QtNodes class NodeState; class NodeDataModel; class Node; +class NodeStyle; class NODE_EDITOR_PUBLIC NodeGeometry { public: - NodeGeometry(std::unique_ptr const &dataModel); + NodeGeometry(std::unique_ptr const &dataModel, NodeStyle const &style); public: unsigned int @@ -154,5 +155,7 @@ class NODE_EDITOR_PUBLIC NodeGeometry mutable QFontMetrics _fontMetrics; mutable QFontMetrics _boldFontMetrics; + + NodeStyle const* _nodeStyle; }; } diff --git a/include/nodes/internal/NodePainterDelegate.hpp b/include/nodes/internal/NodePainterDelegate.hpp index d532619f..f22496c8 100644 --- a/include/nodes/internal/NodePainterDelegate.hpp +++ b/include/nodes/internal/NodePainterDelegate.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "NodeGeometry.hpp" #include "NodeDataModel.hpp" diff --git a/include/nodes/internal/NodeStyle.hpp b/include/nodes/internal/NodeStyle.hpp index 5f051888..24bad2a0 100644 --- a/include/nodes/internal/NodeStyle.hpp +++ b/include/nodes/internal/NodeStyle.hpp @@ -2,55 +2,96 @@ #include +#include +#include + #include "Export.hpp" -#include "Style.hpp" namespace QtNodes { -class NODE_EDITOR_PUBLIC NodeStyle : public Style +class NODE_EDITOR_PUBLIC NodeStyle { public: - NodeStyle(); - NodeStyle(QString jsonText); + static NodeStyle const& + defaultStyle(); -public: + static NodeStyle + fromJson(QString const& jsonText); - static void setNodeStyle(QString jsonText); + QColor normalBoundaryColor() const; + QColor selectedBoundaryColor() const; + QColor gradientColor0() const; + QColor gradientColor1() const; + QColor gradientColor2() const; + QColor gradientColor3() const; + QColor shadowColor() const; -private: + QColor fontColor() const; + QColor fontColorFaded() const; - void loadJsonText(QString jsonText) override; + QColor connectionPointColor() const; + QColor filledConnectionPointColor() const; - void loadJsonFile(QString fileName) override; + QColor warningColor() const; + QColor errorColor() const; - void loadJsonFromByteArray(QByteArray const &byteArray) override; + float penWidth() const; + float hoveredPenWidth() const; + float connectionPointDiameter() const; + float opacity() const; -public: + void setNormalBoundaryColor(QColor); + void setSelectedBoundaryColor(QColor); + void setGradientColor0(QColor); + void setGradientColor1(QColor); + void setGradientColor2(QColor); + void setGradientColor3(QColor); + void setShadowColor(QColor); + + void setFontColor(QColor); + void setFontColorFaded(QColor); + + void setConnectionPointColor(QColor); + void setFilledConnectionPointColor(QColor); + + void setWarningColor(QColor); + void setErrorColor(QColor); + + void setPenWidth(float); + void setHoveredPenWidth(float); + void setConnectionPointDiameter(float); + void setOpacity(float); + +private: + + NodeStyle(QByteArray const& jsonBytes); + +private: - QColor NormalBoundaryColor; - QColor SelectedBoundaryColor; - QColor GradientColor0; - QColor GradientColor1; - QColor GradientColor2; - QColor GradientColor3; - QColor ShadowColor; - QColor FontColor; - QColor FontColorFaded; + QColor _normalBoundaryColor; + QColor _selectedBoundaryColor; + QColor _gradientColor0; + QColor _gradientColor1; + QColor _gradientColor2; + QColor _gradientColor3; + QColor _shadowColor; + QColor _fontColor; + QColor _fontColorFaded; - QColor ConnectionPointColor; - QColor FilledConnectionPointColor; + QColor _connectionPointColor; + QColor _filledConnectionPointColor; - QColor WarningColor; - QColor ErrorColor; + QColor _warningColor; + QColor _errorColor; - float PenWidth; - float HoveredPenWidth; + float _penWidth; + float _hoveredPenWidth; - float ConnectionPointDiameter; + float _connectionPointDiameter; - float Opacity; + float _opacity; }; } diff --git a/include/nodes/internal/Style.hpp b/include/nodes/internal/Style.hpp deleted file mode 100644 index a0d24cf6..00000000 --- a/include/nodes/internal/Style.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -class Style -{ -public: - - virtual - ~Style() = default; - -private: - - virtual void - loadJsonText(QString jsonText) = 0; - - virtual void - loadJsonFile(QString fileName) = 0; - - virtual void - loadJsonFromByteArray(QByteArray const &byteArray) = 0; -}; diff --git a/src/Connection.cpp b/src/Connection.cpp index f6c59656..0a65ccd0 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -15,6 +15,7 @@ #include "NodeDataModel.hpp" #include "ConnectionState.hpp" +#include "ConnectionStyle.hpp" #include "ConnectionGeometry.hpp" #include "ConnectionGraphicsObject.hpp" @@ -27,16 +28,20 @@ using QtNodes::NodeData; using QtNodes::NodeDataType; using QtNodes::ConnectionGraphicsObject; using QtNodes::ConnectionGeometry; +using QtNodes::ConnectionStyle; using QtNodes::TypeConverter; Connection:: Connection(PortType portType, Node& node, - PortIndex portIndex) + PortIndex portIndex, + ConnectionStyle const &style) : _uid(QUuid::createUuid()) , _outPortIndex(INVALID) , _inPortIndex(INVALID) , _connectionState() + , _connectionGeometry(style) + , _connectionStyle(style) { setNodeToPort(node, portType, portIndex); @@ -49,6 +54,7 @@ Connection(Node& nodeIn, PortIndex portIndexIn, Node& nodeOut, PortIndex portIndexOut, + ConnectionStyle const &style, TypeConverter typeConverter) : _uid(QUuid::createUuid()) , _outNode(&nodeOut) @@ -56,6 +62,8 @@ Connection(Node& nodeIn, , _outPortIndex(portIndexOut) , _inPortIndex(portIndexIn) , _connectionState() + , _connectionGeometry(style) + , _connectionStyle(style) , _converter(std::move(typeConverter)) { setNodeToPort(nodeIn, PortType::In, portIndexIn); @@ -402,6 +410,13 @@ setTypeConverter(TypeConverter converter) } +ConnectionStyle const & +Connection::connectionStyle() const +{ + return _connectionStyle; +} + + void Connection:: propagateData(std::shared_ptr nodeData) const diff --git a/src/ConnectionGeometry.cpp b/src/ConnectionGeometry.cpp index 2f8e4be3..d1530bc7 100644 --- a/src/ConnectionGeometry.cpp +++ b/src/ConnectionGeometry.cpp @@ -2,18 +2,20 @@ #include -#include "StyleCollection.hpp" +#include "ConnectionStyle.hpp" using QtNodes::ConnectionGeometry; +using QtNodes::ConnectionStyle; using QtNodes::PortType; ConnectionGeometry:: -ConnectionGeometry() +ConnectionGeometry(ConnectionStyle const &style) : _in(0, 0) , _out(0, 0) //, _animationPhase(0) , _lineWidth(3.0) , _hovered(false) + , _style(&style) { } QPointF const& @@ -78,10 +80,7 @@ boundingRect() const QRectF c1c2Rect = QRectF(points.first, points.second).normalized(); - auto const &connectionStyle = - StyleCollection::connectionStyle(); - - float const diam = connectionStyle.pointDiameter(); + float const diam = _style->pointDiameter(); QRectF commonRect = basicRect.united(c1c2Rect); diff --git a/src/ConnectionPainter.cpp b/src/ConnectionPainter.cpp index 11d31af0..588409fa 100644 --- a/src/ConnectionPainter.cpp +++ b/src/ConnectionPainter.cpp @@ -4,17 +4,17 @@ #include "ConnectionGeometry.hpp" #include "ConnectionState.hpp" +#include "ConnectionStyle.hpp" #include "ConnectionGraphicsObject.hpp" #include "Connection.hpp" #include "NodeData.hpp" -#include "StyleCollection.hpp" - -using QtNodes::ConnectionPainter; -using QtNodes::ConnectionGeometry; using QtNodes::Connection; +using QtNodes::ConnectionGeometry; +using QtNodes::ConnectionPainter; +using QtNodes::ConnectionStyle; static @@ -110,7 +110,7 @@ drawSketchLine(QPainter * painter, if (state.requiresPort()) { auto const & connectionStyle = - QtNodes::StyleCollection::connectionStyle(); + connection.connectionStyle(); QPen p; p.setWidth(connectionStyle.constructionLineWidth()); @@ -150,7 +150,7 @@ drawHoveredOrSelected(QPainter * painter, QPen p; auto const &connectionStyle = - QtNodes::StyleCollection::connectionStyle(); + connection.connectionStyle(); double const lineWidth = connectionStyle.lineWidth(); p.setWidth(2 * lineWidth); @@ -184,7 +184,7 @@ drawNormalLine(QPainter * painter, // colors auto const &connectionStyle = - QtNodes::StyleCollection::connectionStyle(); + connection.connectionStyle(); QColor normalColorOut = connectionStyle.normalColor(); QColor normalColorIn = connectionStyle.normalColor(); @@ -201,8 +201,8 @@ drawNormalLine(QPainter * painter, gradientColor = (dataTypeOut.id != dataTypeIn.id); - normalColorOut = connectionStyle.normalColor(dataTypeOut.id); - normalColorIn = connectionStyle.normalColor(dataTypeIn.id); + normalColorOut = ConnectionStyle::computeNormalColor(dataTypeOut.id); + normalColorIn = ConnectionStyle::computeNormalColor(dataTypeIn.id); selectedColor = normalColorOut.darker(200); } @@ -301,7 +301,7 @@ paint(QPainter* painter, QPointF const & sink = geom.sink(); auto const & connectionStyle = - QtNodes::StyleCollection::connectionStyle(); + connection.connectionStyle(); double const pointDiameter = connectionStyle.pointDiameter(); diff --git a/src/ConnectionStyle.cpp b/src/ConnectionStyle.cpp index 24511644..9fc34833 100644 --- a/src/ConnectionStyle.cpp +++ b/src/ConnectionStyle.cpp @@ -1,179 +1,116 @@ #include "ConnectionStyle.hpp" #include +#include #include +#include +#include #include #include #include -#include -#include - -#include "StyleCollection.hpp" +#include "StyleImport.hpp" using QtNodes::ConnectionStyle; - -inline void initResources() { Q_INIT_RESOURCE(resources); } - -ConnectionStyle:: -ConnectionStyle() -{ - // Explicit resources inialization for preventing the static initialization - // order fiasco: https://isocpp.org/wiki/faq/ctors#static-init-order - initResources(); - - // This configuration is stored inside the compiled unit and is loaded statically - loadJsonFile(":DefaultStyle.json"); -} +using QtNodes::StyleImport; ConnectionStyle:: -ConnectionStyle(QString jsonText) +ConnectionStyle(QByteArray const& jsonBytes) { - loadJsonFile(":DefaultStyle.json"); - loadJsonText(jsonText); + loadJson(jsonBytes); } void ConnectionStyle:: -setConnectionStyle(QString jsonText) +loadJson(QByteArray const& jsonBytes) { - ConnectionStyle style(jsonText); - - StyleCollection::setConnectionStyle(style); -} - -#ifdef STYLE_DEBUG - #define CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(v, variable) { \ - if (v.type() == QJsonValue::Undefined || \ - v.type() == QJsonValue::Null) \ - qWarning() << "Undefined value for parameter:" << #variable; \ - } -#else - #define CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(v, variable) -#endif + QJsonDocument json(QJsonDocument::fromJson(jsonBytes)); + QJsonObject topLevelObject = json.object(); + QJsonValueRef nodeStyleValues = topLevelObject["ConnectionStyle"]; + QJsonObject obj = nodeStyleValues.toObject(); -#define CONNECTION_VALUE_EXISTS(v) \ - (v.type() != QJsonValue::Undefined && \ - v.type() != QJsonValue::Null) + StyleImport::readColor(obj, "ConstructionColor", &_constructionColor); + StyleImport::readColor(obj, "NormalColor", &_normalColor); + StyleImport::readColor(obj, "SelectedColor", &_selectedColor); + StyleImport::readColor(obj, "SelectedHaloColor", &_selectedHaloColor); + StyleImport::readColor(obj, "HoveredColor", &_hoveredColor); -#define CONNECTION_STYLE_READ_COLOR(values, variable) { \ - auto valueRef = values[#variable]; \ - CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (CONNECTION_VALUE_EXISTS(valueRef)) {\ - if (valueRef.isArray()) { \ - auto colorArray = valueRef.toArray(); \ - std::vector rgb; rgb.reserve(3); \ - for (auto it = colorArray.begin(); it != colorArray.end(); ++it) { \ - rgb.push_back((*it).toInt()); \ - } \ - variable = QColor(rgb[0], rgb[1], rgb[2]); \ - } else { \ - variable = QColor(valueRef.toString()); \ - } \ - } \ -} + StyleImport::readFloat(obj, "LineWidth", &_lineWidth); + StyleImport::readFloat(obj, "ConstructionLineWidth", &_constructionLineWidth); + StyleImport::readFloat(obj, "PointDiameter", &_pointDiameter); -#define CONNECTION_STYLE_READ_FLOAT(values, variable) { \ - auto valueRef = values[#variable]; \ - CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (CONNECTION_VALUE_EXISTS(valueRef)) \ - variable = valueRef.toDouble(); \ + StyleImport::readBool(obj, "UseDataDefinedColors", &_useDataDefinedColors); } -#define CONNECTION_STYLE_READ_BOOL(values, variable) { \ - auto valueRef = values[#variable]; \ - CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (CONNECTION_VALUE_EXISTS(valueRef)) \ - variable = valueRef.toBool(); \ -} -void +ConnectionStyle const& ConnectionStyle:: -loadJsonFile(QString styleFile) +defaultStyle() { - QFile file(styleFile); - - if (!file.open(QIODevice::ReadOnly)) - { - qWarning() << "Couldn't open file " << styleFile; + static ConnectionStyle const DefaultStyle = [] { + StyleImport::initResources(); - return; - } + return ConnectionStyle(StyleImport::readJsonFile(":DefaultStyle.json")); + }(); - loadJsonFromByteArray(file.readAll()); + return DefaultStyle; } -void +ConnectionStyle ConnectionStyle:: -loadJsonText(QString jsonText) +fromJson(QString const& jsonText) { - loadJsonFromByteArray(jsonText.toUtf8()); + auto style = defaultStyle(); + + style.loadJson(StyleImport::readJsonText(jsonText)); + + return style; } -void +// static +QColor ConnectionStyle:: -loadJsonFromByteArray(QByteArray const &byteArray) +computeNormalColor(QString const& typeId) { - QJsonDocument json(QJsonDocument::fromJson(byteArray)); - - QJsonObject topLevelObject = json.object(); - - QJsonValueRef nodeStyleValues = topLevelObject["ConnectionStyle"]; + std::size_t hash = qHash(typeId); - QJsonObject obj = nodeStyleValues.toObject(); + std::size_t const hue_range = 0xFF; - CONNECTION_STYLE_READ_COLOR(obj, ConstructionColor); - CONNECTION_STYLE_READ_COLOR(obj, NormalColor); - CONNECTION_STYLE_READ_COLOR(obj, SelectedColor); - CONNECTION_STYLE_READ_COLOR(obj, SelectedHaloColor); - CONNECTION_STYLE_READ_COLOR(obj, HoveredColor); + qsrand(hash); + std::size_t hue = qrand() % hue_range; - CONNECTION_STYLE_READ_FLOAT(obj, LineWidth); - CONNECTION_STYLE_READ_FLOAT(obj, ConstructionLineWidth); - CONNECTION_STYLE_READ_FLOAT(obj, PointDiameter); + std::size_t sat = 120 + hash % 129; - CONNECTION_STYLE_READ_BOOL(obj, UseDataDefinedColors); + return QColor::fromHsl(hue, + sat, + 160); } -QColor ConnectionStyle:: -constructionColor() const -{ - return ConstructionColor; -} +ConnectionStyle() += default; QColor ConnectionStyle:: -normalColor() const +constructionColor() const { - return NormalColor; + return _constructionColor; } QColor ConnectionStyle:: -normalColor(QString typeId) const +normalColor() const { - std::size_t hash = qHash(typeId); - - std::size_t const hue_range = 0xFF; - - qsrand(hash); - std::size_t hue = qrand() % hue_range; - - std::size_t sat = 120 + hash % 129; - - return QColor::fromHsl(hue, - sat, - 160); + return _normalColor; } @@ -181,7 +118,7 @@ QColor ConnectionStyle:: selectedColor() const { - return SelectedColor; + return _selectedColor; } @@ -189,7 +126,7 @@ QColor ConnectionStyle:: selectedHaloColor() const { - return SelectedHaloColor; + return _selectedHaloColor; } @@ -197,7 +134,7 @@ QColor ConnectionStyle:: hoveredColor() const { - return HoveredColor; + return _hoveredColor; } @@ -205,7 +142,7 @@ float ConnectionStyle:: lineWidth() const { - return LineWidth; + return _lineWidth; } @@ -213,7 +150,7 @@ float ConnectionStyle:: constructionLineWidth() const { - return ConstructionLineWidth; + return _constructionLineWidth; } @@ -221,7 +158,7 @@ float ConnectionStyle:: pointDiameter() const { - return PointDiameter; + return _pointDiameter; } @@ -229,5 +166,77 @@ bool ConnectionStyle:: useDataDefinedColors() const { - return UseDataDefinedColors; + return _useDataDefinedColors; +} + + +void +ConnectionStyle:: +setConstructionColor(QColor color) +{ + _constructionColor = std::move(color); +} + + +void +ConnectionStyle:: +setNormalColor(QColor color) +{ + _normalColor = std::move(color); +} + + +void +ConnectionStyle:: +setSelectedColor(QColor color) +{ + _selectedColor = std::move(color); +} + + +void +ConnectionStyle:: +setSelectedHaloColor(QColor color) +{ + _selectedHaloColor = std::move(color); +} + + +void +ConnectionStyle:: +setHoveredColor(QColor color) +{ + _hoveredColor = std::move(color); +} + + +void +ConnectionStyle:: +setLineWidth(float value) +{ + _lineWidth = value; +} + + +void +ConnectionStyle:: +setConstructionLineWidth(float value) +{ + _constructionLineWidth = value; +} + + +void +ConnectionStyle:: +setPointDiameter(float value) +{ + _pointDiameter = value; +} + + +void +ConnectionStyle:: +useDataDefinedColors(bool use) +{ + _useDataDefinedColors = use; } diff --git a/src/FlowScene.cpp b/src/FlowScene.cpp index 838d125e..b5618a02 100644 --- a/src/FlowScene.cpp +++ b/src/FlowScene.cpp @@ -27,10 +27,15 @@ #include "FlowView.hpp" #include "DataModelRegistry.hpp" +#include "NodeStyle.hpp" +#include "ConnectionStyle.hpp" + using QtNodes::FlowScene; using QtNodes::Node; +using QtNodes::NodeStyle; using QtNodes::NodeGraphicsObject; using QtNodes::Connection; +using QtNodes::ConnectionStyle; using QtNodes::DataModelRegistry; using QtNodes::NodeDataModel; using QtNodes::PortType; @@ -42,6 +47,8 @@ FlowScene:: FlowScene(std::shared_ptr registry, QObject * parent) : QGraphicsScene(parent) + , _connectionStyle(ConnectionStyle::defaultStyle()) + , _nodeStyle(NodeStyle::defaultStyle()) , _registry(std::move(registry)) { setItemIndexMethod(QGraphicsScene::NoIndex); @@ -69,9 +76,12 @@ createConnection(PortType connectedPort, Node& node, PortIndex portIndex) { - auto connection = std::make_shared(connectedPort, node, portIndex); + auto connection = std::make_shared(connectedPort, + node, + portIndex, + connectionStyle()); - auto cgo = detail::make_unique(*this, *connection); + auto cgo = QtNodes::detail::make_unique(*this, *connection); // after this function connection points are set to node port connection->setGraphicsObject(std::move(cgo)); @@ -96,9 +106,10 @@ createConnection(Node& nodeIn, portIndexIn, nodeOut, portIndexOut, + connectionStyle(), converter); - auto cgo = detail::make_unique(*this, *connection); + auto cgo = QtNodes::detail::make_unique(*this, *connection); nodeIn.nodeState().setConnection(PortType::In, portIndexIn, *connection); nodeOut.nodeState().setConnection(PortType::Out, portIndexOut, *connection); @@ -173,23 +184,34 @@ deleteConnection(Connection& connection) } -Node& -FlowScene:: -createNode(std::unique_ptr && dataModel) +static +Node & +makeNode(FlowScene & scene, + std::unordered_map> &nodes, + std::unique_ptr && dataModel) { - auto node = detail::make_unique(std::move(dataModel)); - auto ngo = detail::make_unique(*this, *node); + auto node = QtNodes::detail::make_unique(std::move(dataModel), scene.nodeStyle()); + auto ngo = QtNodes::detail::make_unique(scene, *node); node->setGraphicsObject(std::move(ngo)); - auto nodePtr = node.get(); - _nodes[node->id()] = std::move(node); + auto nodePtr = node.get(); + nodes[node->id()] = std::move(node); - nodeCreated(*nodePtr); return *nodePtr; } +Node& +FlowScene:: +createNode(std::unique_ptr && dataModel) +{ + Node& node = ::makeNode(*this, _nodes, std::move(dataModel)); + nodeCreated(node); + return node; +} + + Node& FlowScene:: restoreNode(QJsonObject const& nodeJson) @@ -202,17 +224,10 @@ restoreNode(QJsonObject const& nodeJson) throw std::logic_error(std::string("No registered model with name ") + modelName.toLocal8Bit().data()); - auto node = detail::make_unique(std::move(dataModel)); - auto ngo = detail::make_unique(*this, *node); - node->setGraphicsObject(std::move(ngo)); - - node->restore(nodeJson); - - auto nodePtr = node.get(); - _nodes[node->id()] = std::move(node); - - nodeCreated(*nodePtr); - return *nodePtr; + auto& node = ::makeNode(*this, _nodes, std::move(dataModel)); + node.restore(nodeJson); + nodeCreated(node); + return node; } @@ -552,6 +567,38 @@ loadFromMemory(const QByteArray& data) } +ConnectionStyle const & +FlowScene:: +connectionStyle() const +{ + return _connectionStyle; +} + + +NodeStyle const & +FlowScene:: +nodeStyle() const +{ + return _nodeStyle; +} + + +void +FlowScene:: +setConnectionStyle(ConnectionStyle style) +{ + _connectionStyle = std::move(style); +} + + +void +FlowScene:: +setNodeStyle(NodeStyle style) +{ + _nodeStyle = std::move(style); +} + + //------------------------------------------------------------------------------ namespace QtNodes { diff --git a/src/FlowView.cpp b/src/FlowView.cpp index 4e5e1e9b..45399875 100644 --- a/src/FlowView.cpp +++ b/src/FlowView.cpp @@ -21,13 +21,20 @@ #include "Node.hpp" #include "NodeGraphicsObject.hpp" #include "ConnectionGraphicsObject.hpp" -#include "StyleCollection.hpp" using QtNodes::FlowView; +using QtNodes::FlowViewStyle; using QtNodes::FlowScene; + FlowView:: FlowView(QWidget *parent) + : FlowView(FlowViewStyle::defaultStyle(), parent) +{} + + +FlowView:: +FlowView(FlowViewStyle style, QWidget *parent) : QGraphicsView(parent) , _clearSelectionAction(Q_NULLPTR) , _deleteSelectionAction(Q_NULLPTR) @@ -36,9 +43,6 @@ FlowView(QWidget *parent) setDragMode(QGraphicsView::ScrollHandDrag); setRenderHint(QPainter::Antialiasing); - auto const &flowViewStyle = StyleCollection::flowViewStyle(); - - setBackgroundBrush(flowViewStyle.BackgroundColor); //setViewportUpdateMode(QGraphicsView::FullViewportUpdate); //setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate); @@ -50,17 +54,26 @@ FlowView(QWidget *parent) setCacheMode(QGraphicsView::CacheBackground); //setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); + + setStyle(std::move(style)); } FlowView:: -FlowView(FlowScene *scene, QWidget *parent) +FlowView(FlowScene *scene, FlowViewStyle style, QWidget *parent) : FlowView(parent) { setScene(scene); + setStyle(std::move(style)); } +FlowView:: +FlowView(FlowScene *scene, QWidget *parent) + : FlowView(scene, FlowViewStyle::defaultStyle(), parent) +{} + + QAction* FlowView:: clearSelectionAction() const @@ -98,6 +111,15 @@ FlowView::setScene(FlowScene *scene) } +void +FlowView::setStyle(FlowViewStyle style) +{ + _style = std::move(style); + + setBackgroundBrush(_style.backgroundColor()); +} + + void FlowView:: contextMenuEvent(QContextMenuEvent *event) @@ -375,16 +397,14 @@ drawBackground(QPainter* painter, const QRectF& r) } }; - auto const &flowViewStyle = StyleCollection::flowViewStyle(); - QBrush bBrush = backgroundBrush(); - QPen pfine(flowViewStyle.FineGridColor, 1.0); + QPen pfine(_style.fineGridColor(), 1.0); painter->setPen(pfine); drawGrid(15); - QPen p(flowViewStyle.CoarseGridColor, 1.0); + QPen p(_style.coarseGridColor(), 1.0); painter->setPen(p); drawGrid(150); diff --git a/src/FlowViewStyle.cpp b/src/FlowViewStyle.cpp index e08cf4fc..bf800960 100644 --- a/src/FlowViewStyle.cpp +++ b/src/FlowViewStyle.cpp @@ -1,111 +1,55 @@ #include "FlowViewStyle.hpp" +#include + #include +#include #include #include #include -#include - -#include -#include "StyleCollection.hpp" +#include "StyleImport.hpp" using QtNodes::FlowViewStyle; +using QtNodes::StyleImport; -inline void initResources() { Q_INIT_RESOURCE(resources); } FlowViewStyle:: -FlowViewStyle() +FlowViewStyle(QByteArray const& jsonBytes) { - // Explicit resources inialization for preventing the static initialization - // order fiasco: https://isocpp.org/wiki/faq/ctors#static-init-order - initResources(); - - // This configuration is stored inside the compiled unit and is loaded statically - loadJsonFile(":DefaultStyle.json"); -} + QJsonDocument json(QJsonDocument::fromJson(jsonBytes)); + QJsonObject topLevelObject = json.object(); + QJsonValueRef flowViewStyleValues = topLevelObject["FlowViewStyle"]; + QJsonObject obj = flowViewStyleValues.toObject(); -FlowViewStyle:: -FlowViewStyle(QString jsonText) -{ - loadJsonText(jsonText); + _backgroundColor = StyleImport::readColor(obj, "BackgroundColor"); + _fineGridColor = StyleImport::readColor(obj, "FineGridColor"); + _coarseGridColor = StyleImport::readColor(obj, "CoarseGridColor"); } -void +FlowViewStyle const& FlowViewStyle:: -setStyle(QString jsonText) +defaultStyle() { - FlowViewStyle style(jsonText); + static FlowViewStyle const DefaultStyle = [] { + StyleImport::initResources(); + return FlowViewStyle(StyleImport::readJsonFile(":DefaultStyle.json")); + }(); - StyleCollection::setFlowViewStyle(style); + return DefaultStyle; } -#ifdef STYLE_DEBUG - #define FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(v, variable) { \ - if (v.type() == QJsonValue::Undefined || \ - v.type() == QJsonValue::Null) \ - qWarning() << "Undefined value for parameter:" << #variable; \ - } -#else - #define FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(v, variable) -#endif - -#define FLOW_VIEW_STYLE_READ_COLOR(values, variable) { \ - auto valueRef = values[#variable]; \ - FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (valueRef.isArray()) { \ - auto colorArray = valueRef.toArray(); \ - std::vector rgb; rgb.reserve(3); \ - for (auto it = colorArray.begin(); it != colorArray.end(); ++it) { \ - rgb.push_back((*it).toInt()); \ - } \ - variable = QColor(rgb[0], rgb[1], rgb[2]); \ - } else { \ - variable = QColor(valueRef.toString()); \ - } \ -} - -void +FlowViewStyle FlowViewStyle:: -loadJsonFile(QString styleFile) +fromJson(QString const& jsonText) { - QFile file(styleFile); - - if (!file.open(QIODevice::ReadOnly)) - { - qWarning() << "Couldn't open file " << styleFile; - - return; - } - - loadJsonFromByteArray(file.readAll()); + return FlowViewStyle(StyleImport::readJsonText(jsonText)); } -void FlowViewStyle:: -loadJsonText(QString jsonText) -{ - loadJsonFromByteArray(jsonText.toUtf8()); -} - - -void -FlowViewStyle:: -loadJsonFromByteArray(QByteArray const &byteArray) -{ - QJsonDocument json(QJsonDocument::fromJson(byteArray)); - - QJsonObject topLevelObject = json.object(); - - QJsonValueRef nodeStyleValues = topLevelObject["FlowViewStyle"]; - - QJsonObject obj = nodeStyleValues.toObject(); - - FLOW_VIEW_STYLE_READ_COLOR(obj, BackgroundColor); - FLOW_VIEW_STYLE_READ_COLOR(obj, FineGridColor); - FLOW_VIEW_STYLE_READ_COLOR(obj, CoarseGridColor); -} +FlowViewStyle() += default; diff --git a/src/Node.cpp b/src/Node.cpp index 4a052943..4b5fef8c 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -3,12 +3,12 @@ #include #include -#include #include "FlowScene.hpp" #include "NodeGraphicsObject.hpp" #include "NodeDataModel.hpp" +#include "NodeStyle.hpp" #include "ConnectionGraphicsObject.hpp" #include "ConnectionState.hpp" @@ -16,6 +16,7 @@ using QtNodes::Node; using QtNodes::NodeGeometry; using QtNodes::NodeState; +using QtNodes::NodeStyle; using QtNodes::NodeData; using QtNodes::NodeDataType; using QtNodes::NodeDataModel; @@ -23,12 +24,21 @@ using QtNodes::NodeGraphicsObject; using QtNodes::PortIndex; using QtNodes::PortType; + +static NodeStyle const& +computeStyle(NodeStyle const *preferredStyle, NodeStyle const &backupStyle) +{ + return preferredStyle ? *preferredStyle : backupStyle; +} + + Node:: -Node(std::unique_ptr && dataModel) +Node(std::unique_ptr && dataModel, NodeStyle const& style) : _uid(QUuid::createUuid()) , _nodeDataModel(std::move(dataModel)) , _nodeState(_nodeDataModel) - , _nodeGeometry(_nodeDataModel) + , _nodeStyle(computeStyle(_nodeDataModel->nodeStyle(), style)) + , _nodeGeometry(_nodeDataModel, _nodeStyle) , _nodeGraphicsObject(nullptr) { _nodeGeometry.recalculateSize(); @@ -171,6 +181,14 @@ nodeState() } +NodeStyle const & +Node:: +nodeStyle() const +{ + return _nodeStyle; +} + + NodeDataModel* Node:: nodeDataModel() const diff --git a/src/NodeDataModel.cpp b/src/NodeDataModel.cpp index 9737b345..286ef056 100644 --- a/src/NodeDataModel.cpp +++ b/src/NodeDataModel.cpp @@ -1,16 +1,12 @@ #include "NodeDataModel.hpp" -#include "StyleCollection.hpp" +#include using QtNodes::NodeDataModel; -using QtNodes::NodeStyle; NodeDataModel:: NodeDataModel() - : _nodeStyle(StyleCollection::nodeStyle()) -{ - // Derived classes can initialize specific style here -} += default; QJsonObject @@ -23,19 +19,3 @@ save() const return modelJson; } - - -NodeStyle const& -NodeDataModel:: -nodeStyle() const -{ - return _nodeStyle; -} - - -void -NodeDataModel:: -setNodeStyle(NodeStyle const& style) -{ - _nodeStyle = style; -} diff --git a/src/NodeGeometry.cpp b/src/NodeGeometry.cpp index f258e689..8c99ac14 100644 --- a/src/NodeGeometry.cpp +++ b/src/NodeGeometry.cpp @@ -3,22 +3,22 @@ #include #include -#include "PortType.hpp" -#include "NodeState.hpp" -#include "NodeDataModel.hpp" #include "Node.hpp" +#include "NodeDataModel.hpp" #include "NodeGraphicsObject.hpp" +#include "NodeState.hpp" +#include "NodeStyle.hpp" +#include "PortType.hpp" -#include "StyleCollection.hpp" - -using QtNodes::NodeGeometry; +using QtNodes::Node; using QtNodes::NodeDataModel; +using QtNodes::NodeGeometry; +using QtNodes::NodeStyle; using QtNodes::PortIndex; using QtNodes::PortType; -using QtNodes::Node; NodeGeometry:: -NodeGeometry(std::unique_ptr const &dataModel) +NodeGeometry(std::unique_ptr const &dataModel, NodeStyle const &style) : _width(100) , _height(150) , _inputPortWidth(70) @@ -32,6 +32,7 @@ NodeGeometry(std::unique_ptr const &dataModel) , _dataModel(dataModel) , _fontMetrics(QFont()) , _boldFontMetrics(QFont()) + , _nodeStyle(&style) { QFont f; f.setBold(true); @@ -56,9 +57,7 @@ QRectF NodeGeometry:: boundingRect() const { - auto const &nodeStyle = StyleCollection::nodeStyle(); - - double addon = 4 * nodeStyle.ConnectionPointDiameter; + double addon = 4 * _nodeStyle->connectionPointDiameter(); return QRectF(0 - addon, 0 - addon, @@ -135,8 +134,6 @@ portScenePosition(PortIndex index, PortType portType, QTransform const & t) const { - auto const &nodeStyle = StyleCollection::nodeStyle(); - unsigned int step = _entryHeight + _spacing; QPointF result; @@ -154,7 +151,7 @@ portScenePosition(PortIndex index, { case PortType::Out: { - double x = _width + nodeStyle.ConnectionPointDiameter; + double x = _width + _nodeStyle->connectionPointDiameter(); result = QPointF(x, totalHeight); break; @@ -162,7 +159,7 @@ portScenePosition(PortIndex index, case PortType::In: { - double x = 0.0 - nodeStyle.ConnectionPointDiameter; + double x = 0.0 - _nodeStyle->connectionPointDiameter(); result = QPointF(x, totalHeight); break; @@ -182,14 +179,12 @@ checkHitScenePoint(PortType portType, QPointF const scenePoint, QTransform const & sceneTransform) const { - auto const &nodeStyle = StyleCollection::nodeStyle(); - PortIndex result = INVALID; if (portType == PortType::None) return result; - double const tolerance = 2.0 * nodeStyle.ConnectionPointDiameter; + double const tolerance = 2.0 * _nodeStyle->connectionPointDiameter(); unsigned int const nItems = _dataModel->nPorts(portType); diff --git a/src/NodeGraphicsObject.cpp b/src/NodeGraphicsObject.cpp index 3f394e91..974f2eee 100644 --- a/src/NodeGraphicsObject.cpp +++ b/src/NodeGraphicsObject.cpp @@ -16,8 +16,6 @@ #include "NodeDataModel.hpp" #include "NodeConnectionInteraction.hpp" -#include "StyleCollection.hpp" - using QtNodes::NodeGraphicsObject; using QtNodes::Node; using QtNodes::FlowScene; @@ -40,18 +38,18 @@ NodeGraphicsObject(FlowScene &scene, setCacheMode( QGraphicsItem::DeviceCoordinateCache ); - auto const &nodeStyle = node.nodeDataModel()->nodeStyle(); + auto const &nodeStyle = node.nodeStyle(); { auto effect = new QGraphicsDropShadowEffect; effect->setOffset(4, 4); effect->setBlurRadius(20); - effect->setColor(nodeStyle.ShadowColor); + effect->setColor(nodeStyle.shadowColor()); setGraphicsEffect(effect); } - setOpacity(nodeStyle.Opacity); + setOpacity(nodeStyle.opacity()); setAcceptHoverEvents(true); diff --git a/src/NodePainter.cpp b/src/NodePainter.cpp index fffd1b51..6b03b803 100644 --- a/src/NodePainter.cpp +++ b/src/NodePainter.cpp @@ -4,20 +4,23 @@ #include -#include "StyleCollection.hpp" +#include "ConnectionStyle.hpp" #include "PortType.hpp" #include "NodeGraphicsObject.hpp" #include "NodeGeometry.hpp" #include "NodeState.hpp" +#include "FlowScene.hpp" #include "NodeDataModel.hpp" #include "Node.hpp" -#include "FlowScene.hpp" +#include "NodeStyle.hpp" +using QtNodes::ConnectionStyle; using QtNodes::NodePainter; using QtNodes::NodeGeometry; using QtNodes::NodeGraphicsObject; using QtNodes::Node; using QtNodes::NodeState; +using QtNodes::NodeStyle; using QtNodes::NodeDataModel; using QtNodes::FlowScene; @@ -38,19 +41,19 @@ paint(QPainter* painter, //-------------------------------------------- NodeDataModel const * model = node.nodeDataModel(); - drawNodeRect(painter, geom, model, graphicsObject); + drawNodeRect(painter, geom, node, graphicsObject); - drawConnectionPoints(painter, geom, state, model, scene); + drawConnectionPoints(painter, geom, state, node, scene, scene.connectionStyle()); - drawFilledConnectionPoints(painter, geom, state, model); + drawFilledConnectionPoints(painter, geom, state, node, scene.connectionStyle()); - drawModelName(painter, geom, state, model); + drawModelName(painter, geom, state, node); - drawEntryLabels(painter, geom, state, model); + drawEntryLabels(painter, geom, state, node); - drawResizeRect(painter, geom, model); + drawResizeRect(painter, geom, node); - drawValidationRect(painter, geom, model, graphicsObject); + drawValidationRect(painter, geom, node, graphicsObject); /// call custom painter if (auto painterDelegate = model->painterDelegate()) @@ -64,37 +67,37 @@ void NodePainter:: drawNodeRect(QPainter* painter, NodeGeometry const& geom, - NodeDataModel const* model, + Node const& node, NodeGraphicsObject const & graphicsObject) { - NodeStyle const& nodeStyle = model->nodeStyle(); + NodeStyle const& nodeStyle = node.nodeStyle(); auto color = graphicsObject.isSelected() - ? nodeStyle.SelectedBoundaryColor - : nodeStyle.NormalBoundaryColor; + ? nodeStyle.selectedBoundaryColor() + : nodeStyle.normalBoundaryColor(); if (geom.hovered()) { - QPen p(color, nodeStyle.HoveredPenWidth); + QPen p(color, nodeStyle.hoveredPenWidth()); painter->setPen(p); } else { - QPen p(color, nodeStyle.PenWidth); + QPen p(color, nodeStyle.penWidth()); painter->setPen(p); } QLinearGradient gradient(QPointF(0.0, 0.0), QPointF(2.0, geom.height())); - gradient.setColorAt(0.0, nodeStyle.GradientColor0); - gradient.setColorAt(0.03, nodeStyle.GradientColor1); - gradient.setColorAt(0.97, nodeStyle.GradientColor2); - gradient.setColorAt(1.0, nodeStyle.GradientColor3); + gradient.setColorAt(0.0, nodeStyle.gradientColor0()); + gradient.setColorAt(0.03, nodeStyle.gradientColor1()); + gradient.setColorAt(0.97, nodeStyle.gradientColor2()); + gradient.setColorAt(1.0, nodeStyle.gradientColor3()); painter->setBrush(gradient); - float diam = nodeStyle.ConnectionPointDiameter; + float diam = nodeStyle.connectionPointDiameter(); QRectF boundary( -diam, -diam, 2.0 * diam + geom.width(), 2.0 * diam + geom.height()); @@ -107,15 +110,17 @@ drawNodeRect(QPainter* painter, void NodePainter:: drawConnectionPoints(QPainter* painter, - NodeGeometry const& geom, - NodeState const& state, - NodeDataModel const * model, - FlowScene const & scene) + NodeGeometry const & geom, + NodeState const & state, + Node const & node, + FlowScene const & scene, + ConnectionStyle const &connectionStyle) { - NodeStyle const& nodeStyle = model->nodeStyle(); - auto const &connectionStyle = StyleCollection::connectionStyle(); + NodeDataModel const &model = *node.nodeDataModel(); - float diameter = nodeStyle.ConnectionPointDiameter; + NodeStyle const &nodeStyle = node.nodeStyle(); + + float diameter = nodeStyle.connectionPointDiameter(); auto reducedDiameter = diameter * 0.6; auto drawPoints = @@ -127,11 +132,11 @@ drawConnectionPoints(QPainter* painter, { QPointF p = geom.portScenePosition(i, portType); - auto const & dataType = model->dataType(portType, i); + auto const & dataType = model.dataType(portType, i); bool canConnect = (state.getEntries(portType)[i].empty() || (portType == PortType::Out && - model->portOutConnectionPolicy(i) == NodeDataModel::ConnectionPolicy::Many) ); + model.portOutConnectionPolicy(i) == NodeDataModel::ConnectionPolicy::Many) ); double r = 1.0; if (state.isReacting() && @@ -172,11 +177,11 @@ drawConnectionPoints(QPainter* painter, if (connectionStyle.useDataDefinedColors()) { - painter->setBrush(connectionStyle.normalColor(dataType.id)); + painter->setBrush(ConnectionStyle::computeNormalColor(dataType.id)); } else { - painter->setBrush(nodeStyle.ConnectionPointColor); + painter->setBrush(nodeStyle.connectionPointColor()); } painter->drawEllipse(p, @@ -195,12 +200,14 @@ NodePainter:: drawFilledConnectionPoints(QPainter * painter, NodeGeometry const & geom, NodeState const & state, - NodeDataModel const * model) + Node const & node, + ConnectionStyle const & connectionStyle) { - NodeStyle const& nodeStyle = model->nodeStyle(); - auto const & connectionStyle = StyleCollection::connectionStyle(); + NodeDataModel const &model = *node.nodeDataModel(); + + NodeStyle const &nodeStyle = node.nodeStyle(); - auto diameter = nodeStyle.ConnectionPointDiameter; + auto diameter = nodeStyle.connectionPointDiameter(); auto drawPoints = [&](PortType portType) @@ -213,18 +220,18 @@ drawFilledConnectionPoints(QPainter * painter, if (!state.getEntries(portType)[i].empty()) { - auto const & dataType = model->dataType(portType, i); + auto const & dataType = model.dataType(portType, i); if (connectionStyle.useDataDefinedColors()) { - QColor const c = connectionStyle.normalColor(dataType.id); + QColor const c = ConnectionStyle::computeNormalColor(dataType.id); painter->setPen(c); painter->setBrush(c); } else { - painter->setPen(nodeStyle.FilledConnectionPointColor); - painter->setBrush(nodeStyle.FilledConnectionPointColor); + painter->setPen(nodeStyle.filledConnectionPointColor()); + painter->setBrush(nodeStyle.filledConnectionPointColor()); } painter->drawEllipse(p, @@ -244,16 +251,18 @@ NodePainter:: drawModelName(QPainter * painter, NodeGeometry const & geom, NodeState const & state, - NodeDataModel const * model) + Node const &node) { - NodeStyle const& nodeStyle = model->nodeStyle(); + NodeDataModel const &model = *node.nodeDataModel(); + + NodeStyle const& nodeStyle = node.nodeStyle(); Q_UNUSED(state); - if (!model->captionVisible()) + if (!model.captionVisible()) return; - QString const &name = model->caption(); + QString const &name = model.caption(); QFont f = painter->font(); @@ -267,7 +276,7 @@ drawModelName(QPainter * painter, (geom.spacing() + geom.entryHeight()) / 3.0); painter->setFont(f); - painter->setPen(nodeStyle.FontColor); + painter->setPen(nodeStyle.fontColor()); painter->drawText(position, name); f.setBold(false); @@ -280,15 +289,17 @@ NodePainter:: drawEntryLabels(QPainter * painter, NodeGeometry const & geom, NodeState const & state, - NodeDataModel const * model) + Node const &node) { + NodeDataModel const &model = *node.nodeDataModel(); + QFontMetrics const & metrics = painter->fontMetrics(); auto drawPoints = [&](PortType portType) { - auto const &nodeStyle = model->nodeStyle(); + auto const &nodeStyle = node.nodeStyle(); auto& entries = state.getEntries(portType); @@ -299,19 +310,19 @@ drawEntryLabels(QPainter * painter, QPointF p = geom.portScenePosition(i, portType); if (entries[i].empty()) - painter->setPen(nodeStyle.FontColorFaded); + painter->setPen(nodeStyle.fontColorFaded()); else - painter->setPen(nodeStyle.FontColor); + painter->setPen(nodeStyle.fontColor()); QString s; - if (model->portCaptionVisible(portType, i)) + if (model.portCaptionVisible(portType, i)) { - s = model->portCaption(portType, i); + s = model.portCaption(portType, i); } else { - s = model->dataType(portType, i).name; + s = model.dataType(portType, i).name; } auto rect = metrics.boundingRect(s); @@ -346,9 +357,11 @@ void NodePainter:: drawResizeRect(QPainter * painter, NodeGeometry const & geom, - NodeDataModel const * model) + Node const &node) { - if (model->resizable()) + NodeDataModel const &model = *node.nodeDataModel(); + + if (model.resizable()) { painter->setBrush(Qt::gray); @@ -361,43 +374,45 @@ void NodePainter:: drawValidationRect(QPainter * painter, NodeGeometry const & geom, - NodeDataModel const * model, + Node const & node, NodeGraphicsObject const & graphicsObject) { - auto modelValidationState = model->validationState(); + NodeDataModel const &model = *node.nodeDataModel(); + + auto modelValidationState = model.validationState(); if (modelValidationState != NodeValidationState::Valid) { - NodeStyle const& nodeStyle = model->nodeStyle(); + NodeStyle const& nodeStyle = node.nodeStyle(); auto color = graphicsObject.isSelected() - ? nodeStyle.SelectedBoundaryColor - : nodeStyle.NormalBoundaryColor; + ? nodeStyle.selectedBoundaryColor() + : nodeStyle.normalBoundaryColor(); if (geom.hovered()) { - QPen p(color, nodeStyle.HoveredPenWidth); + QPen p(color, nodeStyle.hoveredPenWidth()); painter->setPen(p); } else { - QPen p(color, nodeStyle.PenWidth); + QPen p(color, nodeStyle.penWidth()); painter->setPen(p); } //Drawing the validation message background if (modelValidationState == NodeValidationState::Error) { - painter->setBrush(nodeStyle.ErrorColor); + painter->setBrush(nodeStyle.errorColor()); } else { - painter->setBrush(nodeStyle.WarningColor); + painter->setBrush(nodeStyle.warningColor()); } double const radius = 3.0; - float diam = nodeStyle.ConnectionPointDiameter; + float diam = nodeStyle.connectionPointDiameter(); QRectF boundary(-diam, -diam + geom.height() - geom.validationHeight(), @@ -409,7 +424,7 @@ drawValidationRect(QPainter * painter, painter->setBrush(Qt::gray); //Drawing the validation message itself - QString const &errorMsg = model->validationMessage(); + QString const &errorMsg = model.validationMessage(); QFont f = painter->font(); @@ -421,7 +436,7 @@ drawValidationRect(QPainter * painter, geom.height() - (geom.validationHeight() - diam) / 2.0); painter->setFont(f); - painter->setPen(nodeStyle.FontColor); + painter->setPen(nodeStyle.fontColor()); painter->drawText(position, errorMsg); } } diff --git a/src/NodePainter.hpp b/src/NodePainter.hpp index ba8c3c71..cc2def13 100644 --- a/src/NodePainter.hpp +++ b/src/NodePainter.hpp @@ -12,6 +12,7 @@ class NodeGraphicsObject; class NodeDataModel; class FlowItemEntry; class FlowScene; +class ConnectionStyle; class NodePainter { @@ -31,7 +32,7 @@ class NodePainter void drawNodeRect(QPainter* painter, NodeGeometry const& geom, - NodeDataModel const* model, + Node const& node, NodeGraphicsObject const & graphicsObject); static @@ -39,41 +40,43 @@ class NodePainter drawModelName(QPainter* painter, NodeGeometry const& geom, NodeState const& state, - NodeDataModel const * model); + Node const & node); static void drawEntryLabels(QPainter* painter, NodeGeometry const& geom, NodeState const& state, - NodeDataModel const * model); + Node const & node); static void drawConnectionPoints(QPainter* painter, NodeGeometry const& geom, NodeState const& state, - NodeDataModel const * model, - FlowScene const & scene); + Node const & node, + FlowScene const & scene, + ConnectionStyle const & connectionStyle); static void drawFilledConnectionPoints(QPainter* painter, NodeGeometry const& geom, NodeState const& state, - NodeDataModel const * model); + Node const & node, + ConnectionStyle const & connectionStyle); static void drawResizeRect(QPainter* painter, NodeGeometry const& geom, - NodeDataModel const * model); + Node const & node); static void drawValidationRect(QPainter * painter, NodeGeometry const & geom, - NodeDataModel const * model, + Node const & node, NodeGraphicsObject const & graphicsObject); }; } diff --git a/src/NodeStyle.cpp b/src/NodeStyle.cpp index c62e0ac9..0ea9829c 100644 --- a/src/NodeStyle.cpp +++ b/src/NodeStyle.cpp @@ -1,136 +1,342 @@ #include "NodeStyle.hpp" -#include +#include #include +#include #include #include #include -#include - -#include -#include "StyleCollection.hpp" +#include "StyleImport.hpp" using QtNodes::NodeStyle; +using QtNodes::StyleImport; + + +NodeStyle:: +NodeStyle(QByteArray const& jsonBytes) +{ + QJsonDocument json(QJsonDocument::fromJson(jsonBytes)); + QJsonObject topLevelObject = json.object(); + + QJsonValueRef nodeStyleValues = topLevelObject["NodeStyle"]; + QJsonObject obj = nodeStyleValues.toObject(); + + _normalBoundaryColor = StyleImport::readColor(obj, "NormalBoundaryColor"); + _selectedBoundaryColor = StyleImport::readColor(obj, "SelectedBoundaryColor"); + _gradientColor0 = StyleImport::readColor(obj, "GradientColor0"); + _gradientColor1 = StyleImport::readColor(obj, "GradientColor1"); + _gradientColor2 = StyleImport::readColor(obj, "GradientColor2"); + _gradientColor3 = StyleImport::readColor(obj, "GradientColor3"); + _shadowColor = StyleImport::readColor(obj, "ShadowColor"); + _fontColor = StyleImport::readColor(obj, "FontColor"); + _fontColorFaded = StyleImport::readColor(obj, "FontColorFaded"); + _connectionPointColor = StyleImport::readColor(obj, "ConnectionPointColor"); + _filledConnectionPointColor = StyleImport::readColor(obj, "FilledConnectionPointColor"); + _warningColor = StyleImport::readColor(obj, "WarningColor"); + _errorColor = StyleImport::readColor(obj, "ErrorColor"); + + _penWidth = StyleImport::readFloat(obj, "PenWidth"); + _hoveredPenWidth = StyleImport::readFloat(obj, "HoveredPenWidth"); + _connectionPointDiameter = StyleImport::readFloat(obj, "ConnectionPointDiameter"); + + _opacity = StyleImport::readFloat(obj, "Opacity"); +} + + +NodeStyle const& +NodeStyle:: +defaultStyle() +{ + static NodeStyle const DefaultStyle = [] { + StyleImport::initResources(); + + return NodeStyle(StyleImport::readJsonFile(":DefaultStyle.json")); + }(); + + return DefaultStyle; +} + + +NodeStyle +NodeStyle:: +fromJson(QString const& jsonText) +{ + return NodeStyle(StyleImport::readJsonText(jsonText)); +} -inline void initResources() { Q_INIT_RESOURCE(resources); } NodeStyle:: NodeStyle() += default; + + +QColor +NodeStyle:: +normalBoundaryColor() const +{ + return _normalBoundaryColor; +} + + +QColor +NodeStyle:: +selectedBoundaryColor() const +{ + return _selectedBoundaryColor; +} + + +QColor +NodeStyle:: +gradientColor0() const +{ + return _gradientColor0; +} + + +QColor +NodeStyle:: +gradientColor1() const +{ + return _gradientColor1; +} + + +QColor +NodeStyle:: +gradientColor2() const { - // Explicit resources inialization for preventing the static initialization - // order fiasco: https://isocpp.org/wiki/faq/ctors#static-init-order - initResources(); + return _gradientColor2; +} + - // This configuration is stored inside the compiled unit and is loaded statically - loadJsonFile(":DefaultStyle.json"); +QColor +NodeStyle:: +gradientColor3() const +{ + return _gradientColor3; } +QColor NodeStyle:: -NodeStyle(QString jsonText) +shadowColor() const { - loadJsonText(jsonText); + return _shadowColor; } +QColor +NodeStyle:: +fontColor() const +{ + return _fontColor; +} + + +QColor +NodeStyle:: +fontColorFaded() const +{ + return _fontColorFaded; +} + + +QColor +NodeStyle:: +connectionPointColor() const +{ + return _connectionPointColor; +} + + +QColor +NodeStyle:: +filledConnectionPointColor() const +{ + return _filledConnectionPointColor; +} + + +QColor +NodeStyle:: +warningColor() const +{ + return _warningColor; +} + + +QColor +NodeStyle:: +errorColor() const +{ + return _errorColor; +} + + +float +NodeStyle:: +penWidth() const +{ + return _penWidth; +} + + +float +NodeStyle:: +hoveredPenWidth() const +{ + return _hoveredPenWidth; +} + + +float +NodeStyle:: +connectionPointDiameter() const +{ + return _connectionPointDiameter; +} + + +float +NodeStyle:: +opacity() const +{ + return _opacity; +} + void NodeStyle:: -setNodeStyle(QString jsonText) +setNormalBoundaryColor(QColor color) { - NodeStyle style(jsonText); + _normalBoundaryColor = std::move(color); +} - StyleCollection::setNodeStyle(style); +void +NodeStyle:: +setSelectedBoundaryColor(QColor color) +{ + _selectedBoundaryColor = std::move(color); } -#ifdef STYLE_DEBUG - #define NODE_STYLE_CHECK_UNDEFINED_VALUE(v, variable) { \ - if (v.type() == QJsonValue::Undefined || \ - v.type() == QJsonValue::Null) \ - qWarning() << "Undefined value for parameter:" << #variable; \ - } -#else - #define NODE_STYLE_CHECK_UNDEFINED_VALUE(v, variable) -#endif +void +NodeStyle:: +setGradientColor0(QColor color) +{ + _gradientColor0 = std::move(color); +} -#define NODE_STYLE_READ_COLOR(values, variable) { \ - auto valueRef = values[#variable]; \ - NODE_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (valueRef.isArray()) { \ - auto colorArray = valueRef.toArray(); \ - std::vector rgb; rgb.reserve(3); \ - for (auto it = colorArray.begin(); it != colorArray.end(); ++it) { \ - rgb.push_back((*it).toInt()); \ - } \ - variable = QColor(rgb[0], rgb[1], rgb[2]); \ - } else { \ - variable = QColor(valueRef.toString()); \ - } \ + +void +NodeStyle:: +setGradientColor1(QColor color) +{ + _gradientColor1 = std::move(color); } -#define NODE_STYLE_READ_FLOAT(values, variable) { \ - auto valueRef = values[#variable]; \ - NODE_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - variable = valueRef.toDouble(); \ + +void +NodeStyle:: +setGradientColor2(QColor color) +{ + _gradientColor2 = std::move(color); } + void NodeStyle:: -loadJsonFile(QString styleFile) +setGradientColor3(QColor color) { - QFile file(styleFile); + _gradientColor3 = std::move(color); +} - if (!file.open(QIODevice::ReadOnly)) - { - qWarning() << "Couldn't open file " << styleFile; - return; - } +void +NodeStyle:: +setShadowColor(QColor color) +{ + _shadowColor = std::move(color); +} + - loadJsonFromByteArray(file.readAll()); +void +NodeStyle:: +setFontColor(QColor color) +{ + _fontColor = std::move(color); } void NodeStyle:: -loadJsonText(QString jsonText) +setFontColorFaded(QColor color) { - loadJsonFromByteArray(jsonText.toUtf8()); + _fontColorFaded = std::move(color); } void NodeStyle:: -loadJsonFromByteArray(QByteArray const &byteArray) +setConnectionPointColor(QColor color) { - QJsonDocument json(QJsonDocument::fromJson(byteArray)); + _connectionPointColor = std::move(color); +} - QJsonObject topLevelObject = json.object(); - QJsonValueRef nodeStyleValues = topLevelObject["NodeStyle"]; +void +NodeStyle:: +setFilledConnectionPointColor(QColor color) +{ + _filledConnectionPointColor = std::move(color); +} + + +void +NodeStyle:: +setWarningColor(QColor color) +{ + _warningColor = std::move(color); +} + + +void +NodeStyle:: +setErrorColor(QColor color) +{ + _errorColor = std::move(color); +} + +void +NodeStyle:: +setPenWidth(float value) +{ + _penWidth = value; +} + + +void +NodeStyle:: +setHoveredPenWidth(float value) +{ + _hoveredPenWidth = value; +} - QJsonObject obj = nodeStyleValues.toObject(); - - NODE_STYLE_READ_COLOR(obj, NormalBoundaryColor); - NODE_STYLE_READ_COLOR(obj, SelectedBoundaryColor); - NODE_STYLE_READ_COLOR(obj, GradientColor0); - NODE_STYLE_READ_COLOR(obj, GradientColor1); - NODE_STYLE_READ_COLOR(obj, GradientColor2); - NODE_STYLE_READ_COLOR(obj, GradientColor3); - NODE_STYLE_READ_COLOR(obj, ShadowColor); - NODE_STYLE_READ_COLOR(obj, FontColor); - NODE_STYLE_READ_COLOR(obj, FontColorFaded); - NODE_STYLE_READ_COLOR(obj, ConnectionPointColor); - NODE_STYLE_READ_COLOR(obj, FilledConnectionPointColor); - NODE_STYLE_READ_COLOR(obj, WarningColor); - NODE_STYLE_READ_COLOR(obj, ErrorColor); - - NODE_STYLE_READ_FLOAT(obj, PenWidth); - NODE_STYLE_READ_FLOAT(obj, HoveredPenWidth); - NODE_STYLE_READ_FLOAT(obj, ConnectionPointDiameter); - - NODE_STYLE_READ_FLOAT(obj, Opacity); + +void +NodeStyle:: +setConnectionPointDiameter(float value) +{ + _connectionPointDiameter = value; +} + + +void +NodeStyle:: +setOpacity(float value) +{ + _opacity = value; } diff --git a/src/StyleCollection.cpp b/src/StyleCollection.cpp deleted file mode 100644 index 3f1d3d62..00000000 --- a/src/StyleCollection.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "StyleCollection.hpp" - -using QtNodes::StyleCollection; -using QtNodes::NodeStyle; -using QtNodes::ConnectionStyle; -using QtNodes::FlowViewStyle; - -NodeStyle const& -StyleCollection:: -nodeStyle() -{ - return instance()._nodeStyle; -} - - -ConnectionStyle const& -StyleCollection:: -connectionStyle() -{ - return instance()._connectionStyle; -} - - -FlowViewStyle const& -StyleCollection:: -flowViewStyle() -{ - return instance()._flowViewStyle; -} - - -void -StyleCollection:: -setNodeStyle(NodeStyle nodeStyle) -{ - instance()._nodeStyle = nodeStyle; -} - - -void -StyleCollection:: -setConnectionStyle(ConnectionStyle connectionStyle) -{ - instance()._connectionStyle = connectionStyle; -} - - -void -StyleCollection:: -setFlowViewStyle(FlowViewStyle flowViewStyle) -{ - instance()._flowViewStyle = flowViewStyle; -} - - - -StyleCollection& -StyleCollection:: -instance() -{ - static StyleCollection collection; - - return collection; -} diff --git a/src/StyleCollection.hpp b/src/StyleCollection.hpp deleted file mode 100644 index 71eb2902..00000000 --- a/src/StyleCollection.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "NodeStyle.hpp" -#include "ConnectionStyle.hpp" -#include "FlowViewStyle.hpp" - -namespace QtNodes -{ - -class StyleCollection -{ -public: - - static - NodeStyle const& - nodeStyle(); - - static - ConnectionStyle const& - connectionStyle(); - - static - FlowViewStyle const& - flowViewStyle(); - -public: - - static - void - setNodeStyle(NodeStyle); - - static - void - setConnectionStyle(ConnectionStyle); - - static - void - setFlowViewStyle(FlowViewStyle); - -private: - - StyleCollection() = default; - - StyleCollection(StyleCollection const&) = delete; - - StyleCollection& - operator=(StyleCollection const&) = delete; - - static - StyleCollection& - instance(); - -private: - - NodeStyle _nodeStyle; - - ConnectionStyle _connectionStyle; - - FlowViewStyle _flowViewStyle; -}; -} diff --git a/src/StyleImport.cpp b/src/StyleImport.cpp new file mode 100644 index 00000000..62cc05a8 --- /dev/null +++ b/src/StyleImport.cpp @@ -0,0 +1,178 @@ +#include "StyleImport.hpp" + +#include +#include +#include + +#include + +using QtNodes::StyleImport; + + +static +inline +void +initResources() +{ + // note: this function must be in the global namespace. + // Q_INIT_RESOURCE(...) requires it. + Q_INIT_RESOURCE(resources); +} + + +void +StyleImport:: +initResources() +{ + ::initResources(); +} + + +QByteArray +StyleImport:: +readJsonFile(QString const &fileName) +{ + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly)) + { + qWarning() << "Couldn't open file " << fileName; + + return QByteArray(); + } + + return file.readAll(); +} + + +QByteArray +StyleImport:: +readJsonText(QString const &jsonText) +{ + return jsonText.toUtf8(); +} + + +bool +StyleImport:: +hasValue(QJsonValue const &value, QString const &) +{ + return (value.type() != QJsonValue::Undefined + && value.type() != QJsonValue::Null); +} + + +void +StyleImport:: +checkUndefinedValue(QJsonValue const &value, QString const &name) +{ + if (!hasValue(value, name)) { + qWarning() << "Undefined value for parameter: " << name; + } +} + + +bool +StyleImport:: +readColor(QJsonObject const &obj, QString const &name, QColor *output) +{ + auto valueRef = obj[name]; + + if (StyleDebug) { + checkUndefinedValue(valueRef, name); + } + + if (!hasValue(valueRef, name)) return false; + + if (valueRef.isArray()) { + auto colors = valueRef.toArray(); + + *output = QColor(colors.at(0).toInt(), + colors.at(1).toInt(), + colors.at(2).toInt()); + } + else + { + *output = QColor(valueRef.toString()); + } + + return true; +} + + +bool +StyleImport:: +readFloat(QJsonObject const &obj, QString const &name, float *output) +{ + auto valueRef = obj[name]; + + if (StyleDebug) { + checkUndefinedValue(valueRef, name); + } + + if (!hasValue(valueRef, name)) return false; + + *output = valueRef.toDouble(); + + return true; +} + + +bool +StyleImport:: +readBool(QJsonObject const &obj, QString const &name, bool *output) +{ + auto valueRef = obj[name]; + + if (StyleDebug) { + checkUndefinedValue(valueRef, name); + } + + if (!hasValue(valueRef, name)) return false; + + *output = valueRef.toBool(); + + return true; +} + + +QColor +StyleImport:: +readColor(QJsonObject const &obj, QString const &name) +{ + QColor result; + + if (!readColor(obj, name, &result)) { + throw StyleImportError("Missing " + name.toStdString()); + } + + return result; +} + + +float +StyleImport:: +readFloat(QJsonObject const &obj, QString const &name) +{ + float result; + + if (!readFloat(obj, name, &result)) { + throw StyleImportError("Missing " + name.toStdString()); + } + + return result; +} + + +bool +StyleImport:: +readBool(QJsonObject const &obj, QString const &name) +{ + bool result; + + if (!readBool(obj, name, &result)) { + throw StyleImportError("Missing " + name.toStdString()); + } + + return result; +} diff --git a/src/StyleImport.hpp b/src/StyleImport.hpp new file mode 100644 index 00000000..6f8ad2f9 --- /dev/null +++ b/src/StyleImport.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include + +#include +#include +#include +#include + +namespace QtNodes +{ + +class StyleImportError : public std::logic_error +{ +public: + using std::logic_error::logic_error; +}; + +class StyleImport +{ +public: +#ifdef STYLE_DEBUG + static constexpr bool StyleDebug = true; +#else + static constexpr bool StyleDebug = false; +#endif + + static void + initResources(); + + static QByteArray + readJsonFile(QString const &fileName); + + static QByteArray + readJsonText(QString const &jsonText); + + static bool + hasValue(QJsonValue const &value, QString const &name); + + static void + checkUndefinedValue(QJsonValue const &vlaue, QString const &name); + + static bool + readColor(QJsonObject const &obj, QString const &name, QColor *output); + + static bool + readFloat(QJsonObject const &obj, QString const &name, float *output); + + static bool + readBool(QJsonObject const &obj, QString const &name, bool *output); + + static QColor + readColor(QJsonObject const &obj, QString const &name); + + static float + readFloat(QJsonObject const &obj, QString const &name); + + static bool + readBool(QJsonObject const &obj, QString const &name); +}; +}