added android components
[mardrone] / mardrone / imports / com / nokia / android.1.1 / MenuContent.qml
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the Qt Components project.
8 **
9 ** $QT_BEGIN_LICENSE:BSD$
10 ** You may use this file under the terms of the BSD license as follows:
11 **
12 ** "Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions are
14 ** met:
15 **   * Redistributions of source code must retain the above copyright
16 **     notice, this list of conditions and the following disclaimer.
17 **   * Redistributions in binary form must reproduce the above copyright
18 **     notice, this list of conditions and the following disclaimer in
19 **     the documentation and/or other materials provided with the
20 **     distribution.
21 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22 **     the names of its contributors may be used to endorse or promote
23 **     products derived from this software without specific prior written
24 **     permission.
25 **
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 import QtQuick 1.1
42 import "." 1.1
43
44 Item {
45     id: root
46
47     property alias content: contentArea.children
48     property Popup containingPopup: null
49     property bool platformInverted: false
50
51     signal itemClicked()
52
53     height: flickableArea.height
54
55     QtObject {
56         id: internal
57         // Add padding to align content area top and bottom with rounded background graphics.
58         // Optionsmenu uses mask, thus no padding needed
59         property int clipMargin: containingPopup.objectName == "OptionsMenu" ? 0 : platformStyle.paddingSmall
60         property int preferredHeight: privateStyle.menuItemHeight * ((screen.width < screen.height) ? 5 : 3)
61     }
62
63     BorderImage {
64         source: containingPopup.objectName == "OptionsMenu"
65                 ? privateStyle.imagePath("qtg_fr_popup_options", root.platformInverted)
66                 : privateStyle.imagePath("qtg_fr_popup", root.platformInverted)
67         border { left: 20; top: 20; right: 20; bottom: 20 }
68         anchors.fill: parent
69     }
70
71     Item {
72         id: clipItem
73         y: internal.clipMargin
74         height: flickableArea.height - 2 * internal.clipMargin
75         width: root.width
76         clip: true
77         Flickable {
78             id: flickableArea
79
80             property int index: 0
81             property bool itemAvailable: (contentArea.children[0] != undefined) && (contentArea.children[0].children[0] != undefined)
82             property int itemHeight: itemAvailable ? Math.max(1, contentArea.children[0].children[0].height) : 1
83             property int itemsHidden: Math.floor(contentY / itemHeight)
84             property int interactionMode: android.listInteractionMode
85
86             y: -internal.clipMargin
87             height: contentArea.height; width: root.width
88             clip: true
89             contentHeight: (contentArea.children[0] != undefined) ? contentArea.children[0].height : 0
90             contentWidth: width
91
92             Item {
93                 id: contentArea
94
95                 width: flickableArea.width
96                 height: flickableArea.contentHeight > internal.preferredHeight
97                     ? internal.preferredHeight - (internal.preferredHeight % flickableArea.itemHeight)
98                     : flickableArea.contentHeight
99
100                 function setChildrenWidths() {
101                     for (var i = 0; i < children.length; ++i)
102                         children[i].width = width
103                 }
104
105                 function connectChildren() {
106                     for (var i = 0; i < children.length; ++i) {
107                         if (children[i].clicked != undefined)
108                             children[i].clicked.connect(root.itemClicked)
109                     }
110                 }
111
112                 onWidthChanged: setChildrenWidths()
113                 onChildrenChanged: {
114                     setChildrenWidths()
115                     connectChildren()
116                 }
117             }
118
119             onVisibleChanged: {
120                 enabled = visible
121                 if (itemAvailable)
122                     contentArea.children[0].children[0].focus = visible
123                 contentY = 0
124                 index = 0
125             }
126
127             onItemsHiddenChanged: {
128                 // Check that popup is really open in order to prevent unnecessary feedback
129                 if (containingPopup.status == DialogStatus.Open
130                     && android.listInteractionMode == Android.TouchInteraction)
131                     privateStyle.play(Android.ItemScroll)
132             }
133
134             onInteractionModeChanged: {
135                 if (android.listInteractionMode == Android.KeyNavigation) {
136                     contentY = 0
137                     scrollBar.flash(Android.FadeOut)
138                     if (itemAvailable)
139                         contentArea.children[0].children[index].focus = true
140                 } else if (android.listInteractionMode == Android.TouchInteraction) {
141                     index = 0
142                 }
143             }
144
145             Keys.onPressed: {
146                 if (itemAvailable && (event.key == Qt.Key_Down || event.key == Qt.Key_Up)) {
147                     if (event.key == Qt.Key_Down && index < contentArea.children[0].children.length - 1) {
148                         index++
149                         if (index * itemHeight > contentY + height - itemHeight) {
150                             contentY = index * itemHeight - height + itemHeight
151                         }
152                     } else if (event.key == Qt.Key_Up && index > 0) {
153                         index--
154                         if (index * itemHeight < contentY) {
155                             contentY = index * itemHeight
156                         }
157                     }
158                     scrollBar.flash(Android.FadeOut)
159                     contentArea.children[0].children[index].focus = true
160                     event.accepted = true
161                 }
162             }
163         }
164     }
165
166     ScrollBar {
167         id: scrollBar
168         objectName: "scrollBar"
169         flickableItem: flickableArea
170         interactive: false
171         visible: flickableArea.height < flickableArea.contentHeight
172         anchors {
173             top: clipItem.top
174             bottom: clipItem.bottom
175             right: clipItem.right
176         }
177         platformInverted: root.platformInverted
178     }
179
180     Connections {
181         target: containingPopup
182         onStatusChanged: {
183             if (containingPopup.status == DialogStatus.Open)
184                 scrollBar.flash(Android.FadeInFadeOut)
185         }
186     }
187 }