ui: switch Graph to bucket grid layouting

This change introduces bucket grid layouting, which sorts the nodes into buckets based on how they are connected. Each
bucket is then layouted individually before they are arranged next to each other. Edges go from left to right, except
for inheritance edges that go from bottom to top.
This commit is contained in:
Eberhard Graether
2015-09-24 03:12:42 +02:00
parent c18bd6a8bc
commit 5825fe77ab
15 changed files with 575 additions and 56 deletions
+38 -14
View File
@@ -8,6 +8,8 @@
QtAngledLineItem::QtAngledLineItem(QGraphicsItem* parent)
: QGraphicsLineItem(parent)
, m_onBack(false)
, m_horizontalIn(false)
{
this->setAcceptHoverEvents(true);
}
@@ -38,6 +40,16 @@ void QtAngledLineItem::updateLine(
this->setPen(QPen(QBrush(style.color.c_str()), style.width, Qt::SolidLine, Qt::RoundCap));
}
void QtAngledLineItem::setOnBack(bool back)
{
m_onBack = back;
}
void QtAngledLineItem::setHorizontalIn(bool horizontal)
{
m_horizontalIn = horizontal;
}
QPainterPath QtAngledLineItem::shape() const
{
int w = m_style.arrowWidth / 2 + 1;
@@ -185,23 +197,31 @@ QPolygon QtAngledLineItem::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) };
Vec2f o[2] = { Vec2f(m_ownerParentRect.x, (2 * oR.y + oR.w) / 3), Vec2f(m_ownerParentRect.z, (2 * oR.y + oR.w) / 3) };
Vec2f t[2] = { Vec2f(m_targetParentRect.x, (tR.y + 2 * tR.w) / 3), Vec2f(m_targetParentRect.z, (tR.y + 2 * tR.w) / 3) };
int io = -1;
int it = -1;
float dist = -1;
for (int i = 0; i < 2; i++)
if (m_onBack)
{
for (int j = 0; j < 2; j++)
io = 1;
it = 1;
}
else
{
for (int i = 0; i < 2; i++)
{
Vec2f diff = o[i] - t[j];
if (dist < 0 || diff.getLength() < dist)
for (int j = 0; j < 2; j++)
{
dist = diff.getLength();
io = i;
it = j;
Vec2f diff = o[i] - t[j];
if (dist < 0 || diff.getLength() < dist)
{
dist = diff.getLength();
io = i;
it = j;
}
}
}
}
@@ -233,7 +253,11 @@ QPolygon QtAngledLineItem::getPath() const
}
}
if (it == io && ((it && tp.x() < op.x()) || (!it && tp.x() > op.x())) )
if (it == io && ((it && tp.x() < op.x()) || (!it && tp.x() > op.x())))
{
tp.setX(op.x());
}
else if (it != io && m_horizontalIn)
{
tp.setX(op.x());
}
@@ -242,10 +266,10 @@ QPolygon QtAngledLineItem::getPath() const
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);
o[0] = Vec2f(oR.x, (2 * oR.y + oR.w) / 3);
o[1] = Vec2f(oR.z, (2 * oR.y + oR.w) / 3);
t[0] = Vec2f(tR.x, (tR.y + 2 * tR.w) / 3);
t[1] = Vec2f(tR.z, (tR.y + 2 * tR.w) / 3);
if (o[io].y < t[it].y)
{
+6
View File
@@ -19,6 +19,9 @@ public:
Vec4i ownerParentRect, Vec4i targetParentRect,
GraphViewStyle::EdgeStyle style);
void setOnBack(bool back);
void setHorizontalIn(bool horizontal);
virtual QPainterPath shape() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget);
@@ -33,6 +36,9 @@ private:
Vec4i m_targetParentRect;
GraphViewStyle::EdgeStyle m_style;
bool m_onBack;
bool m_horizontalIn;
};
#endif // QT_ANGLED_LINE_ITEM_H
+21 -4
View File
@@ -22,11 +22,16 @@ QtGraphEdge::QtGraphEdge(
, m_target(target)
, m_child(nullptr)
, m_isActive(false)
, m_fromActive(false)
, m_toActive(false)
, m_weight(weight)
, m_direction(TokenComponentAggregation::DIRECTION_NONE)
, m_mousePos(0.0f, 0.0f)
, m_mouseMoved(false)
{
m_fromActive = m_owner.lock()->getIsActive();
m_toActive = m_target.lock()->getIsActive();
this->updateLine();
}
@@ -100,6 +105,16 @@ void QtGraphEdge::updateLine()
owner->getBoundingRect(), target->getBoundingRect(),
owner->getParentBoundingRect(), target->getParentBoundingRect(),
style);
if (m_fromActive && owner->getLastParent() == target->getLastParent())
{
dynamic_cast<QtAngledLineItem*>(m_child)->setOnBack(true);
}
if (m_toActive)
{
dynamic_cast<QtAngledLineItem*>(m_child)->setHorizontalIn(true);
}
}
this->setZValue(style.zValue); // Used to draw edges always on top of nodes.
@@ -112,9 +127,11 @@ bool QtGraphEdge::getIsActive() const
void QtGraphEdge::setIsActive(bool isActive)
{
m_isActive = isActive;
updateLine();
if (m_isActive != isActive)
{
m_isActive = isActive;
updateLine();
}
}
void QtGraphEdge::onClick()
@@ -138,7 +155,7 @@ void QtGraphEdge::focusIn()
void QtGraphEdge::focusOut()
{
this->setIsActive(m_isActive);
updateLine();
}
void QtGraphEdge::mousePressEvent(QGraphicsSceneMouseEvent* event)
@@ -32,6 +32,7 @@ public:
bool getIsActive() const;
void setIsActive(bool isActive);
void setFromAndToActive(bool fromActive, bool toActive);
void onClick();
@@ -57,6 +58,8 @@ private:
QGraphicsLineItem* m_child;
bool m_isActive;
bool m_fromActive;
bool m_toActive;
size_t m_weight;
TokenComponentAggregation::Direction m_direction;
+16 -12
View File
@@ -61,6 +61,21 @@ QtGraphNode* QtGraphNode::getParent() const
return m_parentNode.lock().get();
}
QtGraphNode* QtGraphNode::getLastParent() const
{
QtGraphNode* node = const_cast<QtGraphNode*>(this);
while (true)
{
QtGraphNode* parent = dynamic_cast<QtGraphNode*>(node->parentItem());
if (!parent)
{
break;
}
node = parent;
}
return node;
}
void QtGraphNode::setParent(std::weak_ptr<QtGraphNode> parentNode)
{
m_parentNode = parentNode;
@@ -134,18 +149,7 @@ Vec4i QtGraphNode::getBoundingRect() const
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();
return getLastParent()->getBoundingRect();
}
void QtGraphNode::addOutEdge(const std::shared_ptr<QtGraphEdge>& edge)
@@ -3,6 +3,8 @@
#include <QGraphicsItem>
#include "utility/math/Vector4.h"
#include "component/view/GraphViewStyle.h"
class QFont;
@@ -33,6 +35,7 @@ public:
virtual ~QtGraphNode();
QtGraphNode* getParent() const;
QtGraphNode* getLastParent() const;
void setParent(std::weak_ptr<QtGraphNode> parentNode);
std::list<std::shared_ptr<QtGraphNode>> getSubNodes() const;