summaryrefslogtreecommitdiff
path: root/src/controls/Styles/Base/PieMenuStyle.qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/controls/Styles/Base/PieMenuStyle.qml')
-rw-r--r--src/controls/Styles/Base/PieMenuStyle.qml388
1 files changed, 388 insertions, 0 deletions
diff --git a/src/controls/Styles/Base/PieMenuStyle.qml b/src/controls/Styles/Base/PieMenuStyle.qml
new file mode 100644
index 00000000..916a0c9e
--- /dev/null
+++ b/src/controls/Styles/Base/PieMenuStyle.qml
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtGraphicalEffects 1.0
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+import QtQuick.Extras.Private.CppUtils 1.0
+
+/*!
+ \qmltype PieMenuStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for PieMenu.
+
+ PieMenuStyle is a style for PieMenu that draws each section of the menu as a
+ filled "slice".
+
+ You can create a custom pie menu by replacing the following delegates:
+ \list
+ \li \l background
+ \li \l cancel
+ \li \l menuItem
+ \li \l title
+ \endlist
+
+ To customize the appearance of each menuItem without having to define your
+ own, you can use the \l backgroundColor and \l selectionColor properties.
+ To customize the drop shadow, use the \l shadowColor, \l shadowRadius and
+ \l shadowSpread properties.
+
+ Icons that are too large for the section that they are in will be scaled
+ down appropriately.
+
+ To style individual sections of the menu, use the menuItem component:
+ \code
+ PieMenuStyle {
+ shadowRadius: 0
+
+ menuItem: Item {
+ id: item
+ rotation: -90 + sectionCenterAngle(styleData.index)
+
+ Rectangle {
+ width: parent.height * 0.2
+ height: width
+ color: "darkorange"
+ radius: width / 2
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+
+ Text {
+ id: textItem
+ text: control.menuItems[styleData.index].text
+ anchors.centerIn: parent
+ color: control.currentIndex === styleData.index ? "red" : "white"
+ rotation: -item.rotation
+ }
+ }
+ }
+ }
+ \endcode
+
+ \image piemenu-menuitem-example.png A custom PieMenu
+*/
+
+Style {
+ id: pieMenuStyle
+
+ /*!
+ The \l PieMenu that this style is attached to.
+ */
+ readonly property PieMenu control: __control
+
+ /*! The background color. */
+ property color backgroundColor: Qt.rgba(0.6, 0.6, 0.6, 0.66)
+
+ /*! The selection color. */
+ property color selectionColor: "#eee"
+
+ /*! The shadow color. */
+ property color shadowColor: Qt.rgba(0, 0, 0, 0.26)
+
+ /*! The shadow radius. */
+ property real shadowRadius: 50
+
+ /*! The shadow spread. */
+ property real shadowSpread: 0.3
+
+ /*!
+ The distance from the center of the menu to the outer edge of the menu.
+
+ \sa cancelRadius
+ */
+ readonly property real radius: Math.min(control.width, control.height) * 0.5
+
+ /*!
+ The radius of the area that is used to cancel the menu.
+
+ \sa radius
+ */
+ property real cancelRadius: radius * 0.4
+
+ /*!
+ The angle (in degrees) at which the first menu item will be drawn.
+
+ The absolute range formed by \a startAngle and \l endAngle must be
+ less than or equal to \c 360 degrees.
+
+ Menu items are displayed clockwise when \a startAngle is less than
+ \l endAngle, otherwise they are displayed anti-clockwise.
+
+ \sa endAngle
+ */
+ property real startAngle: -90
+
+ /*!
+ The angle (in degrees) at which the last menu item will be drawn.
+
+ The absolute range formed by \l startAngle and \a endAngle must be
+ less than or equal to \c 360 degrees.
+
+ Menu items are displayed clockwise when \l startAngle is less than
+ \a endAngle, otherwise they are displayed anti-clockwise.
+
+ \sa startAngle
+ */
+ property real endAngle: 90
+
+ /*!
+ Returns the start of the section at \a itemIndex as an angle in degrees.
+ */
+ function sectionStartAngle(itemIndex) {
+ return MathUtils.radToDegOffset(control.__protectedScope.sectionStartAngle(itemIndex));
+ }
+
+ /*!
+ Returns the center of the section at \a itemIndex as an angle in
+ degrees.
+ */
+ function sectionCenterAngle(itemIndex) {
+ return MathUtils.radToDegOffset(control.__protectedScope.sectionCenterAngle(itemIndex));
+ }
+
+ /*!
+ Returns the end of the section at \a itemIndex as an angle in degrees.
+ */
+ function sectionEndAngle(itemIndex) {
+ return MathUtils.radToDegOffset(control.__protectedScope.sectionEndAngle(itemIndex));
+ }
+
+ /*!
+ \internal
+
+ The distance in pixels from the center of each menu item's icon to the
+ center of the menu. A higher value means that the icons will be further
+ from the center of the menu.
+ */
+ readonly property real __iconOffset: cancelRadius + ((radius - cancelRadius) / 2)
+
+ /*! \internal */
+ readonly property real __selectableRadius: radius - cancelRadius
+
+ /*! \internal */
+ property int __implicitWidth: Math.round(TextSingleton.implicitHeight * 12.5)
+
+ /*! \internal */
+ property int __implicitHeight: __implicitWidth
+
+ /*!
+ The background of the menu.
+
+ By default, there is no background defined.
+ */
+ property Component background
+
+ /*!
+ The cancel component of the menu.
+
+ This is an area in the center of the menu that closes the menu when
+ clicked.
+
+ By default, it is not visible.
+ */
+ property Component cancel: null
+
+ /*!
+ The component that displays the text of the currently selected menu
+ item, or the title if there is no current item.
+
+ The current item's text is available via the \c styleData.text
+ property.
+ */
+ property Component title: Text {
+ font.pointSize: 20
+ text: styleData.text
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ color: "#ccc"
+ antialiasing: true
+ }
+
+ /*!
+ This component defines each section of the pie menu.
+
+ This component covers the width and height of the control.
+
+ No mouse events are propagated to this component, which means that
+ controls like Button will not function when used within it. You can
+ check if the mouse is over this section by comparing
+ \c control.currentIndex to \c styleData.index.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this menu item.
+ \row \li \c {readonly property bool} \b styleData.hovered
+ \li \c true if this menu item is under the mouse.
+ \row \li \c {readonly property bool} \b styleData.pressed
+ \li \c true if the mouse is pressed down on this menu item.
+ \endtable
+ */
+ property Component menuItem: Item {
+ id: actionRootDelegateItem
+
+ function drawRingSection(ctx, x, y, section, r, ringWidth, ringColor) {
+ ctx.fillStyle = ringColor;
+
+ // Draw one section.
+ ctx.beginPath();
+ ctx.moveTo(x,y);
+
+ // Canvas draws 0 degrees at 3 o'clock, whereas we want it to draw it at 12.
+ var start = control.__protectedScope.sectionStartAngle(section);
+ var end = control.__protectedScope.sectionEndAngle(section);
+ ctx.arc(x, y, r, start, end, start > end);
+ ctx.fill();
+
+ // Either change this to the background color, or use the global composition.
+ ctx.fillStyle = "black";
+ ctx.globalCompositeOperation = "destination-out";
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.arc(x, y, ringWidth, 0, Math.PI * 2);
+ ctx.closePath();
+ ctx.fill();
+
+ // If using the global composition method, make sure to change it back to default.
+ ctx.globalCompositeOperation = "source-over";
+ }
+
+ Canvas {
+ id: actionCanvas
+ anchors.fill: parent
+ property color currentColor: control.currentIndex === styleData.index ? selectionColor : backgroundColor
+
+ Connections {
+ target: pieMenuStyle
+ onStartAngleChanged: actionCanvas.requestPaint()
+ onEndAngleChanged: actionCanvas.requestPaint()
+ }
+
+ Connections {
+ target: control
+ onCurrentIndexChanged: actionCanvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+ drawRingSection(ctx, width / 2, height / 2, styleData.index, radius, cancelRadius, currentColor);
+ }
+ }
+
+ readonly property var __styleData: styleData
+
+ PieMenuIcon {
+ control: pieMenuStyle.control
+ styleData: __styleData
+ }
+ }
+
+ /*! \internal */
+ property Component panel: Item {
+ implicitWidth: __implicitWidth
+ implicitHeight: __implicitHeight
+
+ property alias titleItem: titleLoader.item
+
+ Item {
+ id: itemgroup
+ anchors.fill: parent
+ visible: false
+
+ Loader {
+ id: backgroundLoader
+ sourceComponent: background
+ anchors.fill: parent
+ }
+
+ Loader {
+ id: cancelLoader
+ sourceComponent: cancel
+ anchors.centerIn: parent
+ }
+
+ Repeater {
+ id: menuItemRepeater
+ model: control.__protectedScope.visibleItems
+
+ delegate: Loader {
+ id: menuItemLoader
+ anchors.fill: parent
+ sourceComponent: menuItem
+
+ readonly property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property alias index: menuItemLoader.__index
+ readonly property bool hovered: control.currentIndex === index
+ readonly property bool pressed: control.__protectedScope.pressedIndex === index
+ }
+ }
+ }
+ }
+ DropShadow {
+ id: dropShadow
+ anchors.fill: itemgroup
+ fast: true
+ radius: shadowRadius
+ spread: shadowSpread
+ transparentBorder: true
+ samples: 12
+ color: shadowColor
+ source: itemgroup
+ }
+
+ Loader {
+ id: titleLoader
+ sourceComponent: title
+ x: parent.x + parent.width / 2 - width / 2
+ y: -height - 10
+
+ property QtObject styleData: QtObject {
+ property string text: control.currentIndex !== -1
+ ? control.__protectedScope.visibleItems[control.currentIndex].text
+ : control.title
+ }
+ }
+ }
+}