QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
DropButton.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3
4import QGroundControl
5import QGroundControl.Controls
6
7Item {
8 id: _root
9 z: QGroundControl.zOrderWidgets
10
11 signal clicked()
12 property alias buttonImage: roundButton.buttonImage
13 property alias rotateImage: roundButton.rotateImage
14 property real radius: ScreenTools.isMobile ? ScreenTools.defaultFontPixelHeight * 1.75 : ScreenTools.defaultFontPixelHeight * 1.25
15 property int dropDirection: dropDown
16 property alias dropDownComponent: dropDownLoader.sourceComponent
17 property real viewportMargins: 0
18 property real topMargin: parent.height - mainWindow.height
19 property alias lightBorders: roundButton.lightBorders
20
21 width: radius * 2
22 height: radius * 2
23
24 // Should be an enum but that get's into the whole problem of creating a singleton which isn't worth the effort
25 readonly property int dropLeft: 1
26 readonly property int dropRight: 2
27 readonly property int dropUp: 3
28 readonly property int dropDown: 4
29
30 readonly property real _arrowBaseWidth: radius // Width of long side of arrow
31 readonly property real _arrowPointHeight: radius * 0.666 // Height is long side to point
32 readonly property real _dropCornerRadius: ScreenTools.defaultFontPixelWidth * 0.5
33 readonly property real _dropCornerRadiusX2: _dropCornerRadius * 2
34 readonly property real _dropMargin: _dropCornerRadius
35 readonly property real _dropMarginX2: _dropMargin * 2
36
37 property real _viewportMaxLeft: -x + viewportMargins
38 property real _viewportMaxRight: parent.width - (viewportMargins * 2) - x
39 property real _viewportMaxTop: -y + viewportMargins + topMargin
40 property real _viewportMaxBottom: parent.height - (viewportMargins * 2) - y
41
42 // Set up ButtonGroup support. We use the checked property to drive visibility of drop down.
43
44 property alias checked: roundButton.checked
45
46 property ButtonGroup buttonGroup: null
47 onButtonGroupChanged: {
48 if (buttonGroup) {
49 buttonGroup.addButton(_root)
50 }
51 }
52
53 function hideDropDown() {
54 checked = false
55 }
56
57 function _calcPositions() {
58 var dropComponentWidth = dropDownLoader.item.width
59 var dropComponentHeight = dropDownLoader.item.height
60 var dropRectWidth = dropComponentWidth + _dropMarginX2
61 var dropRectHeight = dropComponentHeight + _dropMarginX2
62
63 dropItemHolderRect.width = dropRectWidth
64 dropItemHolderRect.height = dropRectHeight
65
66 dropDownItem.width = dropComponentWidth + _dropMarginX2
67 dropDownItem.height = dropComponentHeight + _dropMarginX2
68
69 if (dropDirection == dropUp || dropDirection == dropDown) {
70 dropDownItem.height += _arrowPointHeight
71
72 dropDownItem.x = -(dropDownItem.width / 2) + radius
73
74 dropItemHolderRect.x = 0
75
76 if (dropDirection == dropUp) {
77 dropDownItem.y = -(dropDownItem.height + _dropMargin)
78
79 dropItemHolderRect.y = 0
80 } else {
81 dropDownItem.y = roundButton.height + _dropMargin
82
83 dropItemHolderRect.y = _arrowPointHeight
84 }
85
86 // Validate that dropdown is within viewport
87 dropDownItem.x = Math.max(dropDownItem.x, _viewportMaxLeft)
88 dropDownItem.x = Math.min(dropDownItem.x + dropDownItem.width, _viewportMaxRight) - dropDownItem.width
89
90 // Arrow points
91 arrowCanvas.arrowPoint.x = (roundButton.x + radius) - dropDownItem.x
92 if (dropDirection == dropUp) {
93 arrowCanvas.arrowPoint.y = dropDownItem.height
94 arrowCanvas.arrowBase1.x = arrowCanvas.arrowPoint.x - (_arrowBaseWidth / 2)
95 arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - _arrowPointHeight
96 arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x + _arrowBaseWidth
97 arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y
98 } else {
99 arrowCanvas.arrowPoint.y = 0
100 arrowCanvas.arrowBase1.x = arrowCanvas.arrowPoint.x + (_arrowBaseWidth / 2)
101 arrowCanvas.arrowBase1.y = _arrowPointHeight
102 arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x - _arrowBaseWidth
103 arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y
104 }
105 } else {
106 dropDownItem.width += _arrowPointHeight
107
108 dropDownItem.y = -(dropDownItem.height / 2) + radius
109
110 dropItemHolderRect.y = 0
111
112 if (dropDirection == dropLeft) {
113 dropDownItem.x = -(dropDownItem.width + _dropMargin)
114
115 dropItemHolderRect.x = 0
116 } else {
117 dropDownItem.x = roundButton.width + _dropMargin
118
119 dropItemHolderRect.x = _arrowPointHeight
120 }
121
122 // Validate that dropdown is within viewport
123 dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop)
124 dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height
125
126 // Arrow points
127 arrowCanvas.arrowPoint.y = (roundButton.y + radius) - dropDownItem.y
128 if (dropDirection == dropLeft) {
129 arrowCanvas.arrowPoint.x = dropDownItem.width
130 arrowCanvas.arrowBase1.x = arrowCanvas.arrowPoint.x - _arrowPointHeight
131 arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseWidth / 2)
132 arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
133 arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseWidth
134 } else {
135 arrowCanvas.arrowPoint.x = 0
136 arrowCanvas.arrowBase1.x = _arrowPointHeight
137 arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseWidth / 2)
138 arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
139 arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseWidth
140 }
141 }
142 arrowCanvas.requestPaint()
143 } // function - _calcPositions
144
145 QGCPalette { id: qgcPal }
146
147 MouseArea {
148 x: _viewportMaxLeft
149 y: _viewportMaxTop
150 width: _viewportMaxRight -_viewportMaxLeft
151 height: _viewportMaxBottom - _viewportMaxTop
152 visible: checked
153 onClicked: {
154 checked = false
155 _root.clicked()
156 }
157 }
158
159 QGCRoundButton {
160 id: roundButton
161 radius: parent.width / 2
162 onClicked: {
163 _calcPositions()
164 _root.clicked()
165 }
166 }
167
168 Item {
169 id: dropDownItem
170 visible: checked
171
172 Canvas {
173 id: arrowCanvas
174 anchors.fill: parent
175
176 property point arrowPoint: Qt.point(0, 0)
177 property point arrowBase1: Qt.point(0, 0)
178 property point arrowBase2: Qt.point(0, 0)
179
180 onPaint: {
181 var context = getContext("2d")
182 context.reset()
183 context.beginPath()
184
185 context.moveTo(dropItemHolderRect.x, dropItemHolderRect.y)
186 if (dropDirection == dropDown) {
187 context.lineTo(arrowBase2.x, arrowBase2.y)
188 context.lineTo(arrowPoint.x, arrowPoint.y)
189 context.lineTo(arrowBase1.x, arrowBase1.y)
190 }
191 context.lineTo(dropItemHolderRect.x + dropItemHolderRect.width, dropItemHolderRect.y)
192 if (dropDirection == dropLeft) {
193 context.lineTo(arrowBase2.x, arrowBase2.y)
194 context.lineTo(arrowPoint.x, arrowPoint.y)
195 context.lineTo(arrowBase1.x, arrowBase1.y)
196 }
197 context.lineTo(dropItemHolderRect.x + dropItemHolderRect.width, dropItemHolderRect.y + dropItemHolderRect.height)
198 if (dropDirection == dropUp) {
199 context.lineTo(arrowBase2.x, arrowBase2.y)
200 context.lineTo(arrowPoint.x, arrowPoint.y)
201 context.lineTo(arrowBase1.x, arrowBase1.y)
202 }
203 context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y + dropItemHolderRect.height)
204 if (dropDirection == dropRight) {
205 context.lineTo(arrowBase2.x, arrowBase2.y)
206 context.lineTo(arrowPoint.x, arrowPoint.y)
207 context.lineTo(arrowBase1.x, arrowBase1.y)
208 }
209 context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y)
210
211 context.closePath()
212 context.fillStyle = qgcPal.windowShade
213 context.fill()
214 }
215 } // Canvas - arrowCanvas
216
217 Item {
218 id: dropItemHolderRect
219
220 Loader {
221 id: dropDownLoader
222 x: _dropMargin
223 y: _dropMargin
224 }
225 }
226 } // Item - dropDownItem
227}