QmlProfiler: Fix jaggy behavior of range start handle

The left handle of the range mover element didn't properly follow
the mouse movement. Also, a lot of code is duplicated between
RangeMover and SelectionRange. This change prepares RangeMover for
being reused in SelectionRange by eliminating external
dependencies.

Task-number: QTCREATORBUG-10762
Change-Id: Ia3b83101263e7af8ed46e1aaf4e92654b0068861
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
Ulf Hermann
2013-11-13 12:10:48 +01:00
parent 188f5de5ed
commit d7cb00d10c
2 changed files with 83 additions and 76 deletions

View File

@@ -49,12 +49,15 @@ Canvas2D {
} }
function updateRange() { function updateRange() {
var newStartTime = Math.round(rangeMover.x * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime(); var newStartTime = Math.round(rangeMover.getLeft() * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime();
var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime(); var newEndTime = Math.round(rangeMover.getRight() * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime();
if (startTime !== newStartTime || endTime !== newEndTime) { if (startTime !== newStartTime || endTime !== newEndTime) {
zoomControl.setRange(newStartTime, newEndTime); zoomControl.setRange(newStartTime, newEndTime);
} }
}
function clamp(val, min, max) {
return Math.min(Math.max(val, min), max);
} }
// ***** connections to external objects // ***** connections to external objects
@@ -62,14 +65,17 @@ Canvas2D {
target: zoomControl target: zoomControl
onRangeChanged: { onRangeChanged: {
if (qmlProfilerModelProxy) { if (qmlProfilerModelProxy) {
startTime = zoomControl.startTime(); startTime = clamp(zoomControl.startTime(), qmlProfilerModelProxy.traceStartTime(), qmlProfilerModelProxy.traceEndTime());
endTime = zoomControl.endTime(); endTime = clamp(zoomControl.endTime(), startTime, qmlProfilerModelProxy.traceEndTime());
var newRangeX = (startTime - qmlProfilerModelProxy.traceStartTime()) * width / qmlProfilerModelProxy.traceDuration(); var newRangeX = (startTime - qmlProfilerModelProxy.traceStartTime()) * width / qmlProfilerModelProxy.traceDuration();
if (rangeMover.x !== newRangeX)
rangeMover.x = newRangeX;
var newWidth = (endTime - startTime) * width / qmlProfilerModelProxy.traceDuration(); var newWidth = (endTime - startTime) * width / qmlProfilerModelProxy.traceDuration();
if (rangeMover.width !== newWidth) var widthChanged = Math.abs(newWidth - rangeMover.getWidth()) > 1;
rangeMover.width = newWidth; var leftChanged = Math.abs(newRangeX - rangeMover.getLeft()) > 1;
if (leftChanged)
rangeMover.setLeft(newRangeX);
if (leftChanged || widthChanged)
rangeMover.setRight(newRangeX + newWidth);
} }
} }
} }
@@ -97,13 +103,20 @@ Canvas2D {
MouseArea { MouseArea {
anchors.fill: canvas anchors.fill: canvas
function jumpTo(posX) { function jumpTo(posX) {
var newX = posX - rangeMover.width/2; var rangeWidth = rangeMover.getWidth();
var newX = posX - rangeWidth / 2;
if (newX < 0) if (newX < 0)
newX = 0; newX = 0;
if (newX + rangeMover.width > canvas.width) if (newX + rangeWidth > canvas.width)
newX = canvas.width - rangeMover.width; newX = canvas.width - rangeWidth;
rangeMover.x = newX;
updateRange(); if (newX < rangeMover.getLeft()) {
rangeMover.setLeft(newX);
rangeMover.setRight(newX + rangeWidth);
} else if (newX > rangeMover.getLeft()) {
rangeMover.setRight(newX + rangeWidth);
rangeMover.setLeft(newX);
}
} }
onPressed: { onPressed: {
@@ -117,6 +130,7 @@ Canvas2D {
RangeMover { RangeMover {
id: rangeMover id: rangeMover
visible: dataReady visible: dataReady
onRangeChanged: canvas.updateRange()
} }
Rectangle { Rectangle {

View File

@@ -31,41 +31,46 @@ import QtQuick 2.1
Rectangle { Rectangle {
id: rangeMover id: rangeMover
anchors.fill: parent
color: "transparent"
signal rangeChanged()
signal rangeDoubleClicked()
property color handleColor: "#869cd1"
property color rangeColor:"#444a64b8" property color rangeColor:"#444a64b8"
property color dragColor:"#664a64b8"
property color borderColor:"#cc4a64b8" property color borderColor:"#cc4a64b8"
property color dragMarkerColor: "#4a64b8" property color dragMarkerColor: "#4a64b8"
width: 20 property color singleLineColor: "#4a64b8"
height: 50
color: rangeColor function setLeft(left) { leftRange.x = left }
function getLeft() { return leftRange.x }
property bool dragStarted: false function setRight(right) { rightRange.x = right }
onXChanged: { function getRight() { return rightRange.x }
if (dragStarted) canvas.updateRange()
}
MouseArea { function getWidth() { return rightRange.x - leftRange.x }
anchors.fill: parent
drag.target: rangeMover Rectangle {
drag.axis: "XAxis" id: selectedRange
drag.minimumX: 0
drag.maximumX: canvas.width - rangeMover.width x: leftRange.x
onPressed: { width: rightRange.x - leftRange.x
parent.dragStarted = true; height: parent.height
}
onReleased: { color: width > 1 ? (dragArea.pressed ? dragColor : rangeColor) : singleLineColor
parent.dragStarted = false;
} onXChanged: parent.rangeChanged()
onWidthChanged: parent.rangeChanged()
} }
Rectangle { Rectangle {
id: leftRange id: leftRange
// used for dragging the borders onXChanged: {
property real initialX: 0 if (dragArea.drag.active)
property real initialWidth: 0 rightRange.x = x + dragArea.origWidth;
}
x: 0 x: 0
height: parent.height height: parent.height
@@ -75,9 +80,9 @@ Rectangle {
Rectangle { Rectangle {
id: leftBorderHandle id: leftBorderHandle
height: parent.height height: parent.height
x: -width anchors.right: parent.left
width: 7 width: 7
color: "#869cd1" color: handleColor
visible: false visible: false
Image { Image {
source: "range_handle.png" source: "range_handle.png"
@@ -85,7 +90,7 @@ Rectangle {
width: 4 width: 4
height: 9 height: 9
fillMode: Image.Tile fillMode: Image.Tile
y: rangeMover.height / 2 - 4 y: parent.height / 2 - 4
} }
} }
@@ -97,25 +102,14 @@ Rectangle {
} }
} }
onXChanged: {
if (x !== 0) {
rangeMover.width = initialWidth - x;
rangeMover.x = initialX + x;
x = 0;
canvas.updateRange();
}
}
MouseArea { MouseArea {
x: -10 anchors.fill: leftBorderHandle
width: 13
y: 0
height: parent.height
drag.target: leftRange drag.target: leftRange
drag.axis: "XAxis" drag.axis: "XAxis"
drag.minimumX: -parent.initialX drag.minimumX: 0
drag.maximumX: parent.initialWidth - 2 drag.maximumX: rangeMover.width
drag.onActiveChanged: drag.maximumX = rightRange.x
hoverEnabled: true hoverEnabled: true
@@ -128,17 +122,13 @@ Rectangle {
onReleased: { onReleased: {
if (!containsMouse) parent.state = ""; if (!containsMouse) parent.state = "";
} }
onPressed: {
parent.initialX = rangeMover.x;
parent.initialWidth = rangeMover.width;
}
} }
} }
Rectangle { Rectangle {
id: rightRange id: rightRange
x: rangeMover.width x: 1
height: parent.height height: parent.height
width: 1 width: 1
color: borderColor color: borderColor
@@ -146,9 +136,9 @@ Rectangle {
Rectangle { Rectangle {
id: rightBorderHandle id: rightBorderHandle
height: parent.height height: parent.height
x: 1 anchors.left: parent.right
width: 7 width: 7
color: "#869cd1" color: handleColor
visible: false visible: false
Image { Image {
source: "range_handle.png" source: "range_handle.png"
@@ -156,7 +146,7 @@ Rectangle {
width: 4 width: 4
height: 9 height: 9
fillMode: Image.Tile fillMode: Image.Tile
y: rangeMover.height / 2 - 4 y: parent.height / 2 - 4
} }
} }
@@ -168,23 +158,14 @@ Rectangle {
} }
} }
onXChanged: {
if (x!=rangeMover.width) {
rangeMover.width = x;
canvas.updateRange();
}
}
MouseArea { MouseArea {
x: -3 anchors.fill: rightBorderHandle
width: 13
y: 0
height: parent.height
drag.target: rightRange drag.target: rightRange
drag.axis: "XAxis" drag.axis: "XAxis"
drag.minimumX: 1 drag.minimumX: 0
drag.maximumX: canvas.width - rangeMover.x drag.maximumX: rangeMover.width
drag.onActiveChanged: drag.minimumX = leftRange.x
hoverEnabled: true hoverEnabled: true
@@ -200,4 +181,16 @@ Rectangle {
} }
} }
MouseArea {
id: dragArea
property int origWidth: 0
anchors.fill: selectedRange
drag.target: leftRange
drag.axis: "XAxis"
drag.minimumX: 0
drag.maximumX: rangeMover.width - origWidth
drag.onActiveChanged: origWidth = selectedRange.width
onDoubleClicked: parent.rangeDoubleClicked()
}
} }