Skip to content
Snippets Groups Projects
DropButton.qml 9.15 KiB
Newer Older
  • Learn to ignore specific revisions
  • dogmaphobic's avatar
    dogmaphobic committed
    import QtQuick                  2.4
    
    Don Gagne's avatar
    Don Gagne committed
    import QtQuick.Controls         1.2
    import QtQuick.Controls.Styles  1.2
    
    import QGroundControl.ScreenTools   1.0
    import QGroundControl.Palette       1.0
    
    Item {
        id: _root
    
    
        property alias  buttonImage:        roundButton.buttonImage
        property alias  rotateImage:        roundButton.rotateImage
    
    dogmaphobic's avatar
    dogmaphobic committed
        property real   radius:             ScreenTools.defaultFontPixelHeight * 1.25
    
    Don Gagne's avatar
    Don Gagne committed
        property int    dropDirection:      dropDown
        property alias  dropDownComponent:  dropDownLoader.sourceComponent
        property real   viewportMargins:    0
    
        property alias  lightBorders:       roundButton.lightBorders
    
    Don Gagne's avatar
    Don Gagne committed
    
        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
    
        readonly property real _arrowBaseWidth:     (radius * 2) / 2    // Width of long side of arrow
        readonly property real _arrowPointHeight:   (radius * 2) / 3    // Height is long side to point
        readonly property real _dropCornerRadius:   ScreenTools.defaultFontPixelWidth / 2
        readonly property real _dropCornerRadiusX2: _dropCornerRadius * 2
        readonly property real _dropMargin:         _dropCornerRadius
        readonly property real _dropMarginX2:       _dropMargin * 2
    
        property real   _viewportMaxLeft:   -x + viewportMargins
        property real   _viewportMaxRight:  parent.width - (viewportMargins * 2) - x
        property real   _viewportMaxTop:    -y + viewportMargins
        property real   _viewportMaxBottom: parent.height - (viewportMargins * 2) - y
    
    
        // Set up ExclusiveGroup support. We use the checked property to drive visibility of drop down.
    
    
        property alias checked: roundButton.checked
    
        property ExclusiveGroup exclusiveGroup: null
    
        onExclusiveGroupChanged: {
            if (exclusiveGroup) {
                exclusiveGroup.bindCheckable(_root)
            }
        }
    
        function hideDropDown() {
            checked = false
        }
    
    Don Gagne's avatar
    Don Gagne committed
    
        Component.onCompleted: _calcPositions()
    
        function _calcPositions() {
            var dropComponentWidth = dropDownLoader.item.width
            var dropComponentHeight = dropDownLoader.item.height
            var dropRectWidth = dropComponentWidth + _dropMarginX2
            var dropRectHeight = dropComponentHeight + _dropMarginX2
    
            dropItemHolderRect.width = dropRectWidth
            dropItemHolderRect.height = dropRectHeight
    
            dropDownItem.width = dropComponentWidth + _dropMarginX2
            dropDownItem.height = dropComponentHeight + _dropMarginX2
    
            if (dropDirection == dropUp || dropDirection == dropDown) {
                dropDownItem.height += _arrowPointHeight
    
                dropDownItem.x = -(dropDownItem.width / 2) + radius
    
                dropItemHolderRect.x = 0
    
                if (dropDirection == dropUp) {
                    dropDownItem.y = -(dropDownItem.height + _dropMargin)
    
                    dropItemHolderRect.y = 0
                } else {
    
                    dropDownItem.y = roundButton.height + _dropMargin
    
    Don Gagne's avatar
    Don Gagne committed
    
                    dropItemHolderRect.y = _arrowPointHeight
                }
    
                // Validate that dropdown is within viewport
                dropDownItem.x = Math.max(dropDownItem.x, _viewportMaxLeft)
                dropDownItem.x = Math.min(dropDownItem.x + dropDownItem.width, _viewportMaxRight) - dropDownItem.width
    
                // Arrow points
    
                arrowCanvas.arrowPoint.x = (roundButton.x + radius) - dropDownItem.x
    
    Don Gagne's avatar
    Don Gagne committed
                if (dropDirection == dropUp) {
                    arrowCanvas.arrowPoint.y = dropDownItem.height
                    arrowCanvas.arrowBase1.x = arrowCanvas.arrowPoint.x - (_arrowBaseWidth / 2)
                    arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - _arrowPointHeight
                    arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x + _arrowBaseWidth
                    arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y
                } else {
                    arrowCanvas.arrowPoint.y = 0
                    arrowCanvas.arrowBase1.x = arrowCanvas.arrowPoint.x + (_arrowBaseWidth / 2)
                    arrowCanvas.arrowBase1.y = _arrowPointHeight
                    arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x - _arrowBaseWidth
                    arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y
                }
            } else {
                dropDownItem.width += _arrowPointHeight
    
                dropDownItem.y = -(dropDownItem.height / 2) + radius
    
                dropItemHolderRect.y = 0
    
                if (dropDirection == dropLeft) {
                    dropDownItem.x = dropDownItem.width + _dropMargin
    
                    dropItemHolderRect.x = 0
                } else {
    
                    dropDownItem.x = roundButton.width + _dropMargin
    
    Don Gagne's avatar
    Don Gagne committed
    
                    dropItemHolderRect.x = _arrowPointHeight
                }
    
                // Validate that dropdown is within viewport
                dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop)
                dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height
    
                // Arrow points
    
                arrowCanvas.arrowPoint.y = (roundButton.y + radius) - dropDownItem.y
    
    Don Gagne's avatar
    Don Gagne committed
                if (dropDirection == dropLeft) {
                    arrowCanvas.arrowPoint.x = dropDownItem.width
                    arrowCanvas.arrowBase1.x = arrowCanvas.arrowPoint.x - _arrowPointHeight
                    arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseWidth / 2)
                    arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
                    arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseWidth
                } else {
                    arrowCanvas.arrowPoint.x = 0
                    arrowCanvas.arrowBase1.x = _arrowPointHeight
                    arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseWidth / 2)
                    arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x
                    arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseWidth
                }
            }
            arrowCanvas.requestPaint()
        } // function - _calcPositions
    
        QGCPalette { id: qgcPal }
    
        MouseArea {
            x:          _viewportMaxLeft
            y:          _viewportMaxTop
            width:      _viewportMaxRight -_viewportMaxLeft
            height:     _viewportMaxBottom - _viewportMaxTop
    
            visible:    checked
    
            onClicked:  {
                checked = false
                _root.clicked()
            }
    
        RoundButton {
            id:             roundButton
            radius:         parent.width / 2
            onClicked:  {
                _root.clicked()
            }
    
    Don Gagne's avatar
    Don Gagne committed
    
        Item {
            id:         dropDownItem
    
            visible:    checked
    
    Don Gagne's avatar
    Don Gagne committed
            Canvas {
    
    Don Gagne's avatar
    Don Gagne committed
                id:             arrowCanvas
                anchors.fill:   parent
    
                property var arrowPoint: Qt.point(0, 0)
                property var arrowBase1: Qt.point(0, 0)
                property var arrowBase2: Qt.point(0, 0)
    
                onPaint: {
                    var context = getContext("2d")
                    context.reset()
                    context.beginPath()
    
                    context.moveTo(dropItemHolderRect.x, dropItemHolderRect.y)
                    if (dropDirection == dropDown) {
                        context.lineTo(arrowBase2.x, arrowBase2.y)
                        context.lineTo(arrowPoint.x, arrowPoint.y)
                        context.lineTo(arrowBase1.x, arrowBase1.y)
                    }
                    context.lineTo(dropItemHolderRect.x + dropItemHolderRect.width, dropItemHolderRect.y)
                    if (dropDirection == dropLeft) {
                        context.lineTo(arrowBase2.x, arrowBase2.y)
                        context.lineTo(arrowPoint.x, arrowPoint.y)
                        context.lineTo(arrowBase1.x, arrowBase1.y)
                    }
                    context.lineTo(dropItemHolderRect.x + dropItemHolderRect.width, dropItemHolderRect.y + dropItemHolderRect.height)
                    if (dropDirection == dropUp) {
                        context.lineTo(arrowBase2.x, arrowBase2.y)
                        context.lineTo(arrowPoint.x, arrowPoint.y)
                        context.lineTo(arrowBase1.x, arrowBase1.y)
                    }
                    context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y + dropItemHolderRect.height)
                    if (dropDirection == dropRight) {
                        context.lineTo(arrowBase2.x, arrowBase2.y)
                        context.lineTo(arrowPoint.x, arrowPoint.y)
                        context.lineTo(arrowBase1.x, arrowBase1.y)
                    }
                    context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y)
    
                    context.closePath()
    
                    context.fillStyle = qgcPal.windowShade
    
    Don Gagne's avatar
    Don Gagne committed
                    context.fill()
                }
            } // Canvas - arrowCanvas
    
            Item {
                id:     dropItemHolderRect
                //color:  qgcPal.button
                //radius: _dropCornerRadius
    
                Loader {
                    id: dropDownLoader
                    x:  _dropMargin
                    y:  _dropMargin
    
    
                    Connections {
                        target: dropDownLoader.item
    
                        onWidthChanged: _calcPositions()
                        onHeightChanged: _calcPositions()
                    }
    
    Don Gagne's avatar
    Don Gagne committed
                }
            }
        } // Item - dropDownItem
    }