188 lines
7.9 KiB
QML
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|