ui: styled edges in graph view
This change styles the edges in the QtGraphView. They get drawn with vertical and horizontal parts and rounded corners.
This commit is contained in:
@@ -87,41 +87,45 @@ void QtGraphView::doRebuildGraph(
|
||||
m_activeTokenIds = activeTokenIds;
|
||||
QGraphicsView* view = getView();
|
||||
|
||||
if (view != NULL)
|
||||
{
|
||||
// Temporary stores all nodes (existing and newly created) needed in the new graph
|
||||
// this is a relatively easy and cheap way to save existing nodes that are still needed
|
||||
std::list<std::shared_ptr<QtGraphNode>> newNodes;
|
||||
|
||||
// create nodes (or find existing nodes for re-use)
|
||||
for (unsigned int i = 0; i < nodes.size(); i++)
|
||||
{
|
||||
std::shared_ptr<QtGraphNode> newNode = createNodeRecursive(view, NULL, nodes[i]);
|
||||
newNode->setPosition(nodes[i].position);
|
||||
newNodes.push_back(newNode);
|
||||
}
|
||||
|
||||
doClear();
|
||||
m_nodes = newNodes;
|
||||
|
||||
for (unsigned int i = 0; i < edges.size(); i++)
|
||||
{
|
||||
std::shared_ptr<QtGraphEdge> edge = createEdge(view, edges[i]);
|
||||
if (edge != NULL)
|
||||
{
|
||||
m_edges.push_back(edge);
|
||||
}
|
||||
}
|
||||
|
||||
// hide node content by default, must be done after all edges are created to keep subnodes with connections visible
|
||||
for (const std::shared_ptr<QtGraphNode>& node : m_nodes)
|
||||
{
|
||||
node->hideContent();
|
||||
}
|
||||
}
|
||||
else
|
||||
if (view == NULL)
|
||||
{
|
||||
LOG_WARNING("Failed to get QGraphicsView");
|
||||
return;
|
||||
}
|
||||
|
||||
// Temporary stores all nodes (existing and newly created) needed in the new graph
|
||||
// this is a relatively easy and cheap way to save existing nodes that are still needed
|
||||
std::list<std::shared_ptr<QtGraphNode>> newNodes;
|
||||
|
||||
// create nodes (or find existing nodes for re-use)
|
||||
for (unsigned int i = 0; i < nodes.size(); i++)
|
||||
{
|
||||
std::shared_ptr<QtGraphNode> newNode = createNodeRecursive(view, NULL, nodes[i]);
|
||||
newNode->setPosition(nodes[i].position);
|
||||
newNodes.push_back(newNode);
|
||||
}
|
||||
|
||||
doClear();
|
||||
m_nodes = newNodes;
|
||||
|
||||
for (unsigned int i = 0; i < edges.size(); i++)
|
||||
{
|
||||
std::shared_ptr<QtGraphEdge> edge = createEdge(view, edges[i]);
|
||||
if (edge != NULL)
|
||||
{
|
||||
m_edges.push_back(edge);
|
||||
}
|
||||
}
|
||||
|
||||
// hide node content by default, must be done after all edges are created to keep subnodes with connections visible
|
||||
for (const std::shared_ptr<QtGraphNode>& node : m_nodes)
|
||||
{
|
||||
node->hideContent();
|
||||
}
|
||||
|
||||
for (const std::shared_ptr<QtGraphEdge>& edge : m_edges)
|
||||
{
|
||||
edge->updateLine();
|
||||
}
|
||||
|
||||
m_graph = graph;
|
||||
@@ -155,82 +159,71 @@ std::shared_ptr<QtGraphNode> QtGraphView::findNodeRecursive(const std::list<std:
|
||||
std::shared_ptr<QtGraphNode> QtGraphView::createNodeRecursive(
|
||||
QGraphicsView* view, std::shared_ptr<QtGraphNode> parentNode, const DummyNode& node
|
||||
){
|
||||
if (view != NULL)
|
||||
std::shared_ptr<QtGraphNode> newNode;
|
||||
if (node.data)
|
||||
{
|
||||
std::shared_ptr<QtGraphNode> newNode;
|
||||
if (node.data)
|
||||
{
|
||||
newNode = std::make_shared<QtGraphNode>(node.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNode = std::make_shared<QtGraphNodeAccess>(node.accessType);
|
||||
}
|
||||
|
||||
newNode->addComponent(std::make_shared<QtGraphNodeComponentClickable>(newNode));
|
||||
|
||||
view->scene()->addItem(newNode.get());
|
||||
|
||||
if (node.data && isActiveTokenId(node.data->getId()))
|
||||
{
|
||||
newNode->setIsActive(true);
|
||||
}
|
||||
|
||||
if (parentNode)
|
||||
{
|
||||
newNode->setParent(parentNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNode->addComponent(std::make_shared<QtGraphNodeComponentMoveable>(newNode));
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node.subNodes.size(); i++)
|
||||
{
|
||||
std::shared_ptr<QtGraphNode> subNode = createNodeRecursive(view, newNode, node.subNodes[i]);
|
||||
newNode->addSubNode(subNode);
|
||||
}
|
||||
|
||||
return newNode;
|
||||
newNode = std::make_shared<QtGraphNode>(node.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("Received pointer to QGraphicsView was NULL. No node created.");
|
||||
return std::shared_ptr<QtGraphNode>();
|
||||
newNode = std::make_shared<QtGraphNodeAccess>(node.accessType);
|
||||
}
|
||||
|
||||
newNode->addComponent(std::make_shared<QtGraphNodeComponentClickable>(newNode));
|
||||
|
||||
view->scene()->addItem(newNode.get());
|
||||
|
||||
if (node.data && isActiveTokenId(node.data->getId()))
|
||||
{
|
||||
newNode->setIsActive(true);
|
||||
}
|
||||
|
||||
if (parentNode)
|
||||
{
|
||||
newNode->setParent(parentNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNode->addComponent(std::make_shared<QtGraphNodeComponentMoveable>(newNode));
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node.subNodes.size(); i++)
|
||||
{
|
||||
std::shared_ptr<QtGraphNode> subNode = createNodeRecursive(view, newNode, node.subNodes[i]);
|
||||
newNode->addSubNode(subNode);
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
std::shared_ptr<QtGraphEdge> QtGraphView::createEdge(QGraphicsView* view, const DummyEdge& edge)
|
||||
{
|
||||
if (view != NULL)
|
||||
std::shared_ptr<QtGraphNode> owner = findNodeRecursive(m_nodes, edge.ownerId);
|
||||
std::shared_ptr<QtGraphNode> target = findNodeRecursive(m_nodes, edge.targetId);
|
||||
|
||||
if (owner != NULL && target != NULL)
|
||||
{
|
||||
std::shared_ptr<QtGraphNode> owner = findNodeRecursive(m_nodes, edge.ownerId);
|
||||
std::shared_ptr<QtGraphNode> target = findNodeRecursive(m_nodes, edge.targetId);
|
||||
std::shared_ptr<QtGraphEdge> qtEdge = std::make_shared<QtGraphEdge>(owner, target, edge.data);
|
||||
bool added = owner->addOutEdge(qtEdge) | target->addInEdge(qtEdge);
|
||||
|
||||
if (owner != NULL && target != NULL)
|
||||
if (!added)
|
||||
{
|
||||
std::shared_ptr<QtGraphEdge> qtEdge = std::make_shared<QtGraphEdge>(owner, target, edge.data);
|
||||
owner->addOutEdge(qtEdge);
|
||||
target->addInEdge(qtEdge);
|
||||
view->scene()->addItem(qtEdge.get());
|
||||
|
||||
if (isActiveTokenId(edge.data->getId()))
|
||||
{
|
||||
qtEdge->setIsActive(true);
|
||||
}
|
||||
|
||||
return qtEdge;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
|
||||
view->scene()->addItem(qtEdge.get());
|
||||
|
||||
if (isActiveTokenId(edge.data->getId()))
|
||||
{
|
||||
LOG_WARNING("Couldn't find owner or target node.");
|
||||
return std::shared_ptr<QtGraphEdge>();
|
||||
qtEdge->setIsActive(true);
|
||||
}
|
||||
|
||||
return qtEdge;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("Received pointer to QGraphicsView was NULL. No node created.");
|
||||
return std::shared_ptr<QtGraphEdge>();
|
||||
LOG_WARNING("Couldn't find owner or target node.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ private:
|
||||
std::shared_ptr<Graph> m_graph;
|
||||
std::vector<Id> m_activeTokenIds;
|
||||
|
||||
std::list<std::shared_ptr<QtGraphEdge>> m_edges;
|
||||
std::list<std::shared_ptr<QtGraphNode>> m_nodes;
|
||||
std::list<std::weak_ptr<QtGraphEdge>> m_edges;
|
||||
};
|
||||
|
||||
#endif // QT_GRAPH_VIEW_H
|
||||
|
||||
@@ -2,130 +2,336 @@
|
||||
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneEvent>
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
|
||||
#include "component/view/graphElements/GraphNode.h"
|
||||
|
||||
|
||||
QtStraightConnection::QtStraightConnection(Vec4i ownerRect, Vec4i targetRect, QGraphicsItem* parent)
|
||||
: QGraphicsLineItem(parent)
|
||||
{
|
||||
const Vec4i& o = ownerRect;
|
||||
const Vec4i& t = targetRect;
|
||||
|
||||
Vec2f po[2] = { Vec2f(o.x, (o.y + 2 * o.w) / 3), Vec2f(o.z, (o.y + 2 * o.w) / 3) };
|
||||
Vec2f pt[2] = { Vec2f(t.x, (2 * t.y + t.w) / 3), Vec2f(t.z, (2 * t.y + t.w) / 3) };
|
||||
|
||||
int io = -1;
|
||||
int it = -1;
|
||||
float dist = -1;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
Vec2f diff = po[i] - pt[j];
|
||||
if (dist < 0 || diff.getLength() < dist)
|
||||
{
|
||||
dist = diff.getLength();
|
||||
io = i;
|
||||
it = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->setLine(po[io].x, po[io].y, pt[it].x, pt[it].y);
|
||||
this->setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
QtStraightConnection::~QtStraightConnection()
|
||||
{
|
||||
}
|
||||
|
||||
QPainterPath QtStraightConnection::shape() const
|
||||
{
|
||||
QPainterPath path;
|
||||
QLineF l = line();
|
||||
QLineF n = l.normalVector();
|
||||
n.setLength(5.0f);
|
||||
|
||||
qreal x = n.x2() - n.x1();
|
||||
qreal y = n.y2() - n.y1();
|
||||
|
||||
path.moveTo(l.x1() + x, l.y1() + y);
|
||||
path.lineTo(l.x2() + x, l.y2() + y);
|
||||
path.lineTo(l.x2() - x, l.y2() - y);
|
||||
path.lineTo(l.x1() - x, l.y1() - y);
|
||||
path.closeSubpath();
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
QtCorneredConnection::QtCorneredConnection(
|
||||
Vec4i ownerRect, Vec4i targetRect, Vec4i ownerParentRect, Vec4i targetParentRect, QGraphicsItem* parent
|
||||
)
|
||||
: QGraphicsLineItem(parent)
|
||||
, m_ownerRect(ownerRect)
|
||||
, m_targetRect(targetRect)
|
||||
, m_ownerParentRect(ownerParentRect)
|
||||
, m_targetParentRect(targetParentRect)
|
||||
{
|
||||
this->setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
QtCorneredConnection::~QtCorneredConnection()
|
||||
{
|
||||
}
|
||||
|
||||
QPainterPath QtCorneredConnection::shape() const
|
||||
{
|
||||
QPainterPath path;
|
||||
QPolygon poly = getPath();
|
||||
for (int i = 0; i < poly.size() - 1; i++)
|
||||
{
|
||||
path.addRect(QRectF(poly.at(i), poly.at(i + 1)).normalized().adjusted(-5, -5, 5, 5));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
void QtCorneredConnection::paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget)
|
||||
{
|
||||
painter->setPen(pen());
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
QPolygon poly = getPath();
|
||||
int i = poly.length() - 1;
|
||||
|
||||
path.moveTo(poly.at(i));
|
||||
|
||||
int radius = 10;
|
||||
int dir = getDirection(poly.at(i), poly.at(i - 1));
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
if (i == 0)
|
||||
{
|
||||
path.lineTo(poly.at(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
QPointF a = poly.at(i);
|
||||
QPointF b = poly.at(i - 1);
|
||||
|
||||
int newDir = getDirection(a, b);
|
||||
int ar = radius;
|
||||
int br = 10;
|
||||
|
||||
if (i != 1)
|
||||
{
|
||||
if (dir % 2 == 1 && abs(a.y() - b.y()) < 2 * br)
|
||||
{
|
||||
br = abs(a.y() - b.y()) / 2;
|
||||
}
|
||||
else if (dir % 2 == 0 && abs(a.x() - b.x()) < 2 * br)
|
||||
{
|
||||
br = abs(a.x() - b.x()) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case 0: a.setY(a.y() + ar); break;
|
||||
case 1: a.setX(a.x() - ar); break;
|
||||
case 2: a.setY(a.y() - ar); break;
|
||||
case 3: a.setX(a.x() + ar); break;
|
||||
}
|
||||
|
||||
b = poly.at(i);
|
||||
switch (newDir)
|
||||
{
|
||||
case 0: b.setY(b.y() - br); break;
|
||||
case 1: b.setX(b.x() + br); break;
|
||||
case 2: b.setY(b.y() + br); break;
|
||||
case 3: b.setX(b.x() - br); break;
|
||||
}
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case 0:
|
||||
if (newDir == 1)
|
||||
{
|
||||
path.arcTo(a.x(), b.y(), 2 * br, 2 * ar, 180, -90);
|
||||
}
|
||||
else if (newDir == 3)
|
||||
{
|
||||
path.arcTo(b.x() - br, a.y() - ar, 2 * br, 2 * ar, 0, 90);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (newDir == 0)
|
||||
{
|
||||
path.arcTo(a.x() - ar, b.y() - br, 2 * ar, 2 * br, -90, 90);
|
||||
}
|
||||
else if (newDir == 2)
|
||||
{
|
||||
path.arcTo(a.x() - ar, a.y(), 2 * ar, 2 * br, 90, -90);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (newDir == 1)
|
||||
{
|
||||
path.arcTo(a.x(), a.y() - ar, 2 * br, 2 * ar, 180, 90);
|
||||
}
|
||||
else if (newDir == 3)
|
||||
{
|
||||
path.arcTo(b.x() - br, a.y() - ar, 2 * br, 2 * ar, 0, -90);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (newDir == 0)
|
||||
{
|
||||
path.arcTo(b.x(), b.y() - br, 2 * ar, 2 * br, -90, -90);
|
||||
}
|
||||
else if (newDir == 2)
|
||||
{
|
||||
path.arcTo(b.x(), a.y(), 2 * ar, 2 * br, 90, 90);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dir = newDir;
|
||||
radius = br;
|
||||
}
|
||||
}
|
||||
|
||||
int arrowLength = 3;
|
||||
int arrowWidth = 6;
|
||||
|
||||
QPointF arrow = poly.at(0) + QPointF((poly.at(0).x() - poly.at(1).x() > 0 ? -1 : 1) * arrowLength, -arrowWidth / 2);
|
||||
path.lineTo(arrow);
|
||||
arrow.setY(arrow.y() + arrowWidth);
|
||||
path.moveTo(arrow);
|
||||
path.lineTo(poly.at(0));
|
||||
|
||||
painter->drawPath(path);
|
||||
}
|
||||
|
||||
QPolygon QtCorneredConnection::getPath() const
|
||||
{
|
||||
const Vec4i& oR = m_ownerRect;
|
||||
const Vec4i& tR = m_targetRect;
|
||||
|
||||
Vec2f o[2] = { Vec2f(m_ownerParentRect.x, (oR.y + 2 * oR.w) / 3), Vec2f(m_ownerParentRect.z, (oR.y + 2 * oR.w) / 3) };
|
||||
Vec2f t[2] = { Vec2f(m_targetParentRect.x, (2 * tR.y + tR.w) / 3), Vec2f(m_targetParentRect.z, (2 * tR.y + tR.w) / 3) };
|
||||
|
||||
int io = -1;
|
||||
int it = -1;
|
||||
float dist = -1;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
Vec2f diff = o[i] - t[j];
|
||||
if (dist < 0 || diff.getLength() < dist)
|
||||
{
|
||||
dist = diff.getLength();
|
||||
io = i;
|
||||
it = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float offset = 15;
|
||||
|
||||
QPoint tp((it ? 1 : -1) * offset + t[it].x, t[it].y);
|
||||
QPoint op((io ? 1 : -1) * offset + o[io].x, o[io].y);
|
||||
|
||||
if (it != io)
|
||||
{
|
||||
if (it && tp.x() < op.x())
|
||||
{
|
||||
io = 0;
|
||||
op = QPoint(o[io].x - offset, o[io].y);
|
||||
}
|
||||
else if (!it && tp.x() < op.x())
|
||||
{
|
||||
it = 1;
|
||||
tp = QPoint(t[it].x + offset, t[it].y);
|
||||
}
|
||||
else if (io && tp.x() > op.x())
|
||||
{
|
||||
io = 1;
|
||||
op = QPoint(o[io].x + offset, o[io].y);
|
||||
}
|
||||
else if (!io && tp.x() > op.x())
|
||||
{
|
||||
it = 0;
|
||||
tp = QPoint(t[it].x - offset, t[it].y);
|
||||
}
|
||||
}
|
||||
|
||||
if (it == io && ((it && tp.x() < op.x()) || (!it && tp.x() > op.x())) )
|
||||
{
|
||||
tp.setX(op.x());
|
||||
}
|
||||
else
|
||||
{
|
||||
op.setX(tp.x());
|
||||
}
|
||||
|
||||
o[0] = Vec2f(oR.x, (oR.y + 2 * oR.w) / 3);
|
||||
o[1] = Vec2f(oR.z, (oR.y + 2 * oR.w) / 3);
|
||||
t[0] = Vec2f(tR.x, (2 * tR.y + tR.w) / 3);
|
||||
t[1] = Vec2f(tR.z, (2 * tR.y + tR.w) / 3);
|
||||
|
||||
QPolygon poly;
|
||||
poly << QPoint(t[it].x, t[it].y);
|
||||
poly << tp;
|
||||
poly << op;
|
||||
poly << QPoint(o[io].x, o[io].y);
|
||||
return poly;
|
||||
}
|
||||
|
||||
int QtCorneredConnection::getDirection(const QPointF& a, const QPointF& b) const
|
||||
{
|
||||
if (a.x() != b.x())
|
||||
{
|
||||
if (a.x() < b.x())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a.y() < b.y())
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QtGraphEdge::QtGraphEdge(const std::weak_ptr<GraphNode>& owner, const std::weak_ptr<GraphNode>& target, const Edge* data)
|
||||
: GraphEdge(data)
|
||||
, m_owner(owner)
|
||||
, m_target(target)
|
||||
, m_child(nullptr)
|
||||
, m_isActive(false)
|
||||
, m_mousePos(0.0f, 0.0f)
|
||||
, m_mouseMoved(false)
|
||||
{
|
||||
std::shared_ptr<GraphNode> o = owner.lock();
|
||||
std::shared_ptr<GraphNode> t = target.lock();
|
||||
|
||||
Vec2i ownerPos;
|
||||
Vec2i targetPos;
|
||||
|
||||
if (o != NULL && t != NULL)
|
||||
{
|
||||
ownerPos = o->getPosition();
|
||||
targetPos = t->getPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("Either the owner or the target node is null.");
|
||||
}
|
||||
|
||||
this->setLine(ownerPos.x, ownerPos.y, targetPos.x, targetPos.y);
|
||||
|
||||
this->setAcceptHoverEvents(true);
|
||||
this->setZValue(1); // Used to draw edges always on top of nodes.
|
||||
|
||||
QPen pen(Qt::transparent);
|
||||
pen.setWidth(10);
|
||||
this->setPen(pen);
|
||||
|
||||
m_child = new QGraphicsLineItem(this);
|
||||
m_child->setLine(ownerPos.x, ownerPos.y, targetPos.x, targetPos.y);
|
||||
|
||||
pen.setColor(Qt::black);
|
||||
pen.setWidth(1);
|
||||
|
||||
switch (data->getType())
|
||||
{
|
||||
case Edge::EDGE_CALL:
|
||||
pen.setColor(QColor(100, 100, 100));
|
||||
break;
|
||||
case Edge::EDGE_USAGE:
|
||||
pen.setColor(QColor(66, 230, 103));
|
||||
break;
|
||||
case Edge::EDGE_TYPE_OF:
|
||||
pen.setColor(QColor(73, 155, 222));
|
||||
break;
|
||||
case Edge::EDGE_RETURN_TYPE_OF:
|
||||
pen.setColor(QColor(231, 65, 65));
|
||||
break;
|
||||
case Edge::EDGE_PARAMETER_TYPE_OF:
|
||||
pen.setColor(QColor(227, 180, 68));
|
||||
break;
|
||||
case Edge::EDGE_INHERITANCE:
|
||||
pen.setColor(QColor(113, 96, 191));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_child->setPen(pen);
|
||||
this->updateLine();
|
||||
}
|
||||
|
||||
QtGraphEdge::~QtGraphEdge()
|
||||
{
|
||||
}
|
||||
|
||||
void QtGraphEdge::ownerMoved()
|
||||
{
|
||||
std::shared_ptr<GraphNode> node = m_owner.lock();
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
Vec2i posA = node->getPosition();
|
||||
Vec2i posB(this->line().x2(), this->line().y2());
|
||||
|
||||
this->setLine(posA.x, posA.y, posB.x, posB.y);
|
||||
m_child->setLine(posA.x, posA.y, posB.x, posB.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("Owner node is null.");
|
||||
}
|
||||
}
|
||||
|
||||
void QtGraphEdge::targetMoved()
|
||||
{
|
||||
std::shared_ptr<GraphNode> node = m_target.lock();
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
Vec2i posA(this->line().x1(), this->line().y1());
|
||||
Vec2i posB = node->getPosition();
|
||||
|
||||
this->setLine(posA.x, posA.y, posB.x, posB.y);
|
||||
m_child->setLine(posA.x, posA.y, posB.x, posB.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("Target node is null.");
|
||||
}
|
||||
}
|
||||
|
||||
void QtGraphEdge::removeEdgeFromScene()
|
||||
{
|
||||
std::shared_ptr<GraphNode> node = m_owner.lock();
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
node->removeOutEdge(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("Target node is null.");
|
||||
}
|
||||
}
|
||||
|
||||
std::weak_ptr<GraphNode> QtGraphEdge::getOwner()
|
||||
{
|
||||
return m_owner;
|
||||
@@ -136,6 +342,49 @@ std::weak_ptr<GraphNode> QtGraphEdge::getTarget()
|
||||
return m_target;
|
||||
}
|
||||
|
||||
void QtGraphEdge::updateLine()
|
||||
{
|
||||
std::shared_ptr<GraphNode> owner = m_owner.lock();
|
||||
std::shared_ptr<GraphNode> target = m_target.lock();
|
||||
|
||||
if (owner == NULL || target == NULL)
|
||||
{
|
||||
LOG_WARNING("Either the owner or the target node is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_child)
|
||||
{
|
||||
delete m_child;
|
||||
}
|
||||
|
||||
m_child = new QtCorneredConnection(
|
||||
owner->getBoundingRect(), target->getBoundingRect(),
|
||||
owner->getParentBoundingRect(), target->getParentBoundingRect(),
|
||||
this
|
||||
);
|
||||
|
||||
QColor color;
|
||||
|
||||
switch (getData()->getType())
|
||||
{
|
||||
case Edge::EDGE_CALL:
|
||||
color = QColor("#F1C100");
|
||||
break;
|
||||
case Edge::EDGE_USAGE:
|
||||
color = QColor("#62B29D");
|
||||
break;
|
||||
case Edge::EDGE_INHERITANCE:
|
||||
color = QColor("#CC5E89");
|
||||
break;
|
||||
default:
|
||||
color = QColor("#878787");
|
||||
break;
|
||||
}
|
||||
|
||||
m_child->setPen(QPen(color, 1));
|
||||
}
|
||||
|
||||
bool QtGraphEdge::getIsActive() const
|
||||
{
|
||||
return m_isActive;
|
||||
@@ -149,17 +398,19 @@ void QtGraphEdge::setIsActive(bool isActive)
|
||||
if (isActive)
|
||||
{
|
||||
p.setWidth(2);
|
||||
this->setZValue(5);
|
||||
}
|
||||
else
|
||||
{
|
||||
p.setWidth(1);
|
||||
this->setZValue(1);
|
||||
}
|
||||
m_child->setPen(p);
|
||||
}
|
||||
|
||||
void QtGraphEdge::onClick()
|
||||
{
|
||||
MessageActivateToken(getTokenId()).dispatch();
|
||||
MessageActivateToken(getData()->getId()).dispatch();
|
||||
}
|
||||
|
||||
void QtGraphEdge::mousePressEvent(QGraphicsSceneMouseEvent* event)
|
||||
|
||||
@@ -12,43 +12,72 @@
|
||||
|
||||
class GraphNode;
|
||||
|
||||
class QtStraightConnection
|
||||
: public QGraphicsLineItem
|
||||
{
|
||||
public:
|
||||
QtStraightConnection(Vec4i ownerRect, Vec4i targetRect, QGraphicsItem* parent);
|
||||
virtual ~QtStraightConnection();
|
||||
|
||||
virtual QPainterPath shape() const;
|
||||
};
|
||||
|
||||
class QtCorneredConnection
|
||||
: public QGraphicsLineItem
|
||||
{
|
||||
public:
|
||||
QtCorneredConnection(Vec4i ownerRect, Vec4i targetRect, Vec4i ownerParentRect, Vec4i targetParentRect, QGraphicsItem* parent);
|
||||
virtual ~QtCorneredConnection();
|
||||
|
||||
virtual QPainterPath shape() const;
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget);
|
||||
|
||||
private:
|
||||
QPolygon getPath() const;
|
||||
int getDirection(const QPointF& a, const QPointF& b) const;
|
||||
|
||||
Vec4i m_ownerRect;
|
||||
Vec4i m_targetRect;
|
||||
|
||||
Vec4i m_ownerParentRect;
|
||||
Vec4i m_targetParentRect;
|
||||
};
|
||||
|
||||
|
||||
class QtGraphEdge
|
||||
: public GraphEdge
|
||||
, public QGraphicsLineItem
|
||||
, public QGraphicsItemGroup
|
||||
{
|
||||
public:
|
||||
QtGraphEdge(const std::weak_ptr<GraphNode>& owner, const std::weak_ptr<GraphNode>& target, const Edge* data);
|
||||
virtual ~QtGraphEdge();
|
||||
|
||||
virtual void ownerMoved();
|
||||
virtual void targetMoved();
|
||||
|
||||
virtual void removeEdgeFromScene();
|
||||
|
||||
virtual std::weak_ptr<GraphNode> getOwner();
|
||||
virtual std::weak_ptr<GraphNode> getTarget();
|
||||
|
||||
virtual void updateLine();
|
||||
|
||||
bool getIsActive() const;
|
||||
void setIsActive(bool isActive);
|
||||
|
||||
void onClick();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent* event);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
|
||||
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent* event);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
|
||||
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event);
|
||||
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
|
||||
|
||||
private:
|
||||
std::weak_ptr<GraphNode> m_owner;
|
||||
std::weak_ptr<GraphNode> m_target;
|
||||
|
||||
bool m_isActive;
|
||||
|
||||
QGraphicsLineItem* m_child;
|
||||
|
||||
bool m_isActive;
|
||||
|
||||
Vec2i m_mousePos;
|
||||
bool m_mouseMoved;
|
||||
};
|
||||
|
||||
@@ -49,14 +49,6 @@ QtGraphNode::QtGraphNode(const Node* data)
|
||||
|
||||
QtGraphNode::~QtGraphNode()
|
||||
{
|
||||
for (std::list<std::weak_ptr<GraphEdge>>::iterator it = m_inEdges.begin(); it != m_inEdges.end(); it++)
|
||||
{
|
||||
std::shared_ptr<GraphEdge> edge = it->lock();
|
||||
if (edge != NULL)
|
||||
{
|
||||
edge->removeEdgeFromScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string QtGraphNode::getName() const
|
||||
@@ -104,6 +96,29 @@ void QtGraphNode::setSize(Vec2i size)
|
||||
}
|
||||
}
|
||||
|
||||
Vec4i QtGraphNode::getBoundingRect() const
|
||||
{
|
||||
Vec2i pos = getPosition();
|
||||
Vec2i size = getSize();
|
||||
return Vec4i(pos.x, pos.y, pos.x + size.x, pos.y + size.y);
|
||||
}
|
||||
|
||||
Vec4i QtGraphNode::getParentBoundingRect() const
|
||||
{
|
||||
const QtGraphNode* node = this;
|
||||
while (true)
|
||||
{
|
||||
const QtGraphNode* parent = dynamic_cast<QtGraphNode*>(node->parentItem());
|
||||
if (!parent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
node = parent;
|
||||
|
||||
}
|
||||
return node->getBoundingRect();
|
||||
}
|
||||
|
||||
bool QtGraphNode::addOutEdge(const std::shared_ptr<GraphEdge>& edge)
|
||||
{
|
||||
for (std::list<std::shared_ptr<GraphEdge>>::iterator it = m_outEdges.begin(); it != m_outEdges.end(); it++)
|
||||
@@ -138,21 +153,6 @@ bool QtGraphNode::addInEdge(const std::weak_ptr<GraphEdge>& edge)
|
||||
return true;
|
||||
}
|
||||
|
||||
void QtGraphNode::removeOutEdge(GraphEdge* edge)
|
||||
{
|
||||
std::list<std::shared_ptr<GraphEdge>>::iterator it = m_outEdges.begin();
|
||||
while (it != m_outEdges.end())
|
||||
{
|
||||
if ((*it).get() == edge)
|
||||
{
|
||||
m_outEdges.erase(it);
|
||||
break;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int QtGraphNode::getOutEdgeCount() const
|
||||
{
|
||||
return m_outEdges.size();
|
||||
@@ -321,7 +321,7 @@ void QtGraphNode::notifyEdgesAfterMove()
|
||||
{
|
||||
for (const std::shared_ptr<GraphEdge>& edge : m_outEdges)
|
||||
{
|
||||
edge->ownerMoved();
|
||||
edge->updateLine();
|
||||
}
|
||||
|
||||
for (const std::weak_ptr<GraphEdge>& e : m_inEdges)
|
||||
@@ -329,7 +329,7 @@ void QtGraphNode::notifyEdgesAfterMove()
|
||||
std::shared_ptr<GraphEdge> edge = e.lock();
|
||||
if (edge)
|
||||
{
|
||||
edge->targetMoved();
|
||||
edge->updateLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
|
||||
#include <QGraphicsItem>
|
||||
|
||||
#include "utility/math/Vector2.h"
|
||||
#include "utility/math/Vector4.h"
|
||||
|
||||
#include "component/view/graphElements/GraphNode.h"
|
||||
|
||||
class QtGraphEdge;
|
||||
@@ -30,11 +27,12 @@ public:
|
||||
virtual Vec2i getSize() const;
|
||||
virtual void setSize(Vec2i size);
|
||||
|
||||
virtual Vec4i getBoundingRect() const;
|
||||
virtual Vec4i getParentBoundingRect() const;
|
||||
|
||||
virtual bool addOutEdge(const std::shared_ptr<GraphEdge>& edge);
|
||||
virtual bool addInEdge(const std::weak_ptr<GraphEdge>& edge);
|
||||
|
||||
virtual void removeOutEdge(GraphEdge* edge);
|
||||
|
||||
virtual unsigned int getOutEdgeCount() const;
|
||||
virtual unsigned int getInEdgeCount() const;
|
||||
|
||||
|
||||
@@ -9,11 +9,6 @@ GraphEdge::~GraphEdge()
|
||||
{
|
||||
}
|
||||
|
||||
Id GraphEdge::getTokenId() const
|
||||
{
|
||||
return m_data->getId();
|
||||
}
|
||||
|
||||
const Edge* GraphEdge::getData() const
|
||||
{
|
||||
return m_data;
|
||||
|
||||
@@ -15,18 +15,14 @@ public:
|
||||
GraphEdge(const Edge* data);
|
||||
virtual ~GraphEdge();
|
||||
|
||||
virtual void ownerMoved() = 0;
|
||||
virtual void targetMoved() = 0;
|
||||
|
||||
virtual void removeEdgeFromScene() = 0;
|
||||
|
||||
virtual std::weak_ptr<GraphNode> getOwner() = 0;
|
||||
virtual std::weak_ptr<GraphNode> getTarget() = 0;
|
||||
|
||||
Id getTokenId() const;
|
||||
virtual void updateLine() = 0;
|
||||
|
||||
const Edge* getData() const;
|
||||
|
||||
protected:
|
||||
private:
|
||||
const Edge* m_data;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "utility/math/Vector2.h"
|
||||
#include "utility/math/Vector4.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
#include "data/graph/Node.h"
|
||||
@@ -28,12 +29,12 @@ public:
|
||||
virtual void setPosition(const Vec2i& position) = 0;
|
||||
|
||||
virtual Vec2i getSize() const = 0;
|
||||
virtual Vec4i getBoundingRect() const = 0;
|
||||
virtual Vec4i getParentBoundingRect() const = 0;
|
||||
|
||||
virtual bool addOutEdge(const std::shared_ptr<GraphEdge>& edge) = 0;
|
||||
virtual bool addInEdge(const std::weak_ptr<GraphEdge>& edge) = 0;
|
||||
|
||||
virtual void removeOutEdge(GraphEdge* edge) = 0;
|
||||
|
||||
virtual unsigned int getOutEdgeCount() const = 0;
|
||||
virtual unsigned int getInEdgeCount() const = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user