added android components
[mardrone] / mardrone / imports / com / nokia / android.1.1 / TabGroup.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 import "TabGroup.js" as Engine
44
45 Item {
46     id: root
47     property Item currentTab
48
49     property list<Item> privateContents
50     // Qt defect: cannot have list as default property
51     default property alias privateContentsDefault: root.privateContents
52     property bool platformAnimated: true
53
54     onChildrenChanged: {
55         //  [0] is containerHost
56         if (children.length > 1)
57             Engine.addTab(children[1])
58     }
59
60     onPrivateContentsChanged: {
61         Engine.ensureContainers()
62     }
63
64     Component.onCompleted: {
65         // Set first tabs as current if currentTab is not set by application
66         if (currentTab == null && containerHost.children[0] && containerHost.children[0].children[0])
67             currentTab = containerHost.children[0].children[0]
68         priv.complete = true;
69     }
70
71     Item {
72         id: containerHost
73         objectName: "containerHost"
74         anchors.fill: parent
75     }
76
77     Component {
78         id: tabContainerComponent
79         Item {
80             id: tabContainerItem
81
82             onChildrenChanged: {
83                 if (children.length == 0)
84                     Engine.removeContainer(tabContainerItem)
85
86                 else if (children.length == 1) {
87                     children[0].width = width
88                     children[0].height = height
89                     // tab content created. set the first tab as current (if not set before, and if
90                     // child is added after TabGroup has completed)
91                     if (priv.complete && root.currentTab == null)
92                         root.currentTab = children[0]
93                 }
94             }
95
96             onWidthChanged: {
97                 if (children.length > 0)
98                     children[0].width = width
99             }
100
101             onHeightChanged: {
102                 if (children.length > 0)
103                     children[0].height = height
104             }
105
106             Component.onDestruction: {
107                 if (typeof(root) != "undefined" && !root.currentTab) {
108                     // selected one deleted. try to activate the neighbour
109                     var removedIndex = -1
110                     for (var i = 0; i < containerHost.children.length; i++) {
111                         if (containerHost.children[i] == tabContainerItem) {
112                             removedIndex = i
113                             break
114                         }
115                     }
116                     var newIndex = -1
117                     if (removedIndex != -1) {
118                         if (removedIndex != containerHost.children.length - 1)
119                             newIndex = removedIndex + 1
120                         else if (removedIndex != 0)
121                             newIndex = removedIndex - 1
122                     }
123
124                     if (newIndex != -1)
125                         root.currentTab = containerHost.children[newIndex].children[0]
126                     else
127                         root.currentTab = null
128                 }
129             }
130
131             function incomingDone() {
132                 state = ""
133                 if (priv.incomingPage) {
134                     priv.incomingPage.status = PageStatus.Active
135                     priv.incomingPage = null
136                 }
137             }
138
139             function outgoingDone() {
140                 if (priv.outgoingPage) {
141                     priv.outgoingPage.status = PageStatus.Inactive
142                     priv.outgoingPage.visible = false
143                     priv.outgoingPage = null
144                 }
145                 state = "Hidden"
146             }
147
148             width: parent ? parent.width : 0
149             height: parent ? parent.height : 0
150             state: "Hidden"
151
152             states: [
153                 State { name: ""; PropertyChanges { target: tabContainerItem; opacity: 1.0 } },
154                 State { name: "Incoming"; PropertyChanges { target: tabContainerItem; opacity: 1.0 } },
155                 State { name: "Outgoing"; PropertyChanges { target: tabContainerItem; opacity: 0.0 } },
156                 State { name: "Hidden"; PropertyChanges { target: tabContainerItem; opacity: 0.0 } }
157             ]
158
159             transitions:  [
160                 Transition {
161                     to: "Incoming"
162                     SequentialAnimation {
163                         PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: 250 }
164                         ScriptAction { script: incomingDone() }
165                     }
166                 },
167                 Transition {
168                     to: "Outgoing"
169                     SequentialAnimation {
170                         PropertyAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: 250 }
171                         ScriptAction { script: outgoingDone() }
172                     }
173                 }
174             ]
175         }
176     }
177
178     QtObject {
179         id: priv
180         property bool reparenting: false
181         property bool complete: false
182         property Item currentTabContainer: root.currentTab ? root.currentTab.parent : null
183         property Item incomingPage
184         property Item outgoingPage
185         property bool animate
186
187         function disableAnimations() {
188             animate = false
189
190             // outgoingPage might have been found before the incomingPage changes the orientation
191             if (outgoingPage)
192                 outgoingPage.parent.outgoingDone()
193         }
194
195         onCurrentTabContainerChanged: {
196             animate = platformAnimated // updated on orientation change
197             screen.currentOrientationChanged.connect(priv.disableAnimations)
198             for (var i = 0; i < containerHost.children.length; i++) {
199                 var tabContainer = containerHost.children[i]
200                 var isNewTab = (tabContainer == currentTabContainer)
201                 if (isNewTab) {
202                     if (tabContainer.state != "") {
203                         if (tabContainer.children[0].status != undefined) {
204                             incomingPage = tabContainer.children[0]
205                             incomingPage.status = PageStatus.Activating // triggers the orientation change
206                             incomingPage.visible = true
207                             if (incomingPage == outgoingPage)
208                                 outgoingPage = null
209                         }
210                         if (animate)
211                             tabContainer.state = "Incoming"
212                         else
213                             tabContainer.incomingDone()
214                     }
215                 } else {
216                     if (tabContainer.state != "Hidden") {
217                         if (tabContainer.children.length > 0 && tabContainer.children[0].status != undefined) {
218                             outgoingPage = tabContainer.children[0]
219                             outgoingPage.status = PageStatus.Deactivating
220                             if (incomingPage == outgoingPage)
221                                 incomingPage = null
222                         }
223                         if (animate)
224                             tabContainer.state = "Outgoing"
225                         else
226                             tabContainer.outgoingDone()
227                     }
228                 }
229             }
230             screen.currentOrientationChanged.disconnect(priv.disableAnimations)
231         }
232     }
233 }