Skip to content

Commit

Permalink
#185 First working implementation (at least with zoom == 1.0)
Browse files Browse the repository at this point in the history
Signed-off-by: cneben <[email protected]>
  • Loading branch information
cneben committed Dec 25, 2022
1 parent cfcb184 commit 7d3f208
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 27 deletions.
69 changes: 48 additions & 21 deletions src/qanDraggableCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,13 @@ bool DraggableCtrl::handleMouseMoveEvent(QMouseEvent* event)
const auto rootItem = getGraph()->getContainerItem();
if (rootItem != nullptr && // Root item exist, left button is pressed and the target item
event->buttons().testFlag(Qt::LeftButton)) { // is draggable and not collapsed
const auto globalPos = rootItem->mapFromGlobal(event->globalPos());
const auto sceneDragPos = rootItem->mapFromGlobal(event->globalPos());
if (!_targetItem->getDragged()) {
beginDragMove(globalPos, _targetItem->getSelected());
_initialTargetPos = _targetItem->position();
beginDragMove(sceneDragPos, _targetItem->getSelected());
return true;
} else {
const auto delta = globalPos - _dragLastPos;
_dragLastPos = globalPos;
dragMove(delta, _targetItem->getSelected());
dragMove(sceneDragPos, _targetItem->getSelected());
return true;
}
}
Expand All @@ -154,7 +153,7 @@ void DraggableCtrl::handleMouseReleaseEvent(QMouseEvent* event)
endDragMove();
}

