diff options
Diffstat (limited to 'src/controls/Styles/Base/PieMenuStyle.qml')
-rw-r--r-- | src/controls/Styles/Base/PieMenuStyle.qml | 388 |
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 + } + } + } +} |