diff options
Diffstat (limited to 'tikzit/src/gui')
-rw-r--r-- | tikzit/src/gui/edgeitem.cpp | 27 | ||||
-rw-r--r-- | tikzit/src/gui/edgeitem.h | 5 | ||||
-rw-r--r-- | tikzit/src/gui/tikzscene.cpp | 184 | ||||
-rw-r--r-- | tikzit/src/gui/tikzscene.h | 4 | ||||
-rw-r--r-- | tikzit/src/gui/undocommands.cpp | 10 |
5 files changed, 194 insertions, 36 deletions
diff --git a/tikzit/src/gui/edgeitem.cpp b/tikzit/src/gui/edgeitem.cpp index cb275a5..497fa07 100644 --- a/tikzit/src/gui/edgeitem.cpp +++ b/tikzit/src/gui/edgeitem.cpp @@ -24,12 +24,12 @@ EdgeItem::EdgeItem(Edge *edge) GLOBAL_SCALEF * 0.1, GLOBAL_SCALEF * 0.1); _cp2Item->setVisible(false); - syncPos(); + readPos(); } -void EdgeItem::syncPos() +void EdgeItem::readPos() { - _edge->setAttributesFromData(); + //_edge->setAttributesFromData(); _edge->updateControls(); QPainterPath path; @@ -104,7 +104,28 @@ QRectF EdgeItem::boundingRect() const return shape().boundingRect().adjusted(-r,-r,r,r); } +QPainterPath EdgeItem::shape() const +{ + // get the shape of the edge, and expand a bit to make selection easier + QPainterPath oldShape = QGraphicsPathItem::shape(); + QPainterPathStroker stroker; + stroker.setWidth(5); + stroker.setJoinStyle(Qt::MiterJoin); + QPainterPath newShape = (stroker.createStroke(oldShape) + oldShape).simplified(); + return newShape; +} + Edge *EdgeItem::edge() const { return _edge; } + +QGraphicsEllipseItem *EdgeItem::cp1Item() const +{ + return _cp1Item; +} + +QGraphicsEllipseItem *EdgeItem::cp2Item() const +{ + return _cp2Item; +} diff --git a/tikzit/src/gui/edgeitem.h b/tikzit/src/gui/edgeitem.h index 5bdf3be..b017265 100644 --- a/tikzit/src/gui/edgeitem.h +++ b/tikzit/src/gui/edgeitem.h @@ -18,11 +18,14 @@ class EdgeItem : public QGraphicsPathItem { public: EdgeItem(Edge *edge); - void syncPos(); + void readPos(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QRectF boundingRect() const; + QPainterPath shape() const; Edge *edge() const; + QGraphicsEllipseItem *cp1Item() const; + QGraphicsEllipseItem *cp2Item() const; private: Edge *_edge; diff --git a/tikzit/src/gui/tikzscene.cpp b/tikzit/src/gui/tikzscene.cpp index b12b769..b502f84 100644 --- a/tikzit/src/gui/tikzscene.cpp +++ b/tikzit/src/gui/tikzscene.cpp @@ -1,4 +1,5 @@ #include "tikzit.h" +#include "util.h" #include "tikzscene.h" #include "undocommands.h" @@ -10,6 +11,7 @@ TikzScene::TikzScene(TikzDocument *tikzDocument, QObject *parent) : QGraphicsScene(parent), _tikzDocument(tikzDocument) { + _modifyEdgeItem = 0; } TikzScene::~TikzScene() { @@ -49,23 +51,59 @@ void TikzScene::graphReplaced() void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { + // current mouse position, in scene coordinates QPointF mousePos(event->buttonDownScenePos(Qt::LeftButton).x(), event->buttonDownScenePos(Qt::LeftButton).y()); + // radius of a control point for bezier edges, in scene coordinates + qreal cpR = GLOBAL_SCALEF * (0.05); + qreal cpR2 = cpR * cpR; switch (tikzit->toolPalette()->currentTool()) { case ToolPalette::SELECT: - // TODO: check if we grabbed a control point - QGraphicsScene::mousePressEvent(event); - if (!selectedItems().empty() && !items(mousePos).empty()) { + // check if we grabbed a control point of an edge + foreach (QGraphicsItem *gi, selectedItems()) { + if (EdgeItem *ei = dynamic_cast<EdgeItem*>(gi)) { + qreal dx, dy; + + dx = ei->cp1Item()->pos().x() - mousePos.x(); + dy = ei->cp1Item()->pos().y() - mousePos.y(); + + if (dx*dx + dy*dy <= cpR2) { + _modifyEdgeItem = ei; + _firstControlPoint = true; + break; + } + + dx = ei->cp2Item()->pos().x() - mousePos.x(); + dy = ei->cp2Item()->pos().y() - mousePos.y(); + + if (dx*dx + dy*dy <= cpR2) { + _modifyEdgeItem = ei; + _firstControlPoint = false; + break; + } + } + } + + if (_modifyEdgeItem != 0) { + // disable rubber band drag, which will clear the selection + views()[0]->setDragMode(QGraphicsView::NoDrag); + qDebug() << "Got a control point"; + } else { + // since we are not dragging a control point, process the click normally + views()[0]->setDragMode(QGraphicsView::RubberBandDrag); + QGraphicsScene::mousePressEvent(event); + + // save current node positions for undo support _oldNodePositions.clear(); foreach (QGraphicsItem *gi, selectedItems()) { if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)) { _oldNodePositions.insert(ni->node(), ni->node()->point()); } } - qDebug() << "I am dragging"; } + break; case ToolPalette::VERTEX: break; @@ -78,9 +116,96 @@ void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { + // current mouse position, in scene coordinates + + QPointF mousePos = event->scenePos(); + switch (tikzit->toolPalette()->currentTool()) { case ToolPalette::SELECT: - QGraphicsScene::mouseMoveEvent(event); + if (_modifyEdgeItem != 0) { + Edge *e = _modifyEdgeItem->edge(); + // dragging a control point + QPointF src = toScreen(e->source()->point()); + QPointF targ = toScreen(e->target()->point()); + float dx1 = targ.x() - src.x(); + float dy1 = targ.y() - src.y(); + float dx2, dy2; + if (_firstControlPoint) { + dx2 = mousePos.x() - src.x(); + dy2 = mousePos.y() - src.y(); + } else { + dx2 = mousePos.x() - targ.x(); + dy2 = mousePos.y() - targ.y(); + } + + float baseDist = sqrt(dx1*dx1 + dy1*dy1); + float handleDist = sqrt(dx2*dx2 + dy2*dy2); + float wcoarseness = 0.1f; + + if (!e->isSelfLoop()) { + if (baseDist != 0) { + e->setWeight(roundToNearest(wcoarseness, handleDist/baseDist)); + } else { + e->setWeight(roundToNearest(wcoarseness, handleDist/GLOBAL_SCALEF)); + } + } + + float control_angle = atan2(-dy2, dx2); + + int bcoarseness = 15; + + if(e->basicBendMode()) { + float bnd; + float base_angle = atan2(-dy1, dx1); + if (_firstControlPoint) { + bnd = base_angle - control_angle; + } else { + bnd = control_angle - base_angle + M_PI; + if (bnd > M_PI) bnd -= 2*M_PI; + } + + e->setBend(round(bnd * (180.0f / M_PI) * (1.0f / (float)bcoarseness)) * bcoarseness); + + } else { + int bnd = round(control_angle * (180.0f / M_PI) * + (1.0f / (float)bcoarseness)) * + bcoarseness; + if (_firstControlPoint) { + // TODO: enable moving both control points +// if ([theEvent modifierFlags] & NSAlternateKeyMask) { +// if ([modifyEdge isSelfLoop]) { +// [modifyEdge setInAngle:[modifyEdge inAngle] + +// (bnd - [modifyEdge outAngle])]; +// } else { +// [modifyEdge setInAngle:[modifyEdge inAngle] - +// (bnd - [modifyEdge outAngle])]; +// } +// } + + e->setOutAngle(bnd); + } else { +// if (theEvent.modifierFlags & NSAlternateKeyMask) { +// if ([modifyEdge isSelfLoop]) { +// [modifyEdge setOutAngle:[modifyEdge outAngle] + +// (bnd - [modifyEdge inAngle])]; +// } else { +// [modifyEdge setOutAngle:[modifyEdge outAngle] - +// (bnd - [modifyEdge inAngle])]; +// } +// } + + e->setInAngle(bnd); + } + } + + _modifyEdgeItem->readPos(); + + } else { + // otherwise, process mouse move normally + QGraphicsScene::mouseMoveEvent(event); + refreshAdjacentEdges(_oldNodePositions.keys()); + } + break; case ToolPalette::VERTEX: break; @@ -89,35 +214,37 @@ void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) case ToolPalette::CROP: break; } - - // TODO: only sync edges that change - foreach (EdgeItem *ei, _edgeItems) { - ei->edge()->updateControls(); - ei->syncPos(); - } } void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { switch (tikzit->toolPalette()->currentTool()) { case ToolPalette::SELECT: - QGraphicsScene::mouseReleaseEvent(event); + if (_modifyEdgeItem != 0) { + // finished dragging a control point + // TODO - if (!_oldNodePositions.empty()) { - QMap<Node*,QPointF> newNodePositions; + _modifyEdgeItem = 0; + } else { + // otherwise, process mouse move normally + QGraphicsScene::mouseReleaseEvent(event); - foreach (QGraphicsItem *gi, selectedItems()) { - if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)) { - ni->writePos(); - newNodePositions.insert(ni->node(), ni->node()->point()); + if (!_oldNodePositions.empty()) { + QMap<Node*,QPointF> newNodePositions; + + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)) { + ni->writePos(); + newNodePositions.insert(ni->node(), ni->node()->point()); + } } - } - //qDebug() << _oldNodePositions; - //qDebug() << newNodePositions; + //qDebug() << _oldNodePositions; + //qDebug() << newNodePositions; - _tikzDocument->undoStack()->push(new MoveCommand(this, _oldNodePositions, newNodePositions)); - _oldNodePositions.clear(); + _tikzDocument->undoStack()->push(new MoveCommand(this, _oldNodePositions, newNodePositions)); + _oldNodePositions.clear(); + } } break; @@ -146,6 +273,17 @@ QVector<EdgeItem *> TikzScene::edgeItems() const return _edgeItems; } +void TikzScene::refreshAdjacentEdges(QList<Node*> nodes) +{ + if (nodes.empty()) return; + foreach (EdgeItem *ei, _edgeItems) { + if (nodes.contains(ei->edge()->source()) || nodes.contains(ei->edge()->target())) { + ei->edge()->updateControls(); + ei->readPos(); + } + } +} + QVector<NodeItem *> TikzScene::nodeItems() const { return _nodeItems; diff --git a/tikzit/src/gui/tikzscene.h b/tikzit/src/gui/tikzscene.h index 9d598ad..cc7f4e4 100644 --- a/tikzit/src/gui/tikzscene.h +++ b/tikzit/src/gui/tikzscene.h @@ -27,8 +27,8 @@ public: ~TikzScene(); Graph *graph() const; QVector<NodeItem *> nodeItems() const; - QVector<EdgeItem *> edgeItems() const; + void refreshAdjacentEdges(QList<Node*> nodes); TikzDocument *tikzDocument() const; void setTikzDocument(TikzDocument *tikzDocument); @@ -43,6 +43,8 @@ private: TikzDocument *_tikzDocument; QVector<NodeItem*> _nodeItems; QVector<EdgeItem*> _edgeItems; + EdgeItem *_modifyEdgeItem; + bool _firstControlPoint; QMap<Node*,QPointF> _oldNodePositions; }; diff --git a/tikzit/src/gui/undocommands.cpp b/tikzit/src/gui/undocommands.cpp index b8a045b..c28611f 100644 --- a/tikzit/src/gui/undocommands.cpp +++ b/tikzit/src/gui/undocommands.cpp @@ -21,10 +21,7 @@ void MoveCommand::undo() } } - foreach (EdgeItem *ei, _scene->edgeItems()) { - ei->edge()->updateControls(); - ei->syncPos(); - } + _scene->refreshAdjacentEdges(_oldNodePositions.keys()); } void MoveCommand::redo() @@ -36,8 +33,5 @@ void MoveCommand::redo() } } - foreach (EdgeItem *ei, _scene->edgeItems()) { - ei->edge()->updateControls(); - ei->syncPos(); - } + _scene->refreshAdjacentEdges(_newNodePositions.keys()); } |