st-ten-1/src/ui/qml_circular_gauge/qml_circular_gauge.qml
matteo porta 0beb139753 init
2022-06-01 18:37:27 +02:00

188 lines
7.9 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
import QtQuick.Extras.Private 1.0
import QtQuick.Shapes 1.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.12
import "./components"
// WRAPPER FOR VARIABLES
Item {
id: root
objectName: "gauge"
// EXTERNALLY CONFIGURABLE PROPERTIES
property real size: 300
property real padding: 10
property real min: -10.0
property real max: 10.0
property real step: 1.0
property real minor_step_n: -4 // positive for count negative for angle
property real value: 0.0
property string unit: "number"
property real min_angle: -60
property real max_angle: +60
property
var colorRanges: []
// SHOWN HEIGHT AND WIDTH
height: wrapper.height
width: wrapper.width
// COLOR
function _get_color(value) {
var rs, r;
for (var i = 0; i < root.colorRanges.length; i += 1) {
rs = root.colorRanges[i];
for (var j = 0; j < rs[0].length; j += 1) {
r = rs[0][j];
if (value >= r[0] && value <= r[1]) {
return rs[1];
}
}
}
return "#c8c8c8";
}
// PADDING
Control {
id: wrapper
width: root.size * 1.2 * Math.sin((gauge.angleRange / 2) * (Math.PI / 180)) + padding * 2
property real max_side_angle: Math.max(Math.abs(root.min_angle), Math.abs(root.max_angle))
height: root.size * 1.2 / 2 * (max_side_angle <= 90 ? 1 : (1 + Math.sin((max_side_angle - 90) * (Math.PI / 180)))) + padding * 2
padding: root.padding
background: Rectangle {
color: "#555"
}
// CROP TO THIS RECTANGLE
contentItem: Rectangle {
clip: true
color: "transparent"
// GAUGE
CircularGauge {
id: gauge
value: root.value
minimumValue: root.min
maximumValue: root.max
// STYLING
// align
anchors.horizontalCenter: parent.horizontalCenter
// anchors.verticalCenter: parent.bottom
y: root.size * 0.03
tickmarksVisible: true
property real valueRange: maximumValue - minimumValue
property real valueCenter: (root.min + root.max) / 2
property real angleRange: Math.abs(root.min_angle) + Math.abs(root.max_angle)
property real angleCenter: (root.min_angle + root.max_angle) / 2
// labels, ticks, minor ticks density
property real minorTickmarkAngleStep: Math.abs(root.minor_step_n)
// apply styling
style: CircularGaugeStyle {
id: style
objectName: "style"
// GAUGE ANGLE
minimumValueAngle: -(gauge.angleRange / 2)
maximumValueAngle: +(gauge.angleRange / 2)
// value to angle
function _valueToAngle(value) {
return ((value - gauge.valueCenter) / gauge.valueRange) * gauge.angleRange + gauge.angleCenter
}
// BACKGROUND (COLORED RANGES)
background: Rectangle {
id: background
// implicitWidth and implicitHeight set outerRadius for the style
implicitWidth: root.size - root.padding
implicitHeight: root.size - root.padding
width: implicitWidth
height: implicitHeight
color: "transparent"
Connections {
target: root
function onColorRangesChanged() {
var rs, color, r;
for (var i = 0; i < root.colorRanges.length; i += 1) {
rs = root.colorRanges[i];
color = rs[1];
for (var j = 0; j < rs[0].length; j += 1) {
r = rs[0][j];
Qt.createQmlObject(`
import "./components"
Arch {
radius: outerRadius
startAngle: ${_valueToAngle(r[0])}
stopAngle: ${_valueToAngle(r[1])}
strokeWidth: outerRadius * 0.02
color: "${color}"
}
`, background);
}
}
}
}
}
// // NEEDLE
// needle: Component
// // FOREGROUND (CENTRAL DIAL)
// foreground: Component
// LABELS
tickmarkLabel: Text {
font.pixelSize: Math.max(6, outerRadius * 0.1)
text: styleData.value % 1 == 0 ? styleData.value : styleData.value.toFixed(2)
color: "#c8c8c8" // root._get_color(styleData.value)
antialiasing: true
}
labelStepSize: root.step
property real labelCount: Math.floor(gauge.valueRange / labelStepSize)
// labelInset: 0.0
// TICKS
tickmark: Rectangle {
implicitWidth: outerRadius * 0.02
implicitHeight: outerRadius * 0.075
color: root._get_color(styleData.value)
antialiasing: true
}
tickmarkStepSize: root.step
tickmarkInset: 0.0
// MINOR TICKS
minorTickmark: Rectangle {
implicitWidth: outerRadius * 0.01
implicitHeight: outerRadius * 0.05
color: root._get_color(styleData.value)
antialiasing: true
}
minorTickmarkCount: root.minor_step_n > 0 ? Math.floor(root.minor_step_n) : Math.floor(gauge.angleRange / tickmarkCount / gauge.minorTickmarkAngleStep) // every minorTickmarkAngleStep degreees or more
minorTickmarkInset: 0.0
}
}
Rectangle {
anchors.centerIn: parent
width: root.size * 0.4
height: root.size * 0.25
color: "transparent"
Text {
id: value_text
anchors.centerIn: parent
property real font_size: root.size * 0.1
font.pixelSize: font_size
fontSizeMode: Text.Fit
font.bold: true
text: root.value % 1 == 0 ? root.value : root.value.toFixed(2)
color: "#c8c8c8" // root._get_color(root.value)
antialiasing: true
}
Text {
anchors.top: value_text.bottom
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: value_text.font_size * 0.5
fontSizeMode: Text.Fit
font.bold: true
text: root.unit
color: "#c8c8c8" // root._get_color(root.value)
antialiasing: true
}
}
}
}
}