diff options
author | Tomasz Olszak <olszak.tomasz@gmail.com> | 2013-06-10 21:33:34 +0000 |
---|---|---|
committer | Tomasz Olszak <olszak.tomasz@gmail.com> | 2013-06-11 00:12:14 +0200 |
commit | 278f27435db9ef18e0db053cda6b6569fb3dd05f (patch) | |
tree | e6f9ee44ff9ebb7dfea6379368492e35e8e00972 | |
parent | b4947898bcbf275622e4d6615ed48cfd00fa8f0f (diff) |
ContextMenu: Added Control element.
Some of content need to be moved to ContextMenuStyle in the future.
Additionally it should inherit from Control - not Item.
Change-Id: I3549abd7eec2d5028a8d621328a8d232a283e720
Reviewed-by: Tomasz Olszak <olszak.tomasz@gmail.com>
-rw-r--r-- | examples/touch/content/ContextMenuPage.qml | 118 | ||||
-rw-r--r-- | examples/touch/content/TabBarPage.qml | 2 | ||||
-rw-r--r-- | examples/touch/images/NOTICE.txt | 8 | ||||
-rw-r--r-- | examples/touch/images/internet-mail.png | bin | 0 -> 3899 bytes | |||
-rw-r--r-- | examples/touch/images/internet-web-browser.png | bin | 0 -> 6376 bytes | |||
-rw-r--r-- | examples/touch/main.qml | 4 | ||||
-rw-r--r-- | examples/touch/touch.pro | 3 | ||||
-rw-r--r-- | src/controls/Menu.qml | 339 | ||||
-rw-r--r-- | src/controls/controls.pro | 3 | ||||
-rw-r--r-- | src/controls/qmldir | 1 | ||||
-rw-r--r-- | src/styles/DefaultSettings.js | 71 | ||||
-rw-r--r-- | src/styles/Floater.qml | 6 | ||||
-rw-r--r-- | src/styles/styles.pro | 6 |
13 files changed, 551 insertions, 10 deletions
diff --git a/examples/touch/content/ContextMenuPage.qml b/examples/touch/content/ContextMenuPage.qml new file mode 100644 index 0000000..06de2b7 --- /dev/null +++ b/examples/touch/content/ContextMenuPage.qml @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2013 Tomasz Olszak <olszak.tomasz@gmail.com> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Tizen 1.0 + +Item { + id:root + width: parent.width + height: parent.height + + + Menu { + id: menu + anchorItem: center + anchorPoint: Qt.point(center.width/2, center.height/2) + MenuItem { + text: "Test" + onTriggered: { + console.log("Test triggered") + } + } + MenuItem { + text: "Mail" + iconSource: "../images/internet-mail.png" + } + MenuItem { + text: "Web Browser" + iconSource: "../images/internet-web-browser.png" + } + + MenuItem { + text: "Test4" + } + } + + + Text { + id: center + x: parent.width/2 - width/2 + y: parent.height/2 - height/2 + width: 100 + height: 100 + text: "Drag Anchor Point" + font.pixelSize: 26 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + Rectangle { + anchors.fill: parent + border.width: 1 + border.color: "darkgrey" + color:"transparent" + } + MouseArea { + anchors.fill: parent + drag.target: center + onPressAndHold: menu.popup() + } + } + + Button { + id:btnShow + width: 150 + anchors.margins: 50 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + text: "Show" + onClicked: { + menu.popup() + } + } + Button { + width: 150 + anchors.topMargin: 50 + anchors.top: parent.top + anchors.left: btnShow.right + text: "Animate" + onClicked: animation.running = !animation.running + } + NumberAnimation { + id:animation + target: center + property: "x" + from: 0 + to: parent.width + loops: Animation.Infinite + running: false + duration: 5000 + } + +} diff --git a/examples/touch/content/TabBarPage.qml b/examples/touch/content/TabBarPage.qml index 30e6ca2..5c7372c 100644 --- a/examples/touch/content/TabBarPage.qml +++ b/examples/touch/content/TabBarPage.qml @@ -70,7 +70,7 @@ Item { } Tab { title: "5" - TextInputPage{ visible: true } + ContextMenuPage{ visible: true } } } } diff --git a/examples/touch/images/NOTICE.txt b/examples/touch/images/NOTICE.txt index 93a9afc..88ef2dc 100644 --- a/examples/touch/images/NOTICE.txt +++ b/examples/touch/images/NOTICE.txt @@ -1,2 +1,10 @@ Notice some of these images are derived from Google applications resources. They were provided under the following license: You may use the materials in this directory without restriction to develop your apps and to use in your apps. + + +================ + + +icons are from the Tango Desktop project(http://tango.freedesktop.org/Tango_Desktop_Project): +internet-mail.png +internet-web-browser.png diff --git a/examples/touch/images/internet-mail.png b/examples/touch/images/internet-mail.png Binary files differnew file mode 100644 index 0000000..7e6b93b --- /dev/null +++ b/examples/touch/images/internet-mail.png diff --git a/examples/touch/images/internet-web-browser.png b/examples/touch/images/internet-web-browser.png Binary files differnew file mode 100644 index 0000000..a979a92 --- /dev/null +++ b/examples/touch/images/internet-web-browser.png diff --git a/examples/touch/main.qml b/examples/touch/main.qml index 9d6678c..136d961 100644 --- a/examples/touch/main.qml +++ b/examples/touch/main.qml @@ -124,6 +124,10 @@ ApplicationWindow { page: "content/CheckBoxPage.qml" } ListElement { + title: "ContextMenu" + page: "content/ContextMenuPage.qml" + } + ListElement { title: "TextInput" page: "content/TextInputPage.qml" } diff --git a/examples/touch/touch.pro b/examples/touch/touch.pro index 3cec48a..747c8dc 100644 --- a/examples/touch/touch.pro +++ b/examples/touch/touch.pro @@ -8,6 +8,7 @@ OTHER_FILES += \ content/SliderPage.qml \ content/TabBarPage.qml \ content/CheckBoxPage.qml \ - content/TextInputPage.qml + content/TextInputPage.qml \ + content/ContextMenuPage.qml diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml new file mode 100644 index 0000000..a1167ff --- /dev/null +++ b/src/controls/Menu.qml @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2013 Tomasz Olszak <olszak.tomasz@gmail.com> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import QtQuick 2.0 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Styles.Tizen 1.0 +import QtQuick.Window 2.0 + + +Floater { + id: menu + visible:false + + /*! In anchorPoint of this item menu arrow will be placed */ + property Item anchorItem + /*! It is the point where top of the arrow will be placed. + + If anchorItem is set then point is interpreter in anchorItem's coordinates + */ + property point anchorPoint + + + /* for getting all menu items to model*/ + default property alias menuItems: workaround.data + + /* shows ContextMenu */ + onVisibleChanged: { + if (visible) { + popup() + } else { + hide() + } + } + property string __state: "hidden" + function popup(){ + __state = "shown" + } + function hide() { + __state = "hidden" + } + + QtObject { + id:workaround + property list<QtObject> data + + } + + property Item control: menu + + content: Item { + id: contentItem + + property point __menuAnchorPoint: control.anchorItem ? + __globalAnchorPoint(control.width,control.height,control.x,control.y,control.anchorItem.x,control.anchorItem.y,control.anchorPoint) : + __globalAnchorPoint(control.width,control.height,control.x,control.y,control.anchorPoint) + + /* internal position of ContextMenu relative to anchorPoint */ + property int __position: updatePosition(__menuAnchorPoint) + + function __globalAnchorPoint() { + var tmp = menu.parent.mapFromItem(anchorItem, anchorPoint.x, anchorPoint.y) + return Qt.point(tmp.x,tmp.y) + } + state: control.__state === "hidden" ? "contentHidden" : "contentShown" + states: [ + State { + name:"contentHidden" + PropertyChanges { + target: contentItem + opacity:0 + } + }, + State { + name:"contentShown" + PropertyChanges { + target: contentItem + opacity:0 + } + } + ] + + transitions: [ + Transition { + to: "contentHidden" + SequentialAnimation { + NumberAnimation { + target: contentItem + property: "opacity" + duration: 250 + } + PropertyAction { + target: menu + property: "visible" + value:false + } + } + }, + Transition { + to: "contentShown" + SequentialAnimation { + PropertyAction { + target: menu + property: "visible" + value:true + } + NumberAnimation { + target: contentItem + property: "opacity" + to: 1 + duration: 250 + } + } + } + ] + + function updatePosition() { + var pos = Qt.BottomEdge + if (arrow.height/2 + bg.height - Theme.contextMenu.arrow.anchors.bottomMargin < (menu.height - __menuAnchorPoint.y) ) { + pos = Qt.BottomEdge + } else if ( arrow.height/2 + bg.height - Theme.contextMenu.arrow.anchors.topMargin < __menuAnchorPoint.y ) { + pos = Qt.TopEdge + } else if (arrow.width/2 + bg.width - Theme.contextMenu.arrow.anchors.rightMargin < (menu.width - __menuAnchorPoint.x)) { + pos = Qt.RightEdge + } else if (arrow.width/2 + bg.width - Theme.contextMenu.arrow.anchors.leftMargin < __menuAnchorPoint.x) { + pos = Qt.LeftEdge + } + return pos + } + anchors.fill: parent + Binding { + target: control + property: "anchors.fill" + value: control.parent + } + + Behavior on opacity { + NumberAnimation{duration:250} + } + MouseArea { + anchors.fill: parent + onClicked: menu.hide() + } + implicitWidth: bg.width + implicitHeight: bg.height + + TizenBorderImage { + id:arrow + + source: "../Styles/Tizen/"+Theme.contextMenu.arrow.source.top + effectSource: "../Styles/Tizen/"+Theme.contextMenu.arrow.effectSource.top + backgroundColor: Theme.contextMenu.color + + states: [ + State { + name:"bottom" + when: __position === Qt.BottomEdge + PropertyChanges { + target: arrow + rotation: 0 + x: Math.max(Math.min(__menuAnchorPoint.x - width/2, menu.width - arrow.width),0) + y: __menuAnchorPoint.y - arrow.height/2 + } + AnchorChanges { + target: bg + anchors.top: arrow.bottom + } + PropertyChanges { + target: bg + anchors.topMargin: -Theme.contextMenu.arrow.anchors.bottomMargin + x: Math.min(Math.max(arrow.x+arrow.width/2-bg.width/2,0),menu.width - bg.width) + } + }, + State { + name:"top" + when: __position === Qt.TopEdge + PropertyChanges { + target: arrow + rotation: 180 + x: Math.max(Math.min(__menuAnchorPoint.x - width/2, menu.width - arrow.width),0) + y: __menuAnchorPoint.y - arrow.height/2 + } + AnchorChanges { + target: bg + anchors.bottom: arrow.top + } + PropertyChanges { + target: bg + anchors.bottomMargin: -Theme.contextMenu.arrow.anchors.topMargin + x: Math.min(Math.max(arrow.x+arrow.width/2-bg.width/2,0),menu.width - bg.width) + } + }, + State { + name: "right" + when: __position === Qt.RightEdge + PropertyChanges { + target: arrow + rotation: -90 + x: __menuAnchorPoint.x + -arrow.width/2 + y: __menuAnchorPoint.y - arrow.height/2 + } + AnchorChanges { + target: bg + anchors.left: arrow.right + } + PropertyChanges { + target: bg + anchors.leftMargin: -Theme.contextMenu.arrow.anchors.rightMargin + y: Math.min(Math.max(arrow.y+arrow.height/2-bg.height/2,0),menu.height-bg.height) + } + + }, + State { + name:"left" + when: __position === Qt.LeftEdge + PropertyChanges { + target: arrow + rotation: 90 + x: __menuAnchorPoint.x - arrow.width/2 + y: __menuAnchorPoint.y - arrow.height/2 + } + AnchorChanges { + target: bg + anchors.right: arrow.left + } + PropertyChanges { + target: bg + anchors.rightMargin: -Theme.contextMenu.arrow.anchors.leftMargin + y: Math.min(Math.max(arrow.y+arrow.height/2-bg.height/2,0),menu.height-bg.height) + } + } + ] + } + TizenBorderImage { + id:bg + width: Math.min(layout.contentWidth + layout.anchors.leftMargin + layout.anchors.rightMargin,Theme.contextMenu.maximumWidth) + height: layout.implicitHeight + layout.anchors.topMargin + layout.anchors.bottomMargin + source: "../Styles/Tizen/"+Theme.contextMenu.source + effectSource: "../Styles/Tizen/"+Theme.contextMenu.effectSource + backgroundColor: Theme.contextMenu.color + + MouseArea { + anchors.fill: bg + } + } + + Column { + id:layout + anchors.fill: bg + + anchors.leftMargin: Theme.contextMenu.listLeftMargin + Theme.contextMenu.screen.leftMargin + anchors.rightMargin: Theme.contextMenu.listRightMargin + Theme.contextMenu.screen.rightMargin + anchors.topMargin: Theme.contextMenu.listTopMargin + Theme.contextMenu.screen.topMargin + anchors.bottomMargin: Theme.contextMenu.listBottomMargin + Theme.contextMenu.screen.bottomMargin + + property real contentWidth: Theme.contextMenu.minimumWidth + Repeater { + model: menuItems + + Item { + id: delegateRoot + implicitWidth: Math.max(itemBg.implicitWidth,label.contentWidth) + implicitHeight: Theme.contextMenu.item.height// Math.max(itemBg.implicitHeight+separator.height,label.contentHeight+separator.height) + width: layout.contentWidth + MouseArea { + id: mouseArea + anchors.fill: parent + TizenBorderImage { + id:itemBg + anchors.fill: parent + source: "../Styles/Tizen/"+Theme.contextMenu.item.source.pressed + backgroundColor: mouseArea.pressed && enabled ? Theme.contextMenu.item.color.pressed: Theme.contextMenu.item.color.normal + } + Image { + id:icon + anchors.left:parent.left + anchors.verticalCenter: parent.verticalCenter + source: modelData.iconSource + width: Theme.contextMenu.item.iconWidth + height: Theme.contextMenu.item.iconHeight + } + + Text { + id:label + anchors.left: icon.right + anchors.leftMargin: Theme.contextMenu.item.spacing + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.bottomMargin: 3 + text: modelData.text + color: Theme.contextMenu.item.text.color.normal + font.pixelSize: Theme.contextMenu.item.text.font.pixelSize + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id:separator + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + height: 2 + color: Theme.contextMenu.listItemDividerColor2 + visible: index < menuItems.length -1 + } + onClicked: menu.visible = false + } + } + + onItemAdded: { + layout.contentWidth = Math.max(item.implicitWidth, layout.contentWidth) + } + } + } + } +} diff --git a/src/controls/controls.pro b/src/controls/controls.pro index 011d27b..ed6df76 100644 --- a/src/controls/controls.pro +++ b/src/controls/controls.pro @@ -3,7 +3,8 @@ TARGETPATH = QtQuick/Controls/Tizen QML_FILES += \ Switch.qml \ - DetailButton.qml + DetailButton.qml\ + Menu.qml CONFIG += force_independent diff --git a/src/controls/qmldir b/src/controls/qmldir index 61e242f..6275a9c 100644 --- a/src/controls/qmldir +++ b/src/controls/qmldir @@ -2,3 +2,4 @@ module QtQuick.Controls.Tizen Switch 1.0 Switch.qml DetailButton 1.0 DetailButton.qml +Menu 1.0 Menu.qml diff --git a/src/styles/DefaultSettings.js b/src/styles/DefaultSettings.js index 8936db7..b0563ca 100644 --- a/src/styles/DefaultSettings.js +++ b/src/styles/DefaultSettings.js @@ -959,3 +959,74 @@ var detailButton = { //highlighted: colors.F032L1P, } } + +var contextMenu = { + + color: colors.B061L4, + listItemDividerColor1: colors.B0622L1, + listItemDividerColor2: colors.B0622L2, + item: { + color: { + normal: colors.B061L4, + pressed: colors.B044, + highlighted: colors.B044, + }, + text: { + color: { + normal: colors.B063L5, + pressed: colors.B063L5, + highlighted: colors.B063L5, + }, + font: { + pixelSize:40 + } + }, + source: { + pressed: images.img_00_more_popup_press + }, + height: 112, + iconWidth: 45, + iconHeight: 45, + spacing: 16 + }, + gridItemDividerColor1: colors.B0623L1, + gridItemDividerColor2: colors.B0623L2, + + source: images.img_00_popup_bubble_bg, + effectSource: images.img_00_popup_bubble_bg_ef, + + arrow: { + source: { + left: images.img_00_popup_bubble_tail_left, + right: images.img_00_popup_bubble_tail_right, + top: images.img_00_popup_bubble_tail_top, + bottom: images.img_00_popup_bubble_tail_bottom + }, + effectSource: { + left: images.img_00_popup_bubble_tail_left_ef, + right: images.img_00_popup_bubble_tail_right_ef, + top: images.img_00_popup_bubble_tail_top_ef, + bottom: images.img_00_popup_bubble_tail_bottom_ef + }, + width: 36, + height: 36, + anchors: { + topMargin: 18, + leftMargin: 12, + rightMargin:12, + bottomMargin:10 + } + }, + minimumWidth: 386, + maximumWidth: 620, + listTopMargin: 8, + listBottomMargin: 16, + listLeftMargin: 10, + listRightMargin: 10, + screen: { + topMargin: 24, + bottomMargin: 24, + leftMargin: 24, + rightMargin: 24 + } +} diff --git a/src/styles/Floater.qml b/src/styles/Floater.qml index 00a2d86..326bdd2 100644 --- a/src/styles/Floater.qml +++ b/src/styles/Floater.qml @@ -4,8 +4,8 @@ Item { id: floaterBehavior visible: false property Component content - width: contentLoader ? contentLoader.item.width:0 - height: contentLoader ? contentLoader.item.height:0 + width: contentLoader ? contentLoader.item.implicitWidth:0 + height: contentLoader ? contentLoader.item.implicitHeight:0 property Item root: findRoot() function findRoot() { @@ -19,6 +19,7 @@ Item { Loader { id: contentLoader sourceComponent: content + anchors.fill: parent } states: State { @@ -26,5 +27,4 @@ Item { when: Qt.isQtObject(contentLoader.item) && contentLoader.item.opacity > 0 ParentChange { target: floaterBehavior; parent: root } } - } diff --git a/src/styles/styles.pro b/src/styles/styles.pro index 9a05b35..84925a2 100644 --- a/src/styles/styles.pro +++ b/src/styles/styles.pro @@ -10,7 +10,8 @@ QML_FILES = \ TabViewStyle.qml \ Floater.qml \ SwitchStyle.qml\ - DetailButtonStyle.qml + DetailButtonStyle.qml\ + DefaultSettings.js # Images QML_FILES += \ @@ -19,9 +20,6 @@ QML_FILES += \ images/720x1280/white/*.png \ images/720x1280/white/*.sci -QML_FILES += \ - DefaultSettings.js - CONFIG += force_independent OTHER_FILES += qmldir |