summaryrefslogtreecommitdiff
path: root/src/controls/Styles/Base/MenuStyle.qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/controls/Styles/Base/MenuStyle.qml')
-rw-r--r--src/controls/Styles/Base/MenuStyle.qml462
1 files changed, 347 insertions, 115 deletions
diff --git a/src/controls/Styles/Base/MenuStyle.qml b/src/controls/Styles/Base/MenuStyle.qml
index c05c6a6d..bec8410b 100644
--- a/src/controls/Styles/Base/MenuStyle.qml
+++ b/src/controls/Styles/Base/MenuStyle.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
@@ -45,67 +45,190 @@ import QtQuick.Controls.Private 1.0
/*!
\qmltype MenuStyle
- \internal
- \ingroup menusstyling
\inqmlmodule QtQuick.Controls.Styles
+ \since 5.3
+ \ingroup controlsstyling
+ \brief Provides custom styling for Menu
+
+ \target styleData properties
+ The \b styleData object contains the following read-only properties:
+ \table
+ \row \li \b {styleData.index} : int \li The index of the menu item in its menu.
+ \row \li \b {styleData.type} : enumeration \li The type of menu item. See below for possible values.
+ \row \li \b {styleData.selected} : bool \li \c true if the menu item is selected.
+ \row \li \b {styleData.text} : string \li The menu item's text, or title if it's a submenu.
+ \row \li \b {styleData.underlineMnemonic} : bool \li Whether the style should underline the menu item's label mnemonic.
+ \row \li \b {styleData.shortcut} : string \li The text for the menu item's shortcut.
+ \row \li \b {styleData.iconSource} : url \li The source URL to the menu item's icon. Undefined if it has no icon.
+ \row \li \b {styleData.enabled} : bool \li \c true if the menu item is enabled.
+ \row \li \b {styleData.checkable} : bool \li \c true if the menu item is checkable.
+ \row \li \b {styleData.exclusive} : bool \li \c true if the menu item is checkable, and it's part of an \l ExclusiveGroup.
+ \row \li \b {styleData.checked} : bool \li \c true if the menu item is checkable and currently checked.
+ \row \li \b {styleData.scrollerDirection} : enumeration \li If the menu item is a scroller, its pointing direction.
+ Valid values are \c Qt.UpArrow, \c Qt.DownArrow, and \c Qt.NoArrow.
+ \endtable
+
+ The valid values for \b {styleData.type} are:
+ \list
+ \li MenuItemType.Item
+ \li MenuItemType.Menu
+ \li MenuItemType.Separator
+ \li MenuItemType.ScrollIndicator
+ \endlist
+
+ \note Styling menus may not be supported on platforms using native menus
+ through their QPA plugin.
*/
Style {
id: styleRoot
- property string __menuItemType: "menuitem"
- property real maxPopupHeight: 600 // ### FIXME Screen.desktopAvailableHeight * 0.99
+ padding {
+ top: 1
+ bottom: 1
+ left: 1
+ right: 1
+ }
- property Component frame: Rectangle {
- width: (parent ? parent.contentWidth : 0) + 2
- height: (parent ? parent.contentHeight : 0) + 2
+ /*! The amount of pixels by which a submenu popup overlaps horizontally its parent menu. */
+ property int submenuOverlap: 1
+
+ /*! Returns a rich-text string to render mnemonics for a given menu item.
+
+ The mnemonic character is prefixed by an ampersand in the original string.
- color: "lightgray"
- border { width: 1; color: "darkgray" }
+ Passing \c true for \c underline will underline the mnemonic character (e.g.,
+ \c formatMnemonic("&Open...", true) will return \c "<u>O</u>pen..."). Passing \c false
+ for \c underline will return the plain text form (e.g., \c formatMnemonic("&Open...", false)
+ will return \c "Open...").
- property int subMenuOverlap: -1
- property real maxHeight: maxPopupHeight
- property int margin: 1
+ \sa label
+ */
+ function formatMnemonic(text, underline) {
+ return underline ? StyleHelpers.stylizeMnemonics(text) : StyleHelpers.removeMnemonics(text)
}
- property Component menuItem: Rectangle {
- x: 1
- y: 1
- implicitWidth: Math.max((parent ? parent.width : 0),
- 18 + text.paintedWidth + (rightDecoration.visible ? rightDecoration.width + 40 : 12))
- implicitHeight: isSeparator ? text.font.pixelSize / 2 : !!scrollerDirection ? text.font.pixelSize * 0.75 : text.paintedHeight + 4
- color: selected && enabled ? "" : backgroundColor
- gradient: selected && enabled ? selectedGradient : undefined
- border.width: 1
- border.color: selected && enabled ? Qt.darker(selectedColor, 1) : color
- readonly property int leftMargin: __menuItemType === "menuitem" ? 18 : 0
-
- readonly property color backgroundColor: "#dcdcdc"
- readonly property color selectedColor: "#49d"
- Gradient {
- id: selectedGradient
- GradientStop {color: Qt.lighter(selectedColor, 1.3) ; position: -0.2}
- GradientStop {color: selectedColor; position: 1.4}
+ /*! The background frame for the menu popup.
+
+ The \l Menu will resize the frame to its contents plus the padding.
+ */
+ property Component frame: Rectangle {
+ color: styleRoot.__backgroundColor
+ border { width: 1; color: styleRoot.__borderColor }
+ }
+
+ /*! \qmlproperty Object MenuStyle::itemDelegate
+
+ The object containing the menu item subcontrol components. These subcontrols are used
+ for normal menu items only, i.e. not for separators or scroll indicators.
+
+ The subcontrols are:
+
+ \list
+ \li \b {itemDelegate.background} : Component
+
+ The menu item background component.
+
+ Its appearance generally changes with \l {styleData properties} {styleData.selected}
+ and \l {styleData properties} {styleData.enabled}.
+
+ The default implementation shows only when the item is enabled and selected. It remains
+ invisible otherwise.
+
+ \li \b {itemDelegate.label} : Component
+
+ Component for the actual text label.
+
+ The text itself is fetched from \l {styleData properties} {styleData.text}, and its appearance should depend
+ on \l {styleData properties} {styleData.enabled} and \l {styleData properties} {styleData.selected}.
+
+ If \l {styleData properties} {styleData.underlineMnemonic} is true, the label should underline its mnemonic
+ character. \l formatMnemonic provides the default formatting.
+
+ \li \b {itemDelegate.submenuIndicator} : Component
+
+ It indicates that the current menu item is a submenu.
+
+ Only used when \l {styleData properties} {styleData.type} equals \c MenuItemType.Menu.
+
+ \li \b {itemDelegate.shortcut} : Component
+
+ Displays the shortcut attached to the menu item.
+
+ Only used when \l {styleData properties} {styleData.shortcut} is not empty.
+
+ \li \b {itemDelegate.checkmarkIndicator} : Component
+
+ Will be used when \l {styleData properties} {styleData.checkable} is \c true and its appearance
+ may depend on \l {styleData properties} {styleData.exclusive}, i.e., whether it will behave like a
+ checkbox or a radio button. Use \l {styleData properties} {styleData.checked} for the checked state.
+ \endlist
+
+ \note This property cannot be overwritten although all of the subcontrol properties can.
+ */
+ property alias itemDelegate: internalMenuItem
+
+ MenuItemSubControls {
+ id: internalMenuItem
+
+ background: Rectangle {
+ visible: styleData.selected && styleData.enabled
+ gradient: Gradient {
+ id: selectedGradient
+ GradientStop { color: Qt.lighter(__selectedBackgroundColor, 1.3); position: -0.2 }
+ GradientStop { color: __selectedBackgroundColor; position: 1.4 }
+ }
+
+ border.width: 1
+ border.color: Qt.darker(__selectedBackgroundColor, 1)
+ antialiasing: true
}
- antialiasing: true
- SystemPalette {
- id: syspal
- colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
+ label: Text {
+ text: formatMnemonic(styleData.text, styleData.underlineMnemonic)
+ color: __currentTextColor
+ font.pixelSize: __labelFontPixelSize
}
- readonly property string itemText: parent ? parent.text : ""
- readonly property bool mirrored: Qt.application.layoutDirection === Qt.RightToLeft
+ submenuIndicator: Text {
+ text: __mirrored ? "\u25c2" : "\u25b8" // BLACK LEFT/RIGHT-POINTING SMALL TRIANGLE
+ font.pixelSize: __labelFontPixelSize
+ color: __currentTextColor
+ style: styleData.selected ? Text.Normal : Text.Raised
+ styleColor: Qt.lighter(color, 4)
+ }
- Loader {
- id: checkMark
- x: mirrored ? parent.width - width - 4 : 4
- y: 6
- active: __menuItemType === "menuitem" && !!menuItem && !!menuItem["checkable"]
- sourceComponent: exclusive ? exclusiveCheckMark : nonExclusiveCheckMark
+ shortcut: Text {
+ text: styleData.shortcut
+ font.pixelSize: __labelFontPixelSize * 0.9
+ color: __currentTextColor
+ }
- readonly property bool checked: !!menuItem && !!menuItem.checked
- readonly property bool exclusive: !!menuItem && !!menuItem["exclusiveGroup"]
+ checkmarkIndicator: Loader {
+ sourceComponent: styleData.exclusive ? exclusiveCheckMark : nonExclusiveCheckMark
+ Component {
+ id: exclusiveCheckMark
+ Rectangle {
+ x: 1
+ width: 10
+ height: 10
+ color: "white"
+ border.color: "gray"
+ antialiasing: true
+ radius: height/2
+
+ Rectangle {
+ anchors.centerIn: parent
+ visible: styleData.checked
+ width: 4
+ height: 4
+ color: "#666"
+ border.color: "#222"
+ antialiasing: true
+ radius: height/2
+ }
+ }
+ }
Component {
id: nonExclusiveCheckMark
@@ -120,13 +243,11 @@ Style {
Rectangle {
antialiasing: true
- visible: checkMark.checked
+ visible: styleData.checked
color: "#666"
radius: 1
anchors.margins: 4
anchors.fill: parent
- anchors.topMargin: 3
- anchors.bottomMargin: 5
border.color: "#222"
Rectangle {
anchors.fill: parent
@@ -137,70 +258,15 @@ Style {
}
}
}
-
- Component {
- id: exclusiveCheckMark
- Rectangle {
- x: 1
- width: 10
- height: 10
- color: "white"
- border.color: "gray"
- antialiasing: true
- radius: height/2
-
- Rectangle {
- anchors.centerIn: parent
- visible: checkMark.checked
- width: 4
- height: 4
- color: "#666"
- border.color: "#222"
- antialiasing: true
- radius: height/2
- }
- }
- }
- }
-
- Text {
- id: text
- visible: !isSeparator
- text: StyleHelpers.stylizeMnemonics(itemText)
- readonly property real offset: __menuItemType === "menuitem" ? 24 : 6
- x: mirrored ? parent.width - width - offset : offset
- anchors.verticalCenter: parent.verticalCenter
- renderType: Text.NativeRendering
- color: selected && enabled ? "white" : syspal.text
}
+ }
- Text {
- id: rightDecoration
- readonly property string shortcut: !!menuItem && menuItem["shortcut"] || ""
- visible: isSubmenu || shortcut !== ""
- text: isSubmenu ? mirrored ? "\u25c2" : "\u25b8" // BLACK LEFT/RIGHT-POINTING SMALL TRIANGLE
- : shortcut
- LayoutMirroring.enabled: mirrored
- anchors {
- right: parent.right
- rightMargin: 6
- baseline: isSubmenu ? undefined : text.baseline
- }
- font.pixelSize: isSubmenu ? text.font.pixelSize : text.font.pixelSize * 0.9
- color: text.color
- renderType: Text.NativeRendering
- style: selected || !isSubmenu ? Text.Normal : Text.Raised; styleColor: Qt.lighter(color, 4)
- }
-
- Image {
- id: scrollerDecoration
- visible: !!scrollerDirection
- anchors.centerIn: parent
- source: scrollerDirection === "up" ? "images/arrow-up.png" : "images/arrow-down.png"
- }
+ /*! Component for the separator menu item.
+ Will be used when \l {styleData properties} {styleData.type} equals \c MenuItemType.Separator.
+ */
+ property Component separator: Item {
Rectangle {
- visible: isSeparator
width: parent.width - 2
height: 1
x: 1
@@ -209,12 +275,178 @@ Style {
}
}
- property Component scrollerStyle: Style {
- padding { left: 0; right: 0; top: 0; bottom: 0 }
- property bool scrollToClickedPosition: false
- property Component frame: Item { visible: false }
- property Component corner: Item { visible: false }
- property Component __scrollbar: Item { visible: false }
- property bool useScrollers: true
+ /*! Component for the scroll indicator menu item.
+
+ Will be used when \l {styleData properties} {styleData.type} equals \c MenuItemType.ScrollIndicator.
+ Its appearance should follow \l {styleData properties} {styleData.scrollerDirection}.
+
+ This is the item added at the top and bottom of the menu popup when its contents won't fit the screen
+ to indicate more content is available in the direction of the arrow.
+ */
+ property Component scrollIndicator: Image {
+ anchors.centerIn: parent
+ source: styleData.scrollerDirection === Qt.UpArrow ? "images/arrow-up.png" : "images/arrow-down.png"
+ }
+
+ /*! \internal */
+ property string __menuItemType: "menuitem"
+
+ /*! \internal
+ The menu popup frame background color.
+
+ This is set to be a uniform background. If you want a gradient or a pixmap,
+ you should override \l frame.
+
+ \sa frame, borderColor
+ */
+ property color __backgroundColor: "#dcdcdc"
+
+ /*! \internal
+ The menu popup frame border color.
+
+ The border width is set to 1 pixel. Override \l frame if you want a larger border.
+
+ \sa frame, backgroundColor
+ */
+ property color __borderColor: "darkgray"
+
+ /*! \internal
+ The maximum height for a popup before it will show scrollers.
+ */
+ property int __maxPopupHeight: 600
+
+ /*! \internal
+ The menu item background color when selected.
+
+ This property is provided for convenience and only sets the color.
+ It does not change the style in any other way.
+ */
+ property color __selectedBackgroundColor: "#49d"
+
+ /*! \internal
+ The menu item label color.
+
+ When set, keyboard shorcuts get the same color as the item's text.
+
+ \sa selectedLabelColor, disabledLabelColor
+ */
+ property color __labelColor: "#444"
+
+ /*! \internal
+ The menu item label color when selected.
+
+ \sa labelColor, selectedLabelColor
+ */
+ property color __selectedLabelColor: "white"
+
+ /*! \internal
+ The menu item label color when disabled.
+
+ \sa labelColor, disabledLabelColor
+ */
+ property color __disabledLabelColor: "gray"
+
+
+ /*! \internal */
+ readonly property bool __mirrored: Qt.application.layoutDirection === Qt.RightToLeft
+
+ /*! \internal */
+ readonly property real __labelFontPixelSize: TextSingleton.font.pixelSize
+
+ /*! \internal
+ The margin between the frame and the menu item label's left side.
+
+ Generally, this should be large enough to fit optional checkmarks on
+ the label's left side.
+ */
+ property int __leftLabelMargin: 18
+
+ /*! \internal
+ The margin between the menu item label's right side and the frame. */
+ property int __rightLabelMargin: 12
+
+ /*! \internal
+ The minimum spacing between the menu item label's text right side and any
+ element located on its right (submenu indicator or shortcut).
+ */
+ property int __minRightLabelSpacing: 28
+
+ /*! \internal */
+ property Component __scrollerStyle: null
+
+ /*! \internal
+ The menu item contents itself.
+
+ The default implementation uses \l MenuItemStyle.
+ */
+ property Component menuItemPanel: Item {
+ id: panel
+
+ property QtObject __styleData: styleData
+ /*! \internal
+ The current color of the text label.
+
+ Use this if you're overriding e.g. \l shortcutIndicator to keep the color matched
+ with \l label, or to derive new colors from it.
+ */
+ property color currentTextColor: !styleData.enabled ? __disabledLabelColor :
+ styleData.selected ? __selectedLabelColor : __labelColor
+
+ implicitWidth: Math.max((parent ? parent.width : 0),
+ Math.round(__leftLabelMargin + labelLoader.width + __rightLabelMargin +
+ (rightIndicatorLoader.active ? __minRightLabelSpacing + rightIndicatorLoader.width : 0)))
+ implicitHeight: Math.round(styleData.isSeparator ? __labelFontPixelSize / 2 :
+ !!styleData.scrollerDirection ? __labelFontPixelSize * 0.75 : labelLoader.height + 4)
+
+ Loader {
+ property alias styleData: panel.__styleData
+ property alias __currentTextColor: panel.currentTextColor
+ anchors.fill: parent
+ sourceComponent: itemDelegate.background
+ }
+
+ Loader {
+ property alias styleData: panel.__styleData
+ property alias __currentTextColor: panel.currentTextColor
+ anchors.fill: parent
+ sourceComponent: separator
+ active: styleData.type === MenuItemType.Separator
+ }
+
+ Loader {
+ property alias styleData: panel.__styleData
+ property alias __currentTextColor: panel.currentTextColor
+ x: __mirrored ? parent.width - width - 4 : 4
+ y: styleData.exclusive ? 5 : 4
+ active: __menuItemType === "menuitem" && styleData.checkable
+ sourceComponent: itemDelegate.checkmarkIndicator
+ }
+
+ Loader {
+ id: labelLoader
+ readonly property real offset: __menuItemType === "menuitem" ? __leftLabelMargin : 6
+ property alias styleData: panel.__styleData
+ property alias __currentTextColor: panel.currentTextColor
+ x: __mirrored ? parent.width - width - offset : offset
+ y: 1
+ active: styleData.type !== MenuItemType.Separator
+ sourceComponent: itemDelegate.label
+ baselineOffset: item ? item.baselineOffset : 0.0
+ }
+
+ Loader {
+ id: rightIndicatorLoader
+ property alias styleData: panel.__styleData
+ property alias __currentTextColor: panel.currentTextColor
+ active: styleData.type === MenuItemType.Menu || styleData.shortcut !== ""
+ sourceComponent: styleData.type === MenuItemType.Menu ? itemDelegate.submenuIndicator : itemDelegate.shortcut
+ LayoutMirroring.enabled: __mirrored
+ baselineOffset: item ? item.baselineOffset : 0.0
+ anchors {
+ right: parent.right
+ rightMargin: 6
+ baseline: !styleData.isSubmenu ? labelLoader.baseline : undefined
+ }
+ }
}
}