forked from qt-creator/qt-creator
QmlDesigner: Rework SpinBox dragging functionality
* Replace DragHandler with MouseArea due to the DragHandler not being able to accept MouseEvents * Replace TapHandler with MouseArea due to MouseArea stealing press signals from TapHandler, but needed to get press events due to removal of DragHandler * Add functionality to keep cursor in place while dragging * Keep ActionIndicator visible while dragging * Fix qsTr in RectangleSpecifics Change-Id: I6558623287e1864359128d4194c9db78736ee3a4 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
fcb3fabd13
commit
15db0bb173
@@ -63,7 +63,7 @@ Column {
|
||||
Section {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
caption: "Rectangle"
|
||||
caption: qsTr("Rectangle")
|
||||
|
||||
SectionLayout {
|
||||
rows: 2
|
||||
|
@@ -45,7 +45,10 @@ Item {
|
||||
width: 96
|
||||
implicitHeight: spinBox.height
|
||||
|
||||
onFocusChanged: transaction.end();
|
||||
onFocusChanged: {
|
||||
restoreCursor();
|
||||
transaction.end();
|
||||
}
|
||||
|
||||
StudioControls.RealSpinBox {
|
||||
id: spinBox
|
||||
@@ -60,6 +63,8 @@ Item {
|
||||
transaction.end();
|
||||
}
|
||||
|
||||
onDragging: holdCursorInPlace();
|
||||
|
||||
onRealValueModified: {
|
||||
if (transaction.active())
|
||||
commitValue();
|
||||
|
@@ -55,7 +55,8 @@ Rectangle {
|
||||
visible: text !== StudioTheme.Constants.actionIcon || actionIndicator.forceVisible
|
||||
|| (myControl !== undefined &&
|
||||
((myControl.edit !== undefined && myControl.edit)
|
||||
|| (myControl.hover !== undefined && myControl.hover)))
|
||||
|| (myControl.hover !== undefined && myControl.hover)
|
||||
|| (myControl.drag !== undefined && myControl.drag)))
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.family: StudioTheme.Constants.iconFont.family
|
||||
font.pixelSize: StudioTheme.Values.myIconFontSize
|
||||
|
@@ -55,6 +55,7 @@ T.SpinBox {
|
||||
|
||||
property bool dirty: false // user modification flag
|
||||
|
||||
// TODO Not used anymore. Will be removed when all dependencies were removed.
|
||||
property real realDragRange: mySpinBox.realTo - mySpinBox.realFrom
|
||||
|
||||
property alias actionIndicatorVisible: actionIndicator.visible
|
||||
@@ -77,6 +78,7 @@ T.SpinBox {
|
||||
signal compressedRealValueModified
|
||||
signal dragStarted
|
||||
signal dragEnded
|
||||
signal dragging
|
||||
|
||||
// Use custom wheel handling due to bugs
|
||||
property bool __wheelEnabled: false
|
||||
|
@@ -70,61 +70,25 @@ TextInput {
|
||||
height: StudioTheme.Values.height
|
||||
}
|
||||
|
||||
DragHandler {
|
||||
id: dragHandler
|
||||
target: null
|
||||
acceptedDevices: PointerDevice.Mouse
|
||||
enabled: true
|
||||
|
||||
property real initialValue: myControl.realValue
|
||||
property real multiplier: 1.0
|
||||
|
||||
onActiveChanged: {
|
||||
if (dragHandler.active) {
|
||||
dragHandler.initialValue = myControl.realValue
|
||||
mouseArea.cursorShape = Qt.ClosedHandCursor // TODO
|
||||
myControl.drag = true
|
||||
myControl.dragStarted()
|
||||
// Force focus on the non visible component to receive key events
|
||||
dragModifierWorkaround.forceActiveFocus()
|
||||
} else {
|
||||
if (myControl.compressedValueTimer.running) {
|
||||
myControl.compressedValueTimer.stop()
|
||||
calcValue(myControl.compressedRealValueModified)
|
||||
}
|
||||
mouseArea.cursorShape = Qt.PointingHandCursor // TODO
|
||||
myControl.drag = false
|
||||
myControl.dragEnded()
|
||||
// Avoid active focus on the component after dragging
|
||||
dragModifierWorkaround.focus = false
|
||||
textInput.focus = false
|
||||
myControl.focus = false
|
||||
}
|
||||
}
|
||||
onTranslationChanged: calcValue(myControl.realValueModified)
|
||||
onMultiplierChanged: calcValue(myControl.realValueModified)
|
||||
|
||||
function calcValue(callback) {
|
||||
var tmp = myControl.realDragRange / StudioTheme.Values.dragLength
|
||||
myControl.setRealValue(dragHandler.initialValue + (tmp * dragHandler.translation.x * dragHandler.multiplier))
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: dragModifierWorkaround
|
||||
Keys.onPressed: {
|
||||
event.accepted = true
|
||||
|
||||
if (event.modifiers & Qt.ControlModifier)
|
||||
dragHandler.multiplier = 0.1
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
mouseArea.stepSize = myControl.minStepSize
|
||||
mouseArea.calcValue(myControl.realValueModified)
|
||||
}
|
||||
|
||||
if (event.modifiers & Qt.ShiftModifier)
|
||||
dragHandler.multiplier = 10.0
|
||||
if (event.modifiers & Qt.ShiftModifier) {
|
||||
mouseArea.stepSize = myControl.maxStepSize
|
||||
mouseArea.calcValue(myControl.realValueModified)
|
||||
}
|
||||
}
|
||||
Keys.onReleased: {
|
||||
event.accepted = true
|
||||
dragHandler.multiplier = 1.0
|
||||
mouseArea.stepSize = myControl.realStepSize
|
||||
mouseArea.calcValue(myControl.realValueModified)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,21 +97,21 @@ TextInput {
|
||||
event.accepted = (event.key === Qt.Key_Up || event.key === Qt.Key_Down)
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
id: tapHandler
|
||||
acceptedDevices: PointerDevice.Mouse
|
||||
enabled: true
|
||||
onTapped: {
|
||||
textInput.forceActiveFocus()
|
||||
textInput.deselect() // QTBUG-75862
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
property real stepSize: myControl.realStepSize
|
||||
|
||||
property bool dragging: false
|
||||
property bool wasDragging: false
|
||||
property bool potentialDragStart: false
|
||||
|
||||
property real initialValue: myControl.realValue
|
||||
|
||||
property real pressStartX: 0.0
|
||||
property real dragStartX: 0.0
|
||||
property real translationX: 0.0
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: true
|
||||
hoverEnabled: true
|
||||
@@ -156,7 +120,90 @@ TextInput {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
// Sets the global hover
|
||||
onContainsMouseChanged: myControl.hover = containsMouse
|
||||
onPressed: mouse.accepted = false
|
||||
|
||||
onPositionChanged: {
|
||||
if (!mouseArea.dragging
|
||||
&& !myControl.edit
|
||||
&& Math.abs(mouseArea.pressStartX - mouse.x) > StudioTheme.Values.dragThreshold
|
||||
&& mouse.buttons === 1
|
||||
&& mouseArea.potentialDragStart) {
|
||||
mouseArea.dragging = true
|
||||
mouseArea.potentialDragStart = false
|
||||
mouseArea.initialValue = myControl.realValue
|
||||
mouseArea.cursorShape = Qt.ClosedHandCursor
|
||||
mouseArea.dragStartX = mouseArea.mouseX
|
||||
|
||||
myControl.drag = true
|
||||
myControl.dragStarted()
|
||||
// Force focus on the non visible component to receive key events
|
||||
dragModifierWorkaround.forceActiveFocus()
|
||||
textInput.deselect()
|
||||
}
|
||||
|
||||
if (!mouseArea.dragging)
|
||||
return
|
||||
|
||||
mouse.accepted = true
|
||||
|
||||
mouseArea.translationX += (mouseArea.mouseX - mouseArea.dragStartX)
|
||||
mouseArea.calcValue(myControl.realValueModified)
|
||||
}
|
||||
|
||||
onCanceled: mouseArea.endDrag()
|
||||
|
||||
onClicked: {
|
||||
if (mouseArea.wasDragging) {
|
||||
mouseArea.wasDragging = false
|
||||
return
|
||||
}
|
||||
|
||||
textInput.forceActiveFocus()
|
||||
textInput.deselect() // QTBUG-75862
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
mouseArea.potentialDragStart = true
|
||||
mouseArea.pressStartX = mouseArea.mouseX
|
||||
}
|
||||
|
||||
onReleased: mouseArea.endDrag()
|
||||
|
||||
function endDrag() {
|
||||
if (!mouseArea.dragging)
|
||||
return
|
||||
|
||||
mouseArea.dragging = false
|
||||
mouseArea.wasDragging = true
|
||||
|
||||
if (myControl.compressedValueTimer.running) {
|
||||
myControl.compressedValueTimer.stop()
|
||||
mouseArea.calcValue(myControl.compressedRealValueModified)
|
||||
}
|
||||
mouseArea.cursorShape = Qt.PointingHandCursor
|
||||
myControl.drag = false
|
||||
myControl.dragEnded()
|
||||
// Avoid active focus on the component after dragging
|
||||
dragModifierWorkaround.focus = false
|
||||
textInput.focus = false
|
||||
myControl.focus = false
|
||||
|
||||
mouseArea.translationX = 0
|
||||
}
|
||||
|
||||
function calcValue(callback) {
|
||||
var minTranslation = (myControl.realFrom - mouseArea.initialValue) / mouseArea.stepSize
|
||||
var maxTranslation = (myControl.realTo - mouseArea.initialValue) / mouseArea.stepSize
|
||||
|
||||
mouseArea.translationX = Math.min(Math.max(mouseArea.translationX, minTranslation), maxTranslation)
|
||||
|
||||
myControl.setRealValue(mouseArea.initialValue + (mouseArea.translationX * mouseArea.stepSize))
|
||||
|
||||
if (mouseArea.dragging)
|
||||
myControl.dragging()
|
||||
|
||||
callback()
|
||||
}
|
||||
|
||||
onWheel: {
|
||||
if (!myControl.__wheelEnabled)
|
||||
return
|
||||
@@ -187,14 +234,6 @@ TextInput {
|
||||
color: StudioTheme.Values.themeControlBackground
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
}
|
||||
PropertyChanges {
|
||||
target: dragHandler
|
||||
enabled: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: tapHandler
|
||||
enabled: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: mouseArea
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
@@ -217,14 +256,6 @@ TextInput {
|
||||
color: StudioTheme.Values.themeFocusEdit
|
||||
border.color: StudioTheme.Values.themeInteraction
|
||||
}
|
||||
PropertyChanges {
|
||||
target: dragHandler
|
||||
enabled: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: tapHandler
|
||||
enabled: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: mouseArea
|
||||
cursorShape: Qt.IBeamCursor
|
||||
|
@@ -50,7 +50,7 @@ QtObject {
|
||||
property real sliderControlSize: 12
|
||||
property real sliderControlSizeMulti: values.sliderControlSize * values.scaleFactor
|
||||
|
||||
property int dragLength: 400 // px
|
||||
property int dragThreshold: 10 // px
|
||||
property real spinControlIconSize: 8
|
||||
property real spinControlIconSizeMulti: values.spinControlIconSize * values.scaleFactor
|
||||
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#include <QFontDatabase>
|
||||
#include <QMessageBox>
|
||||
#include <QQmlContext>
|
||||
#include <QWindow>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
@@ -495,7 +496,9 @@ void PropertyEditorContextObject::hideCursor()
|
||||
return;
|
||||
|
||||
QApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
|
||||
m_lastPos = QCursor::pos();
|
||||
|
||||
if (QWidget *w = QApplication::activeWindow())
|
||||
m_lastPos = QCursor::pos(w->screen());
|
||||
}
|
||||
|
||||
void PropertyEditorContextObject::restoreCursor()
|
||||
@@ -503,8 +506,19 @@ void PropertyEditorContextObject::restoreCursor()
|
||||
if (!QApplication::overrideCursor())
|
||||
return;
|
||||
|
||||
QCursor::setPos(m_lastPos);
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if (QWidget *w = QApplication::activeWindow())
|
||||
QCursor::setPos(w->screen(), m_lastPos);
|
||||
}
|
||||
|
||||
void PropertyEditorContextObject::holdCursorInPlace()
|
||||
{
|
||||
if (!QApplication::overrideCursor())
|
||||
return;
|
||||
|
||||
if (QWidget *w = QApplication::activeWindow())
|
||||
QCursor::setPos(w->screen(), m_lastPos);
|
||||
}
|
||||
|
||||
QStringList PropertyEditorContextObject::styleNamesForFamily(const QString &family)
|
||||
|
@@ -91,6 +91,7 @@ public:
|
||||
|
||||
Q_INVOKABLE void hideCursor();
|
||||
Q_INVOKABLE void restoreCursor();
|
||||
Q_INVOKABLE void holdCursorInPlace();
|
||||
|
||||
Q_INVOKABLE QStringList styleNamesForFamily(const QString &family);
|
||||
|
||||
|
Reference in New Issue
Block a user