(Go: >> BACK << -|- >> HOME <<)

Skip to content

Commit

Permalink
#185 Add snapToGrid and snapToGridSize to qan::Graph.
Browse files Browse the repository at this point in the history
Modify groups sample for snap to grid support.
Nice.

Signed-off-by: cneben <benoit@destrat.io>
  • Loading branch information
cneben committed Dec 25, 2022
1 parent 381eaeb commit b0351e6
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 31 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# CHANGELOG

## 20221225 prev2.3.0:
- #185: Add support for "snap to grid" when moving node or groups.
- Add |qan::Graph`, `snapToGrid` and `snapToGridSize` properties.

## 20221225 v2.2.0:
- Release v2.2.0

## 20221215 v2.2.0:
- #183: Add a `multipleSelectionEnabled` property to `qan::Graph` to enable or disable multiple selection.

Expand All @@ -16,7 +23,7 @@
- #167: Add partial edge selection support.
- #164: Change signature of qan::Graph::connectorRequestEdgeCreation().

## 20220824 v2.1.1:
## 20220824 v2*$.1.1:
- Change signature of two public API methods (public but presumably mainly used internally):
- Rename qan::Graph::collectInerEdges() to qan::Graph::collectInnerEdges().
- Rename qan::Graph::collectAncestorsDfs() to qan::Graph::collectAncestors().
Expand Down
18 changes: 16 additions & 2 deletions samples/groups/groups.qml
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ ApplicationWindow {
RowLayout {
anchors.top: parent.top; anchors.topMargin: 15
anchors.horizontalCenter: parent.horizontalCenter
width: 200
width: 550
ToolButton {
text: "Add Group"
onClicked: {
Expand Down Expand Up @@ -221,7 +221,6 @@ ApplicationWindow {
property var node: undefined
enabled: node !== undefined
onClicked: {
console.info("node.group=" + node.group)
if (node && node.group )
topology.ungroupNode(node)
}
Expand All @@ -236,6 +235,21 @@ ApplicationWindow {
;
}
}

Switch {
text: "Snap to Grid"
checked: topology.snapToGrid
onClicked: topology.snapToGrid = checked
}
Label { text: "Grid size:" }
SpinBox {
enabled: topology.snapToGrid
from: 1
to: 100
stepSize: 5
value: topology.snapToGridSize.width
onValueModified: { topology.snapToGridSize = Qt.size(value, value) }
}
}
Pane {
id: groupEditor
Expand Down
48 changes: 26 additions & 22 deletions src/qanDraggableCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,28 +242,32 @@ void DraggableCtrl::dragMove(const QPointF& sceneDragPos, bool dragSelection)
// 2.2. If target position is "centered" on grid
// or mouse delta > grid
// 2.2.1 Compute snapped position, apply it
const auto gridSize = QSizeF{10., 10.};
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) {
const auto posModGridX = fmod(targetUnsnapPos.x(), gridSize.width());
//qWarning() << "posModGridX=" << posModGridX;
applyX = qFuzzyIsNull(posModGridX);
}
if (!applyY) {
const auto posModGridY = fmod(targetUnsnapPos.y(), gridSize.height());
//qWarning() << "posModGridY=" << posModGridY;
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());
_targetItem->setPosition(QPointF{targetSnapPosX,
targetSnapPosY});
if (getGraph()->getSnapToGrid()) {
const auto& gridSize = getGraph()->getSnapToGridSize();
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) {
const auto posModGridX = fmod(targetUnsnapPos.x(), gridSize.width());
//qWarning() << "posModGridX=" << posModGridX;
applyX = qFuzzyIsNull(posModGridX);
}
if (!applyY) {
const auto posModGridY = fmod(targetUnsnapPos.y(), gridSize.height());
//qWarning() << "posModGridY=" << posModGridY;
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());
_targetItem->setPosition(QPointF{targetSnapPosX,
targetSnapPosY});
}
} else { // Do not snap to grid
_targetItem->setPosition(targetUnsnapPos);
}
// FIXME #185 Selection move does not works...
if (dragSelection) {
Expand Down
19 changes: 19 additions & 0 deletions src/qanGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,25 @@ std::vector<QQuickItem*> Graph::getSelectedItems() const


/* Alignment Management *///---------------------------------------------------
bool Graph::setSnapToGrid(bool snapToGrid) noexcept
{
if (snapToGrid != _snapToGrid) {
_snapToGrid = snapToGrid;
emit snapToGridChanged();
return true;
}
return false;
}
bool Graph::setSnapToGridSize(QSizeF snapToGridSize) noexcept
{
if (snapToGridSize != _snapToGridSize) {
_snapToGridSize = snapToGridSize;
emit snapToGridSizeChanged();
return true;
}
return false;
}

void Graph::alignSelectionHorizontalCenter() { alignHorizontalCenter(getSelectedItems()); }

void Graph::alignSelectionRight() { alignRight(getSelectedItems()); }
Expand Down
32 changes: 26 additions & 6 deletions src/qanGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,8 +780,28 @@ class Graph : public gtpo::graph<QQuickItem, qan::Node, qan::Group, qan::Edge>
//@}
//-------------------------------------------------------------------------

/*! \name Alignment Management *///----------------------------------------
/*! \name Grid and Alignment Management *///-------------------------------
//@{
public:
//! Snap dragged objects (both groups and nodes) to grid based on \c snapGridSize (default to false is no snap).
Q_PROPERTY(bool snapToGrid READ getSnapToGrid WRITE setSnapToGrid NOTIFY snapToGridChanged FINAL)
bool setSnapToGrid(bool snapToGrid) noexcept;
bool getSnapToGrid() const noexcept { return _snapToGrid; }
private:
bool _snapToGrid = false;
signals:
void snapToGridChanged();

public:
//! Snap to grid size (default to 10x10), active only when \c snapToGrid is true.
Q_PROPERTY(QSizeF snapToGridSize READ getSnapToGridSize WRITE setSnapToGridSize NOTIFY snapToGridSizeChanged FINAL)
bool setSnapToGridSize(QSizeF snapToGridSize) noexcept;
QSizeF getSnapToGridSize() const noexcept { return _snapToGridSize; }
private:
QSizeF _snapToGridSize{10., 10.};
signals:
void snapToGridSizeChanged();

public:
//! \brief Align selected nodes/groups items horizontal center.
Q_INVOKABLE void alignSelectionHorizontalCenter();
Expand Down Expand Up @@ -812,11 +832,11 @@ class Graph : public gtpo::graph<QQuickItem, qan::Node, qan::Group, qan::Edge>
public:
/*! \brief Graph style manager (ie list of style applicable to graph primitive).
*/
Q_PROPERTY( qan::StyleManager* styleManager READ getStyleManager CONSTANT FINAL )
inline qan::StyleManager* getStyleManager() noexcept { return &_styleManager; }
inline const qan::StyleManager* getStyleManager() const noexcept { return &_styleManager; }
Q_PROPERTY(qan::StyleManager* styleManager READ getStyleManager CONSTANT FINAL)
qan::StyleManager* getStyleManager() noexcept { return &_styleManager; }
const qan::StyleManager* getStyleManager() const noexcept { return &_styleManager; }
private:
qan::StyleManager _styleManager;
qan::StyleManager _styleManager;
//@}
//-------------------------------------------------------------------------

Expand Down Expand Up @@ -851,7 +871,7 @@ class Graph : public gtpo::graph<QQuickItem, qan::Node, qan::Group, qan::Edge>

public:
//! Default delegate for node in/out port.
Q_PROPERTY( QQmlComponent* portDelegate READ getPortDelegate WRITE qmlSetPortDelegate NOTIFY portDelegateChanged FINAL )
Q_PROPERTY(QQmlComponent* portDelegate READ getPortDelegate WRITE qmlSetPortDelegate NOTIFY portDelegateChanged FINAL)
//! \copydoc portDelegate
inline QQmlComponent* getPortDelegate() noexcept { return _portDelegate.get(); }
protected:
Expand Down

0 comments on commit b0351e6

Please sign in to comment.