diff options
Diffstat (limited to 'examples/graphicsview/elasticnodes/node.cpp')
-rw-r--r-- | examples/graphicsview/elasticnodes/node.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/examples/graphicsview/elasticnodes/node.cpp b/examples/graphicsview/elasticnodes/node.cpp new file mode 100644 index 0000000..6942fa0 --- /dev/null +++ b/examples/graphicsview/elasticnodes/node.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGraphicsScene> +#include <QGraphicsSceneMouseEvent> +#include <QPainter> +#include <QStyleOption> + +#include "edge.h" +#include "node.h" +#include "graphwidget.h" + +Node::Node(GraphWidget *graphWidget) + : graph(graphWidget) +{ + setFlag(ItemIsMovable); + setCacheMode(DeviceCoordinateCache); + setZValue(1); +} + +void Node::addEdge(Edge *edge) +{ + edgeList << edge; + edge->adjust(); +} + +QList<Edge *> Node::edges() const +{ + return edgeList; +} + +void Node::calculateForces() +{ + if (!scene() || scene()->mouseGrabberItem() == this) { + newPos = pos(); + return; + } + + // Sum up all forces pushing this item away + qreal xvel = 0; + qreal yvel = 0; + foreach (QGraphicsItem *item, scene()->items()) { + Node *node = qgraphicsitem_cast<Node *>(item); + if (!node) + continue; + + QLineF line(mapFromItem(node, 0, 0), QPointF(0, 0)); + qreal dx = line.dx(); + qreal dy = line.dy(); + double l = 2.0 * (dx * dx + dy * dy); + if (l > 0) { + xvel += (dx * 150.0) / l; + yvel += (dy * 150.0) / l; + } + } + + // Now subtract all forces pulling items together + double weight = (edgeList.size() + 1) * 10; + foreach (Edge *edge, edgeList) { + QPointF pos; + if (edge->sourceNode() == this) + pos = mapFromItem(edge->destNode(), 0, 0); + else + pos = mapFromItem(edge->sourceNode(), 0, 0); + xvel += pos.x() / weight; + yvel += pos.y() / weight; + } + + if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1) + xvel = yvel = 0; + + QRectF sceneRect = scene()->sceneRect(); + newPos = pos() + QPointF(xvel, yvel); + newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)); + newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); +} + +bool Node::advance() +{ + if (newPos == pos()) + return false; + + setPos(newPos); + return true; +} + +QRectF Node::boundingRect() const +{ + qreal adjust = 2; + return QRectF(-10 - adjust, -10 - adjust, + 23 + adjust, 23 + adjust); +} + +QPainterPath Node::shape() const +{ + QPainterPath path; + path.addEllipse(-10, -10, 20, 20); + return path; +} + +void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::darkGray); + painter->drawEllipse(-7, -7, 20, 20); + + QRadialGradient gradient(-3, -3, 10); + if (option->state & QStyle::State_Sunken) { + gradient.setCenter(3, 3); + gradient.setFocalPoint(3, 3); + gradient.setColorAt(1, QColor(Qt::yellow).light(120)); + gradient.setColorAt(0, QColor(Qt::darkYellow).light(120)); + } else { + gradient.setColorAt(0, Qt::yellow); + gradient.setColorAt(1, Qt::darkYellow); + } + painter->setBrush(gradient); + painter->setPen(QPen(Qt::black, 0)); + painter->drawEllipse(-10, -10, 20, 20); +} + +QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) +{ + switch (change) { + case ItemPositionHasChanged: + foreach (Edge *edge, edgeList) + edge->adjust(); + graph->itemMoved(); + break; + default: + break; + }; + + return QGraphicsItem::itemChange(change, value); +} + +void Node::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mousePressEvent(event); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mouseReleaseEvent(event); +} |