DropPanel.qml 6.15 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

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

    function hide() {
53 54 55
        if (_dropPanelCancel) {
            _dropPanelCancel.destroy()
        }
56 57 58
        if (visible) {
            visible = false
            _dropDownComponent = undefined
DonLakeFlyer's avatar
DonLakeFlyer committed
59 60 61
            if (toolStrip.lastClickedButton) {
                toolStrip.lastClickedButton.checked = false
            }
62 63 64 65
        }
    }

    function _calcPositions() {
66
        var panelComponentWidth  = panelLoader.item.width
67
        var panelComponentHeight = panelLoader.item.height
68

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

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

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

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

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

    QGCPalette { id: qgcPal }

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

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

DonLakeFlyer's avatar
DonLakeFlyer committed
109 110 111 112
        DeadMouseArea {
            anchors.fill: parent
        }

113 114 115 116
        Canvas {
            id:             arrowCanvas
            anchors.fill:   parent

117 118 119
            property point arrowPoint: Qt.point(0, 0)
            property point arrowBase1: Qt.point(0, 0)
            property point arrowBase2: Qt.point(0, 0)
120 121

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

127 128 129 130
                var context = getContext("2d")
                context.reset()
                context.beginPath()

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

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

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

            Loader {
156
                id: panelLoader
157

158 159 160
                onHeightChanged:    _calcPositions()
                onWidthChanged:     _calcPositions()

161 162 163 164 165
                property var dropPanel: _root
            }
        }
    } // Item - dropDownItem
}