209 lines
7.1 KiB
QML
209 lines
7.1 KiB
QML
import QtQuick 2.12
|
|
import QtCharts 2.3
|
|
import QtQuick.Shapes 1.12
|
|
|
|
import Controls 1.0 as Controls
|
|
import Utils 1.0
|
|
|
|
ChartView {
|
|
id: chart
|
|
|
|
antialiasing: true
|
|
backgroundColor: Palette.backgroundColor
|
|
margins.left: 20
|
|
|
|
legend.visible: false
|
|
legend.alignment: Qt.AlignRight
|
|
legend.markerShape: Legend.MarkerShapeCircle
|
|
|
|
property AbstractAxis xAxis: valueAxisX
|
|
property AbstractAxis yAxis: valueAxisY
|
|
|
|
property int defaultXMax: 10
|
|
property int defaultYMax: 1
|
|
property bool autoScaling: true
|
|
property int selectedSeriesIndex: 0
|
|
|
|
property string infoXMark: ""
|
|
property string infoYMark: ""
|
|
|
|
ValueAxis {
|
|
id: valueAxisX
|
|
min: 0
|
|
max: chart.defaultXMax
|
|
tickCount: 8
|
|
gridVisible: false
|
|
gridLineColor: Palette.borderColor
|
|
labelsColor: Palette.contentTextColor
|
|
labelsFont.pixelSize: 18
|
|
color: Palette.borderColor
|
|
titleVisible: false
|
|
}
|
|
|
|
ValueAxis {
|
|
id: valueAxisY
|
|
min: 0
|
|
max: chart.defaultYMax
|
|
tickCount: 6
|
|
labelsColor: Palette.contentTextColor
|
|
labelsFont.pixelSize: 18
|
|
color: Palette.borderColor
|
|
titleVisible: false
|
|
}
|
|
|
|
Shape {
|
|
id: currentPointLine
|
|
implicitWidth: 1
|
|
implicitHeight: chart.plotArea.height
|
|
x: chart.plotArea.x
|
|
y: chart.plotArea.y
|
|
|
|
ShapePath {
|
|
strokeColor: Palette.borderColor
|
|
strokeStyle: ShapePath.SolidLine
|
|
startX: 0
|
|
startY: 0
|
|
PathLine { x: 0; y: currentPointLine.height }
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: currentPointInfo
|
|
|
|
width: currentPointInfoLabel.width
|
|
height: currentPointInfoLabel.height
|
|
color: Palette.backgroundColor
|
|
border.width: 1
|
|
border.color: Palette.borderColor
|
|
opacity: 0.9
|
|
radius: 6
|
|
visible: false
|
|
|
|
Controls.SubtitleLabel {
|
|
id: currentPointInfoLabel
|
|
horizontalAlignment: Text.AlignHCenter
|
|
anchors.centerIn: parent
|
|
padding: 10
|
|
}
|
|
}
|
|
|
|
MouseArea {
|
|
id: chartMouseArea
|
|
anchors.fill: parent
|
|
acceptedButtons: Qt.LeftButton
|
|
hoverEnabled: true
|
|
|
|
property real lastMouseX: 0
|
|
property real lastMouseY: 0
|
|
|
|
property real scrollThreshold: 0
|
|
|
|
onMouseXChanged: {
|
|
if ((mouse.buttons & Qt.LeftButton) == Qt.LeftButton) {
|
|
if (mouseX - lastMouseX > scrollThreshold) {
|
|
chart.scrollLeft(mouseX - lastMouseX)
|
|
} else if (mouseX - lastMouseX < scrollThreshold) {
|
|
chart.scrollRight(lastMouseX - mouseX)
|
|
}
|
|
lastMouseX = mouseX
|
|
chart.autoScaling = false
|
|
}
|
|
|
|
updatePointInfo()
|
|
}
|
|
onMouseYChanged: {
|
|
|
|
if ((mouse.buttons & Qt.LeftButton) == Qt.LeftButton) {
|
|
if (mouseY - lastMouseY > scrollThreshold) {
|
|
chart.scrollUp(mouseY - lastMouseY)
|
|
} else if (mouseY - lastMouseY < scrollThreshold) {
|
|
chart.scrollDown(lastMouseY - mouseY)
|
|
}
|
|
lastMouseY = mouseY
|
|
chart.autoScaling = false
|
|
}
|
|
|
|
updatePointInfo()
|
|
}
|
|
onPressed: {
|
|
if (mouse.button === Qt.LeftButton) {
|
|
lastMouseX = mouseX
|
|
lastMouseY = mouseY
|
|
}
|
|
}
|
|
onWheel: {
|
|
var scaleFactor = 0.75
|
|
var area = chart.plotArea
|
|
chart.autoScaling = false
|
|
|
|
var yAxisPosition = mouseX <= chart.plotArea.x
|
|
if (yAxisPosition) {
|
|
if (wheel.angleDelta.y > 0) {
|
|
chart.zoomIn(Qt.rect(area.x, area.y + Math.round(area.height * (1 - scaleFactor) / 2), area.width, Math.round(area.height * scaleFactor)))
|
|
} else {
|
|
chart.zoomIn(Qt.rect(area.x, area.y - Math.round((area.height / scaleFactor) * (1 - scaleFactor) / 2), area.width, Math.round(area.height / scaleFactor)))
|
|
}
|
|
return
|
|
}
|
|
|
|
var xAxisPosition = mouseY >= (chart.plotArea.y + chart.plotArea.height)
|
|
if (xAxisPosition) {
|
|
if (wheel.angleDelta.y > 0) {
|
|
chart.zoomIn(Qt.rect(area.x + area.width * (1 - scaleFactor) / 2, area.y, Math.round(area.width * scaleFactor), area.height))
|
|
} else {
|
|
chart.zoomIn(Qt.rect(area.x - (area.width / scaleFactor) * (1 - scaleFactor) / 2, area.y, Math.round(area.width / scaleFactor), area.height))
|
|
}
|
|
return
|
|
}
|
|
|
|
if (wheel.angleDelta.y > 0) {
|
|
let zoomedInArea = Qt.rect(area.x + Math.round((mouseX - area.x) * (1 - scaleFactor)),
|
|
area.y + Math.round((mouseY - area.y) * (1 - scaleFactor)),
|
|
Math.round(area.width * scaleFactor),
|
|
Math.round(area.height * scaleFactor))
|
|
chart.zoomIn(zoomedInArea)
|
|
} else {
|
|
let zoomedOutArea = Qt.rect(area.x - Math.floor((mouseX - area.x) * (1 - scaleFactor)),
|
|
area.y - Math.floor((mouseY - area.y) * (1 - scaleFactor)),
|
|
Math.round(area.width * (1 + (1 - scaleFactor))),
|
|
Math.round(area.height * (1 + (1 - scaleFactor))))
|
|
chart.zoomIn(zoomedOutArea)
|
|
}
|
|
|
|
updatePointInfo()
|
|
}
|
|
|
|
function updatePointInfo() {
|
|
let currentPointVisibility = mouseX >= chart.plotArea.x && mouseX <= chart.plotArea.x + chart.plotArea.width &&
|
|
mouseY >= chart.plotArea.y && mouseY <= chart.plotArea.y + chart.plotArea.height
|
|
|
|
currentPointInfo.visible = currentPointVisibility
|
|
currentPointInfo.x = mouseX + 5
|
|
currentPointInfo.y = mouseY - currentPointInfo.height - 5
|
|
|
|
let currentX = mapToValue(Qt.point(mouseX, mouseY), chart.series(selectedSeriesIndex)).x
|
|
let selectedPoint = Qt.point(0, 0)
|
|
|
|
for(let i = 0; i < chart.series(selectedSeriesIndex).count; ++i) {
|
|
let point = chart.series(selectedSeriesIndex).at(i)
|
|
if (point.x > currentX || i === chart.series(selectedSeriesIndex).count - 1) {
|
|
selectedPoint = chart.series(selectedSeriesIndex).at(i)
|
|
currentPointInfoLabel.text = selectedPoint.x + " " + infoXMark + ", " + selectedPoint.y + " " + infoYMark
|
|
break
|
|
}
|
|
}
|
|
|
|
if (chart.series(selectedSeriesIndex).count === 0) {
|
|
currentPointInfo.visible = false
|
|
}
|
|
|
|
currentPointLine.visible = currentPointVisibility
|
|
currentPointLine.x = mouseX
|
|
}
|
|
}
|
|
|
|
onSeriesAdded: if (count === 1) {
|
|
series.pointAdded.connect(function (index){ chartMouseArea.updatePointInfo() })
|
|
}
|
|
}
|