diff options
Diffstat (limited to 'tikzit/src/gui/tikzscene.cpp')
-rw-r--r-- | tikzit/src/gui/tikzscene.cpp | 184 |
1 files changed, 161 insertions, 23 deletions
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; |