@@ -19,14 +19,30 @@ import QtQuick 2.0
1919Item {
2020 id: container
2121 property Item surface: null
22− property string animation
23− property bool show: false
22+ readonly property alias surfaceArea: _surfaceArea
23+ property bool removing: false
2424
2525 onSurfaceChanged: {
2626 if (surface) {
2727 surface.parent = container;
28− surface.anchors.fill = container;
2928 surface.z = 1;
29+ state = "initial"
30+ }
31+ }
32+
33+ Item {
34+ id: _surfaceArea
35+ anchors.fill: parent
36+ }
37+
38+ Connections {
39+ target: surface
40+ onRemoved: {
41+ if (surface.parentSurface) {
42+ surface.parentSurface.parent.animateOut();
43+ }
44+ container.removing = true;
45+ animateOut();
3046 }
3147 }
3248
@@ -35,60 +51,126 @@ Item {
3551
3652 delegate: Loader {
3753 z: 2
38− anchors.fill: surface
54+ anchors.fill: surfaceArea
3955
4056 // Only way to do recursive qml items.
4157 source: Qt.resolvedUrl("SurfaceContainer.qml")
4258 onLoaded: {
43− item.parent = container.surface;
4459 item.surface = modelData;
45− item.animation = "overlaySwipeBottom"
46− item.show = true;
60+ item.animateIn("swipeFromBottom");
61+ container.animateIn("swipeUp");
4762 }
4863 }
4964 }
5065
66+ function animateIn(type) {
67+ var tmp = d.animations;
68+ tmp.push(type);
69+ d.animations = tmp;
70+
71+ container.state = d.currentAnimation + "-prep";
72+ container.state = d.currentAnimation + "-in";
73+ }
74+
75+ function animateOut() {
76+ if (d.animations.length > 0) {
77+ var tmp = d.animations;
78+ var popped = tmp.pop();
79+ d.animations = tmp;
80+ container.state = popped + "-out";
81+ if (d.currentAnimation !== "") {
82+ container.state = d.currentAnimation + "-in";
83+ }
84+ } else {
85+ container.state = "initial";
86+ }
87+ }
88+
89+ QtObject {
90+ id: d
91+ property variant animations: []
92+ property string currentAnimation: animations.length > 0 ? animations[animations.length-1] : ""
93+ }
94+
5195 states: [
96+ State {
97+ name: "initial"
98+ PropertyChanges { target: surface; anchors.fill: surfaceArea }
99+ },
100+
52101 State {
53102 name: "baseAnimation"
54103 PropertyChanges { target: surface; anchors.fill: undefined }
55104 },
56105
57106 State {
58− name: "overlaySwipeBottom-out"
107+ name: "swipeFromBottom-prep"
59108 extend: "baseAnimation"
60− when: surface && animation === "overlaySwipeBottom" && !show
61− AnchorChanges { target: surface; anchors.top: surface.parent.bottom }
109+ AnchorChanges { target: surface; anchors.top: surfaceArea.bottom }
62110 },
63111 State {
64− name: "overlaySwipeBottom-in"
112+ name: "swipeFromBottom-out"
113+ extend: "swipeFromBottom-prep"
114+ },
115+ State {
116+ name: "swipeFromBottom-in"
65117 extend: "baseAnimation"
66− when: surface && animation === "overlaySwipeBottom" && show
67− AnchorChanges { target: surface; anchors.top: surface.parent.top }
68− }
118+ AnchorChanges { target: surface; anchors.top: surfaceArea.top }
119+ },
69120
121+ State {
122+ name: "swipeUp-prep"
123+ extend: "baseAnimation"
124+ },
125+ State {
126+ name: "swipeUp-out"
127+ extend: "swipeUp-prep"
128+ },
129+ State {
130+ name: "swipeUp-in"
131+ extend: "baseAnimation"
132+ AnchorChanges { target: surface; anchors.bottom: surfaceArea.top }
133+ }
70134 // TODO: more animations!
71− // Surface needs to stick around so that we can dimiss them with animation.
72135 ]
73136
74137 transitions: [
75138 Transition {
76− from: "overlaySwipeBottom-out"
77− to: "overlaySwipeBottom-in"
139+ to: "swipeFromBottom-in"
140+ SequentialAnimation {
141+ PropertyAction { target: surface.parent; property: "clip"; value: true }
142+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
143+ PropertyAction { target: surface.parent; property: "clip"; value: false }
144+ }
145+ },
146+ Transition {
147+ to: "swipeFromBottom-out"
78148 SequentialAnimation {
79− PropertyAction { target: surface.parent; property: "clip"; value: true}
149+ PropertyAction { target: surface.parent; property: "clip"; value: true }
80150 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
81− PropertyAction { target: surface.parent; property: "clip"; value: false}
151+ PropertyAction { target: surface; property: "visible"; value: !removing }
152+ PropertyAction { target: surface.parent; property: "clip"; value: false }
153+ ScriptAction { script: { if (container.removing) surface.release() } }
82154 }
83155 },
156+
84157 Transition {
85− from: "overlaySwipeBottom-in"
86− to: "overlaySwipeBottom-out"
158+ to: "swipeUp-in"
87159 SequentialAnimation {
88− PropertyAction { target: surface.parent; property: "clip"; value: true}
160+ PropertyAction { target: surface.parent; property: "clip"; value: true }
89161 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
90162 PropertyAction { target: surface; property: "visible"; value: false}
91− PropertyAction { target: surface.parent; property: "clip"; value: false}
163+ PropertyAction { target: surface.parent; property: "clip"; value: false }
164+ }
165+ },
166+ Transition {
167+ to: "swipeUp-out"
168+ SequentialAnimation {
169+ PropertyAction { target: surface.parent; property: "clip"; value: true }
170+ PropertyAction { target: surface; property: "visible"; value: true }
171+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
172+ PropertyAction { target: surface.parent; property: "clip"; value: false }
173+ ScriptAction { script: { if (container.removing) surface.release() } }
92174 }
93175 }
94176 ]