123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- /****************************************************************************
- **
- ** Copyright (C) 2016 The Qt Company Ltd.
- ** Contact: https://www.qt.io/licensing/
- **
- ** This file is part of the Qt Quick Extras module of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:LGPL$
- ** 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 https://www.qt.io/terms-conditions. For further
- ** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
- ** Public license version 3 or any later version approved by the KDE Free
- ** Qt Foundation. The licenses are as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
- ** included in the packaging of this file. Please review the following
- ** information to ensure the GNU General Public License requirements will
- ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
- ** https://www.gnu.org/licenses/gpl-3.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.
- \sa DropShadow
- */
- property color shadowColor: Qt.rgba(0, 0, 0, 0.26)
- /*!
- The shadow radius.
- \sa DropShadow
- */
- property real shadowRadius: 10
- /*!
- The shadow spread.
- \sa DropShadow
- */
- 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
- /*!
- \qmlmethod real PieMenuStyle::sectionStartAngle(int itemIndex)
- Returns the start of the section at \a itemIndex as an angle in degrees.
- */
- function sectionStartAngle(itemIndex) {
- return MathUtils.radToDegOffset(control.__protectedScope.sectionStartAngle(itemIndex));
- }
- /*!
- \qmlmethod real PieMenuStyle::sectionCenterAngle(int 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));
- }
- /*!
- \qmlmethod real PieMenuStyle::sectionEndAngle(int 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
- function onStartAngleChanged() { actionCanvas.requestPaint() }
- function onEndAngleChanged() { actionCanvas.requestPaint() }
- }
- Connections {
- target: control
- function 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
- spread: shadowSpread
- samples: shadowRadius * 2 + 1
- transparentBorder: true
- 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
- }
- }
- }
- }
|