void DraggableCtrl::beginDragMove(const QPointF& dragInitialMousePos, bool dragSelection)
void DraggableCtrl::beginDragMove(const QPointF& sceneDragPos, bool dragSelection)
{
if (_targetItem == nullptr)
return;
Expand All @@ -163,20 +162,20 @@ void DraggableCtrl::beginDragMove(const QPointF& dragInitialMousePos, bool dr
_target != nullptr)
emit graph->nodeAboutToBeMoved(_target);
_targetItem->setDragged(true);
_dragLastPos = dragInitialMousePos;
_initialDragPos = sceneDragPos;

// If there is a selection, keep start position for all selected nodes.
if (dragSelection) {
const auto graph = getGraph();
if (graph != nullptr &&
graph->hasMultipleSelection()) {

auto beginDragMoveSelected = [this, &dragInitialMousePos] (auto primitive) { // Call beginDragMove() on a given node or group
auto beginDragMoveSelected = [this, &sceneDragPos] (auto primitive) { // Call beginDragMove() on a given node or group
if (primitive != nullptr &&
primitive->getItem() != nullptr &&
static_cast<QQuickItem*>(primitive->getItem()) != static_cast<QQuickItem*>(this->_targetItem.data()) &&
primitive->get_group() == nullptr) // Do not drag nodes that are inside a group
primitive->getItem()->draggableCtrl().beginDragMove( dragInitialMousePos, false );
primitive->getItem()->draggableCtrl().beginDragMove(sceneDragPos, false);
};

// Call beginDragMove on all selected nodes and groups.
Expand All @@ -186,7 +185,7 @@ void DraggableCtrl::beginDragMove(const QPointF& dragInitialMousePos, bool dr
}
}

void DraggableCtrl::dragMove(const QPointF& delta, bool dragSelection)
void DraggableCtrl::dragMove(const QPointF& sceneDragPos, bool dragSelection)
{
// PRECONDITIONS:
// _graph must be configured (non nullptr)
Expand Down Expand Up @@ -214,7 +213,8 @@ void DraggableCtrl::dragMove(const QPointF& delta, bool dragSelection)
auto movedInsideGroup = false;
if (targetGroup &&
targetGroup->getItem() != nullptr) {
const QRectF targetRect{_targetItem->position() + delta,
// FIXME #185 pb ici
const QRectF targetRect{_targetItem->position() + sceneDragPos /*delta*/,
QSizeF{ _targetItem->width(), _targetItem->height() }};
const QRectF groupRect{QPointF{0., 0.},
QSizeF{ targetGroup->getItem()->width(), targetGroup->getItem()->height() }};
Expand All @@ -226,16 +226,42 @@ void DraggableCtrl::dragMove(const QPointF& delta, bool dragSelection)
}

// FIXME #185
// Cache initial position "somewhere"
// Cache un-snapped delta "somewhere"
// Only move if fmod(delta, gridsize)==0

// Algorithm:
// 1. Convert the mouse drag position to "target item" space
// 2. If target position is "centered" on grid
// or mouse delta > grid
// 2.1 Compute snapped position, apply it

const auto delta = (sceneDragPos - _initialDragPos);
const auto targetUnsnapPos = _initialTargetPos + delta;
const auto gridSize = QSizeF{10., 10.};
const auto localPos = _targetItem->position();
qWarning() << "delta=" << delta;
qWarning() << "std::fmod(delta.x(), gridSize.width())=" << std::fmod(delta.x(), gridSize.width());
qWarning() << "std::fmod(delta.y(), gridSize.height())=" << std::fmod(delta.x(), gridSize.width());
const auto snappedDelta = QPointF{
std::trunc(delta.x() / gridSize.width()) * gridSize.width(),
std::trunc(delta.y() / gridSize.height()) * gridSize.height(),
};
_targetItem->setPosition(localPos + snappedDelta);
bool applyX = std::fabs(delta.x()) > (gridSize.width() / 2.001);
bool applyY = std::fabs(delta.y()) > (gridSize.height() / 2.001);

qWarning() << "--------";
qWarning() << "targetUnsnapPos=" << targetUnsnapPos;
if (!applyX || !applyY) { // FIXME Split that... handle x and if in <> branchers (small gain)
const auto posModGridX = fmod(targetUnsnapPos.x(), gridSize.width());
const auto posModGridY = fmod(targetUnsnapPos.y(), gridSize.height());
qWarning() << "posModGridX=" << posModGridX << " posModGridY=" << posModGridY;
applyX = qFuzzyIsNull(posModGridX);
applyY = qFuzzyIsNull(posModGridY);
}
qWarning() << "applyX=" << applyX << " applyY=" << applyY;
if (applyX || applyY) {
const auto targetSnapPosX = gridSize.width() * std::round(targetUnsnapPos.x() / gridSize.width());
const auto targetSnapPosY = gridSize.height() * std::round(targetUnsnapPos.y() / gridSize.height());
//qWarning() << "snapPos=" << QPointF{snapPosX, snapPosY};
_targetItem->setPosition(QPointF{targetSnapPosX,
targetSnapPosY});
}

// FIXME #185 old working code, remove...
//const auto localPos = _targetItem->position();
//_targetItem->setPosition(localPos + delta);

if (dragSelection) {
Expand Down Expand Up @@ -280,7 +306,8 @@ void DraggableCtrl::dragMove(const QPointF& delta, bool dragSelection)

void DraggableCtrl::endDragMove(bool dragSelection)
{
_dragLastPos = QPointF{0., 0.}; // Invalid all cached coordinates when drag ends
_initialDragPos = QPointF{0., 0.}; // Invalid all cached coordinates when drag ends
_initialTargetPos = QPointF{0., 0.};
_lastProposedGroup = nullptr;

// PRECONDITIONS:
Expand Down
15 changes: 9 additions & 6 deletions src/qanDraggableCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,18 @@ class DraggableCtrl : public qan::AbstractDraggableCtrl
void handleMouseReleaseEvent(QMouseEvent* event);

public:
//! \c dragInitialMousePos in window coordinate system.
virtual void beginDragMove(const QPointF& dragInitialMousePos, bool dragSelection = true) override;
//! \c delta in scene coordinate system.
virtual void dragMove(const QPointF& delta, bool dragSelection = true) override;
//! \c sceneDragPos is current mouse drag position in scene coordinate system.
virtual void beginDragMove(const QPointF& sceneDragPos, bool dragSelection = true) override;
//! \c sceneDragPos is current mouse drag position in scene coordinate system.
virtual void dragMove(const QPointF& sceneDragPos, bool dragSelection = true) override;
virtual void endDragMove(bool dragSelection = true) override;

private:
//! Internal position cache.
QPointF _dragLastPos{0., 0.};
//! Internal (mouse) initial dragging position.
QPointF _initialDragPos{0., 0.};
//! Internal (target) initial dragging position.
QPointF _initialTargetPos{0., 0.};

//! Last group hovered during a node drag (cached to generate a dragLeave signal on qan::Group).
QPointer<qan::Group> _lastProposedGroup{nullptr};
//@}
Expand Down

0 comments on commit 7d3f208

Please sign in to comment.