DropPanel.qml 6.25 KB
Newer Older
1 2 3 4 5 6 7 8 9
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * 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 33 34 35 36 37

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

Item {
    id:         _root
    z:          QGroundControl.zOrderWidgets
    visible:    false

    signal          clicked()
    property real   radius:             ScreenTools.isMobile ? ScreenTools.defaultFontPixelHeight * 1.75 : ScreenTools.defaultFontPixelHeight * 1.25
    property real   viewportMargins:    0
    property var    toolStrip


    width:  radius * 2
    height: radius * 2

    // 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

38 39
    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
40
    readonly property real _dropMargin:         ScreenTools.defaultFontPixelWidth
41 42 43

    property var    _dropEdgeTopPoint
    property real   _dropEdgeHeight
44
    property alias  _dropDownComponent: panelLoader.sourceComponent
45 46
    property real   _viewportMaxTop:    0
    property real   _viewportMaxBottom: parent.parent.height - parent.y
47
    property real   _viewportMaxHeight: _viewportMaxBottom - _viewportMaxTop
48
    property var    _dropPanelCancel
49 50 51 52 53 54 55

    function show(panelEdgeTopPoint, panelEdgeHeight, panelComponent) {
        _dropEdgeTopPoint = panelEdgeTopPoint
        _dropEdgeHeight = panelEdgeHeight
        _dropDownComponent = panelComponent
        _calcPositions()
        visible = true
56
        _dropPanelCancel = dropPanelCancelComponent.createObject(toolStrip.parent)
57 58 59
    }

    function hide() {
60 61 62
        if (_dropPanelCancel) {
            _dropPanelCancel.destroy()
        }
63 64 65 66 67 68 69 70
        if (visible) {
            visible = false
            _dropDownComponent = undefined
            toolStrip.uncheckAll()
        }
    }

    function _calcPositions() {
71
        var panelComponentWidth  = panelLoader.item.width
72
        var panelComponentHeight = panelLoader.item.height
73

Don Gagne's avatar
Don Gagne committed
74 75
        dropDownItem.width  = panelComponentWidth  + (_dropMargin * 2) + _arrowPointWidth
        dropDownItem.height = panelComponentHeight + (_dropMargin * 2)
76 77

        dropDownItem.x = _dropEdgeTopPoint.x + _dropMargin
78
        dropDownItem.y = _dropEdgeTopPoint.y -(dropDownItem.height / 2) + radius
79 80 81

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

84 85 86
        // Adjust height to not exceed viewport bounds
        dropDownItem.height = Math.min(dropDownItem.height, _viewportMaxHeight - dropDownItem.y)

87 88 89
        // Arrow points
        arrowCanvas.arrowPoint.y = (_dropEdgeTopPoint.y + radius) - dropDownItem.y
        arrowCanvas.arrowPoint.x = 0
90 91
        arrowCanvas.arrowBase1.x = _arrowPointWidth
        arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseHeight / 2)
92
        arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
93
        arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseHeight
94 95 96 97 98
        arrowCanvas.requestPaint()
    } // function - _calcPositions

    QGCPalette { id: qgcPal }

99 100 101 102 103 104 105 106 107 108 109
    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()
        }
    }

110
    // This item is sized to hold the entirety of the drop panel including the arrow point
111 112 113
    Item {
        id: dropDownItem

DonLakeFlyer's avatar
DonLakeFlyer committed
114 115 116 117
        DeadMouseArea {
            anchors.fill: parent
        }

118 119 120 121
        Canvas {
            id:             arrowCanvas
            anchors.fill:   parent

122 123 124
            property point arrowPoint: Qt.point(0, 0)
            property point arrowBase1: Qt.point(0, 0)
            property point arrowBase2: Qt.point(0, 0)
125 126

            onPaint: {
127 128 129 130 131
                var panelX = _arrowPointWidth
                var panelY = 0
                var panelWidth = parent.width - _arrowPointWidth
                var panelHeight = parent.height

132 133 134 135
                var context = getContext("2d")
                context.reset()
                context.beginPath()

136 137 138 139
                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
140 141 142
                context.lineTo(arrowBase2.x, arrowBase2.y)
                context.lineTo(arrowPoint.x, arrowPoint.y)
                context.lineTo(arrowBase1.x, arrowBase1.y)
143 144
                context.lineTo(panelX, panelY)                              // top left

145 146 147 148 149 150
                context.closePath()
                context.fillStyle = qgcPal.windowShade
                context.fill()
            }
        } // Canvas - arrowCanvas

151 152 153 154 155 156 157 158
        QGCFlickable {
            id:                 panelItemFlickable
            anchors.margins:    _dropMargin
            anchors.leftMargin: _dropMargin + _arrowPointWidth
            anchors.fill:       parent
            flickableDirection: Flickable.VerticalFlick
            contentWidth:       panelLoader.width
            contentHeight:      panelLoader.height
159 160

            Loader {
161
                id: panelLoader
162

163 164 165
                onHeightChanged:    _calcPositions()
                onWidthChanged:     _calcPositions()

166 167 168 169 170
                property var dropPanel: _root
            }
        }
    } // Item - dropDownItem
}