st-ten-1/src/ui/qml_circular_gauge/qml_circular_gauge.qml

188 lines
7.9 KiB
QML
Raw Normal View History

2022-06-01 16:37:19 +00:00
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
}
}
}
}
}