summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleks Kissinger <aleks0@gmail.com>2018-04-21 22:53:05 +0200
committerAleks Kissinger <aleks0@gmail.com>2018-04-21 22:53:05 +0200
commitb00c5250d7a56b6d20980d89cf331a114fdfdee0 (patch)
tree5fef5c2a534cf150f9ae57cd20a90d6789bd3789 /src
parent9dd19037afd93d879ec32c5191314196f7f50592 (diff)
edge styles 90 percent
Diffstat (limited to 'src')
-rw-r--r--src/data/edge.cpp68
-rw-r--r--src/data/edge.h16
-rw-r--r--src/data/edgestyle.cpp6
-rw-r--r--src/gui/edgeitem.cpp56
-rw-r--r--src/gui/edgeitem.h2
-rw-r--r--src/gui/stylepalette.cpp11
-rw-r--r--src/gui/stylepalette.h1
-rw-r--r--src/gui/tikzscene.cpp7
-rw-r--r--src/gui/undocommands.cpp39
-rw-r--r--src/gui/undocommands.h11
10 files changed, 200 insertions, 17 deletions
diff --git a/src/data/edge.cpp b/src/data/edge.cpp
index d0f0deb..a18c8ea 100644
--- a/src/data/edge.cpp
+++ b/src/data/edge.cpp
@@ -16,6 +16,7 @@ Edge::Edge(Node *s, Node *t, QObject *parent) :
_inAngle = 0;
_outAngle = 0;
_weight = 0.4f;
+ _style = noneEdgeStyle;
updateControls();
}
@@ -43,6 +44,7 @@ Edge *Edge::copy(QMap<Node*,Node*> *nodeTable)
e->setInAngle(_inAngle);
e->setOutAngle(_outAngle);
e->setWeight(_weight);
+ e->attachStyle();
e->updateControls();
return e;
}
@@ -79,6 +81,19 @@ void Edge::setData(GraphElementData *data)
setAttributesFromData();
}
+QString Edge::styleName() const
+{
+ QString nm = _data->property("style");
+ if (nm.isNull()) return "none";
+ else return nm;
+}
+
+void Edge::setStyleName(const QString &styleName)
+{
+ if (!styleName.isNull() && styleName != "none") _data->setProperty("style", styleName);
+ else _data->unsetProperty("style");
+}
+
QString Edge::sourceAnchor() const
{
return _sourceAnchor;
@@ -142,15 +157,15 @@ void Edge::updateControls() {
if (_source->style()->isNone()) {
_tail = src;
} else {
- _tail = QPointF(src.x() + std::cos(outAngleR) * 0.1,
- src.y() + std::sin(outAngleR) * 0.1);
+ _tail = QPointF(src.x() + std::cos(outAngleR) * 0.2,
+ src.y() + std::sin(outAngleR) * 0.2);
}
if (_target->style()->isNone()) {
_head = targ;
} else {
- _head = QPointF(targ.x() + std::cos(inAngleR) * 0.1,
- targ.y() + std::sin(inAngleR) * 0.1);
+ _head = QPointF(targ.x() + std::cos(inAngleR) * 0.2,
+ targ.y() + std::sin(inAngleR) * 0.2);
}
// give a default distance for self-loops
@@ -163,12 +178,8 @@ void Edge::updateControls() {
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;
- //}
+ _tailTangent = bezierTangent(0.0f, 0.1f);
+ _headTangent = bezierTangent(1.0f, 0.9f);
}
void Edge::setAttributesFromData()
@@ -344,4 +355,41 @@ QPointF Edge::mid() const
return _mid;
}
+QPointF Edge::headTangent() const
+{
+ return _headTangent;
+}
+
+QPointF Edge::tailTangent() const
+{
+ return _tailTangent;
+}
+
+void Edge::attachStyle()
+{
+ QString nm = styleName();
+ if (nm.isNull()) _style = noneEdgeStyle;
+ else _style = tikzit->styles()->edgeStyle(nm);
+}
+EdgeStyle * Edge::style() const
+{
+ return _style;
+}
+
+QPointF Edge::bezierTangent(float start, float end) const
+{
+ float dx = bezierInterpolate(end, _tail.x(), _cp1.x(), _cp2.x(), _head.x()) -
+ bezierInterpolate(start, _tail.x(), _cp1.x(), _cp2.x(), _head.x());
+ float dy = bezierInterpolate(end, _tail.y(), _cp1.y(), _cp2.y(), _head.y()) -
+ bezierInterpolate(start, _tail.y(), _cp1.y(), _cp2.y(), _head.y());
+
+ // normalise
+ float len = sqrt(dx*dx + dy * dy);
+ if (len != 0) {
+ dx = (dx / len) * 0.1f;
+ dy = (dy / len) * 0.1f;
+ }
+
+ return QPointF(dx, dy);
+}
diff --git a/src/data/edge.h b/src/data/edge.h
index 7df899f..3dc0211 100644
--- a/src/data/edge.h
+++ b/src/data/edge.h
@@ -3,6 +3,7 @@
#include "graphelementdata.h"
#include "node.h"
+#include "edgestyle.h"
#include <QObject>
#include <QPointF>
@@ -43,6 +44,8 @@ public:
QPointF cp1() const;
QPointF cp2() const;
QPointF mid() const;
+ QPointF headTangent() const;
+ QPointF tailTangent() const;
int bend() const;
int inAngle() const;
@@ -60,11 +63,18 @@ public:
int tikzLine() const;
void setTikzLine(int tikzLine);
+
+ void attachStyle();
+ QString styleName() const;
+ void setStyleName(const QString & styleName);
+ EdgeStyle *style() const;
+
signals:
public slots:
private:
+ QPointF bezierTangent(float start, float end) const;
QString _sourceAnchor;
QString _targetAnchor;
@@ -76,6 +86,9 @@ private:
Node *_source;
Node *_target;
+
+ EdgeStyle *_style;
+
bool _dirty;
bool _basicBendMode;
int _bend;
@@ -90,6 +103,9 @@ private:
QPointF _cp2;
QPointF _mid;
+ QPointF _headTangent;
+ QPointF _tailTangent;
+
int _tikzLine;
};
diff --git a/src/data/edgestyle.cpp b/src/data/edgestyle.cpp
index d366946..9fb2638 100644
--- a/src/data/edgestyle.cpp
+++ b/src/data/edgestyle.cpp
@@ -41,7 +41,7 @@ EdgeStyle::DrawStyle EdgeStyle::drawStyle() const
QPen EdgeStyle::pen() const
{
QPen p(strokeColor());
- p.setWidthF((float)strokeThickness() * 3.0f);
+ p.setWidthF((float)strokeThickness() * 2.0f);
QVector<qreal> pat;
switch (drawStyle()) {
@@ -84,6 +84,10 @@ QIcon EdgeStyle::icon() const
painter.drawLine(10, 50, 90, 50);
+ QPen pn = pen();
+ pn.setStyle(Qt::SolidLine);
+ painter.setPen(pn);
+
switch (arrowHead()) {
case Pointer:
painter.drawLine(90,50,80,40);
diff --git a/src/gui/edgeitem.cpp b/src/gui/edgeitem.cpp
index 88a4e85..de51db3 100644
--- a/src/gui/edgeitem.cpp
+++ b/src/gui/edgeitem.cpp
@@ -50,12 +50,61 @@ void EdgeItem::readPos()
void EdgeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
//QGraphicsPathItem::paint(painter, option, widget);
- QPen pen(Qt::black);
- pen.setWidth(2);
- painter->setPen(pen);
+ QPen pen = _edge->style()->pen();
+ painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
painter->drawPath(path());
+ QPointF ht = _edge->headTangent();
+ QPointF hLeft(-ht.y(), ht.x());
+ QPointF hRight(ht.y(), -ht.x());
+ QPointF tt = _edge->tailTangent();
+ QPointF tLeft(-ht.y(), ht.x());
+ QPointF tRight(ht.y(), -ht.x());
+
+ pen.setStyle(Qt::SolidLine);
+ painter->setPen(pen);
+
+
+
+ switch (_edge->style()->arrowHead()) {
+ case EdgeStyle::Flat:
+ {
+ painter->drawLine(
+ toScreen(_edge->head() + hLeft),
+ toScreen(_edge->head() + hRight));
+ break;
+ }
+ case EdgeStyle::Pointer:
+ {
+ QPainterPath pth;
+ pth.moveTo(toScreen(_edge->head() + ht + hLeft));
+ pth.lineTo(toScreen(_edge->head()));
+ pth.lineTo(toScreen(_edge->head() + ht + hRight));
+ painter->drawPath(pth);
+ break;
+ }
+ }
+
+ switch (_edge->style()->arrowTail()) {
+ case EdgeStyle::Flat:
+ {
+ painter->drawLine(
+ toScreen(_edge->tail() + tLeft),
+ toScreen(_edge->tail() + tRight));
+ break;
+ }
+ case EdgeStyle::Pointer:
+ {
+ QPainterPath pth;
+ pth.moveTo(toScreen(_edge->tail() + tt + tLeft));
+ pth.lineTo(toScreen(_edge->tail()));
+ pth.lineTo(toScreen(_edge->tail() + tt + tRight));
+ painter->drawPath(pth);
+ break;
+ }
+ }
+
if (isSelected()) {
QColor draw;
QColor draw1;
@@ -151,3 +200,4 @@ void EdgeItem::setPath(const QPainterPath &path)
update();
}
+
diff --git a/src/gui/edgeitem.h b/src/gui/edgeitem.h
index 5641912..948f137 100644
--- a/src/gui/edgeitem.h
+++ b/src/gui/edgeitem.h
@@ -13,6 +13,7 @@
#include <QStyleOptionGraphicsItem>
#include <QWidget>
#include <QGraphicsEllipseItem>
+#include <QString>
class EdgeItem : public QGraphicsItem
{
@@ -30,6 +31,7 @@ public:
QPainterPath path() const;
void setPath(const QPainterPath &path);
+
private:
Edge *_edge;
QPainterPath _path;
diff --git a/src/gui/stylepalette.cpp b/src/gui/stylepalette.cpp
index f7c17c0..f1462df 100644
--- a/src/gui/stylepalette.cpp
+++ b/src/gui/stylepalette.cpp
@@ -114,6 +114,17 @@ QString StylePalette::activeNodeStyleName()
}
}
+QString StylePalette::activeEdgeStyleName()
+{
+ const QModelIndexList i = ui->edgeStyleListView->selectionModel()->selectedIndexes();
+
+ if (i.isEmpty()) {
+ return "none";
+ } else {
+ return i[0].data().toString();
+ }
+}
+
void StylePalette::nodeStyleDoubleClicked(const QModelIndex &index)
{
tikzit->activeWindow()->tikzScene()->applyActiveStyleToNodes();
diff --git a/src/gui/stylepalette.h b/src/gui/stylepalette.h
index 8663cc4..cc8fb73 100644
--- a/src/gui/stylepalette.h
+++ b/src/gui/stylepalette.h
@@ -19,6 +19,7 @@ public:
void nextNodeStyle();
void previousNodeStyle();
QString activeNodeStyleName();
+ QString activeEdgeStyleName();
public slots:
diff --git a/src/gui/tikzscene.cpp b/src/gui/tikzscene.cpp
index bc55ada..3c8fb71 100644
--- a/src/gui/tikzscene.cpp
+++ b/src/gui/tikzscene.cpp
@@ -71,6 +71,7 @@ void TikzScene::graphReplaced()
_edgeItems.clear();
foreach (Edge *e, graph()->edges()) {
+ e->attachStyle();
EdgeItem *ei = new EdgeItem(e);
_edgeItems.insert(e, ei);
addItem(ei);
@@ -420,6 +421,7 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
case ToolPalette::EDGE:
if (_edgeStartNodeItem != 0 && _edgeEndNodeItem != 0) {
Edge *e = new Edge(_edgeStartNodeItem->node(), _edgeEndNodeItem->node(), _tikzDocument);
+ e->setStyleName(_styles->activeEdgeStyleName());
AddEdgeCommand *cmd = new AddEdgeCommand(this, e);
_tikzDocument->undoStack()->push(cmd);
}
@@ -687,6 +689,11 @@ void TikzScene::setTikzDocument(TikzDocument *tikzDocument)
void TikzScene::reloadStyles()
{
_styles->reloadStyles();
+ foreach(EdgeItem *ei, _edgeItems) {
+ ei->edge()->attachStyle();
+ ei->readPos(); // trigger a repaint
+ }
+
foreach (NodeItem *ni, _nodeItems) {
ni->node()->attachStyle();
ni->readPos(); // trigger a repaint
diff --git a/src/gui/undocommands.cpp b/src/gui/undocommands.cpp
index baa8c0e..5ce6941 100644
--- a/src/gui/undocommands.cpp
+++ b/src/gui/undocommands.cpp
@@ -130,6 +130,7 @@ void DeleteCommand::undo()
for (auto it = _deleteEdges.begin(); it != _deleteEdges.end(); ++it) {
Edge *e = it.value();
+ e->attachStyle();
_scene->graph()->addEdge(e, it.key());
EdgeItem *ei = new EdgeItem(e);
_scene->edgeItems().insert(e, ei);
@@ -185,7 +186,7 @@ void AddNodeCommand::undo()
void AddNodeCommand::redo()
{
- _node->attachStyle(); // in case styles have changed
+ _node->attachStyle(); // do for every redo, in case styles have changed
_scene->graph()->addNode(_node);
NodeItem *ni = new NodeItem(_node);
_scene->nodeItems().insert(_node, ni);
@@ -214,12 +215,13 @@ void AddEdgeCommand::undo()
void AddEdgeCommand::redo()
{
- // TODO: get the current style
+ _edge->attachStyle(); // do for every redo, in case styles have changed
_scene->graph()->addEdge(_edge);
EdgeItem *ei = new EdgeItem(_edge);
_scene->edgeItems().insert(_edge, ei);
_scene->addItem(ei);
+ // TODO: deal consistently with stacking order
// edges should always be stacked below nodes
if (!_scene->graph()->nodes().isEmpty()) {
ei->stackBefore(_scene->nodeItems()[_scene->graph()->nodes().first()]);
@@ -235,7 +237,8 @@ ChangeEdgeModeCommand::ChangeEdgeModeCommand(TikzScene *scene, Edge *edge, QUndo
void ChangeEdgeModeCommand::undo()
{
- _edge->setBasicBendMode(!_edge->basicBendMode());
+ // FIXME: this act strangely sometimes
+ _edge->setBasicBendMode(!_edge->basicBendMode());
_scene->edgeItems()[_edge]->readPos();
GraphUpdateCommand::undo();
}
@@ -276,6 +279,35 @@ void ApplyStyleToNodesCommand::redo()
GraphUpdateCommand::redo();
}
+ApplyStyleToEdgesCommand::ApplyStyleToEdgesCommand(TikzScene *scene, QString style, QUndoCommand *parent) :
+ GraphUpdateCommand(scene, parent), _style(style), _oldStyles()
+{
+ foreach(QGraphicsItem *it, scene->selectedItems()) {
+ if (EdgeItem *ei = dynamic_cast<EdgeItem*>(it)) {
+ _oldStyles.insert(ei->edge(), ei->edge()->styleName());
+ }
+ }
+}
+
+void ApplyStyleToEdgesCommand::undo()
+{
+ foreach(Edge *e, _oldStyles.keys()) {
+ e->setStyleName(_oldStyles[e]);
+ e->attachStyle();
+ }
+
+ GraphUpdateCommand::undo();
+}
+
+void ApplyStyleToEdgesCommand::redo()
+{
+ foreach(Edge *e, _oldStyles.keys()) {
+ e->setStyleName(_style);
+ e->attachStyle();
+ }
+ GraphUpdateCommand::redo();
+}
+
PasteCommand::PasteCommand(TikzScene *scene, Graph *graph, QUndoCommand *parent) :
GraphUpdateCommand(scene, parent), _graph(graph)
{
@@ -316,6 +348,7 @@ void PasteCommand::redo()
_scene->graph()->insertGraph(_graph);
foreach (Edge *e, _graph->edges()) {
+ e->attachStyle(); // in case styles have changed
EdgeItem *ei = new EdgeItem(e);
_scene->edgeItems().insert(e, ei);
_scene->addItem(ei);
diff --git a/src/gui/undocommands.h b/src/gui/undocommands.h
index 3f74afb..ad76479 100644
--- a/src/gui/undocommands.h
+++ b/src/gui/undocommands.h
@@ -120,6 +120,17 @@ private:
QMap<Node*,QString> _oldStyles;
};
+class ApplyStyleToEdgesCommand : public GraphUpdateCommand
+{
+public:
+ explicit ApplyStyleToEdgesCommand(TikzScene *scene, QString style, QUndoCommand *parent = 0);
+ void undo() override;
+ void redo() override;
+private:
+ QString _style;
+ QMap<Edge*, QString> _oldStyles;
+};
+
class PasteCommand : public GraphUpdateCommand
{
public: