DropPanel.qml 6.34 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
        if (visible) {
            visible = false
            _dropDownComponent = undefined
DonLakeFlyer's avatar
DonLakeFlyer committed
66 67 68
            if (toolStrip.lastClickedButton) {
                toolStrip.lastClickedButton.checked = false
            }
69 70 71 72
        }
    }

    function _calcPositions() {
73
        var panelComponentWidth  = panelLoader.item.width
74
        var panelComponentHeight = panelLoader.item.height
75

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

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

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

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

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

    QGCPalette { id: qgcPal }

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

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

DonLakeFlyer's avatar
DonLakeFlyer committed
116 117 118 119
        DeadMouseArea {
            anchors.fill: parent
        }

120 121 122 123
        Canvas {
            id:             arrowCanvas
            anchors.fill:   parent

124 125 126
            property point arrowPoint: Qt.point(0, 0)
            property point arrowBase1: Qt.point(0, 0)
            property point arrowBase2: Qt.point(0, 0)
127 128

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

134 135 136 137
                var context = getContext("2d")
                context.reset()
                context.beginPath()

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

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

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

            Loader {
163
                id: panelLoader
164

165 166 167
                onHeightChanged:    _calcPositions()
                onWidthChanged:     _calcPositions()

168 169 170 171 172
                property var dropPanel: _root
            }
        }
    } // Item - dropDownItem
}