diff --git a/custom-example/qgroundcontrol.qrc b/custom-example/qgroundcontrol.qrc
index 0a717639462f..57d510f1eb37 100644
--- a/custom-example/qgroundcontrol.qrc
+++ b/custom-example/qgroundcontrol.qrc
@@ -193,6 +193,7 @@
../src/PlanView/TakeoffItemMapVisual.qml
../src/QmlControls/ToolIndicatorPage.qml
../src/QmlControls/ToolStrip.qml
+ ../src/QmlControls/ToolStripDropPanel.qml
../src/QmlControls/ToolStripHoverButton.qml
../src/PlanView/TransectStyleComplexItemEditor.qml
../src/PlanView/TransectStyleComplexItemStats.qml
diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 1a689064d3d4..ef613f923fb3 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -196,6 +196,7 @@
src/PlanView/TakeoffItemMapVisual.qml
src/QmlControls/ToolIndicatorPage.qml
src/QmlControls/ToolStrip.qml
+ src/QmlControls/ToolStripDropPanel.qml
src/QmlControls/ToolStripHoverButton.qml
src/PlanView/TransectStyleComplexItemEditor.qml
src/PlanView/TransectStyleComplexItemStats.qml
diff --git a/src/FlightDisplay/FlyViewMap.qml b/src/FlightDisplay/FlyViewMap.qml
index 5aabb6db1018..f4ca80762f96 100644
--- a/src/FlightDisplay/FlyViewMap.qml
+++ b/src/FlightDisplay/FlyViewMap.qml
@@ -500,10 +500,12 @@ FlightMap {
MouseArea {
anchors.fill: parent
onClicked: (position) => {
- var roiEditMenu = popupMenuComponent.createObject(_root, { coord: roiLocationItem.coordinate, contentItemComponent: roiEditMenuComponent })
- var clickPoint = mapToItem(_root, position.x, position.y)
- roiEditMenu.setPosition(clickPoint.x, clickPoint.y)
- roiEditMenu.open()
+ position = Qt.point(position.x, position.y)
+ var clickCoord = _root.toCoordinate(position, false /* clipToViewPort */)
+ // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow
+ position = mapToItem(globals.parent, position)
+ var dropPanel = roiEditDropPanelComponent.createObject(mainWindow, { clickRect: Qt.rect(position.x, position.y, 0, 0) })
+ dropPanel.open()
}
}
@@ -542,171 +544,129 @@ FlightMap {
}
Component {
- id: popupMenuComponent
-
- Popup {
- id: mapClickMenu
- modal: true
-
- property var coord
- property var contentItemComponent
-
- function setPosition(mouseX, mouseY) {
- var newX = mouseX
- var newY = mouseY
-
- // Filtering coordinates
- if (newX + mapClickMenu.width > _root.width) {
- newX = _root.width - mapClickMenu.width
- }
- if (newY + mapClickMenu.height > _root.height) {
- newY = _root.height - mapClickMenu.height
- }
-
- // Set coordiantes
- x = newX
- y = newY
- }
-
- background: Rectangle {
- radius: ScreenTools.defaultFontPixelHeight * 0.5
- color: qgcPal.window
- border.color: qgcPal.text
- }
-
- contentItem: Loader {
- sourceComponent: contentItemComponent
+ id: roiEditPositionDialogComponent
- property var mapClickCoord: mapClickMenu.coord
- property var popup: mapClickMenu
+ EditPositionDialog {
+ title: qsTr("Edit ROI Position")
+ coordinate: roiLocationItem.coordinate
+ onCoordinateChanged: {
+ roiLocationItem.coordinate = coordinate
+ _activeVehicle.guidedModeROI(coordinate)
}
}
}
Component {
- id: mapClickMenuComponent
-
- ColumnLayout {
- id: mainLayout
- spacing: ScreenTools.defaultFontPixelWidth / 2
-
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("Go to location")
- visible: globals.guidedControllerFlyView.showGotoLocation
- onClicked: {
- if (popup.opened) {
- popup.close()
+ id: roiEditDropPanelComponent
+
+ DropPanel {
+ id: roiEditDropPanel
+
+ sourceComponent: Component {
+ ColumnLayout {
+ spacing: ScreenTools.defaultFontPixelWidth / 2
+
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Cancel ROI")
+ onClicked: {
+ _activeVehicle.stopGuidedModeROI()
+ roiEditDropPanel.close()
+ }
}
- gotoLocationItem.show(mapClickCoord)
- globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionGoto, mapClickCoord, gotoLocationItem)
- }
- }
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("Orbit at location")
- visible: globals.guidedControllerFlyView.showOrbit
- onClicked: {
- if (popup.opened) {
- popup.close()
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Edit Position")
+ onClicked: {
+ roiEditPositionDialogComponent.createObject(mainWindow, { showSetPositionFromVehicle: false }).open()
+ roiEditDropPanel.close()
+ }
}
- orbitMapCircle.show(mapClickCoord)
- globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionOrbit, mapClickCoord, orbitMapCircle)
}
}
+ }
+ }
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("ROI at location")
- visible: globals.guidedControllerFlyView.showROI
- onClicked: {
- if (popup.opened) {
- popup.close()
+ Component {
+ id: mapClickDropPanelComponent
+
+ DropPanel {
+ id: mapClickDropPanel
+
+ property var mapClickCoord
+
+ sourceComponent: Component {
+ ColumnLayout {
+ spacing: ScreenTools.defaultFontPixelWidth / 2
+
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Go to location")
+ visible: globals.guidedControllerFlyView.showGotoLocation
+ onClicked: {
+ mapClickDropPanel.close()
+ gotoLocationItem.show(mapClickCoord)
+ globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionGoto, mapClickCoord, gotoLocationItem)
+ }
}
- globals.guidedControllerFlyView.executeAction(globals.guidedControllerFlyView.actionROI, mapClickCoord, 0, false)
- }
- }
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("Set home here")
- visible: globals.guidedControllerFlyView.showSetHome
- onClicked: {
- if (popup.opened) {
- popup.close()
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Orbit at location")
+ visible: globals.guidedControllerFlyView.showOrbit
+ onClicked: {
+ mapClickDropPanel.close()
+ orbitMapCircle.show(mapClickCoord)
+ globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionOrbit, mapClickCoord, orbitMapCircle)
+ }
}
- globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetHome, mapClickCoord)
- }
- }
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("Set Estimator Origin")
- visible: globals.guidedControllerFlyView.showSetEstimatorOrigin
- onClicked: {
- if (popup.opened) {
- popup.close()
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("ROI at location")
+ visible: globals.guidedControllerFlyView.showROI
+ onClicked: {
+ mapClickDropPanel.close()
+ globals.guidedControllerFlyView.executeAction(globals.guidedControllerFlyView.actionROI, mapClickCoord, 0, false)
+ }
}
- globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetEstimatorOrigin, mapClickCoord)
- }
- }
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("Set Heading")
- visible: globals.guidedControllerFlyView.showChangeHeading
- onClicked: {
- if (popup.opened) {
- popup.close()
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Set home here")
+ visible: globals.guidedControllerFlyView.showSetHome
+ onClicked: {
+ mapClickDropPanel.close()
+ globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetHome, mapClickCoord)
+ }
}
- globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionChangeHeading, mapClickCoord)
- }
- }
-
- ColumnLayout {
- spacing: 0
- QGCLabel { text: qsTr("Lat: %1").arg(mapClickCoord.latitude.toFixed(6)) }
- QGCLabel { text: qsTr("Lon: %1").arg(mapClickCoord.longitude.toFixed(6)) }
- }
- }
- }
-
- Component {
- id: roiEditPositionDialogComponent
- EditPositionDialog {
- title: qsTr("Edit ROI Position")
- coordinate: roiLocationItem.coordinate
- onCoordinateChanged: {
- roiLocationItem.coordinate = coordinate
- _activeVehicle.guidedModeROI(coordinate)
- }
- }
- }
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Set Estimator Origin")
+ visible: globals.guidedControllerFlyView.showSetEstimatorOrigin
+ onClicked: {
+ mapClickDropPanel.close()
+ globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetEstimatorOrigin, mapClickCoord)
+ }
+ }
- Component {
- id: roiEditMenuComponent
-
- ColumnLayout {
- id: mainLayout
- spacing: ScreenTools.defaultFontPixelWidth / 2
-
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("Cancel ROI")
- onClicked: {
- _activeVehicle.stopGuidedModeROI()
- popup.close()
- }
- }
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Set Heading")
+ visible: globals.guidedControllerFlyView.showChangeHeading
+ onClicked: {
+ mapClickDropPanel.close()
+ globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionChangeHeading, mapClickCoord)
+ }
+ }
- QGCButton {
- Layout.fillWidth: true
- text: qsTr("Edit Position")
- onClicked: {
- roiEditPositionDialogComponent.createObject(mainWindow, { showSetPositionFromVehicle: false }).open()
- popup.close()
+ ColumnLayout {
+ spacing: 0
+ QGCLabel { text: qsTr("Lat: %1").arg(mapClickCoord.latitude.toFixed(6)) }
+ QGCLabel { text: qsTr("Lon: %1").arg(mapClickCoord.longitude.toFixed(6)) }
+ }
}
}
}
@@ -714,13 +674,16 @@ FlightMap {
onMapClicked: (position) => {
if (!globals.guidedControllerFlyView.guidedUIVisible &&
- (globals.guidedControllerFlyView.showGotoLocation || globals.guidedControllerFlyView.showOrbit || globals.guidedControllerFlyView.showROI || globals.guidedControllerFlyView.showSetHome || globals.guidedControllerFlyView.showSetEstimatorOrigin)) {
+ (globals.guidedControllerFlyView.showGotoLocation || globals.guidedControllerFlyView.showOrbit || globals.guidedControllerFlyView.showROI || globals.guidedControllerFlyView.showSetHome || globals.guidedControllerFlyView.showSetEstimatorOrigin)) {
orbitMapCircle.hide()
gotoLocationItem.hide()
- var clickCoord = _root.toCoordinate(Qt.point(position.x, position.y), false /* clipToViewPort */)
- var mapClickMenu = popupMenuComponent.createObject(_root, { coord: clickCoord, contentItemComponent: mapClickMenuComponent })
- mapClickMenu.setPosition(position.x, position.y)
- mapClickMenu.open()
+
+ position = Qt.point(position.x, position.y)
+ var clickCoord = _root.toCoordinate(position, false /* clipToViewPort */)
+ // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow
+ position = _root.mapToItem(globals.parent, position)
+ var dropPanel = mapClickDropPanelComponent.createObject(mainWindow, { mapClickCoord: clickCoord, clickRect: Qt.rect(position.x, position.y, 0, 0) })
+ dropPanel.open()
}
}
diff --git a/src/PlanView/MissionItemEditor.qml b/src/PlanView/MissionItemEditor.qml
index e0f362a2a02f..726f177300d5 100644
--- a/src/PlanView/MissionItemEditor.qml
+++ b/src/PlanView/MissionItemEditor.qml
@@ -181,81 +181,114 @@ Rectangle {
}
}
- QGCColoredImage {
- id: hamburger
- anchors.margins: _margin
- anchors.right: parent.right
- anchors.verticalCenter: topRowLayout.verticalCenter
- width: _hamburgerSize
- height: _hamburgerSize
- sourceSize.height: _hamburgerSize
- source: "qrc:/qmlimages/Hamburger.svg"
- visible: missionItem.isCurrentItem && missionItem.sequenceNumber !== 0
- color: qgcPal.text
+ Component {
+ id: hamburgerMenuDropPanelComponent
- QGCMouseArea {
- fillItem: hamburger
- onClicked: {
- currentItemScope.focus = true
- hamburgerMenu.popup()
- }
+ DropPanel {
+ id: hamburgerMenuDropPanel
- QGCMenu {
- id: hamburgerMenu
+ sourceComponent: Component {
+ ColumnLayout {
+ spacing: ScreenTools.defaultFontPixelHeight / 2
- QGCMenuItem {
- text: qsTr("Move to vehicle position")
- enabled: _activeVehicle && missionItem.specifiesCoordinate
- onTriggered: missionItem.coordinate = _activeVehicle.coordinate
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Move to vehicle position")
+ enabled: _activeVehicle && missionItem.specifiesCoordinate
- property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
- }
+ onClicked: {
+ missionItem.coordinate = _activeVehicle.coordinate
+ hamburgerMenuDropPanel.close()
+ }
- QGCMenuItem {
- text: qsTr("Move to previous item position")
- enabled: _missionController.previousCoordinate.isValid
- onTriggered: missionItem.coordinate = _missionController.previousCoordinate
- }
+ property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
+ }
- QGCMenuItem {
- text: qsTr("Edit position...")
- enabled: missionItem.specifiesCoordinate
- onTriggered: editPositionDialog.createObject(mainWindow).open()
- }
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Move to previous item position")
+ enabled: _missionController.previousCoordinate.isValid
+ onClicked: {
+ missionItem.coordinate = _missionController.previousCoordinate
+ hamburgerMenuDropPanel.close()
+ }
+ }
- QGCMenuSeparator {
- //visible: missionItem.isSimpleItem && !_waypointsOnlyMode
- }
+ QGCButton {
+ Layout.fillWidth: true
+ text: qsTr("Edit position...")
+ enabled: missionItem.specifiesCoordinate
+ onClicked: {
+ editPositionDialog.createObject(mainWindow).open()
+ hamburgerMenuDropPanel.close()
+ }
+ }
- QGCMenuItem {
- text: qsTr("Show all values")
- visible: QGroundControl.corePlugin.showAdvancedUI
- checkable: true
- checked: missionItem.isSimpleItem ? missionItem.rawEdit : false
- enabled: missionItem.isSimpleItem && !_waypointsOnlyMode
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 1
+ color: qgcPal.groupBorder
+ }
+
+ QGCCheckBoxSlider {
+ Layout.fillWidth: true
+ text: qsTr("Show all values")
+ visible: QGroundControl.corePlugin.showAdvancedUI
+ checked: missionItem.isSimpleItem ? missionItem.rawEdit : false
+ enabled: missionItem.isSimpleItem && !_waypointsOnlyMode
- onTriggered: {
- if (missionItem.rawEdit) {
- if (missionItem.friendlyEditAllowed) {
+ onClicked: {
+ missionItem.rawEdit = checked
+ if (missionItem.rawEdit && !missionItem.friendlyEditAllowed) {
missionItem.rawEdit = false
- } else {
+ checked = false
mainWindow.showMessageDialog(qsTr("Mission Edit"), qsTr("You have made changes to the mission item which cannot be shown in Simple Mode"))
}
- } else {
- missionItem.rawEdit = true
+ hamburgerMenuDropPanel.close()
}
- checked = missionItem.rawEdit
}
- }
- QGCMenuItem {
- text: qsTr("Item #%1").arg(missionItem.sequenceNumber)
- enabled: false
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 1
+ color: qgcPal.groupBorder
+ }
+
+ QGCLabel {
+ text: qsTr("Item #%1").arg(missionItem.sequenceNumber)
+ enabled: false
+ }
}
}
}
}
+
+ QGCColoredImage {
+ id: hamburger
+ anchors.margins: _margin
+ anchors.right: parent.right
+ anchors.verticalCenter: topRowLayout.verticalCenter
+ width: _hamburgerSize
+ height: _hamburgerSize
+ sourceSize.height: _hamburgerSize
+ source: "qrc:/qmlimages/Hamburger.svg"
+ visible: missionItem.isCurrentItem && missionItem.sequenceNumber !== 0
+ color: qgcPal.text
+
+ QGCMouseArea {
+ fillItem: hamburger
+ onClicked: (position) => {
+ currentItemScope.focus = true
+ position = Qt.point(position.x, position.y)
+ // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow
+ position = mapToItem(globals.parent, position)
+ var dropPanel = hamburgerMenuDropPanelComponent.createObject(mainWindow, { clickRect: Qt.rect(position.x, position.y, 0, 0) })
+ dropPanel.open()
+ }
+ }
+ }
+
/*
QGCLabel {
id: notReadyForSaveLabel
diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml
index bc25e8317544..12cc2e3a27a3 100644
--- a/src/PlanView/PlanView.qml
+++ b/src/PlanView/PlanView.qml
@@ -910,7 +910,7 @@ Item {
UTMSPStateStorage.currentStateIndex = 0}})
}
- //- ToolStrip DropPanel Components
+ //- ToolStrip ToolStripDropPanel Components
Component {
id: centerMapDropPanel
diff --git a/src/QmlControls/DropPanel.qml b/src/QmlControls/DropPanel.qml
index 472966c54ef4..5b3928731874 100644
--- a/src/QmlControls/DropPanel.qml
+++ b/src/QmlControls/DropPanel.qml
@@ -9,154 +9,94 @@
import QtQuick
import QtQuick.Controls
+import QtQuick.Layouts
import QGroundControl
import QGroundControl.ScreenTools
import QGroundControl.Palette
-Item {
- id: _root
- visible: false
-
- signal clicked()
- property real radius: ScreenTools.isMobile ? ScreenTools.defaultFontPixelHeight * 1.75 : ScreenTools.defaultFontPixelHeight * 1.25
- property real viewportMargins: 0
- property var toolStrip
-
- // Should be an enum but that get's into the whole problem of creating a singleton which isn't worth the effort
- readonly property int dropLeft: 1
- readonly property int dropRight: 2
- readonly property int dropUp: 3
- readonly property int dropDown: 4
-
- readonly property real _arrowBaseHeight: radius // Height of vertical side of arrow
- readonly property real _arrowPointWidth: radius * 0.666 // Distance from vertical side to point
- readonly property real _dropMargin: ScreenTools.defaultFontPixelWidth
-
- property var _dropEdgeTopPoint
- property alias _dropDownComponent: panelLoader.sourceComponent
- property real _viewportMaxTop: 0
- property real _viewportMaxBottom: parent.parent.height - parent.y
- property real _viewportMaxHeight: _viewportMaxBottom - _viewportMaxTop
- property var _dropPanelCancel
- property var _parentButton
-
- function show(panelEdgeTopPoint, panelComponent, parentButton) {
- _parentButton = parentButton
- _dropEdgeTopPoint = panelEdgeTopPoint
- _dropDownComponent = panelComponent
- _calcPositions()
- visible = true
- _dropPanelCancel = dropPanelCancelComponent.createObject(toolStrip.parent)
- }
-
- function hide() {
- if (_dropPanelCancel) {
- _dropPanelCancel.destroy()
- _parentButton.checked = false
- visible = false
- _dropDownComponent = undefined
+/// Drop panel that displays positioned next to the specified click position.
+/// By default the panel drops to the right of the click position. If there isn't
+/// enough room to the right then the panel will drop to the left.
+Popup {
+ id: _root
+ padding: _innerMargin
+ leftPadding: _dropRight ? _innerMargin + _arrowPointWidth : _innerMargin
+ rightPadding: _dropRight ? _innerMargin : _innerMargin + _arrowPointWidth
+ modal: true
+ focus: true
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
+ clip: false
+
+ property var sourceComponent // Component to display within the popup
+ property var clickRect: Qt.rect(0, 0, 0, 0) // Rectangle of clicked item - used to position drop down
+ property var dropViewPort: Qt.rect(0, 0, parent.width, parent.height) // Available viewport for dropdown
+
+ property var _qgcPal: QGroundControl.globalPalette
+ property real _innerMargin: ScreenTools.defaultFontPixelWidth * 0.5 // Margin between content and rectanglular portion of background
+ property real _arrowPointWidth: ScreenTools.defaultFontPixelWidth * 2 // Distance from vertical side to point
+ property real _arrowPointPositionY: height / 2
+ property bool _dropRight: true
+
+ onAboutToShow: {
+ // Panel defaults to dropping to the right of click position
+ _root.x = clickRect.x + clickRect.width
+
+ // If there isn't room to the right then we switch to drop to the left
+ if (_root.x + _root.width > dropViewPort.x + dropViewPort.width) {
+ _dropRight = false
+ _root.x = clickRect.x - _root.width
}
- }
-
- function _calcPositions() {
- var panelComponentWidth = panelLoader.item.width
- var panelComponentHeight = panelLoader.item.height
-
- dropDownItem.width = panelComponentWidth + (_dropMargin * 2) + _arrowPointWidth
- dropDownItem.height = panelComponentHeight + (_dropMargin * 2)
-
- dropDownItem.x = _dropEdgeTopPoint.x + _dropMargin
- dropDownItem.y = _dropEdgeTopPoint.y -(dropDownItem.height / 2) + radius
-
- // Validate that dropdown is within viewport
- dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height
- dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop)
-
- // Adjust height to not exceed viewport bounds
- dropDownItem.height = Math.min(dropDownItem.height, _viewportMaxHeight - dropDownItem.y)
-
- // Arrow points
- arrowCanvas.arrowPoint.y = (_dropEdgeTopPoint.y + radius) - dropDownItem.y
- arrowCanvas.arrowPoint.x = 0
- arrowCanvas.arrowBase1.x = _arrowPointWidth
- arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseHeight / 2)
- arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
- arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseHeight
- arrowCanvas.requestPaint()
- } // function - _calcPositions
- QGCPalette { id: qgcPal }
+ // Default position of panel is vertically centered on click position
+ _root.y = clickRect.y + (clickRect.height / 2)
+ _root.y -= _root.height / 2
- Component {
- // Overlay which is used to cancel the panel when the user clicks away
- id: dropPanelCancelComponent
+ // Make sure panel is within viewport
+ let originRootY = _root.y
+ _root.y = Math.max(_root.y, dropViewPort.y)
+ _root.y = Math.min(_root.y, dropViewPort.y + dropViewPort.height - _root.height)
- MouseArea {
- anchors.fill: parent
- z: toolStrip.z - 1
- onClicked: dropPanel.hide()
- }
+ // Adjust arrow position back to point at click position
+ _arrowPointPositionY += originRootY - _root.y
}
- // This item is sized to hold the entirety of the drop panel including the arrow point
- Item {
- id: dropDownItem
+ background: Item {
+ implicitWidth: contentItem.implicitWidth + _innerMargin * 2 + _arrowPointWidth
+ implicitHeight: contentItem.implicitHeight + _innerMargin * 2
- DeadMouseArea {
- anchors.fill: parent
+ Rectangle {
+ x: _dropRight ? _arrowPointWidth : 0
+ radius: ScreenTools.defaultFontPixelHeight / 2
+ width: parent.implicitWidth - _arrowPointWidth
+ height: parent.implicitHeight
+ color: _qgcPal.window
}
+ // Arrowhead
Canvas {
- id: arrowCanvas
- anchors.fill: parent
-
- property point arrowPoint: Qt.point(0, 0)
- property point arrowBase1: Qt.point(0, 0)
- property point arrowBase2: Qt.point(0, 0)
-
+ x: _dropRight ? 0 : parent.width - _arrowPointWidth
+ y: _arrowPointPositionY - _arrowPointWidth
+ width: _arrowPointWidth
+ height: _arrowPointWidth * 2
+
onPaint: {
- var panelX = _arrowPointWidth
- var panelY = 0
- var panelWidth = parent.width - _arrowPointWidth
- var panelHeight = parent.height
-
var context = getContext("2d")
context.reset()
context.beginPath()
-
- context.moveTo(panelX, panelY) // top left
- context.lineTo(panelX + panelWidth, panelY) // top right
- context.lineTo(panelX + panelWidth, panelX + panelHeight) // bottom right
- context.lineTo(panelX, panelY + panelHeight) // bottom left
- context.lineTo(arrowBase2.x, arrowBase2.y)
- context.lineTo(arrowPoint.x, arrowPoint.y)
- context.lineTo(arrowBase1.x, arrowBase1.y)
- context.lineTo(panelX, panelY) // top left
-
+ context.moveTo(_dropRight ? 0 : _arrowPointWidth, _arrowPointWidth)
+ context.lineTo(_dropRight ? _arrowPointWidth : 0, 0)
+ context.lineTo(_dropRight ? _arrowPointWidth : 0, _arrowPointWidth * 2)
context.closePath()
- context.fillStyle = qgcPal.windowShade
+ context.fillStyle = _qgcPal.window
context.fill()
}
- } // Canvas - arrowCanvas
-
- QGCFlickable {
- id: panelItemFlickable
- anchors.margins: _dropMargin
- anchors.leftMargin: _dropMargin + _arrowPointWidth
- anchors.fill: parent
- flickableDirection: Flickable.VerticalFlick
- contentWidth: panelLoader.width
- contentHeight: panelLoader.height
-
- Loader {
- id: panelLoader
-
- onHeightChanged: _calcPositions()
- onWidthChanged: _calcPositions()
+ }
+ }
- property var dropPanel: _root
- }
+ contentItem: SettingsGroupLayout {
+ Loader {
+ sourceComponent: _root.sourceComponent
}
- } // Item - dropDownItem
+ }
}
diff --git a/src/QmlControls/QGroundControl/Controls/qmldir b/src/QmlControls/QGroundControl/Controls/qmldir
index 1c366fe526fa..28ce27c4828e 100644
--- a/src/QmlControls/QGroundControl/Controls/qmldir
+++ b/src/QmlControls/QGroundControl/Controls/qmldir
@@ -117,6 +117,7 @@ SurveyMapVisuals 1.0 SurveyMapVisuals.qml
TerrainStatus 1.0 TerrainStatus.qml
ToolIndicatorPage 1.0 ToolIndicatorPage.qml
ToolStrip 1.0 ToolStrip.qml
+ToolStripDropPanel 1.0 ToolStripDropPanel.qml
ToolStripHoverButton 1.0 ToolStripHoverButton.qml
TransectStyleComplexItemEditor 1.0 TransectStyleComplexItemEditor.qml
TransectStyleComplexItemStats 1.0 TransectStyleComplexItemStats.qml
diff --git a/src/QmlControls/ToolStrip.qml b/src/QmlControls/ToolStrip.qml
index daf07f7d637f..5b2e5ebdf3a8 100644
--- a/src/QmlControls/ToolStrip.qml
+++ b/src/QmlControls/ToolStrip.qml
@@ -102,7 +102,7 @@ Rectangle {
}
}
- DropPanel {
+ ToolStripDropPanel {
id: dropPanel
toolStrip: _root
}
diff --git a/src/QmlControls/ToolStripDropPanel.qml b/src/QmlControls/ToolStripDropPanel.qml
new file mode 100644
index 000000000000..472966c54ef4
--- /dev/null
+++ b/src/QmlControls/ToolStripDropPanel.qml
@@ -0,0 +1,162 @@
+/****************************************************************************
+ *
+ * (c) 2009-2020 QGROUNDCONTROL PROJECT
+ *
+ * QGroundControl is licensed according to the terms in the file
+ * COPYING.md in the root of the source code directory.
+ *
+ ****************************************************************************/
+
+import QtQuick
+import QtQuick.Controls
+
+import QGroundControl
+import QGroundControl.ScreenTools
+import QGroundControl.Palette
+
+Item {
+ id: _root
+ visible: false
+
+ signal clicked()
+ property real radius: ScreenTools.isMobile ? ScreenTools.defaultFontPixelHeight * 1.75 : ScreenTools.defaultFontPixelHeight * 1.25
+ property real viewportMargins: 0
+ property var toolStrip
+
+ // Should be an enum but that get's into the whole problem of creating a singleton which isn't worth the effort
+ readonly property int dropLeft: 1
+ readonly property int dropRight: 2
+ readonly property int dropUp: 3
+ readonly property int dropDown: 4
+
+ readonly property real _arrowBaseHeight: radius // Height of vertical side of arrow
+ readonly property real _arrowPointWidth: radius * 0.666 // Distance from vertical side to point
+ readonly property real _dropMargin: ScreenTools.defaultFontPixelWidth
+
+ property var _dropEdgeTopPoint
+ property alias _dropDownComponent: panelLoader.sourceComponent
+ property real _viewportMaxTop: 0
+ property real _viewportMaxBottom: parent.parent.height - parent.y
+ property real _viewportMaxHeight: _viewportMaxBottom - _viewportMaxTop
+ property var _dropPanelCancel
+ property var _parentButton
+
+ function show(panelEdgeTopPoint, panelComponent, parentButton) {
+ _parentButton = parentButton
+ _dropEdgeTopPoint = panelEdgeTopPoint
+ _dropDownComponent = panelComponent
+ _calcPositions()
+ visible = true
+ _dropPanelCancel = dropPanelCancelComponent.createObject(toolStrip.parent)
+ }
+
+ function hide() {
+ if (_dropPanelCancel) {
+ _dropPanelCancel.destroy()
+ _parentButton.checked = false
+ visible = false
+ _dropDownComponent = undefined
+ }
+ }
+
+ function _calcPositions() {
+ var panelComponentWidth = panelLoader.item.width
+ var panelComponentHeight = panelLoader.item.height
+
+ dropDownItem.width = panelComponentWidth + (_dropMargin * 2) + _arrowPointWidth
+ dropDownItem.height = panelComponentHeight + (_dropMargin * 2)
+
+ dropDownItem.x = _dropEdgeTopPoint.x + _dropMargin
+ dropDownItem.y = _dropEdgeTopPoint.y -(dropDownItem.height / 2) + radius
+
+ // Validate that dropdown is within viewport
+ dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height
+ dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop)
+
+ // Adjust height to not exceed viewport bounds
+ dropDownItem.height = Math.min(dropDownItem.height, _viewportMaxHeight - dropDownItem.y)
+
+ // Arrow points
+ arrowCanvas.arrowPoint.y = (_dropEdgeTopPoint.y + radius) - dropDownItem.y
+ arrowCanvas.arrowPoint.x = 0
+ arrowCanvas.arrowBase1.x = _arrowPointWidth
+ arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseHeight / 2)
+ arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
+ arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseHeight
+ arrowCanvas.requestPaint()
+ } // function - _calcPositions
+
+ QGCPalette { id: qgcPal }
+
+ Component {
+ // Overlay which is used to cancel the panel when the user clicks away
+ id: dropPanelCancelComponent
+
+ MouseArea {
+ anchors.fill: parent
+ z: toolStrip.z - 1
+ onClicked: dropPanel.hide()
+ }
+ }
+
+ // This item is sized to hold the entirety of the drop panel including the arrow point
+ Item {
+ id: dropDownItem
+
+ DeadMouseArea {
+ anchors.fill: parent
+ }
+
+ Canvas {
+ id: arrowCanvas
+ anchors.fill: parent
+
+ property point arrowPoint: Qt.point(0, 0)
+ property point arrowBase1: Qt.point(0, 0)
+ property point arrowBase2: Qt.point(0, 0)
+
+ onPaint: {
+ var panelX = _arrowPointWidth
+ var panelY = 0
+ var panelWidth = parent.width - _arrowPointWidth
+ var panelHeight = parent.height
+
+ var context = getContext("2d")
+ context.reset()
+ context.beginPath()
+
+ context.moveTo(panelX, panelY) // top left
+ context.lineTo(panelX + panelWidth, panelY) // top right
+ context.lineTo(panelX + panelWidth, panelX + panelHeight) // bottom right
+ context.lineTo(panelX, panelY + panelHeight) // bottom left
+ context.lineTo(arrowBase2.x, arrowBase2.y)
+ context.lineTo(arrowPoint.x, arrowPoint.y)
+ context.lineTo(arrowBase1.x, arrowBase1.y)
+ context.lineTo(panelX, panelY) // top left
+
+ context.closePath()
+ context.fillStyle = qgcPal.windowShade
+ context.fill()
+ }
+ } // Canvas - arrowCanvas
+
+ QGCFlickable {
+ id: panelItemFlickable
+ anchors.margins: _dropMargin
+ anchors.leftMargin: _dropMargin + _arrowPointWidth
+ anchors.fill: parent
+ flickableDirection: Flickable.VerticalFlick
+ contentWidth: panelLoader.width
+ contentHeight: panelLoader.height
+
+ Loader {
+ id: panelLoader
+
+ onHeightChanged: _calcPositions()
+ onWidthChanged: _calcPositions()
+
+ property var dropPanel: _root
+ }
+ }
+ } // Item - dropDownItem
+}