DropPanel.qml 6.13 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

10 11
import QtQuick                  2.3
import QtQuick.Controls         1.2
12
import QtQuick.Controls.Styles  1.4
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

import QGroundControl               1.0
import QGroundControl.ScreenTools   1.0
import QGroundControl.Palette       1.0

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

33 34
    readonly property real _arrowBaseHeight:    radius             // Height of vertical side of arrow
    readonly property real _arrowPointWidth:    radius * 0.666     // Distance from vertical side to point
Don Gagne's avatar
Don Gagne committed
35
    readonly property real _dropMargin:         ScreenTools.defaultFontPixelWidth
36 37

    property var    _dropEdgeTopPoint
38
    property alias  _dropDownComponent: panelLoader.sourceComponent
39 40
    property real   _viewportMaxTop:    0
    property real   _viewportMaxBottom: parent.parent.height - parent.y
41
    property real   _viewportMaxHeight: _viewportMaxBottom - _viewportMaxTop
42
    property var    _dropPanelCancel
43
    property var    _parentButton
44

45 46
    function show(panelEdgeTopPoint, panelComponent, parentButton) {
        _parentButton = parentButton
47 48 49 50
        _dropEdgeTopPoint = panelEdgeTopPoint
        _dropDownComponent = panelComponent
        _calcPositions()
        visible = true
51
        _dropPanelCancel = dropPanelCancelComponent.createObject(toolStrip.parent)
52 53 54
    }

    function hide() {
55 56
        if (_dropPanelCancel) {
            _dropPanelCancel.destroy()
57
            _parentButton.checked = false
58 59 60 61 62 63
            visible = false
            _dropDownComponent = undefined
        }
    }

    function _calcPositions() {
64
        var panelComponentWidth  = panelLoader.item.width
65
        var panelComponentHeight = panelLoader.item.height
66

Don Gagne's avatar
Don Gagne committed
67 68
        dropDownItem.width  = panelComponentWidth  + (_dropMargin * 2) + _arrowPointWidth
        dropDownItem.height = panelComponentHeight + (_dropMargin * 2)
69 70

        dropDownItem.x = _dropEdgeTopPoint.x + _dropMargin
71
        dropDownItem.y = _dropEdgeTopPoint.y -(dropDownItem.height / 2) + radius
72 73 74

        // Validate that dropdown is within viewport
        dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height
75
        dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop)
76

77 78 79
        // Adjust height to not exceed viewport bounds
        dropDownItem.height = Math.min(dropDownItem.height, _viewportMaxHeight - dropDownItem.y)

80 81 82
        // Arrow points
        arrowCanvas.arrowPoint.y = (_dropEdgeTopPoint.y + radius) - dropDownItem.y
        arrowCanvas.arrowPoint.x = 0
83 84
        arrowCanvas.arrowBase1.x = _arrowPointWidth
        arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseHeight / 2)
85
        arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
86
        arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseHeight
87 88 89 90 91
        arrowCanvas.requestPaint()
    } // function - _calcPositions

    QGCPalette { id: qgcPal }

92 93 94 95 96 97 98 99 100 101 102
    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()
        }
    }

103
    // This item is sized to hold the entirety of the drop panel including the arrow point
104 105 106
    Item {
        id: dropDownItem

DonLakeFlyer's avatar
DonLakeFlyer committed
107 108 109 110
        DeadMouseArea {
            anchors.fill: parent
        }

111 112 113 114
        Canvas {
            id:             arrowCanvas
            anchors.fill:   parent

115 116 117
            property point arrowPoint: Qt.point(0, 0)
            property point arrowBase1: Qt.point(0, 0)
            property point arrowBase2: Qt.point(0, 0)
118 119

            onPaint: {
120 121 122 123 124
                var panelX = _arrowPointWidth
                var panelY = 0
                var panelWidth = parent.width - _arrowPointWidth
                var panelHeight = parent.height

125 126 127 128
                var context = getContext("2d")
                context.reset()
                context.beginPath()

129 130 131 132
                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
133 134 135
                context.lineTo(arrowBase2.x, arrowBase2.y)
                context.lineTo(arrowPoint.x, arrowPoint.y)
                context.lineTo(arrowBase1.x, arrowBase1.y)
136 137
                context.lineTo(panelX, panelY)                              // top left

138 139 140 141 142 143
                context.closePath()
                context.fillStyle = qgcPal.windowShade
                context.fill()
            }
        } // Canvas - arrowCanvas

144 145 146 147 148 149 150 151
        QGCFlickable {
            id:                 panelItemFlickable
            anchors.margins:    _dropMargin
            anchors.leftMargin: _dropMargin + _arrowPointWidth
            anchors.fill:       parent
            flickableDirection: Flickable.VerticalFlick
            contentWidth:       panelLoader.width
            contentHeight:      panelLoader.height
152 153

            Loader {
154
                id: panelLoader
155

156 157 158
                onHeightChanged:    _calcPositions()
                onWidthChanged:     _calcPositions()

159 160 161 162 163
                property var dropPanel: _root
            }
        }
    } // Item - dropDownItem
}