diff --git a/bin/app/data/ApplicationSettings_template.xml b/bin/app/data/ApplicationSettings_template.xml
index 27c846f7..340f4ac2 100644
--- a/bin/app/data/ApplicationSettings_template.xml
+++ b/bin/app/data/ApplicationSettings_template.xml
@@ -50,15 +50,15 @@
#ededed
- #dddddd
+ #ededed
#ededed
- #dddddd
+ #ededed
#ededed
- #dddddd
+ #ededed
#ffe47a
@@ -77,32 +77,28 @@
#62b29d
- #ededed
- #dddddd
+ #00000000
+ #00000000
- #ededed
- #dddddd
+ #9ab4ad
+ #62b29d
- #ededed
- #dddddd
+ #ffe47a
+ #ffcc00
#ededed
- #dddddd
+ #ededed
-
- #ededed
- #dddddd
-
- #ededed
- #dddddd
+ #00000000
+ #00000000
#ededed
- #dddddd
+ #ededed
#9ab4ad
@@ -110,7 +106,7 @@
#ededed
- #dddddd
+ #ededed
#A3BA8A
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 93b88d55..d4a12059 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -26,8 +26,12 @@ add_files(
qt/element/QtUndoRedo.cpp
qt/element/QtUndoRedo.h
- qt/graphics/QtGraphicsRoundedRectItem.cpp
- qt/graphics/QtGraphicsRoundedRectItem.h
+ qt/graphics/QtAngledLineItem.cpp
+ qt/graphics/QtAngledLineItem.h
+ qt/graphics/QtRoundedRectItem.cpp
+ qt/graphics/QtRoundedRectItem.h
+ qt/graphics/QtStraightLineItem.cpp
+ qt/graphics/QtStraightLineItem.h
qt/utility/QtDeviceScaledPixmap.h
qt/utility/QtGraphPostprocessor.cpp
@@ -58,6 +62,8 @@ add_files(
qt/view/QtCompositeView.h
qt/view/QtGraphView.cpp
qt/view/QtGraphView.h
+ qt/view/QtGraphViewStyleImpl.cpp
+ qt/view/QtGraphViewStyleImpl.h
qt/view/QtMainView.cpp
qt/view/QtMainView.h
qt/view/QtRefreshView.cpp
diff --git a/src/app/qt/graphics/QtAngledLineItem.cpp b/src/app/qt/graphics/QtAngledLineItem.cpp
new file mode 100644
index 00000000..aeddfd1e
--- /dev/null
+++ b/src/app/qt/graphics/QtAngledLineItem.cpp
@@ -0,0 +1,293 @@
+#include "qt/graphics/QtAngledLineItem.h"
+
+#include
+
+#include
+
+#include "utility/math/Vector2.h"
+
+QtAngledLineItem::QtAngledLineItem(QGraphicsItem* parent)
+ : QGraphicsLineItem(parent)
+{
+ this->setAcceptHoverEvents(true);
+}
+
+QtAngledLineItem::~QtAngledLineItem()
+{
+}
+
+void QtAngledLineItem::updateLine(
+ Vec4i ownerRect, Vec4i targetRect,
+ Vec4i ownerParentRect, Vec4i targetParentRect,
+ GraphViewStyle::EdgeStyle style
+){
+ prepareGeometryChange();
+
+ m_ownerRect = ownerRect;
+ m_targetRect = targetRect;
+ m_ownerParentRect = ownerParentRect;
+ m_targetParentRect = targetParentRect;
+
+ m_ownerRect.x = m_ownerRect.x - 1;
+ m_ownerRect.z = m_ownerRect.z + 1;
+ m_targetRect.x = m_targetRect.x - 1;
+ m_targetRect.z = m_targetRect.z + 1;
+
+ m_style = style;
+
+ this->setPen(QPen(QBrush(style.color.c_str()), style.width, Qt::SolidLine, Qt::RoundCap));
+}
+
+QPainterPath QtAngledLineItem::shape() const
+{
+ int w = m_style.arrowWidth / 2 + 1;
+ 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(-w, -w, w, w));
+ }
+ return path;
+}
+
+void QtAngledLineItem::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 = m_style.cornerRadius;
+ int dir = getDirection(poly.at(i), poly.at(i - 1));
+ while (i > 1)
+ {
+ i--;
+
+ QPointF a = poly.at(i);
+ QPointF b = poly.at(i - 1);
+
+ int newDir = getDirection(a, b);
+ int ar = radius;
+ int br = m_style.cornerRadius;
+
+ if (i != 1)
+ {
+ if (dir % 2 == 1 && std::abs(a.y() - b.y()) < 2 * br)
+ {
+ br = std::abs(a.y() - b.y()) / 2;
+ }
+ else if (dir % 2 == 0 && std::abs(a.x() - b.x()) < 2 * br)
+ {
+ br = std::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;
+ }
+
+ QPointF arrow = poly.at(0) + QPointF((poly.at(0).x() - poly.at(1).x() > 0 ? -1 : 1) * m_style.arrowLength, 0);
+
+ if (m_style.arrowClosed)
+ {
+ path.lineTo(arrow);
+ path.moveTo(poly.at(0));
+ }
+ else
+ {
+ path.lineTo(poly.at(0));
+ }
+
+ arrow.setY(arrow.y() - m_style.arrowWidth / 2);
+ path.lineTo(arrow);
+ arrow.setY(arrow.y() + m_style.arrowWidth);
+
+ if (m_style.arrowClosed)
+ {
+ path.lineTo(arrow);
+ }
+ else
+ {
+ path.moveTo(arrow);
+ }
+ path.lineTo(poly.at(0));
+
+ painter->drawPath(path);
+}
+
+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) };
+
+ 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;
+ }
+ }
+ }
+
+ 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);
+
+ if (it != io)
+ {
+ if (it && tp.x() < op.x())
+ {
+ io = 0;
+ op = QPoint(o[io].x - m_style.originOffset.x, o[io].y + m_style.originOffset.y);
+ }
+ else if (!it && tp.x() < op.x())
+ {
+ it = 1;
+ tp = QPoint(t[it].x + m_style.targetOffset.x, t[it].y + m_style.targetOffset.y);
+ }
+ else if (io && tp.x() > op.x())
+ {
+ 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);
+ }
+ }
+
+ 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);
+
+ if (o[io].y < t[it].y)
+ {
+ op.setX(op.x() + m_style.verticalOffset);
+ tp.setX(tp.x() + m_style.verticalOffset);
+ }
+ else
+ {
+ op.setX(op.x() - m_style.verticalOffset);
+ tp.setX(tp.x() - m_style.verticalOffset);
+ }
+
+ 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);
+ return poly;
+}
+
+int QtAngledLineItem::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;
+ }
+ }
+}
diff --git a/src/app/qt/graphics/QtAngledLineItem.h b/src/app/qt/graphics/QtAngledLineItem.h
new file mode 100644
index 00000000..46ab6ddd
--- /dev/null
+++ b/src/app/qt/graphics/QtAngledLineItem.h
@@ -0,0 +1,38 @@
+#ifndef QT_ANGLED_LINE_ITEM_H
+#define QT_ANGLED_LINE_ITEM_H
+
+#include
+
+#include "utility/math/Vector4.h"
+
+#include "component/view/GraphViewStyle.h"
+
+class QtAngledLineItem
+ : public QGraphicsLineItem
+{
+public:
+ QtAngledLineItem(QGraphicsItem* parent);
+ virtual ~QtAngledLineItem();
+
+ void updateLine(
+ Vec4i ownerRect, Vec4i targetRect,
+ Vec4i ownerParentRect, Vec4i targetParentRect,
+ GraphViewStyle::EdgeStyle style);
+
+ 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;
+
+ GraphViewStyle::EdgeStyle m_style;
+};
+
+#endif // QT_ANGLED_LINE_ITEM_H
diff --git a/src/app/qt/graphics/QtGraphicsRoundedRectItem.cpp b/src/app/qt/graphics/QtRoundedRectItem.cpp
similarity index 55%
rename from src/app/qt/graphics/QtGraphicsRoundedRectItem.cpp
rename to src/app/qt/graphics/QtRoundedRectItem.cpp
index 40abbbe4..b5001642 100644
--- a/src/app/qt/graphics/QtGraphicsRoundedRectItem.cpp
+++ b/src/app/qt/graphics/QtRoundedRectItem.cpp
@@ -1,20 +1,20 @@
-#include "qt/graphics/QtGraphicsRoundedRectItem.h"
+#include "qt/graphics/QtRoundedRectItem.h"
#include
#include
-QtGraphicsRoundedRectItem::QtGraphicsRoundedRectItem(QGraphicsItem* parent)
+QtRoundedRectItem::QtRoundedRectItem(QGraphicsItem* parent)
: QGraphicsRectItem(parent)
, m_radius(0.0f)
{
this->setZValue(-1.0f);
}
-QtGraphicsRoundedRectItem::~QtGraphicsRoundedRectItem()
+QtRoundedRectItem::~QtRoundedRectItem()
{
}
-void QtGraphicsRoundedRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget)
+void QtRoundedRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget)
{
painter->setPen(pen());
painter->setBrush(brush());
@@ -24,7 +24,7 @@ void QtGraphicsRoundedRectItem::paint(QPainter *painter, const QStyleOptionGraph
painter->drawRoundedRect(this->rect(), m_radius, m_radius);
}
-void QtGraphicsRoundedRectItem::setShadow(QColor color, int blurRadius)
+void QtRoundedRectItem::setShadow(QColor color, int blurRadius)
{
QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();
effect->setColor(color);
@@ -33,7 +33,7 @@ void QtGraphicsRoundedRectItem::setShadow(QColor color, int blurRadius)
this->setGraphicsEffect(effect);
}
-void QtGraphicsRoundedRectItem::setShadowEnabled(bool enabled)
+void QtRoundedRectItem::setShadowEnabled(bool enabled)
{
if (this->graphicsEffect())
{
@@ -41,7 +41,7 @@ void QtGraphicsRoundedRectItem::setShadowEnabled(bool enabled)
}
}
-void QtGraphicsRoundedRectItem::setRadius(qreal radius)
+void QtRoundedRectItem::setRadius(qreal radius)
{
m_radius = radius;
}
diff --git a/src/app/qt/graphics/QtGraphicsRoundedRectItem.h b/src/app/qt/graphics/QtRoundedRectItem.h
similarity index 78%
rename from src/app/qt/graphics/QtGraphicsRoundedRectItem.h
rename to src/app/qt/graphics/QtRoundedRectItem.h
index 2526c20f..93dd4ed9 100644
--- a/src/app/qt/graphics/QtGraphicsRoundedRectItem.h
+++ b/src/app/qt/graphics/QtRoundedRectItem.h
@@ -3,12 +3,12 @@
#include
-class QtGraphicsRoundedRectItem
+class QtRoundedRectItem
: public QGraphicsRectItem
{
public:
- QtGraphicsRoundedRectItem(QGraphicsItem* parent);
- virtual ~QtGraphicsRoundedRectItem();
+ QtRoundedRectItem(QGraphicsItem* parent);
+ virtual ~QtRoundedRectItem();
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget);
diff --git a/src/app/qt/graphics/QtStraightLineItem.cpp b/src/app/qt/graphics/QtStraightLineItem.cpp
new file mode 100644
index 00000000..d6acf9a4
--- /dev/null
+++ b/src/app/qt/graphics/QtStraightLineItem.cpp
@@ -0,0 +1,89 @@
+#include "qt/graphics/QtStraightLineItem.h"
+
+#include
+#include
+#include
+
+#include "utility/math/Vector2.h"
+#include "utility/utility.h"
+
+#include "qt/graphics/QtRoundedRectItem.h"
+
+QtStraightLineItem::QtStraightLineItem(QGraphicsItem* parent)
+ : QGraphicsLineItem(parent)
+{
+ this->setAcceptHoverEvents(true);
+
+ m_circle = new QtRoundedRectItem(this);
+ m_circle->setRadius(10);
+ m_circle->setBrush(QBrush(QColor("#FFF")));
+ m_circle->setAcceptHoverEvents(true);
+
+ QFont font;
+ font.setFamily(GraphViewStyle::getFontNameOfNumber().c_str());
+ font.setPixelSize(GraphViewStyle::getFontSizeOfNumber());
+ font.setWeight(QFont::Normal);
+
+ m_number = new QGraphicsSimpleTextItem(this);
+ m_number->setFont(font);
+}
+
+QtStraightLineItem::~QtStraightLineItem()
+{
+}
+
+void QtStraightLineItem::updateLine(Vec4i ownerRect, Vec4i targetRect, int number, GraphViewStyle::EdgeStyle style)
+{
+ prepareGeometryChange();
+
+ const Vec4i& o = ownerRect;
+ const Vec4i& t = targetRect;
+
+ Vec2f oc((o.x + o.z) / 2, (o.y + o.w) / 2);
+ Vec2f tc((t.x + t.z) / 2, (t.y + t.w) / 2);
+
+ Vec2f mid;
+ Vec2f op;
+ Vec2f tp;
+
+ bool intersects = false;
+ for (int i = 0; !intersects && i < 4; i++)
+ {
+ switch (i)
+ {
+ case 0: intersects = utility::intersectionPoint(oc, tc, Vec2f(o.x, o.y), Vec2f(o.x, o.w), &op); break;
+ case 1: intersects = utility::intersectionPoint(oc, tc, Vec2f(o.x, o.y), Vec2f(o.z, o.y), &op); break;
+ case 2: intersects = utility::intersectionPoint(oc, tc, Vec2f(o.z, o.y), Vec2f(o.z, o.w), &op); break;
+ case 3: intersects = utility::intersectionPoint(oc, tc, Vec2f(o.x, o.w), Vec2f(o.z, o.w), &op); break;
+ }
+ }
+
+ intersects = false;
+ for (int i = 0; !intersects && i < 4; i++)
+ {
+ switch (i)
+ {
+ case 0: intersects = utility::intersectionPoint(oc, tc, Vec2f(t.x, t.y), Vec2f(t.x, t.w), &tp); break;
+ case 1: intersects = utility::intersectionPoint(oc, tc, Vec2f(t.x, t.y), Vec2f(t.z, t.y), &tp); break;
+ case 2: intersects = utility::intersectionPoint(oc, tc, Vec2f(t.z, t.y), Vec2f(t.z, t.w), &tp); break;
+ case 3: intersects = utility::intersectionPoint(oc, tc, Vec2f(t.x, t.w), Vec2f(t.z, t.w), &tp); break;
+ }
+ }
+
+ mid = (op + tp) / 2;
+
+ this->setLine(oc.x, oc.y, tc.x, tc.y);
+
+ m_circle->setRect(mid.x - 10, mid.y - 10, 20, 20);
+ m_circle->setPen(QPen(QColor(style.color.c_str()), 2));
+
+ QString numberStr = QString::number(number);
+ m_number->setText(numberStr);
+ m_number->setBrush(QBrush(QColor("#666")));
+ m_number->setPos(
+ mid.x - QFontMetrics(m_number->font()).width(numberStr) / 2,
+ mid.y - QFontMetrics(m_number->font()).height() / 2
+ );
+
+ this->setPen(QPen(QBrush(style.color.c_str()), number + style.width, Qt::SolidLine, Qt::RoundCap));
+}
diff --git a/src/app/qt/graphics/QtStraightLineItem.h b/src/app/qt/graphics/QtStraightLineItem.h
new file mode 100644
index 00000000..6f79934e
--- /dev/null
+++ b/src/app/qt/graphics/QtStraightLineItem.h
@@ -0,0 +1,26 @@
+#ifndef QT_STRAIGHT_LINE_ITEM_H
+#define QT_STRAIGHT_LINE_ITEM_H
+
+#include
+
+#include "utility/math/Vector4.h"
+
+#include "component/view/GraphViewStyle.h"
+
+class QtRoundedRectItem;
+
+class QtStraightLineItem
+ : public QGraphicsLineItem
+{
+public:
+ QtStraightLineItem(QGraphicsItem* parent);
+ virtual ~QtStraightLineItem();
+
+ void updateLine(Vec4i ownerRect, Vec4i targetRect, int number, GraphViewStyle::EdgeStyle style);
+
+private:
+ QtRoundedRectItem* m_circle;
+ QGraphicsSimpleTextItem* m_number;
+};
+
+#endif // QT_STRAIGHT_LINE_ITEM_H
diff --git a/src/app/qt/view/QtGraphView.cpp b/src/app/qt/view/QtGraphView.cpp
index a1acdde8..0c08520e 100644
--- a/src/app/qt/view/QtGraphView.cpp
+++ b/src/app/qt/view/QtGraphView.cpp
@@ -69,19 +69,10 @@ void QtGraphView::clear()
m_clearFunctor();
}
-GraphView::Metrics QtGraphView::getViewMetrics() const
+Vec2i QtGraphView::getViewSize() const
{
- GraphView::Metrics metrics;
QGraphicsView* view = getView();
-
- metrics.width = view->width();
- metrics.height = view->height();
-
- metrics.typeNameCharWidth = QFontMetrics(QtGraphNode::getFontForNodeType(Node::NODE_CLASS)).width("QtGraphNode") / 11.0f;
- metrics.variableNameCharWidth = QFontMetrics(QtGraphNode::getFontForNodeType(Node::NODE_FIELD)).width("QtGraphNode") / 11.0f;
- metrics.functionNameCharWidth = QFontMetrics(QtGraphNode::getFontForNodeType(Node::NODE_METHOD)).width("QtGraphNode") / 11.0f;
-
- return metrics;
+ return Vec2i(view->width(), view->height());
}
void QtGraphView::finishedTransition()
@@ -261,7 +252,7 @@ std::shared_ptr QtGraphView::createNodeRecursive(
}
}
- newNode->setStyle();
+ newNode->updateStyle();
return newNode;
}
@@ -281,11 +272,8 @@ std::shared_ptr QtGraphView::createEdge(QGraphicsView* view, const
std::shared_ptr qtEdge = std::make_shared(owner, target, edge.data);
qtEdge->setIsActive(edge.active);
- bool added = owner->addOutEdge(qtEdge) | target->addInEdge(qtEdge);
- if (!added)
- {
- return NULL;
- }
+ owner->addOutEdge(qtEdge);
+ target->addInEdge(qtEdge);
view->scene()->addItem(qtEdge.get());
diff --git a/src/app/qt/view/QtGraphView.h b/src/app/qt/view/QtGraphView.h
index ec4069eb..f884119a 100644
--- a/src/app/qt/view/QtGraphView.h
+++ b/src/app/qt/view/QtGraphView.h
@@ -35,7 +35,7 @@ public:
virtual void rebuildGraph(std::shared_ptr graph, const std::vector& nodes, const std::vector& edges);
virtual void clear();
- virtual GraphView::Metrics getViewMetrics() const;
+ virtual Vec2i getViewSize() const;
private slots:
void finishedTransition();
diff --git a/src/app/qt/view/QtGraphViewStyleImpl.cpp b/src/app/qt/view/QtGraphViewStyleImpl.cpp
new file mode 100644
index 00000000..3bd032bf
--- /dev/null
+++ b/src/app/qt/view/QtGraphViewStyleImpl.cpp
@@ -0,0 +1,8 @@
+#include "qt/view/QtGraphViewStyleImpl.h"
+
+#include
+
+float QtGraphViewStyleImpl::getCharWidthForNodeType(Node::NodeType type)
+{
+ return QFontMetrics(QtGraphNode::getFontForNodeType(type)).width("QtGraphNode::QtGraphNode::QtGraphNode") / 37.0f;
+}
diff --git a/src/app/qt/view/QtGraphViewStyleImpl.h b/src/app/qt/view/QtGraphViewStyleImpl.h
new file mode 100644
index 00000000..9957a9da
--- /dev/null
+++ b/src/app/qt/view/QtGraphViewStyleImpl.h
@@ -0,0 +1,14 @@
+#ifndef QT_GRAPH_VIEW_STYLE_IMPL_H
+#define QT_GRAPH_VIEW_STYLE_IMPL_H
+
+#include "component/view/GraphViewStyleImpl.h"
+#include "qt/view/graphElements/QtGraphNode.h"
+
+class QtGraphViewStyleImpl
+ : public GraphViewStyleImpl
+{
+public:
+ virtual float getCharWidthForNodeType(Node::NodeType type);
+};
+
+#endif // QT_GRAPH_VIEW_STYLE_IMPL_H
diff --git a/src/app/qt/view/QtViewFactory.cpp b/src/app/qt/view/QtViewFactory.cpp
index 81cb8735..1685fc69 100644
--- a/src/app/qt/view/QtViewFactory.cpp
+++ b/src/app/qt/view/QtViewFactory.cpp
@@ -1,8 +1,10 @@
#include "qt/view/QtViewFactory.h"
+#include "component/view/GraphViewStyle.h"
#include "qt/view/QtCodeView.h"
#include "qt/view/QtCompositeView.h"
#include "qt/view/QtGraphView.h"
+#include "qt/view/QtGraphViewStyleImpl.h"
#include "qt/view/QtMainView.h"
#include "qt/view/QtRefreshView.h"
#include "qt/view/QtSearchView.h"
@@ -38,6 +40,7 @@ std::shared_ptr QtViewFactory::createCodeView(ViewLayout* viewLayout)
std::shared_ptr QtViewFactory::createGraphView(ViewLayout* viewLayout) const
{
+ GraphViewStyle::setImpl(std::make_shared());
return View::createInitAndAddToLayout(viewLayout);
}
diff --git a/src/app/qt/view/graphElements/QtGraphEdge.cpp b/src/app/qt/view/graphElements/QtGraphEdge.cpp
index 0dc22b3c..c800e55d 100644
--- a/src/app/qt/view/graphElements/QtGraphEdge.cpp
+++ b/src/app/qt/view/graphElements/QtGraphEdge.cpp
@@ -1,384 +1,16 @@
#include "qt/view/graphElements/QtGraphEdge.h"
-#include
-
#include
#include
-#include
#include
#include "utility/messaging/type/MessageActivateTokens.h"
#include "component/view/graphElements/GraphNode.h"
+#include "component/view/GraphViewStyle.h"
#include "data/graph/token_component/TokenComponentAggregation.h"
-#include "qt/graphics/QtGraphicsRoundedRectItem.h"
-
-QtStraightConnection::QtStraightConnection(Vec4i ownerRect, Vec4i targetRect, int number, QGraphicsItem* parent)
- : QGraphicsLineItem(parent)
-{
- const Vec4i& o = ownerRect;
- const Vec4i& t = targetRect;
-
- Vec2f a((o.x + o.z) / 2, (o.y + o.w) / 2);
- Vec2f b((t.x + t.z) / 2, (t.y + t.w) / 2);
-
- this->setLine(a.x, a.y, b.x, b.y);
- this->setAcceptHoverEvents(true);
-
- Vec2f mid = (a + b) / 2;
- Vec2f u = b - a;
- float len = u.getLength();
- u.normalize();
-
- float alpha = atan2(u.y, u.x);
-
- Vec2f w;
- w.x = (o.z - o.x) / 2 * cos(alpha);
- w.y = (o.w - o.y) / 2 * sin(alpha);
- a += u * w.getLength();
- float newLen = w.getLength();
-
- w.x = (t.z - t.x) / 2 * cos(alpha);
- w.y = (t.w - t.y) / 2 * sin(alpha);
- b += u * -w.getLength();
- newLen -= w.getLength();
-
- if (newLen > 0 && newLen < len)
- {
- mid = (a + b) / 2;
- }
-
- m_circle = new QtGraphicsRoundedRectItem(this);
- m_circle->setRect(mid.x - 10, mid.y - 10, 20, 20);
- m_circle->setRadius(10);
- m_circle->setPen(QPen(QColor("#F8F8F8"), 2));
- m_circle->setBrush(QBrush(QColor("#FFF")));
- m_circle->setAcceptHoverEvents(true);
-
- QFont font;
- font.setFamily("Myriad Pro");
- font.setWeight(QFont::Normal);
- font.setPixelSize(9);
-
- m_number = new QGraphicsSimpleTextItem(this);
- m_number->setFont(font);
-
- QString numberStr = QString::number(number);
- m_number->setText(numberStr);
- m_number->setBrush(QBrush(QColor("#666")));
- m_number->setPos(
- mid.x - QFontMetrics(m_number->font()).width(numberStr) / 2,
- mid.y - QFontMetrics(m_number->font()).height() / 2
- );
-}
-
-QtStraightConnection::~QtStraightConnection()
-{
-}
-
-void QtStraightConnection::setColor(QColor color)
-{
- QPen p = this->pen();
- p.setColor(color);
- this->setPen(p);
-
- p = m_circle->pen();
- p.setColor(color);
- m_circle->setPen(p);
-}
-
-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)
- , m_closed(false)
- , m_big(false)
-{
- this->setAcceptHoverEvents(true);
-
- m_ownerRect.x = m_ownerRect.x - 1;
- m_ownerRect.z = m_ownerRect.z + 1;
- m_targetRect.x = m_targetRect.x - 1;
- m_targetRect.z = m_targetRect.z + 1;
-}
-
-QtCorneredConnection::~QtCorneredConnection()
-{
-}
-
-QPainterPath QtCorneredConnection::shape() const
-{
- int w = m_big ? 10 : 5;
- 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(-w, -w, w, w));
- }
- 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 > 1)
- {
- i--;
-
- 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 && std::abs(a.y() - b.y()) < 2 * br)
- {
- br = std::abs(a.y() - b.y()) / 2;
- }
- else if (dir % 2 == 0 && std::abs(a.x() - b.x()) < 2 * br)
- {
- br = std::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 = m_big ? 15 : 5;
- int arrowWidth = m_big ? 20 : 8;
- QPointF arrow = poly.at(0) + QPointF((poly.at(0).x() - poly.at(1).x() > 0 ? -1 : 1) * arrowLength, 0);
-
- if (m_closed)
- {
- path.lineTo(arrow);
- path.moveTo(poly.at(0));
- }
- else
- {
- path.lineTo(poly.at(0));
- }
-
- arrow.setY(arrow.y() - arrowWidth / 2);
- path.lineTo(arrow);
- arrow.setY(arrow.y() + arrowWidth);
- if (m_closed)
- {
- path.lineTo(arrow);
- }
- else
- {
- path.moveTo(arrow);
- }
- path.lineTo(poly.at(0));
-
- painter->drawPath(path);
-}
-
-void QtCorneredConnection::setClosed(bool closed)
-{
- m_closed = closed;
-}
-
-void QtCorneredConnection::setBig(bool big)
-{
- m_big = big;
-}
-
-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 offsetO = 17;
- float offsetT = m_big ? 29 : 17;
-
- QPoint tp((it ? 1 : -1) * offsetT + t[it].x, t[it].y);
- QPoint op((io ? 1 : -1) * offsetO + o[io].x, o[io].y);
-
- if (it != io)
- {
- if (it && tp.x() < op.x())
- {
- io = 0;
- op = QPoint(o[io].x - offsetO, o[io].y);
- }
- else if (!it && tp.x() < op.x())
- {
- it = 1;
- tp = QPoint(t[it].x + offsetT, t[it].y);
- }
- else if (io && tp.x() > op.x())
- {
- io = 1;
- op = QPoint(o[io].x + offsetO, o[io].y);
- }
- else if (!io && tp.x() > op.x())
- {
- it = 0;
- tp = QPoint(t[it].x - offsetT, 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);
-
- int verticalOffset = 3;
- if (o[io].y < t[it].y)
- {
- op.setX(op.x() + verticalOffset);
- tp.setX(tp.x() + verticalOffset);
- }
- else
- {
- op.setX(op.x() - verticalOffset);
- tp.setX(tp.x() - verticalOffset);
- }
-
- 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;
- }
- }
-}
-
+#include "qt/graphics/QtAngledLineItem.h"
+#include "qt/graphics/QtStraightLineItem.h"
QtGraphEdge::QtGraphEdge(const std::weak_ptr& owner, const std::weak_ptr& target, const Edge* data)
: GraphEdge(data)
@@ -389,9 +21,6 @@ QtGraphEdge::QtGraphEdge(const std::weak_ptr& owner, const std::weak_
, m_mousePos(0.0f, 0.0f)
, m_mouseMoved(false)
{
- this->setAcceptHoverEvents(true);
- this->setZValue(getZValue(false)); // Used to draw edges always on top of nodes.
-
this->updateLine();
}
@@ -420,61 +49,38 @@ void QtGraphEdge::updateLine()
return;
}
- if (m_child)
- {
- delete m_child;
- }
+ GraphViewStyle::EdgeStyle style = GraphViewStyle::getStyleForEdgeType(getData()->getType(), m_isActive, false);
- if (isAggregation())
+ if (style.isStraight)
{
- m_child =
- new QtStraightConnection(owner->getBoundingRect(), target->getBoundingRect(), getAggregationCount(), this);
+ if (!m_child)
+ {
+ m_child = new QtStraightLineItem(this);
+ }
+
+ int number = 0;
+ if (getData()->isType(Edge::EDGE_AGGREGATION))
+ {
+ number = getData()->getComponent()->getAggregationCount();
+ }
+
+ dynamic_cast(m_child)->updateLine(
+ owner->getBoundingRect(), target->getBoundingRect(), number, style);
}
else
{
- QtCorneredConnection* child = new QtCorneredConnection(
- owner->getBoundingRect(), target->getBoundingRect(),
- owner->getParentBoundingRect(), target->getParentBoundingRect(),
- this
- );
-
- if (isInheritance())
+ if (!m_child)
{
- child->setClosed(true);
- child->setBig(true);
+ m_child = new QtAngledLineItem(this);
}
- m_child = child;
+ dynamic_cast(m_child)->updateLine(
+ owner->getBoundingRect(), target->getBoundingRect(),
+ owner->getParentBoundingRect(), target->getParentBoundingRect(),
+ style);
}
- 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:
- case Edge::EDGE_OVERRIDE:
- color = QColor("#CC5E89");
- break;
- case Edge::EDGE_AGGREGATION:
- color = QColor("#F8F8F8");
- break;
- case Edge::EDGE_INCLUDE:
- color = QColor("#87BA50");
- break;
- default:
- color = QColor("#878787");
- break;
- }
-
- m_child->setPen(QPen(color, getPenWidth(), Qt::SolidLine, Qt::RoundCap));
-
- setIsActive(m_isActive);
+ this->setZValue(style.zValue); // Used to draw edges always on top of nodes.
}
bool QtGraphEdge::getIsActive() const
@@ -486,39 +92,12 @@ void QtGraphEdge::setIsActive(bool isActive)
{
m_isActive = isActive;
- if (isActive)
- {
- if (isAggregation())
- {
- dynamic_cast(m_child)->setColor(QColor("#EEE"));
- }
- else
- {
- QPen p = m_child->pen();
- p.setWidthF(getPenWidth() + 1);
- m_child->setPen(p);
- }
- this->setZValue(getZValue(isActive));
- }
- else
- {
- if (isAggregation())
- {
- dynamic_cast(m_child)->setColor(QColor("#F8F8F8"));
- }
- else
- {
- QPen p = m_child->pen();
- p.setWidthF(getPenWidth());
- m_child->setPen(p);
- }
- this->setZValue(getZValue(isActive));
- }
+ updateLine();
}
void QtGraphEdge::onClick()
{
- if (isAggregation())
+ if (getData()->isType(Edge::EDGE_AGGREGATION))
{
const std::set& ids = getData()->getComponent()->getAggregationIds();
MessageActivateTokens message(std::vector(ids.begin(), ids.end()));
@@ -568,49 +147,3 @@ void QtGraphEdge::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
this->setIsActive(m_isActive);
}
-
-bool QtGraphEdge::isAggregation() const
-{
- return getData()->getType() == Edge::EDGE_AGGREGATION;
-}
-
-bool QtGraphEdge::isInheritance() const
-{
- return getData()->getType() == Edge::EDGE_INHERITANCE;
-}
-
-int QtGraphEdge::getZValue(bool active) const
-{
- if (isAggregation())
- {
- if (active)
- {
- return -1;
- }
- return -5;
- }
-
- if (active)
- {
- return 5;
- }
- return 1;
-}
-
-float QtGraphEdge::getPenWidth() const
-{
- if (isAggregation())
- {
- return getAggregationCount() + 1;
- }
- return 1;
-}
-
-int QtGraphEdge::getAggregationCount() const
-{
- if (isAggregation())
- {
- return getData()->getComponent()->getAggregationCount();
- }
- return 0;
-}
diff --git a/src/app/qt/view/graphElements/QtGraphEdge.h b/src/app/qt/view/graphElements/QtGraphEdge.h
index a6b26b0e..b720b798 100644
--- a/src/app/qt/view/graphElements/QtGraphEdge.h
+++ b/src/app/qt/view/graphElements/QtGraphEdge.h
@@ -10,49 +10,6 @@
#include "component/view/graphElements/GraphEdge.h"
class GraphNode;
-class QtGraphicsRoundedRectItem;
-
-class QtStraightConnection
- : public QGraphicsLineItem
-{
-public:
- QtStraightConnection(Vec4i ownerRect, Vec4i targetRect, int number, QGraphicsItem* parent);
- virtual ~QtStraightConnection();
-
- void setColor(QColor color);
-
-private:
- QtGraphicsRoundedRectItem* m_circle;
- QGraphicsSimpleTextItem* m_number;
-};
-
-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);
-
- void setClosed(bool closed);
- void setBig(bool big);
-
-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;
-
- bool m_closed;
- bool m_big;
-};
-
class QtGraphEdge
: public QObject
@@ -85,13 +42,6 @@ protected:
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
private:
- bool isAggregation() const;
- bool isInheritance() const;
-
- int getZValue(bool active) const;
- float getPenWidth() const;
- int getAggregationCount() const;
-
std::weak_ptr m_owner;
std::weak_ptr m_target;
diff --git a/src/app/qt/view/graphElements/QtGraphNode.cpp b/src/app/qt/view/graphElements/QtGraphNode.cpp
index 1c114358..ec996886 100644
--- a/src/app/qt/view/graphElements/QtGraphNode.cpp
+++ b/src/app/qt/view/graphElements/QtGraphNode.cpp
@@ -7,11 +7,10 @@
#include "utility/messaging/type/MessageActivateTokens.h"
#include "utility/messaging/type/MessageGraphNodeMove.h"
-#include "qt/graphics/QtGraphicsRoundedRectItem.h"
+#include "qt/graphics/QtRoundedRectItem.h"
#include "qt/utility/QtDeviceScaledPixmap.h"
#include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h"
#include "qt/view/graphElements/QtGraphEdge.h"
-#include "settings/ApplicationSettings.h"
void QtGraphNode::blendIn()
{
@@ -35,36 +34,8 @@ void QtGraphNode::hideNode()
QFont QtGraphNode::getFontForNodeType(Node::NodeType type)
{
- QFont font("Source Code Pro");
-
- switch (type)
- {
- case Node::NODE_UNDEFINED:
- case Node::NODE_NAMESPACE:
- font.setPixelSize(12);
- break;
-
- case Node::NODE_UNDEFINED_TYPE:
- case Node::NODE_STRUCT:
- case Node::NODE_CLASS:
- case Node::NODE_ENUM:
- case Node::NODE_TYPEDEF:
- case Node::NODE_TEMPLATE_PARAMETER_TYPE:
- case Node::NODE_FILE:
- font.setPixelSize(14);
- break;
-
- case Node::NODE_UNDEFINED_FUNCTION:
- case Node::NODE_UNDEFINED_VARIABLE:
- case Node::NODE_FUNCTION:
- case Node::NODE_METHOD:
- case Node::NODE_GLOBAL_VARIABLE:
- case Node::NODE_FIELD:
- case Node::NODE_ENUM_CONSTANT:
- font.setPixelSize(11);
- break;
- }
-
+ QFont font(GraphViewStyle::getFontNameForNodeType(type).c_str());
+ font.setPixelSize(GraphViewStyle::getFontSizeForNodeType(type));
return font;
}
@@ -76,7 +47,7 @@ QtGraphNode::QtGraphNode()
{
this->setPen(QPen(Qt::transparent));
- m_rect = new QtGraphicsRoundedRectItem(this);
+ m_rect = new QtRoundedRectItem(this);
m_text = new QGraphicsSimpleTextItem(this);
}
@@ -88,7 +59,7 @@ QtGraphNode::QtGraphNode(const Node* data)
{
this->setPen(QPen(Qt::transparent));
- m_rect = new QtGraphicsRoundedRectItem(this);
+ m_rect = new QtRoundedRectItem(this);
m_text = new QGraphicsSimpleTextItem(this);
this->setAcceptHoverEvents(true);
@@ -184,46 +155,22 @@ Vec4i QtGraphNode::getParentBoundingRect() const
return node->getBoundingRect();
}
-bool QtGraphNode::addOutEdge(const std::shared_ptr& edge)
+void QtGraphNode::addOutEdge(const std::shared_ptr& edge)
{
- // for (std::list>::iterator it = m_outEdges.begin(); it != m_outEdges.end(); it++)
- // {
- // if ((*it)->getOwner().lock() == edge->getOwner().lock() &&
- // (*it)->getTarget().lock() == edge->getTarget().lock())
- // {
- // return false;
- // }
- // }
-
m_outEdges.push_back(edge);
- return true;
}
-bool QtGraphNode::addInEdge(const std::weak_ptr& edge)
+void QtGraphNode::addInEdge(const std::weak_ptr& edge)
{
- // for (std::list>::iterator it = m_inEdges.begin(); it != m_inEdges.end(); it++)
- // {
- // std::shared_ptr existingEdge = it->lock();
- // if (existingEdge != NULL)
- // {
- // if (existingEdge->getOwner().lock() == edge.lock()->getOwner().lock() &&
- // existingEdge->getTarget().lock() == edge.lock()->getTarget().lock())
- // {
- // return false;
- // }
- // }
- // }
-
m_inEdges.push_back(edge);
- return true;
}
-unsigned int QtGraphNode::getOutEdgeCount() const
+size_t QtGraphNode::getOutEdgeCount() const
{
return m_outEdges.size();
}
-unsigned int QtGraphNode::getInEdgeCount() const
+size_t QtGraphNode::getInEdgeCount() const
{
return m_inEdges.size();
}
@@ -247,7 +194,7 @@ void QtGraphNode::setIsActive(bool isActive)
{
m_isActive = isActive;
- setStyle();
+ updateStyle();
}
QtGraphNode* QtGraphNode::getParent() const
@@ -281,136 +228,6 @@ void QtGraphNode::addSubNode(const std::shared_ptr& node)
m_subNodes.push_back(node);
}
-void QtGraphNode::setStyle()
-{
- if (!m_data)
- {
- return;
- }
-
- QColor color = Qt::lightGray;
- qreal radius = 0.0f;
- QPen p(Qt::transparent);
- QFont font(getFontForNodeType(m_data->getType()));
-
- bool useUndefinedPattern = false;
- bool useUndefinedColor = false;
-
- Vec2i padding;
-
- switch (m_data->getType())
- {
- case Node::NODE_UNDEFINED:
- p.setStyle(Qt::DashLine);
- case Node::NODE_NAMESPACE:
- color = Qt::transparent;
-
- p.setColor("#cc8d91");
- p.setWidth(1);
-
- radius = 20.0f;
- padding.x = 15;
- padding.y = 6;
- break;
-
- case Node::NODE_UNDEFINED_TYPE:
- useUndefinedPattern = true;
- case Node::NODE_STRUCT:
- case Node::NODE_CLASS:
- case Node::NODE_ENUM:
- case Node::NODE_TYPEDEF:
- case Node::NODE_TEMPLATE_PARAMETER_TYPE:
- case Node::NODE_FILE:
- if (m_isActive)
- {
- font.setWeight(QFont::Bold);
- }
-
- if (m_isHovering)
- {
- m_rect->setShadow(QColor(0, 0, 0, 255), 5);
- }
- else
- {
- m_rect->setShadow(QColor(0, 0, 0, 128), 5);
- }
-
- color = ApplicationSettings::getInstance()->getNodeTypeColor(m_data->getType()).c_str();
- if (m_subNodes.size())
- {
- radius = 20.0f;
- padding.x = 15;
- padding.y = 8;
- }
- else
- {
- radius = 10.0f;
- padding.x = 8;
- padding.y = 4;
- }
- break;
-
- case Node::NODE_UNDEFINED_FUNCTION:
- case Node::NODE_UNDEFINED_VARIABLE:
- useUndefinedPattern = true;
- useUndefinedColor = true;
- case Node::NODE_FUNCTION:
- case Node::NODE_METHOD:
- case Node::NODE_GLOBAL_VARIABLE:
- case Node::NODE_FIELD:
- case Node::NODE_ENUM_CONSTANT:
- if (m_isActive || m_isHovering)
- {
- color = ApplicationSettings::getInstance()->getNodeTypeColor(m_data->getType(), "hover").c_str();
- font.setWeight(QFont::Bold);
- }
- else
- {
- color = ApplicationSettings::getInstance()->getNodeTypeColor(m_data->getType()).c_str();
- }
-
- radius = 8.0f;
- padding.x = 5;
- padding.y = 3;
- break;
- }
-
- if (m_isActive)
- {
- p.setWidthF(1.5f);
- p.setColor("#3c3c3c");
- }
-
- m_rect->setPen(p);
- m_rect->setBrush(QBrush(color));
- m_rect->setRadius(radius);
-
- if (useUndefinedPattern)
- {
- QtDeviceScaledPixmap pixmap("data/gui/graph_view/images/pattern.png");
- pixmap.scaleToHeight(10);
-
- if (!m_undefinedRect)
- {
- m_undefinedRect = new QtGraphicsRoundedRectItem(this);
- setSize(getSize());
- }
-
- p.setWidth(1);
- p.setColor(Qt::transparent);
- if (useUndefinedColor && !m_isActive)
- {
- p.setColor(color);
- }
- m_undefinedRect->setPen(p);
- m_undefinedRect->setBrush(QBrush(pixmap.pixmap()));
- m_undefinedRect->setRadius(radius);
- }
-
- m_text->setFont(font);
- m_text->setPos(padding.x, padding.y);
-}
-
void QtGraphNode::setShadowEnabledRecursive(bool enabled)
{
m_rect->setShadowEnabled(enabled);
@@ -440,6 +257,13 @@ void QtGraphNode::hoverEnter()
}
}
+void QtGraphNode::updateStyle()
+{
+ GraphViewStyle::NodeStyle style =
+ GraphViewStyle::getStyleForNodeType(m_data->getType(), m_isActive, m_isHovering, m_subNodes.size() > 0);
+ setStyle(style);
+}
+
void QtGraphNode::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
event->ignore();
@@ -500,13 +324,13 @@ void QtGraphNode::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
void QtGraphNode::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
m_isHovering = true;
- setStyle();
+ updateStyle();
}
void QtGraphNode::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
m_isHovering = false;
- setStyle();
+ updateStyle();
}
void QtGraphNode::notifyEdgesAfterMove()
@@ -530,3 +354,54 @@ void QtGraphNode::notifyEdgesAfterMove()
node->notifyEdgesAfterMove();
}
}
+
+void QtGraphNode::setStyle(const GraphViewStyle::NodeStyle& style)
+{
+ QColor color = style.color.c_str();
+ qreal radius = style.cornerRadius;
+
+ QPen p(style.borderColor.c_str());
+ p.setWidthF(style.borderWidth);
+ if (style.borderDashed)
+ {
+ p.setStyle(Qt::DashLine);
+ }
+
+ QFont font(style.fontName.c_str());
+ font.setPixelSize(style.fontSize);
+ if (style.fontBold)
+ {
+ font.setWeight(QFont::Bold);
+ }
+
+ if (style.shadowColor.size())
+ {
+ m_rect->setShadow(style.shadowColor.c_str(), style.shadowBlurRadius);
+ }
+
+ m_rect->setPen(p);
+ m_rect->setBrush(QBrush(color));
+ m_rect->setRadius(radius);
+
+ if (style.undefinedPattern)
+ {
+ QtDeviceScaledPixmap pixmap("data/gui/graph_view/images/pattern.png");
+ pixmap.scaleToHeight(10);
+
+ if (!m_undefinedRect)
+ {
+ m_undefinedRect = new QtRoundedRectItem(this);
+ setSize(getSize());
+ }
+
+ p.setWidth(0);
+ p.setColor(Qt::transparent);
+
+ m_undefinedRect->setPen(p);
+ m_undefinedRect->setBrush(QBrush(pixmap.pixmap()));
+ m_undefinedRect->setRadius(radius);
+ }
+
+ m_text->setFont(font);
+ m_text->setPos(style.textOffset.x, style.textOffset.y);
+}
diff --git a/src/app/qt/view/graphElements/QtGraphNode.h b/src/app/qt/view/graphElements/QtGraphNode.h
index 05346fe6..00bee876 100644
--- a/src/app/qt/view/graphElements/QtGraphNode.h
+++ b/src/app/qt/view/graphElements/QtGraphNode.h
@@ -5,9 +5,10 @@
#include
#include "component/view/graphElements/GraphNode.h"
+#include "component/view/GraphViewStyle.h"
class QtGraphEdge;
-class QtGraphicsRoundedRectItem;
+class QtRoundedRectItem;
class QtGraphNodeComponent;
class QtGraphNode
@@ -49,11 +50,11 @@ public:
virtual Vec4i getBoundingRect() const;
virtual Vec4i getParentBoundingRect() const;
- virtual bool addOutEdge(const std::shared_ptr& edge);
- virtual bool addInEdge(const std::weak_ptr& edge);
+ virtual void addOutEdge(const std::shared_ptr& edge);
+ virtual void addInEdge(const std::weak_ptr& edge);
- virtual unsigned int getOutEdgeCount() const;
- virtual unsigned int getInEdgeCount() const;
+ virtual size_t getOutEdgeCount() const;
+ virtual size_t getInEdgeCount() const;
QSize size() const;
void setSize(const QSize& size);
@@ -69,12 +70,13 @@ public:
std::list> getSubNodes() const;
virtual void addSubNode(const std::shared_ptr& node);
- void setStyle();
void setShadowEnabledRecursive(bool enabled);
virtual void onClick();
void hoverEnter();
+ virtual void updateStyle();
+
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
@@ -85,6 +87,8 @@ protected:
void notifyEdgesAfterMove();
+ void setStyle(const GraphViewStyle::NodeStyle& style);
+
std::list> m_outEdges;
std::list> m_inEdges;
@@ -92,8 +96,8 @@ protected:
std::list> m_subNodes;
QGraphicsSimpleTextItem* m_text;
- QtGraphicsRoundedRectItem* m_rect;
- QtGraphicsRoundedRectItem* m_undefinedRect;
+ QtRoundedRectItem* m_rect;
+ QtRoundedRectItem* m_undefinedRect;
Vec2i m_size;
diff --git a/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp b/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp
index 06a64546..74c8c057 100644
--- a/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp
+++ b/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp
@@ -6,7 +6,8 @@
#include "utility/messaging/type/MessageGraphNodeExpand.h"
-#include "qt/graphics/QtGraphicsRoundedRectItem.h"
+#include "component/view/GraphViewStyle.h"
+#include "qt/graphics/QtRoundedRectItem.h"
#include "qt/utility/QtDeviceScaledPixmap.h"
QtGraphNodeAccess::QtAccessToggle::QtAccessToggle(bool expanded, int invisibleSubNodeCount, QGraphicsItem* parent)
@@ -28,9 +29,9 @@ QtGraphNodeAccess::QtAccessToggle::QtAccessToggle(bool expanded, int invisibleSu
if (invisibleSubNodeCount)
{
QFont font;
- font.setFamily("Myriad Pro");
+ font.setFamily(GraphViewStyle::getFontNameOfNumber().c_str());
+ font.setPixelSize(GraphViewStyle::getFontSizeOfNumber());
font.setWeight(QFont::Normal);
- font.setPixelSize(9);
m_number = new QGraphicsSimpleTextItem(this);
m_number->setFont(font);
@@ -64,20 +65,6 @@ QtGraphNodeAccess::QtGraphNodeAccess(
, m_access(accessType)
, m_accessIconSize(20)
{
- Vec2i padding(10, 10);
-
- QFont font;
- font.setFamily("Myriad Pro");
- font.setWeight(QFont::Bold);
- font.setPixelSize(11);
- font.setCapitalization(QFont::AllUppercase);
- m_text->setFont(font);
- m_text->setPos(padding.x + m_accessIconSize + 3, padding.y + m_accessIconSize / 2 - 1);
-
- m_rect->setPen(QPen(Qt::transparent));
- m_rect->setBrush(QBrush(Qt::white));
- m_rect->setRadius(12.0f);
-
std::string accessString = TokenComponentAccess::getAccessString(accessType);
this->setName(accessString);
m_text->hide();
@@ -86,8 +73,6 @@ QtGraphNodeAccess::QtGraphNodeAccess(
pixmap.scaleToHeight(m_accessIconSize);
m_accessIcon = new QGraphicsPixmapItem(pixmap.pixmap(), this);
- m_accessIcon->setPos(padding.x, padding.y);
-
m_accessToggle = new QtAccessToggle(expanded, invisibleSubNodeCount, this);
}
@@ -128,6 +113,19 @@ void QtGraphNodeAccess::onClick()
}
}
+void QtGraphNodeAccess::updateStyle()
+{
+ GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleOfAccessNode();
+ setStyle(style);
+
+ QFont font = m_text->font();
+ font.setCapitalization(QFont::AllUppercase);
+ m_text->setFont(font);
+
+ m_text->setPos(style.textOffset.x + m_accessIconSize + 3, style.textOffset.y + m_accessIconSize / 2 - 1);
+ m_accessIcon->setPos(style.textOffset.x, style.textOffset.y);
+}
+
void QtGraphNodeAccess::hideLabel()
{
m_text->hide();
diff --git a/src/app/qt/view/graphElements/QtGraphNodeAccess.h b/src/app/qt/view/graphElements/QtGraphNodeAccess.h
index 6b4e0da5..90022b7e 100644
--- a/src/app/qt/view/graphElements/QtGraphNodeAccess.h
+++ b/src/app/qt/view/graphElements/QtGraphNodeAccess.h
@@ -30,6 +30,8 @@ public:
virtual void addSubNode(const std::shared_ptr& node);
virtual void onClick();
+ virtual void updateStyle();
+
void hideLabel();
private:
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index d2b4db2e..3456de96 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -54,6 +54,9 @@ add_files(
component/view/CompositeView.h
component/view/GraphView.cpp
component/view/GraphView.h
+ component/view/GraphViewStyle.cpp
+ component/view/GraphViewStyle.h
+ component/view/GraphViewStyleImpl.h
component/view/MainView.cpp
component/view/MainView.h
component/view/RefreshView.cpp
@@ -264,6 +267,8 @@ add_files(
utility/ConfigManager.h
utility/Property.h
utility/types.h
+ utility/utility.cpp
+ utility/utility.h
utility/utilityString.cpp
utility/utilityString.h
utility/Vector.h
diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp
index c5dc9dba..bbf9fe50 100644
--- a/src/lib/component/controller/GraphController.cpp
+++ b/src/lib/component/controller/GraphController.cpp
@@ -7,22 +7,10 @@
#include "component/view/graphElements/GraphEdge.h"
#include "component/view/graphElements/GraphNode.h"
#include "component/view/GraphView.h"
+#include "component/view/GraphViewStyle.h"
#include "data/access/StorageAccess.h"
#include "data/graph/Graph.h"
-GraphController::Margins::Margins()
- : left(0)
- , right(0)
- , top(0)
- , bottom(0)
- , betweenX(0)
- , betweenY(0)
- , minWidth(0)
- , charWidth(0.0f)
-{
-}
-
-
GraphController::GraphController(StorageAccess* storageAccess)
: m_storageAccess(storageAccess)
{
@@ -357,11 +345,6 @@ void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode& node) const
void GraphController::layoutNesting()
{
- if (!m_viewMetrics.width)
- {
- m_viewMetrics = getView()->getViewMetrics();
- }
-
for (DummyNode& node : m_dummyNodes)
{
layoutNestingRecursive(node);
@@ -370,7 +353,26 @@ void GraphController::layoutNesting()
void GraphController::layoutNestingRecursive(DummyNode& node) const
{
- Margins margins = getMarginsForDummyNode(node);
+ GraphViewStyle::NodeMargins margins;
+
+ if (node.data)
+ {
+ margins = GraphViewStyle::getMarginsForNodeType(node.data->getType(), node.subNodes.size() > 0);
+ }
+ else
+ {
+ node.invisibleSubNodeCount = 0;
+ for (const DummyNode& subNode : node.subNodes)
+ {
+ if (!subNode.visible)
+ {
+ node.invisibleSubNodeCount++;
+ }
+ }
+
+ margins = GraphViewStyle::getMarginsOfAccessNode(
+ node.isExpanded(), node.subNodes.size(), node.invisibleSubNodeCount);
+ }
int y = 0;
int x = 0;
@@ -410,7 +412,7 @@ void GraphController::layoutNestingRecursive(DummyNode& node) const
if (layoutHorizontal)
{
- x += subNode.size.x + margins.betweenX;
+ x += subNode.size.x + margins.spacingX;
if (subNode.size.y > height)
{
height = subNode.size.y;
@@ -418,7 +420,7 @@ void GraphController::layoutNestingRecursive(DummyNode& node) const
}
else
{
- y += subNode.size.y + margins.betweenY;
+ y += subNode.size.y + margins.spacingY;
if (subNode.size.x > width)
{
width = subNode.size.x;
@@ -428,11 +430,11 @@ void GraphController::layoutNestingRecursive(DummyNode& node) const
if (x > 0)
{
- x -= margins.betweenX;
+ x -= margins.spacingX;
}
if (y > 0)
{
- y -= margins.betweenY;
+ y -= margins.spacingY;
}
if (layoutHorizontal && x > width)
@@ -444,107 +446,6 @@ void GraphController::layoutNestingRecursive(DummyNode& node) const
node.size.y = margins.top + y + height + margins.bottom;
}
-GraphController::Margins GraphController::getMarginsForDummyNode(DummyNode& node) const
-{
- Margins margins;
- margins.betweenX = margins.betweenY = 8;
-
- if (node.data)
- {
- switch (node.data->getType())
- {
- case Node::NODE_UNDEFINED:
- case Node::NODE_NAMESPACE:
- margins.left = margins.right = 15;
- margins.top = 28;
- margins.bottom = 15;
-
- margins.charWidth = m_viewMetrics.typeNameCharWidth;
- break;
-
- case Node::NODE_UNDEFINED_TYPE:
- case Node::NODE_STRUCT:
- case Node::NODE_CLASS:
- case Node::NODE_ENUM:
- case Node::NODE_TYPEDEF:
- case Node::NODE_TEMPLATE_PARAMETER_TYPE:
- case Node::NODE_FILE:
- if (node.subNodes.size())
- {
- margins.left = margins.right = 15;
- margins.top = 30;
- margins.bottom = 10;
- }
- else
- {
- margins.left = margins.right = 8;
- margins.top = margins.bottom = 13;
- }
-
- margins.charWidth = m_viewMetrics.typeNameCharWidth;
- break;
-
- case Node::NODE_UNDEFINED_FUNCTION:
- case Node::NODE_FUNCTION:
- case Node::NODE_METHOD:
- margins.left = margins.right = 5;
- margins.top = margins.bottom = 10;
-
- margins.charWidth = m_viewMetrics.functionNameCharWidth;
- break;
-
- case Node::NODE_UNDEFINED_VARIABLE:
- case Node::NODE_GLOBAL_VARIABLE:
- case Node::NODE_FIELD:
- case Node::NODE_ENUM_CONSTANT:
- margins.left = margins.right = 5;
- margins.top = margins.bottom = 10;
-
- margins.charWidth = m_viewMetrics.variableNameCharWidth;
- break;
- }
- }
- else
- {
- node.invisibleSubNodeCount = 0;
- for (const DummyNode& subNode : node.subNodes)
- {
- if (!subNode.visible)
- {
- node.invisibleSubNodeCount++;
- }
- }
-
- margins.left = margins.right = 10;
- margins.top = 40;
-
- if (node.invisibleSubNodeCount == node.subNodes.size())
- {
- margins.minWidth = 20;
- margins.bottom = 10;
- }
- else
- {
- margins.minWidth = 82;
-
- if (node.isExpanded())
- {
- margins.bottom = 15;
- }
- else if (node.invisibleSubNodeCount)
- {
- margins.bottom = 23;
- }
- else
- {
- margins.bottom = 10;
- }
- }
- }
-
- return margins;
-}
-
DummyNode* GraphController::findDummyNodeRecursive(std::vector& nodes, Id tokenId)
{
for (DummyNode& node : nodes)
diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h
index 644b63b2..c74a0a9a 100644
--- a/src/lib/component/controller/GraphController.h
+++ b/src/lib/component/controller/GraphController.h
@@ -27,23 +27,6 @@ class GraphController
, public MessageListener
{
public:
- struct Margins
- {
- Margins();
-
- int left;
- int right;
-
- int top;
- int bottom;
-
- int betweenX;
- int betweenY;
-
- int minWidth;
- float charWidth;
- };
-
GraphController(StorageAccess* storageAccess);
~GraphController();
@@ -70,12 +53,10 @@ private:
void layoutNesting();
void layoutNestingRecursive(DummyNode& node) const;
- Margins getMarginsForDummyNode(DummyNode& node) const;
DummyNode* findDummyNodeRecursive(std::vector& nodes, Id tokenId);
DummyNode* findDummyNodeAccessRecursive(std::vector& nodes, Id parentId, TokenComponentAccess::AccessType type);
StorageAccess* m_storageAccess;
- GraphView::Metrics m_viewMetrics;
std::vector m_dummyNodes;
std::vector m_dummyEdges;
diff --git a/src/lib/component/view/GraphView.cpp b/src/lib/component/view/GraphView.cpp
index 265f3da2..e3b3e952 100644
--- a/src/lib/component/view/GraphView.cpp
+++ b/src/lib/component/view/GraphView.cpp
@@ -1,14 +1,5 @@
#include "component/view/GraphView.h"
-GraphView::Metrics::Metrics()
- : width(0)
- , height(0)
- , typeNameCharWidth(0.0f)
- , variableNameCharWidth(0.0f)
- , functionNameCharWidth(0.0f)
-{
-}
-
GraphView::GraphView(ViewLayout* viewLayout)
: View(viewLayout)
{
diff --git a/src/lib/component/view/GraphView.h b/src/lib/component/view/GraphView.h
index cf1c5c2a..b507d337 100644
--- a/src/lib/component/view/GraphView.h
+++ b/src/lib/component/view/GraphView.h
@@ -4,6 +4,7 @@
#include
#include
+#include "utility/math/Vector2.h"
#include "utility/types.h"
#include "component/view/View.h"
@@ -15,18 +16,6 @@ class Graph;
class GraphView : public View
{
public:
- struct Metrics
- {
- Metrics();
-
- int width;
- int height;
-
- float typeNameCharWidth;
- float variableNameCharWidth;
- float functionNameCharWidth;
- };
-
GraphView(ViewLayout* viewLayout);
virtual ~GraphView();
@@ -36,7 +25,7 @@ public:
std::shared_ptr graph, const std::vector& nodes, const std::vector& edges) = 0;
virtual void clear() = 0;
- virtual Metrics getViewMetrics() const = 0;
+ virtual Vec2i getViewSize() const = 0;
};
-#endif // GRAPH_VIEW_H
\ No newline at end of file
+#endif // GRAPH_VIEW_H
diff --git a/src/lib/component/view/GraphViewStyle.cpp b/src/lib/component/view/GraphViewStyle.cpp
new file mode 100644
index 00000000..6397dd92
--- /dev/null
+++ b/src/lib/component/view/GraphViewStyle.cpp
@@ -0,0 +1,401 @@
+#include "component/view/GraphViewStyle.h"
+
+#include "utility/logging/logging.h"
+
+#include "settings/ApplicationSettings.h"
+
+GraphViewStyle::NodeMargins::NodeMargins()
+ : left(0)
+ , right(0)
+ , top(0)
+ , bottom(0)
+ , spacingX(0)
+ , spacingY(0)
+ , minWidth(0)
+ , charWidth(0.0f)
+{
+}
+
+GraphViewStyle::NodeStyle::NodeStyle()
+ : shadowBlurRadius(0)
+ , cornerRadius(0)
+ , borderWidth(0)
+ , borderDashed(false)
+ , fontSize(0)
+ , fontBold(false)
+ , undefinedPattern(false)
+{
+}
+
+GraphViewStyle::EdgeStyle::EdgeStyle()
+ : width(0)
+ , zValue(0)
+ , isStraight(false)
+ , arrowLength(0)
+ , arrowWidth(0)
+ , arrowClosed(false)
+ , cornerRadius(0)
+ , verticalOffset(0)
+{
+}
+
+std::shared_ptr GraphViewStyle::getImpl()
+{
+ if (!s_impl)
+ {
+ LOG_ERROR("No GraphViewStyleImpl instance set.");
+ return nullptr;
+ }
+
+ return s_impl;
+}
+
+void GraphViewStyle::setImpl(std::shared_ptr impl)
+{
+ s_impl = impl;
+}
+
+float GraphViewStyle::getCharWidthForNodeType(Node::NodeType type)
+{
+ std::map::const_iterator it = s_charWidths.find(type);
+
+ if (it != s_charWidths.end())
+ {
+ return it->second;
+ }
+
+ float charWidth = getImpl()->getCharWidthForNodeType(type);
+ s_charWidths.emplace(type, charWidth);
+ return charWidth;
+}
+
+size_t GraphViewStyle::getFontSizeForNodeType(Node::NodeType type)
+{
+ switch (type)
+ {
+ case Node::NODE_UNDEFINED:
+ case Node::NODE_NAMESPACE:
+ return 12;
+
+ case Node::NODE_UNDEFINED_TYPE:
+ case Node::NODE_STRUCT:
+ case Node::NODE_CLASS:
+ case Node::NODE_ENUM:
+ case Node::NODE_TYPEDEF:
+ case Node::NODE_TEMPLATE_PARAMETER_TYPE:
+ case Node::NODE_FILE:
+ return 14;
+
+ case Node::NODE_UNDEFINED_FUNCTION:
+ case Node::NODE_UNDEFINED_VARIABLE:
+ case Node::NODE_FUNCTION:
+ case Node::NODE_METHOD:
+ case Node::NODE_GLOBAL_VARIABLE:
+ case Node::NODE_FIELD:
+ case Node::NODE_ENUM_CONSTANT:
+ return 11;
+ }
+}
+
+size_t GraphViewStyle::getFontSizeOfAccessNode()
+{
+ return 11;
+}
+
+size_t GraphViewStyle::getFontSizeOfNumber()
+{
+ return 9;
+}
+
+std::string GraphViewStyle::getFontNameForNodeType(Node::NodeType type)
+{
+ return "Source Code Pro";
+}
+
+std::string GraphViewStyle::getFontNameOfAccessNode()
+{
+ return "Myriad Pro";
+}
+
+std::string GraphViewStyle::getFontNameOfNumber()
+{
+ return "Myriad Pro";
+}
+
+GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType type, bool hasChildren)
+{
+ NodeMargins margins;
+ margins.spacingX = margins.spacingY = 8;
+
+ switch (type)
+ {
+ case Node::NODE_UNDEFINED:
+ case Node::NODE_NAMESPACE:
+ margins.left = margins.right = 15;
+ margins.top = 28;
+ margins.bottom = 15;
+ break;
+
+ case Node::NODE_UNDEFINED_TYPE:
+ case Node::NODE_STRUCT:
+ case Node::NODE_CLASS:
+ case Node::NODE_ENUM:
+ case Node::NODE_TYPEDEF:
+ case Node::NODE_TEMPLATE_PARAMETER_TYPE:
+ case Node::NODE_FILE:
+ if (hasChildren)
+ {
+ margins.left = margins.right = 15;
+ margins.top = 30;
+ margins.bottom = 10;
+ }
+ else
+ {
+ margins.left = margins.right = 8;
+ margins.top = margins.bottom = 13;
+ }
+ break;
+
+ case Node::NODE_UNDEFINED_FUNCTION:
+ case Node::NODE_FUNCTION:
+ case Node::NODE_METHOD:
+ margins.left = margins.right = 5;
+ margins.top = margins.bottom = 10;
+ break;
+
+ case Node::NODE_UNDEFINED_VARIABLE:
+ case Node::NODE_GLOBAL_VARIABLE:
+ case Node::NODE_FIELD:
+ case Node::NODE_ENUM_CONSTANT:
+ margins.left = margins.right = 5;
+ margins.top = margins.bottom = 10;
+ break;
+ }
+
+ margins.charWidth = getCharWidthForNodeType(type);
+
+ return margins;
+}
+
+GraphViewStyle::NodeMargins GraphViewStyle::getMarginsOfAccessNode(
+ bool expanded, size_t subNodeCount, size_t invisibleSubNodeCount
+){
+ NodeMargins margins;
+ margins.spacingX = margins.spacingY = 8;
+
+ margins.left = margins.right = 10;
+ margins.top = 40;
+
+ if (invisibleSubNodeCount == subNodeCount)
+ {
+ margins.minWidth = 20;
+ margins.bottom = 10;
+ }
+ else
+ {
+ margins.minWidth = 82;
+
+ if (expanded)
+ {
+ margins.bottom = 15;
+ }
+ else if (invisibleSubNodeCount)
+ {
+ margins.bottom = 23;
+ }
+ else
+ {
+ margins.bottom = 10;
+ }
+ }
+
+ return margins;
+}
+
+GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType(
+ Node::NodeType type, bool isActive, bool isFocused, bool hasChildren
+){
+ NodeStyle style;
+
+ style.color = "#D3D3D3";
+ style.borderColor = "#00000000";
+
+ style.fontName = getFontNameForNodeType(type);
+ style.fontSize = getFontSizeForNodeType(type);
+
+ if (isActive)
+ {
+ style.borderColor = "#3c3c3c";
+ }
+
+ if (isActive || isFocused)
+ {
+ style.color = ApplicationSettings::getInstance()->getNodeTypeColor(type, "hover");
+ }
+ else
+ {
+ style.color = ApplicationSettings::getInstance()->getNodeTypeColor(type);
+ }
+
+ switch (type)
+ {
+ case Node::NODE_UNDEFINED:
+ style.borderDashed = true;
+
+ case Node::NODE_NAMESPACE:
+ style.borderColor = "#cc8d91";
+ style.borderWidth = 1;
+
+ style.cornerRadius = 20;
+
+ style.textOffset.x = 15;
+ style.textOffset.y = 6;
+ break;
+
+ case Node::NODE_UNDEFINED_TYPE:
+ style.undefinedPattern = true;
+
+ case Node::NODE_STRUCT:
+ case Node::NODE_CLASS:
+ case Node::NODE_ENUM:
+ case Node::NODE_TYPEDEF:
+ case Node::NODE_TEMPLATE_PARAMETER_TYPE:
+ case Node::NODE_FILE:
+ if (isActive)
+ {
+ style.fontBold = true;
+ }
+
+ if (isFocused)
+ {
+ style.shadowColor = "#FF000000";
+ }
+ else
+ {
+ style.shadowColor = "#80000000";
+ }
+ style.shadowBlurRadius = 5;
+
+ if (hasChildren)
+ {
+ style.cornerRadius = 20;
+ style.textOffset.x = 15;
+ style.textOffset.y = 8;
+ }
+ else
+ {
+ style.cornerRadius = 10;
+ style.textOffset.x = 8;
+ style.textOffset.y = 4;
+ }
+ break;
+
+ case Node::NODE_UNDEFINED_FUNCTION:
+ case Node::NODE_UNDEFINED_VARIABLE:
+ style.undefinedPattern = true;
+
+ case Node::NODE_FUNCTION:
+ case Node::NODE_METHOD:
+ case Node::NODE_GLOBAL_VARIABLE:
+ case Node::NODE_FIELD:
+ case Node::NODE_ENUM_CONSTANT:
+ if (isActive || isFocused)
+ {
+ style.fontBold = true;
+ }
+
+ style.cornerRadius = 8;
+ style.textOffset.x = 5;
+ style.textOffset.y = 3;
+ break;
+ }
+
+ if (isActive)
+ {
+ style.borderWidth = 1.5f;
+ }
+
+ return style;
+}
+
+GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfAccessNode()
+{
+ NodeStyle style;
+
+ style.color = "#FFFFFF";
+ style.borderColor = "#00000000";
+
+ style.cornerRadius = 12;
+
+ style.fontName = getFontNameOfAccessNode();
+ style.fontSize = getFontSizeOfAccessNode();
+ style.fontBold = true;
+
+ style.textOffset.x = 10;
+ style.textOffset.y = 10;
+
+ return style;
+}
+
+GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused)
+{
+ EdgeStyle style;
+
+ style.width = isActive ? 2 : 1;
+ style.zValue = isActive ? 5 : 1;
+
+ style.arrowLength = 5;
+ style.arrowWidth = 8;
+
+ style.cornerRadius = 10;
+ style.verticalOffset = 2;
+
+ style.originOffset.x = 17;
+ style.targetOffset.x = 17;
+
+ style.originOffset.y = -1;
+ style.targetOffset.y = 1;
+
+ switch (type)
+ {
+ case Edge::EDGE_AGGREGATION:
+ style.isStraight = true;
+ style.color = isActive ? "#DDD" : "#EEE";
+ style.width = 1;
+ style.zValue = isActive ? -1 : -5;
+ break;
+
+ case Edge::EDGE_CALL:
+ style.color = "#F1C100";
+ style.originOffset.y = 1;
+ style.targetOffset.y = -1;
+ style.verticalOffset = 4;
+ break;
+ case Edge::EDGE_USAGE:
+ style.color = "#62B29D";
+ style.originOffset.y = 3;
+ style.targetOffset.y = -3;
+ style.verticalOffset = 6;
+ break;
+ case Edge::EDGE_INHERITANCE:
+ style.arrowLength = 15;
+ style.arrowWidth = 20;
+ style.arrowClosed = true;
+ style.targetOffset.x = 29;
+ case Edge::EDGE_OVERRIDE:
+ style.color = "#CC5E89";
+ break;
+ case Edge::EDGE_INCLUDE:
+ style.color = "#87BA50";
+ break;
+
+ default:
+ style.color = "#878787";
+ break;
+ }
+
+ return style;
+}
+
+std::map GraphViewStyle::s_charWidths;
+std::shared_ptr GraphViewStyle::s_impl;
diff --git a/src/lib/component/view/GraphViewStyle.h b/src/lib/component/view/GraphViewStyle.h
new file mode 100644
index 00000000..a74f9b17
--- /dev/null
+++ b/src/lib/component/view/GraphViewStyle.h
@@ -0,0 +1,103 @@
+#ifndef GRAPH_VIEW_STYLE_H
+#define GRAPH_VIEW_STYLE_H
+
+#include