* added buttons to enable grouping by file or namespace * last used group settings saved to ApplicationSettings * made groups hoverable/clickable on label only * improved node hatching and override edge colors * group overview lists fortune cookie message = Seen with the eyes of love, everything gets a new meaning.
This commit is contained in:
@@ -88,8 +88,8 @@ Id QtGraphEdge::getTokenId() const
|
||||
|
||||
void QtGraphEdge::updateLine()
|
||||
{
|
||||
QtGraphNode* owner = m_owner;
|
||||
QtGraphNode* target = m_target;
|
||||
const QtGraphNode* owner = m_owner;
|
||||
const QtGraphNode* target = m_target;
|
||||
|
||||
Edge::EdgeType type = (getData() ? getData()->getType() : Edge::EDGE_AGGREGATION);
|
||||
GraphViewStyle::EdgeStyle style = GraphViewStyle::getStyleForEdgeType(type, m_isActive | m_isFocused, false, m_isTrailEdge);
|
||||
@@ -97,8 +97,22 @@ void QtGraphEdge::updateLine()
|
||||
Vec4i ownerRect = owner->getBoundingRect();
|
||||
Vec4i targetRect = target->getBoundingRect();
|
||||
|
||||
Vec4i ownerParentRect = owner->getParentBoundingRect();
|
||||
Vec4i targetParentRect = target->getParentBoundingRect();
|
||||
Vec4i ownerParentRect;
|
||||
Vec4i targetParentRect;
|
||||
|
||||
const QtGraphNode* ownerNonGroupParent = owner->getLastNonGroupParent();
|
||||
const QtGraphNode* targetNonGroupParent = target->getLastNonGroupParent();
|
||||
|
||||
if (owner->getLastParent() == target->getLastParent() && owner->getLastParent()->isGroupNode())
|
||||
{
|
||||
ownerParentRect = ownerNonGroupParent->getBoundingRect();
|
||||
targetParentRect = targetNonGroupParent->getBoundingRect();
|
||||
}
|
||||
else
|
||||
{
|
||||
ownerParentRect = owner->getLastParent()->getBoundingRect();
|
||||
targetParentRect = target->getLastParent()->getBoundingRect();
|
||||
}
|
||||
|
||||
if (m_useBezier)
|
||||
{
|
||||
@@ -142,7 +156,7 @@ void QtGraphEdge::updateLine()
|
||||
bezier->setRoute(route);
|
||||
bezier->setPivot(QtLineItemBase::PIVOT_MIDDLE);
|
||||
|
||||
if (owner->getLastParent() == target->getLastParent())
|
||||
if (ownerNonGroupParent == targetNonGroupParent)
|
||||
{
|
||||
if (ownerRect.y() < target->getBoundingRect().y())
|
||||
{
|
||||
@@ -163,7 +177,7 @@ void QtGraphEdge::updateLine()
|
||||
|
||||
QtLineItemAngled* child = dynamic_cast<QtLineItemAngled*>(m_child);
|
||||
|
||||
if (owner->getIsActive() && owner->getLastParent() == target->getLastParent())
|
||||
if (owner->getIsActive() && ownerNonGroupParent == targetNonGroupParent)
|
||||
{
|
||||
child->setOnBack(true);
|
||||
}
|
||||
@@ -172,7 +186,7 @@ void QtGraphEdge::updateLine()
|
||||
{
|
||||
child->setEarlyBend(true);
|
||||
|
||||
if (owner->getLastParent() == target->getLastParent() ||
|
||||
if (ownerNonGroupParent == targetNonGroupParent ||
|
||||
(type == Edge::EDGE_OVERRIDE &&
|
||||
targetParentRect.z() + style.targetOffset.x + style.originOffset.x > ownerParentRect.x()))
|
||||
{
|
||||
@@ -185,7 +199,7 @@ void QtGraphEdge::updateLine()
|
||||
}
|
||||
|
||||
if (type == Edge::EDGE_INHERITANCE || (type == Edge::EDGE_TEMPLATE_SPECIALIZATION &&
|
||||
owner == owner->getLastParent() && target == target->getLastParent()))
|
||||
owner == owner->getLastNonGroupParent() && target == target->getLastNonGroupParent()))
|
||||
{
|
||||
child->setRoute(QtLineItemBase::ROUTE_VERTICAL);
|
||||
|
||||
@@ -194,7 +208,8 @@ void QtGraphEdge::updateLine()
|
||||
child->setEarlyBend(true);
|
||||
}
|
||||
}
|
||||
else if (type != Edge::EDGE_AGGREGATION || owner != owner->getLastParent() || target != target->getLastParent())
|
||||
else if (type != Edge::EDGE_AGGREGATION ||
|
||||
owner != owner->getLastNonGroupParent() || target != target->getLastNonGroupParent())
|
||||
{
|
||||
child->setRoute(QtLineItemBase::ROUTE_HORIZONTAL);
|
||||
}
|
||||
@@ -250,13 +265,18 @@ void QtGraphEdge::setIsFocused(bool isFocused)
|
||||
|
||||
void QtGraphEdge::onClick()
|
||||
{
|
||||
Edge::EdgeType type = (getData() ? getData()->getType() : Edge::EDGE_AGGREGATION);
|
||||
|
||||
if (!getData() || m_owner->isGroupNode() || m_target->isGroupNode())
|
||||
{
|
||||
QtGraphNode* node =
|
||||
((m_direction == TokenComponentAggregation::DIRECTION_BACKWARD) == (type != Edge::EDGE_INHERITANCE))
|
||||
? m_owner : m_target;
|
||||
QtGraphNode* node = (m_direction == TokenComponentAggregation::DIRECTION_BACKWARD ? m_owner : m_target);
|
||||
if (m_owner->isGroupNode())
|
||||
{
|
||||
node = m_owner;
|
||||
}
|
||||
else if (m_target->isGroupNode())
|
||||
{
|
||||
node = m_target;
|
||||
}
|
||||
|
||||
MessageGraphNodeBundleSplit(node->getTokenId()).dispatch();
|
||||
}
|
||||
else if (isTrailEdge())
|
||||
|
||||
@@ -61,13 +61,13 @@ QtGraphNode* QtGraphNode::getParent() const
|
||||
return m_parentNode;
|
||||
}
|
||||
|
||||
QtGraphNode* QtGraphNode::getLastParent() const
|
||||
QtGraphNode* QtGraphNode::getLastParent(bool noGroups) const
|
||||
{
|
||||
QtGraphNode* node = const_cast<QtGraphNode*>(this);
|
||||
while (true)
|
||||
{
|
||||
QtGraphNode* parent = dynamic_cast<QtGraphNode*>(node->parentItem());
|
||||
if (!parent)
|
||||
if (!parent || (noGroups && parent->isGroupNode()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -76,6 +76,11 @@ QtGraphNode* QtGraphNode::getLastParent() const
|
||||
return node;
|
||||
}
|
||||
|
||||
QtGraphNode* QtGraphNode::getLastNonGroupParent() const
|
||||
{
|
||||
return getLastParent(true);
|
||||
}
|
||||
|
||||
void QtGraphNode::setParent(QtGraphNode* parentNode)
|
||||
{
|
||||
m_parentNode = parentNode;
|
||||
@@ -86,7 +91,7 @@ void QtGraphNode::setParent(QtGraphNode* parentNode)
|
||||
}
|
||||
}
|
||||
|
||||
std::list<QtGraphNode*> QtGraphNode::getSubNodes() const
|
||||
const std::list<QtGraphNode*>& QtGraphNode::getSubNodes() const
|
||||
{
|
||||
return m_subNodes;
|
||||
}
|
||||
@@ -142,11 +147,6 @@ Vec4i QtGraphNode::getBoundingRect() const
|
||||
return Vec4i(pos.x, pos.y, pos.x + size.x, pos.y + size.y);
|
||||
}
|
||||
|
||||
Vec4i QtGraphNode::getParentBoundingRect() const
|
||||
{
|
||||
return getLastParent()->getBoundingRect();
|
||||
}
|
||||
|
||||
void QtGraphNode::addOutEdge(QtGraphEdge* edge)
|
||||
{
|
||||
m_outEdges.push_back(edge);
|
||||
@@ -348,7 +348,7 @@ void QtGraphNode::addSubNode(QtGraphNode* node)
|
||||
if (node->getIsActive())
|
||||
{
|
||||
QtGraphNode* parent = this;
|
||||
while (parent)
|
||||
while (parent && !parent->isGroupNode())
|
||||
{
|
||||
parent->setZValue(-10.0f);
|
||||
parent->m_text->setZValue(-9.0f);
|
||||
|
||||
@@ -37,10 +37,11 @@ public:
|
||||
virtual ~QtGraphNode();
|
||||
|
||||
QtGraphNode* getParent() const;
|
||||
QtGraphNode* getLastParent() const;
|
||||
QtGraphNode* getLastParent(bool noGroups = false) const;
|
||||
QtGraphNode* getLastNonGroupParent() const;
|
||||
void setParent(QtGraphNode* parentNode);
|
||||
|
||||
std::list<QtGraphNode*> getSubNodes() const;
|
||||
const std::list<QtGraphNode*>& getSubNodes() const;
|
||||
|
||||
Vec2i getPosition() const;
|
||||
virtual bool setPosition(const Vec2i& position);
|
||||
@@ -52,7 +53,6 @@ public:
|
||||
void setSize(const QSize& size);
|
||||
|
||||
Vec4i getBoundingRect() const;
|
||||
Vec4i getParentBoundingRect() const;
|
||||
|
||||
void addOutEdge(QtGraphEdge* edge);
|
||||
void addInEdge(QtGraphEdge* edge);
|
||||
|
||||
@@ -55,11 +55,7 @@ void QtGraphNodeData::onClick()
|
||||
return;
|
||||
}
|
||||
|
||||
FilePath path = getFilePath();
|
||||
|
||||
MessageActivateNodes message;
|
||||
message.addNode(m_data->getId(), path.empty() ? m_data->getNameHierarchy() : NameHierarchy(path.wstr(), NAME_DELIMITER_FILE));
|
||||
message.dispatch();
|
||||
MessageActivateNodes(m_data->getId()).dispatch();
|
||||
}
|
||||
|
||||
void QtGraphNodeData::moved(const Vec2i& oldPosition)
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
#include "qt/view/graphElements/QtGraphNodeGroup.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QGraphicsPolygonItem>
|
||||
#include <QGraphicsSceneHoverEvent>
|
||||
#include <QPainterPath>
|
||||
#include <QPen>
|
||||
|
||||
#include "utility/messaging/type/MessageActivateNodes.h"
|
||||
#include "utility/messaging/type/MessageFocusIn.h"
|
||||
#include "utility/messaging/type/MessageFocusOut.h"
|
||||
#include "utility/messaging/type/MessageGraphNodeBundleSplit.h"
|
||||
|
||||
#include "qt/graphics/QtRoundedRectItem.h"
|
||||
|
||||
QtGraphNodeGroup::QtGraphNodeGroup(Id tokenId, const std::wstring& name, NodeType::GroupType type)
|
||||
QtGraphNodeGroup::QtGraphNodeGroup(
|
||||
Id tokenId, const std::wstring& name, GroupType type, bool interactive
|
||||
)
|
||||
: m_tokenId(tokenId)
|
||||
, m_type(type)
|
||||
, m_interactive(interactive)
|
||||
{
|
||||
setAcceptHoverEvents(true);
|
||||
if (interactive)
|
||||
{
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
setName(name);
|
||||
setZValue(-10.0f);
|
||||
m_rect->setZValue(-10.0f);
|
||||
|
||||
if (type == NodeType::GROUP_FRAMELESS)
|
||||
if (type == GroupType::FRAMELESS)
|
||||
{
|
||||
m_rect->hide();
|
||||
return;
|
||||
@@ -29,25 +38,26 @@ QtGraphNodeGroup::QtGraphNodeGroup(Id tokenId, const std::wstring& name, NodeTyp
|
||||
return;
|
||||
}
|
||||
|
||||
m_background = new QtRoundedRectItem(this);
|
||||
m_backgroundTopRight = new QGraphicsRectItem(this);
|
||||
m_backgroundBottomLeft = new QGraphicsRectItem(this);
|
||||
|
||||
m_background->setZValue(-10.0f);
|
||||
m_backgroundTopRight->setZValue(-10.0f);
|
||||
m_backgroundBottomLeft->setZValue(-10.0f);
|
||||
m_background = new QGraphicsPolygonItem(this);
|
||||
m_background->setZValue(-3.f);
|
||||
|
||||
GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleOfGroupNode(type, false);
|
||||
GraphViewStyle::NodeMargins margins = GraphViewStyle::getMarginsOfGroupNode(type, true);
|
||||
|
||||
int width = style.textOffset.x * 2 + style.borderWidth + margins.charWidth * name.size();
|
||||
int height = margins.top * 2 + margins.charHeight;
|
||||
int height = margins.spacingA + margins.charHeight;
|
||||
int radius = style.cornerRadius;
|
||||
|
||||
m_background->setRadius(style.cornerRadius);
|
||||
m_background->setRect(0, 0, width, height);
|
||||
QPainterPath path;
|
||||
path.moveTo(width, 0);
|
||||
path.lineTo(radius, 0);
|
||||
path.arcTo(0, 0, 2 * radius, 2 * radius, 90, 90);
|
||||
path.lineTo(0, height);
|
||||
path.lineTo(width - radius, height);
|
||||
path.arcTo(width - 2 * radius, height - 2 * radius, 2 * radius, 2 * radius, 270, 90);
|
||||
path.closeSubpath();
|
||||
|
||||
m_backgroundTopRight->setRect(width - style.cornerRadius, 0, style.cornerRadius, style.cornerRadius);
|
||||
m_backgroundBottomLeft->setRect(0, height - style.cornerRadius, style.cornerRadius, style.cornerRadius);
|
||||
m_background->setPolygon(path.toFillPolygon());
|
||||
}
|
||||
|
||||
QtGraphNodeGroup::~QtGraphNodeGroup()
|
||||
@@ -66,24 +76,64 @@ Id QtGraphNodeGroup::getTokenId() const
|
||||
|
||||
void QtGraphNodeGroup::onClick()
|
||||
{
|
||||
MessageGraphNodeBundleSplit(m_tokenId).dispatch();
|
||||
if (!m_interactive || !m_isHovering)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_type == GroupType::FILE || m_type == GroupType::NAMESPACE)
|
||||
{
|
||||
MessageActivateNodes(m_tokenId).dispatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageGraphNodeBundleSplit(m_tokenId).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void QtGraphNodeGroup::updateStyle()
|
||||
{
|
||||
GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleOfGroupNode(m_type, false);
|
||||
GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleOfGroupNode(m_type, m_isHovering);
|
||||
|
||||
if (m_background)
|
||||
{
|
||||
m_background->setBrush(QColor(style.color.border.c_str()));
|
||||
m_background->setPen(QPen(Qt::transparent));
|
||||
|
||||
m_backgroundTopRight->setBrush(QColor(style.color.border.c_str()));
|
||||
m_backgroundTopRight->setPen(QPen(Qt::transparent));
|
||||
|
||||
m_backgroundBottomLeft->setBrush(QColor(style.color.border.c_str()));
|
||||
m_backgroundBottomLeft->setPen(QPen(Qt::transparent));
|
||||
}
|
||||
|
||||
setStyle(style);
|
||||
}
|
||||
|
||||
void QtGraphNodeGroup::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
|
||||
{
|
||||
if (m_type == GroupType::FILE || m_type == GroupType::NAMESPACE)
|
||||
{
|
||||
MessageFocusOut({ m_tokenId }).dispatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
focusOut();
|
||||
}
|
||||
}
|
||||
|
||||
void QtGraphNodeGroup::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
|
||||
{
|
||||
if (!m_background || m_background->contains(event->pos()))
|
||||
{
|
||||
if (!m_isHovering)
|
||||
{
|
||||
if (m_type == GroupType::FILE || m_type == GroupType::NAMESPACE)
|
||||
{
|
||||
MessageFocusIn({ m_tokenId }, TOOLTIP_ORIGIN_GRAPH).dispatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
focusIn();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_isHovering)
|
||||
{
|
||||
hoverLeaveEvent(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
#ifndef QT_GRAPH_NODE_GROUP_H
|
||||
#define QT_GRAPH_NODE_GROUP_H
|
||||
|
||||
#include "data/NodeType.h"
|
||||
#include "data/GroupType.h"
|
||||
#include "qt/view/graphElements/QtGraphNode.h"
|
||||
|
||||
class QGraphicsRectItem;
|
||||
class QtRoundedRectItem;
|
||||
class QGraphicsPolygonItem;
|
||||
|
||||
class QtGraphNodeGroup
|
||||
: public QtGraphNode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QtGraphNodeGroup(Id tokenId, const std::wstring& name, NodeType::GroupType type);
|
||||
QtGraphNodeGroup(Id tokenId, const std::wstring& name, GroupType type, bool interactive);
|
||||
virtual ~QtGraphNodeGroup();
|
||||
|
||||
// QtGraphNode implementation
|
||||
@@ -22,13 +21,16 @@ public:
|
||||
virtual void onClick();
|
||||
virtual void updateStyle();
|
||||
|
||||
protected:
|
||||
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
|
||||
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* event);
|
||||
|
||||
private:
|
||||
Id m_tokenId;
|
||||
NodeType::GroupType m_type;
|
||||
GroupType m_type;
|
||||
const bool m_interactive;
|
||||
|
||||
QtRoundedRectItem* m_background = nullptr;
|
||||
QGraphicsRectItem* m_backgroundTopRight = nullptr;
|
||||
QGraphicsRectItem* m_backgroundBottomLeft = nullptr;
|
||||
QGraphicsPolygonItem* m_background = nullptr;
|
||||
};
|
||||
|
||||
#endif // QT_GRAPH_NODE_GROUP_H
|
||||
|
||||
Reference in New Issue
Block a user