121 lines
3.7 KiB
QML
121 lines
3.7 KiB
QML
import QtQuick
|
|
import QtQuick.Shapes
|
|
import "root:/config"
|
|
|
|
// Radial gauge used across the resource popout. Sweeps a 270° arc with a
|
|
// tick-marked rail behind it and the reading set in the middle.
|
|
Item {
|
|
id: root
|
|
|
|
property real value: 0 // 0..100
|
|
property string label: ""
|
|
property string readout: Math.round(value) + "%"
|
|
property string sub: ""
|
|
property color arcColor: Theme.heat(value)
|
|
property real thickness: 7
|
|
property real startAngle: 135
|
|
property real sweep: 270
|
|
property int ticks: 24
|
|
|
|
implicitWidth: 96
|
|
implicitHeight: 96
|
|
|
|
readonly property real _r: Math.min(width, height) / 2 - thickness / 2 - 4
|
|
readonly property real _cx: width / 2
|
|
readonly property real _cy: height / 2
|
|
|
|
// Rail
|
|
Shape {
|
|
anchors.fill: parent
|
|
preferredRendererType: Shape.CurveRenderer
|
|
ShapePath {
|
|
fillColor: "transparent"
|
|
strokeColor: Theme.alpha(Theme.outline, 0.5)
|
|
strokeWidth: root.thickness
|
|
capStyle: ShapePath.FlatCap
|
|
PathAngleArc {
|
|
centerX: root._cx; centerY: root._cy
|
|
radiusX: root._r; radiusY: root._r
|
|
startAngle: root.startAngle
|
|
sweepAngle: root.sweep
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tick marks around the rail.
|
|
Repeater {
|
|
model: root.ticks
|
|
Rectangle {
|
|
required property int index
|
|
readonly property real a: (root.startAngle + root.sweep * (index / (root.ticks - 1))) * Math.PI / 180
|
|
readonly property real rr: root._r + root.thickness / 2 + 3
|
|
width: 2
|
|
height: index % 4 === 0 ? 6 : 3
|
|
color: Theme.alpha(Theme.primary, index % 4 === 0 ? 0.55 : 0.25)
|
|
x: root._cx + Math.cos(a) * rr - width / 2
|
|
y: root._cy + Math.sin(a) * rr - height / 2
|
|
rotation: (root.startAngle + root.sweep * (index / (root.ticks - 1))) + 90
|
|
}
|
|
}
|
|
|
|
// Value arc
|
|
Shape {
|
|
anchors.fill: parent
|
|
preferredRendererType: Shape.CurveRenderer
|
|
ShapePath {
|
|
fillColor: "transparent"
|
|
strokeColor: root.arcColor
|
|
strokeWidth: root.thickness
|
|
capStyle: ShapePath.FlatCap
|
|
PathAngleArc {
|
|
id: valueArc
|
|
centerX: root._cx; centerY: root._cy
|
|
radiusX: root._r; radiusY: root._r
|
|
startAngle: root.startAngle
|
|
sweepAngle: root.sweep * Math.max(0, Math.min(100, root.value)) / 100
|
|
|
|
Behavior on sweepAngle {
|
|
NumberAnimation {
|
|
duration: Theme.durSlow
|
|
easing.type: Easing.OutExpo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
anchors.centerIn: parent
|
|
spacing: -2
|
|
|
|
SplitText {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
text: root.readout
|
|
pixelSize: Theme.fsLarge
|
|
color: Theme.text
|
|
split: 1.2
|
|
splitOpacity: 0.6
|
|
}
|
|
|
|
Text {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
text: root.label
|
|
color: Theme.muted
|
|
font.family: Theme.fontMono
|
|
font.pixelSize: Theme.fsMicro
|
|
font.letterSpacing: 2
|
|
renderType: Text.NativeRendering
|
|
}
|
|
|
|
Text {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
visible: root.sub !== ""
|
|
text: root.sub
|
|
color: Theme.subtext
|
|
font.family: Theme.fontMono
|
|
font.pixelSize: Theme.fsMicro
|
|
renderType: Text.NativeRendering
|
|
}
|
|
}
|
|
}
|