diff --git a/bin/app/data/color_schemes/bright.xml b/bin/app/data/color_schemes/bright.xml
index 2f3847c6..53660827 100644
--- a/bin/app/data/color_schemes/bright.xml
+++ b/bin/app/data/color_schemes/bright.xml
@@ -295,8 +295,8 @@
- #EEE
- #DDD
+ #DDD
+ #CCC
diff --git a/bin/app/data/color_schemes/dark.xml b/bin/app/data/color_schemes/dark.xml
index 975e5dda..6f49c946 100644
--- a/bin/app/data/color_schemes/dark.xml
+++ b/bin/app/data/color_schemes/dark.xml
@@ -317,8 +317,8 @@
- #5D5D5D
- #6D6D6D
+ #3D3D3D
+ #4D4D4D
diff --git a/src/lib/component/view/GraphViewStyle.cpp b/src/lib/component/view/GraphViewStyle.cpp
index 4c3c640c..c6f291e5 100644
--- a/src/lib/component/view/GraphViewStyle.cpp
+++ b/src/lib/component/view/GraphViewStyle.cpp
@@ -433,8 +433,14 @@ GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType typ
switch (type)
{
case Edge::EDGE_AGGREGATION:
- style.isStraight = true;
- style.width = 4;
+ style.width = 2;
+ style.arrowLength = 7;
+ style.arrowWidth = 10;
+ style.originOffset.x = 22;
+ style.targetOffset.x = 22;
+ style.originOffset.y = 0;
+ style.targetOffset.y = 0;
+ style.verticalOffset = 0;
style.zValue = isActive ? -2 : -5;
break;
case Edge::EDGE_CALL:
@@ -452,6 +458,7 @@ GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType typ
style.arrowWidth = 14;
style.arrowClosed = true;
style.targetOffset.x = 34;
+ style.zValue = isActive ? -1 : -3;
break;
default:
break;
diff --git a/src/lib_gui/qt/graphics/QtAngledLineItem.cpp b/src/lib_gui/qt/graphics/QtAngledLineItem.cpp
index caef62f7..8c520ecb 100644
--- a/src/lib_gui/qt/graphics/QtAngledLineItem.cpp
+++ b/src/lib_gui/qt/graphics/QtAngledLineItem.cpp
@@ -9,8 +9,12 @@
QtAngledLineItem::QtAngledLineItem(QGraphicsItem* parent)
: QGraphicsLineItem(parent)
+ , m_route(ROUTE_ANY)
+ , m_pivot(PIVOT_THIRD)
+ , m_onFront(false)
, m_onBack(false)
, m_horizontalIn(false)
+ , m_showArrow(true)
{
this->setAcceptHoverEvents(true);
this->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
@@ -23,7 +27,8 @@ QtAngledLineItem::~QtAngledLineItem()
void QtAngledLineItem::updateLine(
Vec4i ownerRect, Vec4i targetRect,
Vec4i ownerParentRect, Vec4i targetParentRect,
- GraphViewStyle::EdgeStyle style
+ GraphViewStyle::EdgeStyle style,
+ size_t weight, bool showArrow
){
prepareGeometryChange();
m_polygon.clear();
@@ -39,8 +44,24 @@ void QtAngledLineItem::updateLine(
m_targetRect.z = m_targetRect.z + 1;
m_style = style;
+ m_showArrow = showArrow;
- this->setPen(QPen(QBrush(style.color.c_str()), style.width, Qt::SolidLine, Qt::RoundCap));
+ this->setPen(QPen(QBrush(style.color.c_str()), style.width + int(log10(weight)), Qt::SolidLine, Qt::RoundCap));
+}
+
+void QtAngledLineItem::setRoute(Route route)
+{
+ m_route = route;
+}
+
+void QtAngledLineItem::setPivot(Pivot pivot)
+{
+ m_pivot = pivot;
+}
+
+void QtAngledLineItem::setOnFront(bool front)
+{
+ m_onFront = front;
}
void QtAngledLineItem::setOnBack(bool back)
@@ -68,7 +89,7 @@ QPainterPath QtAngledLineItem::shape() const
return path;
}
-void QtAngledLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget)
+void QtAngledLineItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* options, QWidget* widget)
{
painter->setPen(pen());
@@ -79,6 +100,17 @@ void QtAngledLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem*
path.moveTo(poly.at(i));
+
+ // while (i > 0)
+ // {
+ // i--;
+
+ // path.lineTo(poly.at(i));
+ // }
+ // painter->drawPath(path);
+ // return;
+
+
QRectF drawRect = options->exposedRect;
QRectF partRect;
@@ -194,7 +226,7 @@ void QtAngledLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem*
if (drawRect.intersects(partRect))
{
partRect = getArrowBoundingRect(poly);
- if (drawRect.intersects(partRect))
+ if (drawRect.intersects(partRect) && m_showArrow)
{
drawArrow(poly, &path);
}
@@ -215,30 +247,61 @@ QPolygon QtAngledLineItem::getPath() const
}
const Vec4i& oR = m_ownerRect;
+ const Vec4i& oPR = m_ownerParentRect;
const Vec4i& tR = m_targetRect;
+ const Vec4i& tPR = m_targetParentRect;
- 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) };
+ const Vec2i& oOff = m_style.originOffset;
+ const Vec2i& tOff = m_style.targetOffset;
+
+ Vec2f oP[4];
+ getPivotPoints(oP, oR, oPR, oOff.y, false);
+
+ Vec2f tP[4];
+ getPivotPoints(tP, tR, tPR, tOff.y, true);
int io = -1;
int it = -1;
- float dist = -1;
- if (m_onBack)
+ float dist = -1;
+ std::map dists;
+
+ if (m_onFront)
+ {
+ io = 3;
+ it = 3;
+ }
+ else if (m_onBack)
{
io = 1;
it = 1;
}
else
{
- for (int i = 0; i < 2; i++)
+ for (int i = 0; i < 4; i++)
{
- for (int j = 0; j < 2; j++)
+ for (int j = 0; j < 4; j++)
{
- Vec2f diff = o[i] - t[j];
- if (dist < 0 || diff.getLength() < dist)
+ if (m_route == ROUTE_HORIZONTAL && (i % 2 == 0 || j % 2 == 0))
{
- dist = diff.getLength();
+ continue;
+ }
+ else if (m_route == ROUTE_VERTICAL && (i % 2 == 1 || j % 2 == 1))
+ {
+ continue;
+ }
+ else if (i % 2 != j % 2)
+ {
+ continue;
+ }
+
+ Vec2f diff = oP[i] - tP[j];
+ float d = diff.getLength();
+ dists.emplace((i << 2) + j, d);
+
+ if (dist < 0 || d < dist)
+ {
+ dist = d;
io = i;
it = j;
}
@@ -246,67 +309,139 @@ QPolygon QtAngledLineItem::getPath() const
}
}
- QPoint tp((it ? 1 : -1) * m_style.targetOffset.x + t[it].x, t[it].y + m_style.targetOffset.y);
- QPoint op((io ? 1 : -1) * m_style.originOffset.x + o[io].x, o[io].y + m_style.originOffset.y);
+ Vec2f o[4];
+ getPivotPoints(o, oR, oR, oOff.y, false);
+
+ Vec2f t[4];
+ getPivotPoints(t, tR, tR, tOff.y, true);
+
+ QPoint a(t[it].x, t[it].y);
+ QPoint d(o[io].x, o[io].y);
+
+ QPoint b(tP[it].x, tP[it].y);
+ QPoint c(oP[io].x, oP[io].y);
+
+ switch (it)
+ {
+ case 0: b.setY(b.y() - tOff.x); break;
+ case 1: b.setX(b.x() + tOff.x); break;
+ case 2: b.setY(b.y() + tOff.x); break;
+ case 3: b.setX(b.x() - tOff.x); break;
+ }
+
+ switch (io)
+ {
+ case 0: c.setY(c.y() - oOff.x); break;
+ case 1: c.setX(c.x() + oOff.x); break;
+ case 2: c.setY(c.y() + oOff.x); break;
+ case 3: c.setX(c.x() - oOff.x); break;
+ }
if (it != io)
{
- if (it && tp.x() < op.x())
+ if ((it == 1 && b.x() < c.x()) || (io == 1 && b.x() > c.x()))
{
- io = 0;
- op = QPoint(o[io].x - m_style.originOffset.x, o[io].y + m_style.originOffset.y);
+ if (m_horizontalIn)
+ {
+ b.setX(c.x());
+ }
+ else
+ {
+ c.setX(b.x());
+ }
}
- else if (!it && tp.x() < op.x())
+ else if ((it == 2 && b.y() < c.y()) || (io == 2 && b.y() > c.y()))
{
- it = 1;
- tp = QPoint(t[it].x + m_style.targetOffset.x, t[it].y + m_style.targetOffset.y);
+ c.setY(b.y());
}
- else if (io && tp.x() > op.x())
+ else if (
+ (it == 3 && b.x() < c.x()) || (io == 3 && b.x() > c.x()) ||
+ (it == 0 && b.y() < c.y()) || (io == 0 && b.y() > c.y()))
{
- io = 1;
- op = QPoint(o[io].x + m_style.originOffset.x, o[io].y + m_style.originOffset.y);
- }
- else if (!io && tp.x() > op.x())
- {
- it = 0;
- tp = QPoint(t[it].x - m_style.targetOffset.x, t[it].y + m_style.targetOffset.y);
+ float dist1 = dists[(io << 2) + ((it + 2) % 4)];
+ float dist2 = dists[(((io + 2) % 4) << 2) + it];
+
+ if (dist1 < dist2)
+ {
+ it = (it + 2) % 4;
+
+ a = QPoint(t[it].x, t[it].y);
+ b = QPoint(tP[it].x, tP[it].y);
+
+ switch (it)
+ {
+ case 0: b.setY(b.y() - tOff.x); break;
+ case 1: b.setX(b.x() + tOff.x); break;
+ case 2: b.setY(b.y() + tOff.x); break;
+ case 3: b.setX(b.x() - tOff.x); break;
+ }
+ }
+ else
+ {
+ io = (io + 2) % 4;
+
+ c = QPoint(o[io].x, o[io].y);
+ d = QPoint(oP[io].x, oP[io].y);
+
+ switch (io)
+ {
+ case 0: c.setY(c.y() - oOff.x); break;
+ case 1: c.setX(c.x() + oOff.x); break;
+ case 2: c.setY(c.y() + oOff.x); break;
+ case 3: c.setX(c.x() - oOff.x); break;
+ }
+ }
}
}
- if (it == io && ((it && tp.x() < op.x()) || (!it && tp.x() > op.x())))
+ if (it % 2 == 1)
{
- tp.setX(op.x());
- }
- else if (it != io && m_horizontalIn)
- {
- tp.setX(op.x());
+ if (it == io && ((it == 1 && b.x() < c.x()) || (it == 3 && b.x() > c.x())))
+ {
+ b.setX(c.x());
+ }
+ else
+ {
+ c.setX(b.x());
+ }
}
else
{
- op.setX(tp.x());
+ if (it == io && ((it == 0 && b.y() > c.y()) || (it == 2 && b.y() < c.y())))
+ {
+ b.setY(c.y());
+ }
+ else
+ {
+ c.setY(b.y());
+ }
}
- 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)
+ if (it % 2 == 0)
{
- op.setX(op.x() + m_style.verticalOffset);
- tp.setX(tp.x() + m_style.verticalOffset);
+ int vo = m_style.verticalOffset;
+ if (c.x() > b.x())
+ {
+ vo *= -1;
+ }
+
+ b.setY(b.y() + vo);
+ c.setY(c.y() + vo);
}
else
{
- op.setX(op.x() - m_style.verticalOffset);
- tp.setX(tp.x() - m_style.verticalOffset);
+ int vo = m_style.verticalOffset;
+ if (c.y() > b.y())
+ {
+ vo *= -1;
+ }
+
+ b.setX(b.x() + vo);
+ c.setX(c.x() + vo);
}
QPolygon poly;
- poly << QPoint(t[it].x, t[it].y + m_style.targetOffset.y);
- poly << tp;
- poly << op;
- poly << QPoint(o[io].x, o[io].y + m_style.originOffset.y);
+ poly << a << b << c << d;
m_polygon = poly;
@@ -423,3 +558,14 @@ void QtAngledLineItem::drawArrow(const QPolygon& poly, QPainterPath* path) const
path->lineTo(tip);
}
+
+void QtAngledLineItem::getPivotPoints(Vec2f* p, const Vec4i& in, const Vec4i& out, int offset, bool target) const
+{
+ float f = m_pivot == PIVOT_THIRD ? (target ? 2 / 3.f : 1 / 3.f) : 1 / 2.f;
+
+ p[0] = Vec2f(in.x + (in.z - in.x) * f + offset, out.y);
+ p[2] = Vec2f(in.x + (in.z - in.x) * f + offset, out.w);
+
+ p[1] = Vec2f(out.z, in.y + (in.w - in.y) * f + offset);
+ p[3] = Vec2f(out.x, in.y + (in.w - in.y) * f + offset);
+}
diff --git a/src/lib_gui/qt/graphics/QtAngledLineItem.h b/src/lib_gui/qt/graphics/QtAngledLineItem.h
index e7b36d97..855e9b8b 100644
--- a/src/lib_gui/qt/graphics/QtAngledLineItem.h
+++ b/src/lib_gui/qt/graphics/QtAngledLineItem.h
@@ -11,19 +11,37 @@ class QtAngledLineItem
: public QGraphicsLineItem
{
public:
+ enum Route
+ {
+ ROUTE_ANY,
+ ROUTE_HORIZONTAL,
+ ROUTE_VERTICAL
+ };
+
+ enum Pivot
+ {
+ PIVOT_THIRD,
+ PIVOT_MIDDLE
+ };
+
QtAngledLineItem(QGraphicsItem* parent);
virtual ~QtAngledLineItem();
void updateLine(
Vec4i ownerRect, Vec4i targetRect,
Vec4i ownerParentRect, Vec4i targetParentRect,
- GraphViewStyle::EdgeStyle style);
+ GraphViewStyle::EdgeStyle style,
+ size_t weight, bool showArrow);
+ void setRoute(Route route);
+ void setPivot(Pivot pivot);
+
+ void setOnFront(bool front);
void setOnBack(bool back);
void setHorizontalIn(bool horizontal);
virtual QPainterPath shape() const;
- virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget);
+ virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* options, QWidget* widget);
private:
QPolygon getPath() const;
@@ -32,6 +50,8 @@ private:
QRectF getArrowBoundingRect(const QPolygon& poly) const;
void drawArrow(const QPolygon& poly, QPainterPath* path) const;
+ void getPivotPoints(Vec2f* p, const Vec4i& in, const Vec4i& out, int offset, bool target) const;
+
Vec4i m_ownerRect;
Vec4i m_targetRect;
@@ -40,8 +60,13 @@ private:
GraphViewStyle::EdgeStyle m_style;
+ Route m_route;
+ Pivot m_pivot;
+
+ bool m_onFront;
bool m_onBack;
bool m_horizontalIn;
+ bool m_showArrow;
mutable QPolygon m_polygon;
};
diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp
index 4ae034ae..02b326ce 100644
--- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp
+++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp
@@ -34,6 +34,11 @@ QtGraphEdge::QtGraphEdge(
, m_mousePos(0.0f, 0.0f)
, m_mouseMoved(false)
{
+ if (m_direction == TokenComponentAggregation::DIRECTION_BACKWARD)
+ {
+ m_owner.swap(m_target);
+ }
+
m_fromActive = m_owner.lock()->getIsActive();
m_toActive = m_target.lock()->getIsActive();
@@ -91,11 +96,6 @@ void QtGraphEdge::updateLine()
bool showArrow = m_direction != TokenComponentAggregation::DIRECTION_NONE;
- if (m_direction == TokenComponentAggregation::DIRECTION_BACKWARD)
- {
- owner.swap(target);
- }
-
GraphViewStyle::NodeStyle countStyle = GraphViewStyle::getStyleOfCountCircle();
dynamic_cast(m_child)->updateLine(
@@ -108,30 +108,52 @@ void QtGraphEdge::updateLine()
m_child = new QtAngledLineItem(this);
}
- dynamic_cast(m_child)->updateLine(
- owner->getBoundingRect(), target->getBoundingRect(),
- owner->getParentBoundingRect(), target->getParentBoundingRect(),
- style);
+ QtAngledLineItem* child = dynamic_cast(m_child);
if (m_fromActive && owner->getLastParent() == target->getLastParent())
{
- dynamic_cast(m_child)->setOnBack(true);
+ child->setOnBack(true);
}
if (m_toActive)
{
- dynamic_cast(m_child)->setHorizontalIn(true);
+ child->setHorizontalIn(true);
+
+ if (owner->getLastParent() == target->getLastParent())
+ {
+ child->setOnFront(true);
+ }
}
+
+ if (type != Edge::EDGE_INHERITANCE && type != Edge::EDGE_AGGREGATION)
+ {
+ child->setRoute(QtAngledLineItem::ROUTE_HORIZONTAL);
+ }
+
+ bool showArrow = true;
+ if (type == Edge::EDGE_AGGREGATION)
+ {
+ child->setPivot(QtAngledLineItem::PIVOT_MIDDLE);
+
+ showArrow = m_direction != TokenComponentAggregation::DIRECTION_NONE;
+ }
+
+ child->updateLine(
+ owner->getBoundingRect(), target->getBoundingRect(),
+ owner->getParentBoundingRect(), target->getParentBoundingRect(),
+ style, m_weight, showArrow);
}
- if (m_data)
+ QString toolTip = Edge::getTypeString(type).c_str();
+ if (type == Edge::EDGE_AGGREGATION)
{
- m_child->setToolTip(QString::fromStdString(m_data->getTypeString()));
- }
- else
- {
- m_child->setToolTip(QString::fromStdString(Edge::getTypeString(Edge::EDGE_AGGREGATION)));
+ toolTip += ": " + QString::number(m_weight) + " edge";
+ if (m_weight != 1)
+ {
+ toolTip += "s";
+ }
}
+ m_child->setToolTip(toolTip);
this->setZValue(style.zValue); // Used to draw edges always on top of nodes.
}