QmlDesigner: Allow starting free drag on initial selection press

Changed object selection to be done on press instead of click, and
the initial press now also starts free drag of the selected object
after a short distance moved to prevent accidental drags.

Change-Id: I61656661cd734d167ef9f8db42d986f0e97402a3
Fixes: QDS-2376
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2020-06-30 14:48:34 +03:00
parent 195690973e
commit fccc02de96
7 changed files with 86 additions and 4 deletions

View File

@@ -543,16 +543,61 @@ Item {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
onClicked: { hoverEnabled: false
property MouseArea3D freeDraggerArea
property point pressPoint
property bool initialMoveBlock: false
onPressed: {
if (viewRoot.editView) { if (viewRoot.editView) {
var pickResult = viewRoot.editView.pick(mouse.x, mouse.y); var pickResult = viewRoot.editView.pick(mouse.x, mouse.y);
handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit), handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit),
mouse.modifiers & Qt.ControlModifier); mouse.modifiers & Qt.ControlModifier);
if (!pickResult.objectHit)
if (pickResult.objectHit) {
if (transformMode === EditView3D.TransformMode.Move)
freeDraggerArea = moveGizmo.freeDraggerArea;
else if (transformMode === EditView3D.TransformMode.Rotate)
freeDraggerArea = rotateGizmo.freeDraggerArea;
else if (transformMode === EditView3D.TransformMode.Scale)
freeDraggerArea = scaleGizmo.freeDraggerArea;
pressPoint.x = mouse.x;
pressPoint.y = mouse.y;
initialMoveBlock = true;
} else {
mouse.accepted = false; mouse.accepted = false;
} }
} }
} }
onPositionChanged: {
if (freeDraggerArea) {
if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) {
// Don't force press event at actual press, as that puts the gizmo
// in free-dragging state, which is bad UX if drag is not actually done
freeDraggerArea.forcePressEvent(pressPoint.x, pressPoint.y);
freeDraggerArea.forceMoveEvent(mouse.x, mouse.y);
initialMoveBlock = false;
} else {
freeDraggerArea.forceMoveEvent(mouse.x, mouse.y);
}
}
}
function handleRelease(mouse)
{
if (freeDraggerArea) {
if (initialMoveBlock)
freeDraggerArea.forceReleaseEvent(pressPoint.x, pressPoint.y);
else
freeDraggerArea.forceReleaseEvent(mouse.x, mouse.y);
freeDraggerArea = null;
}
}
onReleased: handleRelease(mouse)
onCanceled: handleRelease(mouse)
}
DropArea { DropArea {
anchors.fill: parent anchors.fill: parent

View File

@@ -38,6 +38,7 @@ Node {
|| planeX.dragging || planeY.dragging || planeZ.dragging || planeX.dragging || planeY.dragging || planeZ.dragging
|| centerBall.dragging || centerBall.dragging
property MouseArea3D dragHelper: null property MouseArea3D dragHelper: null
property alias freeDraggerArea: centerBall.mouseArea
position: dragHelper.pivotScenePosition(targetNode) position: dragHelper.pivotScenePosition(targetNode)

View File

@@ -37,6 +37,7 @@ Model {
property bool dragging: mouseArea.dragging property bool dragging: mouseArea.dragging
property bool active: false property bool active: false
property MouseArea3D dragHelper: null property MouseArea3D dragHelper: null
property alias mouseArea: mouseArea
readonly property bool hovering: mouseArea.hovering readonly property bool hovering: mouseArea.hovering

View File

@@ -39,6 +39,7 @@ Node {
property MouseArea3D dragHelper: null property MouseArea3D dragHelper: null
property real currentAngle property real currentAngle
property point currentMousePos property point currentMousePos
property alias freeDraggerArea: mouseAreaFree
position: dragHelper.pivotScenePosition(targetNode) position: dragHelper.pivotScenePosition(targetNode)

View File

@@ -37,6 +37,7 @@ Node {
|| planeX.dragging || planeY.dragging || planeZ.dragging || planeX.dragging || planeY.dragging || planeZ.dragging
|| centerMouseArea.dragging || centerMouseArea.dragging
property MouseArea3D dragHelper: null property MouseArea3D dragHelper: null
property alias freeDraggerArea: centerMouseArea
position: dragHelper.pivotScenePosition(targetNode) position: dragHelper.pivotScenePosition(targetNode)

View File

@@ -512,6 +512,32 @@ double MouseArea3D::getRelativeScale(QQuick3DNode *node) const
return (scenePos1 - scenePos2).length() / 100.; return (scenePos1 - scenePos2).length() / 100.;
} }
void MouseArea3D::forcePressEvent(double x, double y)
{
m_forceCaptureNextPress = true;
Qt::MouseButtons buttons;
Qt::KeyboardModifiers mods;
QMouseEvent event(QEvent::MouseButtonPress, QPointF(x, y), Qt::LeftButton, buttons, mods);
eventFilter(m_view3D, &event);
}
void QmlDesigner::Internal::MouseArea3D::forceMoveEvent(double x, double y)
{
Qt::MouseButtons buttons;
Qt::KeyboardModifiers mods;
QMouseEvent event(QEvent::MouseMove, QPointF(x, y), Qt::LeftButton, buttons, mods);
eventFilter(m_view3D, &event);
}
void QmlDesigner::Internal::MouseArea3D::forceReleaseEvent(double x, double y)
{
Qt::MouseButtons buttons;
Qt::KeyboardModifiers mods;
QMouseEvent event(QEvent::MouseButtonRelease, QPointF(x, y), Qt::LeftButton, buttons, mods);
eventFilter(m_view3D, &event);
}
QVector3D MouseArea3D::getMousePosInPlane(const MouseArea3D *helper, QVector3D MouseArea3D::getMousePosInPlane(const MouseArea3D *helper,
const QPointF &mousePosInView) const const QPointF &mousePosInView) const
{ {
@@ -535,7 +561,8 @@ QVector3D MouseArea3D::getMousePosInPlane(const MouseArea3D *helper,
bool MouseArea3D::eventFilter(QObject *, QEvent *event) bool MouseArea3D::eventFilter(QObject *, QEvent *event)
{ {
if (!m_active || (m_grabsMouse && s_mouseGrab && s_mouseGrab != this if (!m_active || (m_grabsMouse && s_mouseGrab && s_mouseGrab != this
&& (m_priority <= s_mouseGrab->m_priority || s_mouseGrab->m_dragging))) { && (m_priority <= s_mouseGrab->m_priority || s_mouseGrab->m_dragging
|| s_mouseGrab->m_forceCaptureNextPress))) {
return false; return false;
} }
@@ -596,7 +623,8 @@ bool MouseArea3D::eventFilter(QObject *, QEvent *event)
m_dragHelper->setScale(sceneScale()); m_dragHelper->setScale(sceneScale());
} }
m_mousePosInPlane = getMousePosInPlane(m_dragHelper, mouseEvent->pos()); m_mousePosInPlane = getMousePosInPlane(m_dragHelper, mouseEvent->pos());
if (mouseOnTopOfMouseArea(m_mousePosInPlane, mouseEvent->pos())) { if (m_forceCaptureNextPress || mouseOnTopOfMouseArea(m_mousePosInPlane, mouseEvent->pos())) {
m_forceCaptureNextPress = false;
setDragging(true); setDragging(true);
emit pressed(m_mousePosInPlane.toVector2D(), mouseEvent->pos(), pickAngle); emit pressed(m_mousePosInPlane.toVector2D(), mouseEvent->pos(), pickAngle);
if (m_grabsMouse) { if (m_grabsMouse) {

View File

@@ -116,6 +116,10 @@ public slots:
Q_INVOKABLE QVector3D pivotScenePosition(QQuick3DNode *node) const; Q_INVOKABLE QVector3D pivotScenePosition(QQuick3DNode *node) const;
Q_INVOKABLE double getRelativeScale(QQuick3DNode *node) const; Q_INVOKABLE double getRelativeScale(QQuick3DNode *node) const;
Q_INVOKABLE void forcePressEvent(double x, double y);
Q_INVOKABLE void forceMoveEvent(double x, double y);
Q_INVOKABLE void forceReleaseEvent(double x, double y);
signals: signals:
void view3DChanged(); void view3DChanged();
@@ -171,6 +175,7 @@ private:
qreal m_minAngle = 0.; qreal m_minAngle = 0.;
QQuick3DNode *m_pickNode = nullptr; QQuick3DNode *m_pickNode = nullptr;
MouseArea3D *m_dragHelper = nullptr; MouseArea3D *m_dragHelper = nullptr;
bool m_forceCaptureNextPress = false;
}; };
} }