forked from qt-creator/qt-creator
QmlDesigner: Fix SpinBox dragging
* Add PPU (pixels per unit) property * Include device pixel ratio Task-number: QDS-3081 Task-number: QDS-4798 Change-Id: I23cd26662d719888eca685e54d0706f5da09c4cd Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Henning Gründl
parent
72d932a44e
commit
64e48988ed
@@ -38,6 +38,8 @@ Item {
|
|||||||
property alias sliderIndicatorVisible: spinBox.sliderIndicatorVisible
|
property alias sliderIndicatorVisible: spinBox.sliderIndicatorVisible
|
||||||
property alias hover: spinBox.hover
|
property alias hover: spinBox.hover
|
||||||
|
|
||||||
|
property alias pixelsPerUnit: spinBox.pixelsPerUnit
|
||||||
|
|
||||||
signal valueModified
|
signal valueModified
|
||||||
signal dragStarted
|
signal dragStarted
|
||||||
signal indicatorPressed
|
signal indicatorPressed
|
||||||
@@ -50,6 +52,8 @@ Item {
|
|||||||
StudioControls.RealSpinBox {
|
StudioControls.RealSpinBox {
|
||||||
id: spinBox
|
id: spinBox
|
||||||
|
|
||||||
|
__devicePixelRatio: devicePixelRatio()
|
||||||
|
|
||||||
onDragStarted: {
|
onDragStarted: {
|
||||||
hideCursor()
|
hideCursor()
|
||||||
wrapper.dragStarted()
|
wrapper.dragStarted()
|
||||||
|
@@ -41,6 +41,7 @@ Item {
|
|||||||
property alias sliderIndicatorVisible: spinBox.sliderIndicatorVisible
|
property alias sliderIndicatorVisible: spinBox.sliderIndicatorVisible
|
||||||
|
|
||||||
property alias realDragRange: spinBox.realDragRange
|
property alias realDragRange: spinBox.realDragRange
|
||||||
|
property alias pixelsPerUnit: spinBox.pixelsPerUnit
|
||||||
|
|
||||||
width: 96
|
width: 96
|
||||||
implicitHeight: spinBox.height
|
implicitHeight: spinBox.height
|
||||||
@@ -64,6 +65,8 @@ Item {
|
|||||||
StudioControls.RealSpinBox {
|
StudioControls.RealSpinBox {
|
||||||
id: spinBox
|
id: spinBox
|
||||||
|
|
||||||
|
__devicePixelRatio: devicePixelRatio()
|
||||||
|
|
||||||
onDragStarted: {
|
onDragStarted: {
|
||||||
hideCursor()
|
hideCursor()
|
||||||
transaction.start()
|
transaction.start()
|
||||||
@@ -74,11 +77,12 @@ Item {
|
|||||||
transaction.end()
|
transaction.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Needs to be held in place due to screen size limits potentially being hit while dragging
|
||||||
onDragging: holdCursorInPlace()
|
onDragging: holdCursorInPlace()
|
||||||
|
|
||||||
onRealValueModified: {
|
onRealValueModified: {
|
||||||
if (transaction.active())
|
if (transaction.active())
|
||||||
commitValue()
|
spinBox.commitValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
function commitValue() {
|
function commitValue() {
|
||||||
@@ -105,13 +109,13 @@ Item {
|
|||||||
id: colorLogic
|
id: colorLogic
|
||||||
backendValue: spinBox.backendValue
|
backendValue: spinBox.backendValue
|
||||||
onValueFromBackendChanged: {
|
onValueFromBackendChanged: {
|
||||||
if (valueFromBackend !== undefined)
|
if (colorLogic.valueFromBackend !== undefined)
|
||||||
spinBox.realValue = valueFromBackend
|
spinBox.realValue = colorLogic.valueFromBackend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
labelColor: spinBox.edit ? StudioTheme.Values.themeTextColor : colorLogic.textColor
|
labelColor: spinBox.edit ? StudioTheme.Values.themeTextColor : colorLogic.textColor
|
||||||
|
|
||||||
onCompressedRealValueModified: commitValue()
|
onCompressedRealValueModified: spinBox.commitValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -74,6 +74,9 @@ T.SpinBox {
|
|||||||
property real __sliderIndicatorWidth: StudioTheme.Values.sliderIndicatorWidth
|
property real __sliderIndicatorWidth: StudioTheme.Values.sliderIndicatorWidth
|
||||||
property real __sliderIndicatorHeight: StudioTheme.Values.sliderIndicatorHeight
|
property real __sliderIndicatorHeight: StudioTheme.Values.sliderIndicatorHeight
|
||||||
|
|
||||||
|
property alias __devicePixelRatio: spinBoxInput.devicePixelRatio
|
||||||
|
property alias pixelsPerUnit: spinBoxInput.pixelsPerUnit
|
||||||
|
|
||||||
property alias compressedValueTimer: myTimer
|
property alias compressedValueTimer: myTimer
|
||||||
|
|
||||||
signal realValueModified
|
signal realValueModified
|
||||||
|
@@ -36,6 +36,9 @@ TextInput {
|
|||||||
property bool drag: false
|
property bool drag: false
|
||||||
property bool hover: mouseArea.containsMouse && textInput.enabled
|
property bool hover: mouseArea.containsMouse && textInput.enabled
|
||||||
|
|
||||||
|
property int devicePixelRatio: 1
|
||||||
|
property int pixelsPerUnit: 10
|
||||||
|
|
||||||
z: 2
|
z: 2
|
||||||
font: myControl.font
|
font: myControl.font
|
||||||
color: StudioTheme.Values.themeTextColor
|
color: StudioTheme.Values.themeTextColor
|
||||||
@@ -77,18 +80,21 @@ TextInput {
|
|||||||
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
if (event.modifiers & Qt.ControlModifier) {
|
||||||
mouseArea.stepSize = myControl.minStepSize
|
mouseArea.stepSize = myControl.minStepSize
|
||||||
mouseArea.calcValue(myControl.realValueModified)
|
mouseArea.calcValue()
|
||||||
|
myControl.realValueModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.modifiers & Qt.ShiftModifier) {
|
if (event.modifiers & Qt.ShiftModifier) {
|
||||||
mouseArea.stepSize = myControl.maxStepSize
|
mouseArea.stepSize = myControl.maxStepSize
|
||||||
mouseArea.calcValue(myControl.realValueModified)
|
mouseArea.calcValue()
|
||||||
|
myControl.realValueModified()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keys.onReleased: function(event) {
|
Keys.onReleased: function(event) {
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
mouseArea.stepSize = myControl.realStepSize
|
mouseArea.stepSize = myControl.realStepSize
|
||||||
mouseArea.calcValue(myControl.realValueModified)
|
mouseArea.calcValue()
|
||||||
|
myControl.realValueModified()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,34 +108,42 @@ TextInput {
|
|||||||
|
|
||||||
property real stepSize: myControl.realStepSize
|
property real stepSize: myControl.realStepSize
|
||||||
|
|
||||||
|
// Properties to store the state of a drag operation
|
||||||
property bool dragging: false
|
property bool dragging: false
|
||||||
property bool wasDragging: false
|
property bool hasDragged: false
|
||||||
property bool potentialDragStart: false
|
property bool potentialDragStart: false
|
||||||
|
|
||||||
property real initialValue: myControl.realValue
|
property real initialValue: myControl.realValue // value on drag operation starts
|
||||||
|
|
||||||
property real pressStartX: 0.0
|
property real pressStartX: 0.0
|
||||||
property real dragStartX: 0.0
|
property real dragStartX: 0.0
|
||||||
property real translationX: 0.0
|
property real translationX: 0.0
|
||||||
|
|
||||||
|
property real dragDirection: 0.0
|
||||||
|
property real totalUnits: 0.0 // total number of units dragged
|
||||||
|
property real units: 0.0
|
||||||
|
|
||||||
|
property real __pixelsPerUnit: textInput.devicePixelRatio * textInput.pixelsPerUnit
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
enabled: true
|
enabled: true
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
propagateComposedEvents: true
|
propagateComposedEvents: true
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
preventStealing: true
|
||||||
|
|
||||||
onPositionChanged: function(mouse) {
|
onPositionChanged: function(mouse) {
|
||||||
if (!mouseArea.dragging
|
if (!mouseArea.dragging
|
||||||
&& !myControl.edit
|
&& !myControl.edit
|
||||||
&& Math.abs(mouseArea.pressStartX - mouse.x) > StudioTheme.Values.dragThreshold
|
&& Math.abs(mouseArea.pressStartX - mouse.x) > StudioTheme.Values.dragThreshold
|
||||||
&& mouse.buttons === 1
|
&& mouse.buttons === Qt.LeftButton
|
||||||
&& mouseArea.potentialDragStart) {
|
&& mouseArea.potentialDragStart) {
|
||||||
mouseArea.dragging = true
|
mouseArea.dragging = true
|
||||||
mouseArea.potentialDragStart = false
|
mouseArea.potentialDragStart = false
|
||||||
mouseArea.initialValue = myControl.realValue
|
mouseArea.initialValue = myControl.realValue
|
||||||
mouseArea.cursorShape = Qt.ClosedHandCursor
|
mouseArea.cursorShape = Qt.ClosedHandCursor
|
||||||
mouseArea.dragStartX = mouseArea.mouseX
|
mouseArea.dragStartX = mouse.x
|
||||||
|
|
||||||
myControl.drag = true
|
myControl.drag = true
|
||||||
myControl.dragStarted()
|
myControl.dragStarted()
|
||||||
@@ -143,18 +157,32 @@ TextInput {
|
|||||||
|
|
||||||
mouse.accepted = true
|
mouse.accepted = true
|
||||||
|
|
||||||
mouseArea.translationX += (mouseArea.mouseX - mouseArea.dragStartX)
|
var translationX = mouse.x - mouseArea.dragStartX
|
||||||
mouseArea.calcValue(myControl.realValueModified)
|
|
||||||
|
// Early return if mouse didn't move along x-axis
|
||||||
|
if (translationX === 0.0)
|
||||||
|
return
|
||||||
|
|
||||||
|
var currentDragDirection = Math.sign(translationX)
|
||||||
|
|
||||||
|
// Has drag direction changed
|
||||||
|
if (currentDragDirection !== mouseArea.dragDirection) {
|
||||||
|
mouseArea.translationX = 0.0
|
||||||
|
mouseArea.dragDirection = currentDragDirection
|
||||||
|
mouseArea.totalUnits = mouseArea.units
|
||||||
}
|
}
|
||||||
|
|
||||||
onCanceled: mouseArea.endDrag()
|
mouseArea.translationX += translationX
|
||||||
|
mouseArea.calcValue()
|
||||||
|
myControl.realValueModified()
|
||||||
|
}
|
||||||
|
|
||||||
onClicked: function(mouse) {
|
onClicked: function(mouse) {
|
||||||
if (textInput.edit)
|
if (textInput.edit)
|
||||||
mouse.accepted = false
|
mouse.accepted = false
|
||||||
|
|
||||||
if (mouseArea.wasDragging) {
|
if (mouseArea.hasDragged) {
|
||||||
mouseArea.wasDragging = false
|
mouseArea.hasDragged = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +195,7 @@ TextInput {
|
|||||||
mouse.accepted = false
|
mouse.accepted = false
|
||||||
|
|
||||||
mouseArea.potentialDragStart = true
|
mouseArea.potentialDragStart = true
|
||||||
mouseArea.pressStartX = mouseArea.mouseX
|
mouseArea.pressStartX = mouse.x
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: function(mouse) {
|
onReleased: function(mouse) {
|
||||||
@@ -182,11 +210,12 @@ TextInput {
|
|||||||
return
|
return
|
||||||
|
|
||||||
mouseArea.dragging = false
|
mouseArea.dragging = false
|
||||||
mouseArea.wasDragging = true
|
mouseArea.hasDragged = true
|
||||||
|
|
||||||
if (myControl.compressedValueTimer.running) {
|
if (myControl.compressedValueTimer.running) {
|
||||||
myControl.compressedValueTimer.stop()
|
myControl.compressedValueTimer.stop()
|
||||||
mouseArea.calcValue(myControl.compressedRealValueModified)
|
mouseArea.calcValue()
|
||||||
|
myControl.compressedRealValueModified()
|
||||||
}
|
}
|
||||||
mouseArea.cursorShape = Qt.PointingHandCursor
|
mouseArea.cursorShape = Qt.PointingHandCursor
|
||||||
myControl.drag = false
|
myControl.drag = false
|
||||||
@@ -196,21 +225,21 @@ TextInput {
|
|||||||
textInput.focus = false
|
textInput.focus = false
|
||||||
myControl.focus = false
|
myControl.focus = false
|
||||||
|
|
||||||
mouseArea.translationX = 0
|
mouseArea.translationX = 0.0
|
||||||
|
mouseArea.units = 0.0
|
||||||
|
mouseArea.totalUnits = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcValue(callback) {
|
function calcValue() {
|
||||||
var minTranslation = (myControl.realFrom - mouseArea.initialValue) / mouseArea.stepSize
|
var minUnit = (myControl.realFrom - mouseArea.initialValue) / mouseArea.stepSize
|
||||||
var maxTranslation = (myControl.realTo - mouseArea.initialValue) / mouseArea.stepSize
|
var maxUnit = (myControl.realTo - mouseArea.initialValue) / mouseArea.stepSize
|
||||||
|
|
||||||
mouseArea.translationX = Math.min(Math.max(mouseArea.translationX, minTranslation), maxTranslation)
|
var units = Math.trunc(mouseArea.translationX / mouseArea.__pixelsPerUnit)
|
||||||
|
mouseArea.units = Math.min(Math.max(mouseArea.totalUnits + units, minUnit), maxUnit)
|
||||||
myControl.setRealValue(mouseArea.initialValue + (mouseArea.translationX * mouseArea.stepSize))
|
myControl.setRealValue(mouseArea.initialValue + (mouseArea.units * mouseArea.stepSize))
|
||||||
|
|
||||||
if (mouseArea.dragging)
|
if (mouseArea.dragging)
|
||||||
myControl.dragging()
|
myControl.dragging()
|
||||||
|
|
||||||
callback()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onWheel: function(wheel) {
|
onWheel: function(wheel) {
|
||||||
|
@@ -541,6 +541,14 @@ void PropertyEditorContextObject::holdCursorInPlace()
|
|||||||
QCursor::setPos(w->screen(), m_lastPos);
|
QCursor::setPos(w->screen(), m_lastPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PropertyEditorContextObject::devicePixelRatio()
|
||||||
|
{
|
||||||
|
if (QWidget *w = QApplication::activeWindow())
|
||||||
|
return w->devicePixelRatio();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList PropertyEditorContextObject::styleNamesForFamily(const QString &family)
|
QStringList PropertyEditorContextObject::styleNamesForFamily(const QString &family)
|
||||||
{
|
{
|
||||||
const QFontDatabase dataBase;
|
const QFontDatabase dataBase;
|
||||||
|
@@ -96,6 +96,8 @@ public:
|
|||||||
Q_INVOKABLE void restoreCursor();
|
Q_INVOKABLE void restoreCursor();
|
||||||
Q_INVOKABLE void holdCursorInPlace();
|
Q_INVOKABLE void holdCursorInPlace();
|
||||||
|
|
||||||
|
Q_INVOKABLE int devicePixelRatio();
|
||||||
|
|
||||||
Q_INVOKABLE QStringList styleNamesForFamily(const QString &family);
|
Q_INVOKABLE QStringList styleNamesForFamily(const QString &family);
|
||||||
|
|
||||||
Q_INVOKABLE QStringList allStatesForId(const QString &id);
|
Q_INVOKABLE QStringList allStatesForId(const QString &id);
|
||||||
|
Reference in New Issue
Block a user