Revision control
++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
++
++ import QtQuick
++ import QtQuick.Shapes
++
++ TapHandler {
++ property var labels: [ "upperLeft", "upperRight", "lowerRight", "lowerLeft" ]
++ signal triggered(string text)
++
++ id: menuTap
++ acceptedButtons: Qt.RightButton
++ gesturePolicy: TapHandler.DragWithinBounds
++ onPressedChanged: if (pressed) {
++ impl.x = point.position.x - impl.width / 2
++ impl.y = point.position.y - impl.width / 2
++ } else {
++ if (impl.highlightedShape)
++ menuTap.triggered(impl.highlightedShape.text)
++ }
++
++ property Item impl: Item {
++ parent: menuTap.parent
++ width: 100
++ height: 100
++ // with touchscreen or stylus, long-press slowly expands the menu to size
++ // with mouse or touchpad right-click, it opens instantly
++ scale: menuTap.point.device.pointerType === PointerDevice.Generic ?
++ 1 : Math.min(1, Math.max(0, menuTap.timeHeld * 4))
++ opacity: scale * 2
++ visible: menuTap.pressed
++ property Shape highlightedShape: null
++
++ component PieSegment : Shape {
++ id: shape
++ property int orientation: Qt.TopRightCorner
++ property alias text: text.text
++
++ width: 100
++ height: 100
++ containsMode: Shape.FillContains
++ preferredRendererType: Shape.CurveRenderer
++
++ property bool highlighted: menuTap.pressed &&
++ shape.contains(shape.mapFromItem(menuTap.parent, menuTap.point.position))
++ onHighlightedChanged: {
++ if (highlighted)
++ impl.highlightedShape = shape
++ else if (impl.highlightedShape === shape)
++ impl.highlightedShape = null
++ }
++
++ ShapePath {
++ fillColor: highlighted ? "darkturquoise" : "aliceblue"
++ PathSvg {
++ id: svgPath
++ path: switch (orientation) {
++ case Qt.TopRightCorner:
++ return "M75,50 l 25,0 a50,50 0 0,0 -50,-50 l 0,25 a25,25 0 0,1 25,25";
++ case Qt.BottomRightCorner:
++ return "M75,50 l 25,0 a50,50 0 0,1 -50,50 l 0,-25 a25,25 0 0,0 25,-25";
++ case Qt.TopLeftCorner:
++ return "M50,25 l 0,-25 a50,50 0 0,0 -50,50 l 25,0 a25,25 0 0,1 25,-25";
++ case Qt.BottomLeftCorner:
++ return "M50,75 l 0,25 a50,50 0 0,1 -50,-50 l 25,0 a25,25 0 0,0 25,25";
++ }
++ }
++ }
++ Text {
++ id: text
++ anchors {
++ centerIn: parent
++ horizontalCenterOffset: switch (orientation) {
++ case Qt.TopRightCorner:
++ case Qt.BottomRightCorner:
++ return 25;
++ default:
++ return -25;
++ }
++ verticalCenterOffset: switch (orientation) {
++ case Qt.BottomLeftCorner:
++ case Qt.BottomRightCorner:
++ return 25;
++ default:
++ return -25;
++ }
++ }
++ horizontalAlignment: Text.AlignHCenter
++ rotation: switch (orientation) {
++ case Qt.TopRightCorner:
++ case Qt.BottomLeftCorner:
++ return 45;
++ default:
++ return -45;
++ }
++ }
++ }
++
++ PieSegment {
++ orientation: Qt.TopLeftCorner
++ text: labels[0]
++ }
++ PieSegment {
++ orientation: Qt.TopRightCorner
++ text: labels[1]
++ }
++ PieSegment {
++ orientation: Qt.BottomRightCorner
++ text: labels[2]
++ }
++ PieSegment {
++ orientation: Qt.BottomLeftCorner
++ text: labels[3]
++ }
++ }
++ }