diff options
author | Aleks Kissinger <aleks0@gmail.com> | 2017-02-28 14:46:39 +0100 |
---|---|---|
committer | Aleks Kissinger <aleks0@gmail.com> | 2017-02-28 14:46:39 +0100 |
commit | cb322a3acee9debf40c48ad1e3fb4458b0f51b7f (patch) | |
tree | 2cd3dc1060885152f0c706e0cf52bff0d8181d1e /tikzit/src/data | |
parent | e1756ba69dd626073e22fd0a4f4c5fda42c88829 (diff) |
generic nodes
Diffstat (limited to 'tikzit/src/data')
-rw-r--r-- | tikzit/src/data/edge.cpp | 211 | ||||
-rw-r--r-- | tikzit/src/data/edge.h | 35 | ||||
-rw-r--r-- | tikzit/src/data/node.cpp | 25 | ||||
-rw-r--r-- | tikzit/src/data/node.h | 9 | ||||
-rw-r--r-- | tikzit/src/data/nodestyle.cpp | 30 | ||||
-rw-r--r-- | tikzit/src/data/nodestyle.h | 26 |
6 files changed, 336 insertions, 0 deletions
diff --git a/tikzit/src/data/edge.cpp b/tikzit/src/data/edge.cpp index 9068a1c..b999f8a 100644 --- a/tikzit/src/data/edge.cpp +++ b/tikzit/src/data/edge.cpp @@ -1,12 +1,22 @@ #include "edge.h" +#include "tikzit.h" #include <QDebug> +#include <QPointF> +#include <cmath> Edge::Edge(Node *s, Node *t, QObject *parent) : QObject(parent), _source(s), _target(t) { _data = new GraphElementData(); _edgeNode = 0; + _dirty = true; + _basicBendMode = true; + _bend = 0; + _inAngle = 0; + _outAngle = 0; + _weight = 0.4f; + updateControls(); } Edge::~Edge() @@ -25,6 +35,16 @@ Node *Edge::target() const return _target; } +bool Edge::isSelfLoop() +{ + return (_source == _target); +} + +bool Edge::isStraight() +{ + return (_basicBendMode && _bend == 0); +} + GraphElementData *Edge::data() const { return _data; @@ -34,6 +54,7 @@ void Edge::setData(GraphElementData *data) { delete _data; _data = data; + setAttributesFromData(); } QString Edge::sourceAnchor() const @@ -72,4 +93,194 @@ bool Edge::hasEdgeNode() return _edgeNode != 0; } +void Edge::updateControls() { + //if (_dirty) { + QPointF src = _source->point(); + QPointF targ = _target->point(); + + float dx = (targ.x() - src.x()); + float dy = (targ.y() - src.y()); + + float outAngleR = 0.0f; + float inAngleR = 0.0f; + + if (_basicBendMode) { + float angle = std::atan2(dy, dx); + float bnd = (float)_bend * (M_PI / 180.0f); + outAngleR = angle - bnd; + inAngleR = M_PI + angle + bnd; + _outAngle = outAngleR * (180.f / M_PI); + _inAngle = inAngleR * (180.f / M_PI); + } else { + outAngleR = (float)_outAngle * (M_PI / 180.0f); + inAngleR = (float)_inAngle * (M_PI / 180.0f); + } + + // TODO: calculate head and tail properly, not just for circles + if (_source->style().isNone()) { + _tail = src; + } else { + _tail = QPointF(src.x() + std::cos(outAngleR) * 0.1, + src.y() + std::sin(outAngleR) * 0.1); + } + + if (_target->style().isNone()) { + _head = targ; + } else { + _head = QPointF(targ.x() + std::cos(inAngleR) * 0.1, + targ.y() + std::sin(inAngleR) * 0.1); + } + + // give a default distance for self-loops + _cpDist = (dx==0.0f && dy==0.0f) ? _weight : std::sqrt(dx*dx + dy*dy) * _weight; + + _cp1 = QPointF(src.x() + (_cpDist * std::cos(outAngleR)), + src.y() + (_cpDist * std::sin(outAngleR))); + + _cp2 = QPointF(targ.x() + (_cpDist * std::cos(inAngleR)), + targ.y() + (_cpDist * std::sin(inAngleR))); + + _mid = bezierInterpolateFull (0.5f, _tail, _cp1, _cp2, _head); +// midTan = [self _findTanFor:mid usingSpanFrom:0.4f to:0.6f]; + +// tailTan = [self _findTanFor:tail usingSpanFrom:0.0f to:0.1f]; +// headTan = [self _findTanFor:head usingSpanFrom:1.0f to:0.9f]; + //_dirty = false; + //} +} + +void Edge::setAttributesFromData() +{ + _basicBendMode = true; + bool ok = true; + + if (_data->atom("bend left")) { + _bend = -30; + } else if (_data->atom("bend right")) { + _bend = 30; + } else if (_data->property("bend left") != 0) { + _bend = -_data->property("bend left").toInt(&ok); + if (!ok) _bend = -30; + } else if (_data->property("bend right") != 0) { + _bend = _data->property("bend right").toInt(&ok); + if (!ok) _bend = 30; + } else { + _bend = 0; + + if (_data->property("in") != 0 && _data->property("out") != 0) { + _basicBendMode = false; + _inAngle = _data->property("in").toInt(&ok); + if (!ok) _inAngle = 0; + _outAngle = _data->property("out").toInt(&ok); + if (!ok) _outAngle = 180; + } + } + + if (_data->property("looseness") != 0) { + _weight = _data->property("looseness").toFloat(&ok) / 2.5f; + if (!ok) _weight = 0.4f; + } else { + _weight = (isSelfLoop()) ? 1.0f : 0.4f; + } + + //qDebug() << "bend: " << _bend << " in: " << _inAngle << " out: " << _outAngle; + _dirty = true; +} + +void Edge::updateData() +{ + _data->unsetAtom("loop"); + _data->unsetProperty("in"); + _data->unsetProperty("out"); + _data->unsetAtom("bend left"); + _data->unsetAtom("bend right"); + _data->unsetProperty("bend left"); + _data->unsetProperty("bend right"); + _data->unsetProperty("looseness"); + + // TODO: style handling? + + if (_basicBendMode && _bend != 0) { + QString bendKey; + int b; + if (_bend < 0) { + bendKey = "bend left"; + b = -_bend; + } else { + bendKey = "bend right"; + b = _bend; + } + + if (b == 30) { + _data->setAtom(bendKey); + } else { + _data->setProperty(bendKey, QString::number(b)); + } + } else { + _data->setProperty("in", QString::number(_inAngle)); + _data->setProperty("out", QString::number(_outAngle)); + } + + if (_source == _target) _data->setAtom("loop"); + if (!isSelfLoop() && !isStraight() && _weight != 0.4f) + _data->setProperty("looseness", QString::number(_weight*2.5f, 'f', 2)); + +} + + +QPointF Edge::head() const +{ + return _head; +} + +QPointF Edge::tail() const +{ + return _tail; +} + +QPointF Edge::cp1() const +{ + return _cp1; +} + +QPointF Edge::cp2() const +{ + return _cp2; +} + +int Edge::bend() const +{ + return _bend; +} + +int Edge::inAngle() const +{ + return _inAngle; +} + +int Edge::outAngle() const +{ + return _outAngle; +} + +float Edge::weight() const +{ + return _weight; +} + +bool Edge::basicBendMode() const +{ + return _basicBendMode; +} + +float Edge::cpDist() const +{ + return _cpDist; +} + +QPointF Edge::mid() const +{ + return _mid; +} + diff --git a/tikzit/src/data/edge.h b/tikzit/src/data/edge.h index 9655e98..e392c56 100644 --- a/tikzit/src/data/edge.h +++ b/tikzit/src/data/edge.h @@ -5,6 +5,7 @@ #include "node.h" #include <QObject> +#include <QPointF> class Edge : public QObject { @@ -16,6 +17,9 @@ public: Node *source() const; Node *target() const; + bool isSelfLoop(); + bool isStraight(); + GraphElementData *data() const; void setData(GraphElementData *data); @@ -29,6 +33,23 @@ public: void setEdgeNode(Node *edgeNode); bool hasEdgeNode(); + void updateControls(); + void setAttributesFromData(); + void updateData(); + + QPointF head() const; + QPointF tail() const; + QPointF cp1() const; + QPointF cp2() const; + QPointF mid() const; + + int bend() const; + int inAngle() const; + int outAngle() const; + float weight() const; + bool basicBendMode() const; + float cpDist() const; + signals: public slots: @@ -44,6 +65,20 @@ private: // referenced Node *_source; Node *_target; + + bool _dirty; + bool _basicBendMode; + int _bend; + int _inAngle; + int _outAngle; + float _weight; + float _cpDist; + + QPointF _head; + QPointF _tail; + QPointF _cp1; + QPointF _cp2; + QPointF _mid; }; #endif // EDGE_H diff --git a/tikzit/src/data/node.cpp b/tikzit/src/data/node.cpp index b3b2155..1b8ccf8 100644 --- a/tikzit/src/data/node.cpp +++ b/tikzit/src/data/node.cpp @@ -1,10 +1,13 @@ #include "node.h" +#include "tikzit.h" #include <QDebug> Node::Node(QObject *parent) : QObject(parent) { _data = new GraphElementData(); + _style = NodeStyle(); + _styleName = "none"; } Node::~Node() @@ -51,5 +54,27 @@ void Node::setData(GraphElementData *data) { delete _data; _data = data; + if (_data->property("style") != 0) _styleName = _data->property("style"); +} + +QString Node::styleName() const +{ + return _styleName; +} + +void Node::setStyleName(const QString &styleName) +{ + _styleName = styleName; +} + +void Node::attachStyle() +{ + if (_styleName == "none") _style = NodeStyle(); + else _style = tikzit->nodeStyle(_styleName); +} + +NodeStyle Node::style() const +{ + return _style; } diff --git a/tikzit/src/data/node.h b/tikzit/src/data/node.h index e72e9a7..91b1725 100644 --- a/tikzit/src/data/node.h +++ b/tikzit/src/data/node.h @@ -2,6 +2,7 @@ #define NODE_H #include "graphelementdata.h" +#include "nodestyle.h" #include <QObject> #include <QPointF> @@ -26,6 +27,12 @@ public: GraphElementData *data() const; void setData(GraphElementData *data); + QString styleName() const; + void setStyleName(const QString &styleName); + + void attachStyle(); + NodeStyle style() const; + signals: public slots: @@ -34,6 +41,8 @@ private: QPointF _point; QString _name; QString _label; + QString _styleName; + NodeStyle _style; GraphElementData *_data; }; diff --git a/tikzit/src/data/nodestyle.cpp b/tikzit/src/data/nodestyle.cpp new file mode 100644 index 0000000..109e2af --- /dev/null +++ b/tikzit/src/data/nodestyle.cpp @@ -0,0 +1,30 @@ +#include "nodestyle.h" + +NodeStyle::NodeStyle() +{ + name = "none"; + shape = NodeShape::Circle; + fillColor = Qt::white; + strokeColor = Qt::black; + strokeThickness = 1; +} + +NodeStyle::NodeStyle(QString nm, NodeShape sh, QColor fillCol) +{ + name = nm; + shape = sh; + fillColor = fillCol; + strokeColor = Qt::black; + strokeThickness = 1; +} + +NodeStyle::NodeStyle(QString nm, NodeShape sh, QColor fillCol, QColor strokeCol, int strokeThick) +{ + name = nm; + shape = sh; + fillColor = fillCol; + strokeColor = strokeCol; + strokeThickness = strokeThick; +} + +bool NodeStyle::isNone() { return name == "none"; } diff --git a/tikzit/src/data/nodestyle.h b/tikzit/src/data/nodestyle.h new file mode 100644 index 0000000..baf967c --- /dev/null +++ b/tikzit/src/data/nodestyle.h @@ -0,0 +1,26 @@ +#ifndef NODESTYLE_H +#define NODESTYLE_H + +#include <QColor> + +enum NodeShape { + Square, UpTriangle, DownTriangle, Circle +}; + +class NodeStyle +{ +public: + NodeStyle(); + NodeStyle(QString nm, NodeShape sh, QColor fillCol); + NodeStyle(QString nm, NodeShape sh, QColor fillCol, QColor strokeCol, int strokeThick); + bool isNone(); + QString name; + NodeShape shape; + QColor fillColor; + QColor strokeColor; + int strokeThickness; +}; + +extern NodeStyle noneStyle; + +#endif // NODESTYLE_H |