-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTriStateSwitchIndicatorBasic.qml
More file actions
148 lines (122 loc) · 5.41 KB
/
TriStateSwitchIndicatorBasic.qml
File metadata and controls
148 lines (122 loc) · 5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import QtQuick
import QtQuick.Effects
import QtQuick.Shapes
import TriStateSwitchQt
Item {
id: root
required property TriStateSwitch control
readonly property point position: Qt.point(positionX, positionY)
property real positionX: control.position.x
property real positionY: control.position.y
NumberBehavior on positionX {}
NumberBehavior on positionY {}
readonly property point positionUnchecked: root.control.corners[0]
readonly property point positionPartiallyChecked: root.control.corners[1]
readonly property point positionChecked: root.control.corners[2]
// transitions in normalized coordinates:
// x corresponds to the position between the specified states,
// y corresponds to the perpendicular position between the third state and a line between these two.
readonly property point positionUncheckedToChecked: GeometryUtils.planarPosition(positionUnchecked, positionChecked, positionPartiallyChecked, position)
readonly property point positionUncheckedToPartiallyChecked: GeometryUtils.planarPosition(positionUnchecked, positionPartiallyChecked, positionChecked, position)
readonly property point positionPartiallyCheckedToChecked: GeometryUtils.planarPosition(positionPartiallyChecked, positionChecked, positionUnchecked, position)
readonly property real positionOfChecked: 1 - positionUncheckedToPartiallyChecked.y
readonly property real positionOfPartiallyChecked: 1 - positionUncheckedToChecked.y
readonly property real positionOfUnchecked: 1 - positionPartiallyCheckedToChecked.y
readonly property real knobSize: 28
implicitWidth: 70
implicitHeight: 50
// outline
Shape {
id: shape
x: root.knobSize / 2
y: root.knobSize / 2
width: root.width - root.knobSize
height: root.height - root.knobSize
ShapePath {
fillColor: root.control.palette.base
strokeColor: root.control.visualFocus ? root.control.palette.highlight : root.control.palette.mid
strokeWidth: root.control.visualFocus ? 2 : 1
capStyle: ShapePath.RoundCap
joinStyle: ShapePath.RoundJoin
PathSvg {
path: {
const vertices = GeometryUtils.scaledPoints(root.control.corners, Qt.size(shape.width, shape.height));
return GeometryUtils.roundedTriangleOutlineSvgPath(...vertices, knobSize / 2);
}
}
}
layer.enabled: true
layer.samples: 4
layer.effect: MultiEffect {
shadowEnabled: true
shadowBlur: 0.2
shadowColor: root.control.palette.shadow
}
}
// knob
Item {
width: root.knobSize
height: root.knobSize
// These expressions don't really make the knob 'stick' to the cursor :(
// But rewriting it in the way that makes it 'stick' breaks
// - either dragging from the edges outside indicator,
// - or snapping around the vertices because of the changes to the scale of the triangle.
x: root.control.visualPosition.x * (root.width - root.knobSize)
y: root.control.visualPosition.y * (root.height - root.knobSize)
NumberBehavior on x {}
NumberBehavior on y {}
Rectangle {
anchors.fill: parent
anchors.margins: 2
// that makes it 24x24
color: root.control.down ? root.control.palette.light : root.control.palette.base
border.width: root.control.visualFocus ? 2 : 1
border.color: root.control.visualFocus ? root.control.palette.highlight : root.control.palette.mid
radius: width / 2
// icon canvas
Item {
// that makes it 16x16
anchors.fill: parent
anchors.margins: 4
// horizontal line for Unchecked minus sign & Checked plus sign,
// collapses into a middle dot for PartiallyChecked (...)
Line {
anchors.centerIn: parent
width: GeometryUtils.lerp(parent.width, implicitWidth, root.positionOfPartiallyChecked)
}
// vertical line for Checked plus sign
// collapses into a middle dot for Unchecked & PartiallyChecked (...)
Line {
anchors.centerIn: parent
height: GeometryUtils.lerp(implicitHeight, parent.height, root.positionOfChecked)
}
// left dot for PartiallyChecked (...)
Line {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
opacity: root.positionOfPartiallyChecked
}
// right dot for PartiallyChecked (...)
Line {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
opacity: root.positionOfPartiallyChecked
}
}
}
}
component Line : Rectangle {
anchors.alignWhenCentered: false
implicitWidth: 4
implicitHeight: 4
color: root.control.palette.dark
radius: Math.min(width, height)
}
component NumberBehavior : Behavior {
enabled: !root.control.pressed
NumberAnimation {
duration: 500
easing.type: Easing.OutCubic
}
}
}