on xenial help sign in
Remove some deleted files

For some odd reson these didn't get removed when moved to git from bzr See: https://github.com/ubports/unity8/commit/ba022638122964ac4d6a178ecc574d01ec9a5320#diff-6a656bd446541471deafee99179cdb95

commit2931b2fb94e31ed88d21d200af2c65f291884378 authorMarius Gripsgard <marius@ubports.com> dateSun 30 Jun 2019, 22:57 (7 years ago) parent778b273
10 files changed−4604
qml/Stage/AbstractStage.qml−92 qml/Stage/DesktopSpread.qml−576 qml/Stage/DesktopSpreadDelegate.qml−126 qml/Stage/PhoneStage.qml−789 qml/Stage/SpreadDelegate.qml−424 qml/Stage/SpreadMaths.qml−164 qml/Stage/TabletStage.qml−1183 qml/Stage/TransformedSpreadDelegate.qml−391 qml/Stage/TransformedTabletSpreadDelegate.qml−436 tests/qmltests/Stage/tst_SpreadDelegate.qml−423
qml/Stage/AbstractStage.qmldeleted−92
@@ -1,92 +0,0 @@
1−/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import GlobalShortcut 1.0
20−import GSettings 1.0
21−
22−FocusScope {
23− id: root
24−
25− // Controls to be set from outside
26− property QtObject applicationManager
27− property QtObject topLevelSurfaceList
28− property bool altTabPressed
29− property url background
30− property bool beingResized
31− property int dragAreaWidth
32− property real dragProgress // How far left the stage has been dragged, used externally by tutorial code
33− property bool interactive
34− property real inverseProgress // This is the progress for left edge drags, in pixels.
35− property real maximizedAppTopMargin
36− property real nativeHeight
37− property real nativeWidth
38− property QtObject orientations
39− property int shellOrientation
40− property int shellOrientationAngle
41− property bool spreadEnabled: true // If false, animations and right edge will be disabled
42− property bool suspended
43− // A Stage should paint a wallpaper etc over its full size but not use the margins for window placement
44− property int leftMargin: 0
45− property alias paintBackground: background.visible
46− property bool oskEnabled: false
47−
48− // To be read from outside
49− property var mainApp: null
50− property int mainAppWindowOrientationAngle: 0
51− property bool orientationChangesEnabled
52− property int supportedOrientations: Qt.PortraitOrientation
53− | Qt.LandscapeOrientation
54− | Qt.InvertedPortraitOrientation
55− | Qt.InvertedLandscapeOrientation
56−
57− property Item itemConfiningMouseCursor: null
58−
59−
60− signal stageAboutToBeUnloaded
61− signal itemSnapshotRequested(Item item)
62−
63− // Shared code for use in stage implementations
64− GSettings {
65− id: lifecycleExceptions
66− schema.id: "com.canonical.qtmir"
67− }
68−
69− function isExemptFromLifecycle(appId) {
70− var shortAppId = appId.split('_')[0];
71− for (var i = 0; i < lifecycleExceptions.lifecycleExemptAppids.length; i++) {
72− if (shortAppId === lifecycleExceptions.lifecycleExemptAppids[i]) {
73− return true;
74− }
75− }
76− return false;
77− }
78−
79− Rectangle {
80− id: background
81− color: "#060606"
82− anchors.fill: parent
83− }
84−
85− // shared Alt+F4 functionality
86− function closeFocusedDelegate() {} // to be implemented by stages
87−
88− GlobalShortcut {
89− shortcut: Qt.AltModifier|Qt.Key_F4
90− onTriggered: closeFocusedDelegate()
91− }
92−}
qml/Stage/DesktopSpread.qmldeleted−576
@@ -1,576 +0,0 @@
1−/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import QtQuick.Layouts 1.1
19−import Ubuntu.Components 1.3
20−import Ubuntu.Gestures 0.1
21−import Unity.Application 0.1
22−import "../Components"
23−import Utils 0.1
24−
25−FocusScope {
26− id: root
27−
28− property bool altTabPressed: false
29− property Item workspace: null
30−
31− readonly property alias ready: blurLayer.ready
32− readonly property alias highlightedIndex: spreadRepeater.highlightedIndex
33−
34− signal playFocusAnimation(int index)
35−
36− function show() {
37− spreadContainer.animateIn = true;
38− root.state = "altTab";
39− }
40−
41− onFocusChanged: {
42− // When the spread comes active, we want to keep focus to the input handler below
43− // Make sure nothing inside the ApplicationWindow grabs our focus!
44− if (focus) {
45− forceActiveFocus();
46− }
47− }
48−
49− Keys.onPressed: {
50− switch (event.key) {
51− case Qt.Key_Left:
52− case Qt.Key_Backtab:
53− selectPrevious(event.isAutoRepeat)
54− event.accepted = true;
55− break;
56− case Qt.Key_Right:
57− case Qt.Key_Tab:
58− selectNext(event.isAutoRepeat)
59− event.accepted = true;
60− break;
61− case Qt.Key_Escape:
62− spreadRepeater.highlightedIndex = -1
63− // Falling through intentionally
64− case Qt.Key_Enter:
65− case Qt.Key_Return:
66− case Qt.Key_Space:
67− root.state = ""
68− event.accepted = true;
69− }
70− }
71−
72− function selectNext(isAutoRepeat) {
73− if (isAutoRepeat && spreadRepeater.highlightedIndex >= topLevelSurfaceList.count -1) {
74− return; // AutoRepeat is not allowed to wrap around
75− }
76−
77− spreadRepeater.highlightedIndex = (spreadRepeater.highlightedIndex + 1) % topLevelSurfaceList.count;
78− var newContentX = ((spreadFlickable.contentWidth) / (topLevelSurfaceList.count + 1)) * Math.max(0, Math.min(topLevelSurfaceList.count - 5, spreadRepeater.highlightedIndex - 3));
79− if (spreadFlickable.contentX < newContentX || spreadRepeater.highlightedIndex == 0) {
80− spreadFlickable.snapTo(newContentX)
81− }
82− }
83−
84− function selectPrevious(isAutoRepeat) {
85− if (isAutoRepeat && spreadRepeater.highlightedIndex == 0) {
86− return; // AutoRepeat is not allowed to wrap around
87− }
88−
89− var newIndex = spreadRepeater.highlightedIndex - 1 >= 0 ? spreadRepeater.highlightedIndex - 1 : topLevelSurfaceList.count - 1;
90− spreadRepeater.highlightedIndex = newIndex;
91− var newContentX = ((spreadFlickable.contentWidth) / (topLevelSurfaceList.count + 1)) * Math.max(0, Math.min(topLevelSurfaceList.count - 5, spreadRepeater.highlightedIndex - 1));
92− if (spreadFlickable.contentX > newContentX || newIndex == topLevelSurfaceList.count -1) {
93− spreadFlickable.snapTo(newContentX)
94− }
95− }
96−
97− function focusSelected() {
98− if (spreadRepeater.highlightedIndex != -1) {
99− if (spreadContainer.visible) {
100− root.playFocusAnimation(spreadRepeater.highlightedIndex)
101− }
102− var surface = topLevelSurfaceList.surfaceAt(spreadRepeater.highlightedIndex);
103− surface.requestFocus();
104− }
105− }
106−
107− function cancel() {
108− spreadRepeater.highlightedIndex = -1;
109− state = ""
110− }
111−
112− BlurLayer {
113− id: blurLayer
114− anchors.fill: parent
115− source: root.workspace
116− visible: false
117− }
118−
119− Rectangle {
120− id: spreadBackground
121− anchors.fill: parent
122− color: "#B2000000"
123− visible: false
124− opacity: visible ? 1 : 0
125− Behavior on opacity {
126− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
127− }
128− }
129−
130− MouseArea {
131− id: eventEater
132− anchors.fill: parent
133− visible: spreadBackground.visible
134− enabled: visible
135− acceptedButtons: Qt.AllButtons
136− onWheel: wheel.accepted = true;
137− }
138−
139− Item {
140− id: spreadContainer
141− objectName: "spreadContainer"
142− anchors.fill: parent
143− visible: false
144−
145− property bool animateIn: false
146−
147− Repeater {
148− id: spreadRepeater
149− objectName: "spreadRepeater"
150− model: topLevelSurfaceList
151−
152− property int highlightedIndex: -1
153− property int closingIndex: -1
154−
155− function indexOf(delegateItem) {
156− for (var i = 0; i < spreadRepeater.count; i++) {
157− if (spreadRepeater.itemAt(i) === delegateItem) {
158− return i;
159− }
160− }
161− return -1;
162− }
163−
164− delegate: Item {
165− id: spreadDelegate
166− objectName: "spreadDelegate"
167− width: units.gu(20)
168− height: units.gu(20)
169−
170− property real angle: 0
171− property real itemScale: 1
172− property int itemScaleOriginX: 0
173− property int itemScaleOriginY: 0
174−
175− readonly property string windowTitle: clippedSpreadDelegate.window.title
176−
177− Behavior on x {
178− id: closeBehavior
179− enabled: spreadRepeater.closingIndex >= 0
180− UbuntuNumberAnimation {
181− onRunningChanged: if (!running) spreadRepeater.closingIndex = -1
182− }
183− }
184−
185− DesktopSpreadDelegate {
186− id: clippedSpreadDelegate
187− objectName: "clippedSpreadDelegate"
188− anchors.left: parent.left
189− anchors.top: parent.top
190− application: model.application
191− surface: model.surface
192− width: spreadMaths.spreadHeight
193− height: spreadMaths.spreadHeight
194−
195− transform: [
196− Scale {
197− origin.x: itemScaleOriginX
198− origin.y: itemScaleOriginY
199− xScale: itemScale
200− yScale: itemScale
201− },
202− Rotation {
203− origin { x: 0; y: (clippedSpreadDelegate.height - (clippedSpreadDelegate.height * itemScale / 2)) }
204− axis { x: 0; y: 1; z: 0 }
205− angle: spreadDelegate.angle
206− }
207− ]
208−
209− MouseArea {
210− id: spreadSelectArea
211− anchors.fill: parent
212− anchors.margins: -units.gu(2)
213− enabled: false
214− onClicked: {
215− spreadRepeater.highlightedIndex = index;
216− root.state = "";
217− }
218− }
219− }
220−
221− SpreadMaths {
222− id: spreadMaths
223− flickable: spreadFlickable
224− itemIndex: index
225− totalItems: Math.max(6, topLevelSurfaceList.count)
226− sceneHeight: root.height
227− itemHeight: spreadDelegate.height
228− }
229−
230− states: [
231− State {
232− name: "altTab"; when: root.state == "altTab" && spreadContainer.visible
233− PropertyChanges {
234− target: spreadDelegate
235− x: spreadMaths.animatedX
236− y: spreadMaths.animatedY + (spreadDelegate.height - clippedSpreadDelegate.height) - units.gu(2)
237− width: spreadMaths.spreadHeight
238− height: spreadMaths.sceneHeight
239− angle: spreadMaths.animatedAngle
240− itemScale: spreadMaths.scale
241− itemScaleOriginY: clippedSpreadDelegate.height / 2;
242− z: index
243− visible: spreadMaths.itemVisible
244− }
245− PropertyChanges {
246− target: clippedSpreadDelegate
247− highlightShown: index == spreadRepeater.highlightedIndex
248− state: "transformed"
249− shadowOpacity: spreadMaths.shadowOpacity
250− anchors.topMargin: units.gu(2)
251− }
252− PropertyChanges {
253− target: tileInfo
254− visible: true
255− opacity: spreadMaths.tileInfoOpacity
256− }
257− PropertyChanges {
258− target: spreadSelectArea
259− enabled: true
260− }
261− }
262− ]
263− transitions: [
264− Transition {
265− from: ""
266− to: "altTab"
267− SequentialAnimation {
268− ParallelAnimation {
269− PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
270− PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
271− PropertyAnimation {
272− target: spreadDelegate; properties: "x"
273− from: root.width
274− duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration :0
275− easing: UbuntuAnimation.StandardEasing
276− }
277− UbuntuNumberAnimation { target: clippedSpreadDelegate; property: "shadowOpacity"; from: 0; to: spreadMaths.shadowOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
278− UbuntuNumberAnimation { target: tileInfo; property: "opacity"; from: 0; to: spreadMaths.tileInfoOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
279− }
280− PropertyAction { target: spreadSelectArea; property: "enabled" }
281− }
282− }
283− ]
284−
285− MouseArea {
286− id: tileInfo
287− objectName: "tileInfo"
288− anchors {
289− left: parent.left
290− top: clippedSpreadDelegate.bottom
291− topMargin: ((spreadMaths.sceneHeight - spreadDelegate.y) - clippedSpreadDelegate.height) * 0.2
292− }
293− property int nextItemX: spreadRepeater.count > index + 1 ? spreadRepeater.itemAt(index + 1).x : spreadDelegate.x + units.gu(30)
294− width: Math.min(units.gu(30), nextItemX - spreadDelegate.x)
295− height: titleInfoColumn.height
296− visible: false
297− hoverEnabled: true
298−
299− onContainsMouseChanged: {
300− if (containsMouse) {
301− spreadRepeater.highlightedIndex = index
302− }
303− }
304−
305− onClicked: {
306− root.state = ""
307− }
308−
309− ColumnLayout {
310− id: titleInfoColumn
311− anchors { left: parent.left; top: parent.top; right: parent.right }
312− spacing: units.gu(1)
313−
314− UbuntuShapeForItem {
315− Layout.preferredHeight: Math.min(units.gu(6), root.height * .05)
316− Layout.preferredWidth: height * 8 / 7.6
317− image: Image {
318− anchors.fill: parent
319− source: model.application.icon
320− Rectangle {
321− anchors.fill: parent
322− color: "black"
323− opacity: clippedSpreadDelegate.highlightShown ? 0 : .1
324− Behavior on opacity {
325− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
326− }
327− }
328− }
329− }
330− Label {
331− Layout.fillWidth: true
332− Layout.preferredHeight: units.gu(6)
333− text: model.application ? model.application.name : spreadDelegate.windowTitle
334− wrapMode: Text.WordWrap
335− elide: Text.ElideRight
336− maximumLineCount: 2
337− }
338− }
339− }
340−
341− Image {
342− id: closeImage
343− anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset + units.gu(2) }
344− source: "graphics/window-close.svg"
345− readonly property var mousePos: hoverMouseArea.mapToItem(spreadDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
346− visible: index == spreadRepeater.highlightedIndex
347− && mousePos.y < (clippedSpreadDelegate.height / 3)
348− && mousePos.y > -units.gu(4)
349− && mousePos.x > -units.gu(4)
350− && mousePos.x < (clippedSpreadDelegate.width * 2 / 3)
351− height: units.gu(1.5)
352− width: height
353− sourceSize.width: width
354− sourceSize.height: height
355−
356− MouseArea {
357− id: closeMouseArea
358− objectName: "closeMouseArea"
359− anchors.fill: closeImage
360− anchors.margins: -units.gu(2)
361− onClicked: {
362− spreadRepeater.closingIndex = index;
363− model.surface.close();
364− }
365− }
366− }
367− }
368− }
369− }
370−
371−
372− MouseArea {
373− id: hoverMouseArea
374− objectName: "hoverMouseArea"
375− anchors.fill: spreadContainer
376− propagateComposedEvents: true
377− hoverEnabled: true
378− enabled: false
379− visible: enabled
380−
381− property int scrollAreaWidth: root.width / 3
382− property bool progressiveScrollingEnabled: false
383−
384− onMouseXChanged: {
385− mouse.accepted = false
386−
387− if (hoverMouseArea.pressed) {
388− return;
389− }
390−
391− // Find the hovered item and mark it active
392− var mapped = mapToItem(spreadContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
393− var itemUnder = spreadContainer.childAt(mapped.x, mapped.y)
394− if (itemUnder) {
395− mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
396− var delegateChild = itemUnder.childAt(mapped.x, mapped.y)
397− if (delegateChild && (delegateChild.objectName === "clippedSpreadDelegate" || delegateChild.objectName === "tileInfo")) {
398− spreadRepeater.highlightedIndex = spreadRepeater.indexOf(itemUnder)
399− }
400− }
401−
402− if (spreadFlickable.contentWidth > spreadFlickable.minContentWidth) {
403− var margins = spreadFlickable.width * 0.05;
404−
405− if (!progressiveScrollingEnabled && mouseX < spreadFlickable.width - scrollAreaWidth) {
406− progressiveScrollingEnabled = true
407− }
408−
409− // do we need to scroll?
410− if (mouseX < scrollAreaWidth + margins) {
411− var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins));
412− var contentX = (1 - progress) * (spreadFlickable.contentWidth - spreadFlickable.width)
413− spreadFlickable.contentX = Math.max(0, Math.min(spreadFlickable.contentX, contentX))
414− }
415− if (mouseX > spreadFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) {
416− var progress = Math.min(1, (mouseX - (spreadFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins))
417− var contentX = progress * (spreadFlickable.contentWidth - spreadFlickable.width)
418− spreadFlickable.contentX = Math.min(spreadFlickable.contentWidth - spreadFlickable.width, Math.max(spreadFlickable.contentX, contentX))
419− }
420− }
421− }
422− onPressed: mouse.accepted = false
423− }
424−
425− FloatingFlickable {
426− id: spreadFlickable
427− objectName: "spreadFlickable"
428− anchors.fill: parent
429− property int minContentWidth: 6 * Math.min(height / 4, width / 5)
430− contentWidth: Math.max(6, topLevelSurfaceList.count) * Math.min(height / 4, width / 5)
431− enabled: false
432−
433− function snapTo(contentX) {
434− snapAnimation.stop();
435− snapAnimation.to = contentX
436− snapAnimation.start();
437− }
438−
439− UbuntuNumberAnimation {
440− id: snapAnimation
441− target: spreadFlickable
442− property: "contentX"
443− }
444− }
445−
446− Item {
447− id: workspaceSelector
448− anchors {
449− left: parent.left
450− top: parent.top
451− right: parent.right
452− topMargin: units.gu(3.5)
453− }
454− height: root.height * 0.25
455− visible: false
456−
457− RowLayout {
458− anchors.fill: parent
459− spacing: units.gu(1)
460− Item { Layout.fillWidth: true }
461− Repeater {
462− model: 1 // TODO: will be a workspacemodel in the future
463− Item {
464− Layout.fillHeight: true
465− Layout.preferredWidth: ((height - units.gu(6)) * root.width / root.height)
466− Image {
467− source: root.background
468− anchors {
469− left: parent.left
470− right: parent.right
471− verticalCenter: parent.verticalCenter
472− }
473− height: parent.height * 0.75
474−
475− ShaderEffect {
476− anchors.fill: parent
477−
478− property var source: ShaderEffectSource {
479− id: shaderEffectSource
480− sourceItem: root.workspace
481− }
482−
483− fragmentShader: "
484− varying highp vec2 qt_TexCoord0;
485− uniform sampler2D source;
486− void main(void)
487− {
488− highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
489− gl_FragColor = sourceColor;
490− }"
491− }
492− }
493−
494− // TODO: This is the bar for the currently selected workspace
495− // Enable this once the workspace stuff is implemented
496− // Rectangle {
497− // anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
498− // height: units.dp(2)
499− // color: theme.palette.normal.focus
500− // visible: index == 0 // TODO: should be active workspace index
501− // }
502− }
503−
504− }
505− // TODO: This is the "new workspace" button. Enable this once workspaces are implemented
506− // Item {
507− // Layout.fillHeight: true
508− // Layout.preferredWidth: ((height - units.gu(6)) * root.width / root.height)
509− // Rectangle {
510− // anchors {
511− // left: parent.left
512− // right: parent.right
513− // verticalCenter: parent.verticalCenter
514− // }
515− // height: parent.height * 0.75
516− // color: "#22ffffff"
517−
518− // Label {
519− // anchors.centerIn: parent
520− // font.pixelSize: parent.height / 2
521− // text: "+"
522− // }
523− // }
524− // }
525− Item { Layout.fillWidth: true }
526− }
527− }
528−
529− Label {
530− id: currentSelectedLabel
531− anchors { bottom: parent.bottom; bottomMargin: root.height * 0.625; horizontalCenter: parent.horizontalCenter }
532− text: spreadRepeater.highlightedIndex >= 0 ? spreadRepeater.itemAt(spreadRepeater.highlightedIndex).windowTitle: ""
533− visible: false
534− fontSize: "large"
535− }
536−
537− states: [
538− State {
539− name: "altTab"; when: root.altTabPressed
540− PropertyChanges { target: blurLayer; saturation: 0.8; blurRadius: 60; visible: true }
541− PropertyChanges { target: workspaceSelector; visible: true }
542− PropertyChanges { target: spreadContainer; visible: true }
543− PropertyChanges { target: spreadFlickable; enabled: spreadFlickable.contentWidth > spreadFlickable.minContentWidth }
544− PropertyChanges { target: currentSelectedLabel; visible: true }
545− PropertyChanges { target: spreadBackground; visible: true }
546− PropertyChanges { target: hoverMouseArea; enabled: true }
547− }
548− ]
549− transitions: [
550− Transition {
551− from: "*"
552− to: "altTab"
553− SequentialAnimation {
554− PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: Math.min(topLevelSurfaceList.count - 1, 1) }
555− PauseAnimation { duration: spreadContainer.animateIn ? 0 : 140 }
556− PropertyAction { target: workspaceSelector; property: "visible" }
557− PropertyAction { target: spreadContainer; property: "visible" }
558− ParallelAnimation {
559− UbuntuNumberAnimation { target: blurLayer; properties: "saturation,blurRadius"; duration: UbuntuAnimation.SnapDuration }
560− PropertyAction { target: spreadFlickable; property: "visible" }
561− PropertyAction { targets: [currentSelectedLabel,spreadBackground]; property: "visible" }
562− PropertyAction { target: spreadFlickable; property: "contentX"; value: 0 }
563− }
564− PropertyAction { target: hoverMouseArea; properties: "enabled,progressiveScrollingEnabled"; value: false }
565− }
566− },
567− Transition {
568− from: "*"
569− to: "*"
570− PropertyAnimation { property: "opacity" }
571− ScriptAction { script: { root.focusSelected() } }
572− PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: -1 }
573− PropertyAction { target: spreadContainer; property: "animateIn"; value: false }
574− }
575− ]
576−}
qml/Stage/DesktopSpreadDelegate.qmldeleted−126
@@ -1,126 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17− */
18−
19−import QtQuick 2.4
20−import Ubuntu.Components 1.3
21−import Unity.Application 0.1
22−
23−Item {
24− id: root
25−
26− property alias window: applicationWindow
27− property alias application: applicationWindow.application
28− property alias surface: applicationWindow.surface
29−
30− property bool highlightShown: false
31− property real shadowOpacity: 1
32−
33− property int windowWidth: surface ? surface.size.width : 0
34− property int windowHeight: surface ? surface.size.height : 0
35−
36− state: "normal"
37− states: [
38− State {
39− name: "normal"
40− PropertyChanges {
41− target: root
42− width: windowWidth
43− height: windowHeight
44− }
45− },
46− State {
47− name: "transformed"
48− PropertyChanges {
49− target: applicationWindow
50− itemScale: Math.max(root.width / root.windowWidth, root.height / root.windowHeight)
51− interactive: false
52− }
53− PropertyChanges {
54− target: clipper
55− clip: true
56− }
57− }
58− ]
59−
60− scale: highlightShown ? 1.025 : 1
61− Behavior on scale {
62− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
63− }
64−
65− BorderImage {
66− anchors {
67− fill: root
68− margins: -units.gu(2)
69− }
70− source: "graphics/dropshadow2gu.sci"
71− opacity: root.shadowOpacity * .3
72− }
73−
74− Rectangle {
75− id: selectionHighlight
76− anchors.fill: parent
77− anchors.margins: -units.gu(1)
78− color: "white"
79− opacity: highlightShown ? 0.55 : 0
80− antialiasing: true
81− }
82−
83− Rectangle {
84− anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
85− height: units.dp(2)
86− color: theme.palette.normal.focus
87− visible: root.highlightShown
88− antialiasing: true
89− }
90−
91− Item {
92− id: clipper
93− anchors.fill: parent
94−
95− ApplicationWindow {
96− id: applicationWindow
97− objectName: application ? "appWindow_" + application.appId : "appWindow_null"
98− anchors.top: parent.top
99− anchors.topMargin: 0
100− anchors.left: parent.left
101− width: root.windowWidth
102− height: root.windowHeight
103− interactive: false
104− resizeSurface: false
105− focus: false
106−
107− property real itemScale: 1
108− transform: [
109− Scale {
110− origin.x: 0; origin.y: 0
111− xScale: applicationWindow.itemScale
112− yScale: applicationWindow.itemScale
113− }
114− ]
115− }
116− }
117−
118− Rectangle {
119− anchors.fill: parent
120− color: "black"
121− opacity: root.highlightShown ? 0 : .1
122− Behavior on opacity {
123− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
124− }
125− }
126−}
qml/Stage/PhoneStage.qmldeleted−789
@@ -1,789 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Ubuntu.Gestures 0.1
20−import Unity.Application 0.1
21−import Unity.Session 0.1
22−import Utils 0.1
23−import Powerd 0.1
24−import "../Components"
25−
26−AbstractStage {
27− id: root
28−
29− property bool focusFirstApp: true // If false, focused app will appear on right edge like other apps
30− property bool altTabEnabled: true
31− property real startScale: 1.1
32− property real endScale: 0.7
33−
34− paintBackground: spreadView.shiftedContentX !== 0
35−
36− onBeingResizedChanged: {
37− if (beingResized) {
38− // Brace yourselves for impact!
39− priv.reset();
40− }
41− }
42− onSpreadEnabledChanged: {
43− if (!spreadEnabled) {
44− priv.reset();
45− }
46− }
47−
48− onAltTabPressedChanged: {
49− if (!spreadEnabled || !altTabEnabled) {
50− return;
51− }
52− if (altTabPressed) {
53− spreadView.snapToSpread();
54− priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
55− } else {
56− spreadView.snapTo(priv.highlightIndex)
57− }
58− }
59−
60− FocusScope {
61− focus: root.altTabPressed
62−
63− Keys.onPressed: {
64− switch (event.key) {
65− case Qt.Key_Tab:
66− priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
67− break;
68− case Qt.Key_Backtab:
69− priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
70− break;
71− }
72− }
73− }
74−
75− // Functions to be called from outside
76− function updateFocusedAppOrientation() {
77− if (spreadRepeater.count > 0) {
78− spreadRepeater.itemAt(0).matchShellOrientation();
79− }
80−
81− for (var i = 1; i < spreadRepeater.count; ++i) {
82−
83− var spreadDelegate = spreadRepeater.itemAt(i);
84−
85− var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle;
86− if (delta < 0) { delta += 360; }
87− delta = delta % 360;
88−
89− var supportedOrientations = spreadDelegate.application.supportedOrientations;
90− if (supportedOrientations === Qt.PrimaryOrientation) {
91− supportedOrientations = root.orientations.primary;
92− }
93−
94− if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) {
95− spreadDelegate.matchShellOrientation();
96− }
97− }
98− }
99− function updateFocusedAppOrientationAnimated() {
100− if (spreadRepeater.count > 0) {
101− spreadRepeater.itemAt(0).animateToShellOrientation();
102− }
103− }
104−
105− function pushRightEdge(amount) {
106− if (spreadView.contentX == -spreadView.shift) {
107− edgeBarrier.push(amount);
108− }
109− }
110−
111− function closeFocusedDelegate() {
112− if (priv.focusedAppDelegate && priv.focusedAppDelegate.closeable) {
113− priv.focusedAppDelegate.closed();
114− }
115− }
116−
117− mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null
118−
119− orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled
120− && !priv.focusedAppDelegateIsDislocated
121− && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running)
122− && spreadView.phase === 0
123−
124− supportedOrientations: mainApp ? mainApp.supportedOrientations
125− : (Qt.PortraitOrientation | Qt.LandscapeOrientation
126− | Qt.InvertedPortraitOrientation | Qt.InvertedLandscapeOrientation)
127−
128− // How far left the stage has been dragged, used externally by tutorial code
129− dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0
130−
131− readonly property alias dragging: spreadDragArea.dragging
132−
133− signal opened()
134−
135− function select(appId) {
136− spreadView.snapTo(priv.indexOf(appId));
137− }
138−
139− // <FIXME-contentX> See rationale in the next comment with this tag
140− onWidthChanged: {
141− if (!root.beingResized) {
142− // we're being resized without a warning (ie, the corresponding property wasn't set
143− root.beingResized = true;
144− beingResizedTimer.start();
145− }
146− }
147− Timer {
148− id: beingResizedTimer
149− interval: 100
150− onTriggered: { root.beingResized = false; }
151− }
152−
153− QtObject {
154− id: priv
155−
156− property bool focusedAppOrientationChangesEnabled: false
157− readonly property int firstSpreadIndex: root.focusFirstApp ? 1 : 0
158− property var focusedAppDelegate
159− // NB! This may differ from applicationManager.focusedApplicationId if focusedAppDelegate
160− // contains a screenshot instead of a surface.
161− property string focusedAppId: focusedAppDelegate ? focusedAppDelegate.application.appId : ""
162−
163− property real oldInverseProgress: 0
164− property bool animateX: false
165− property int highlightIndex: 0
166−
167− property bool focusedAppDelegateIsDislocated: focusedAppDelegate ?
168− (focusedAppDelegate.x !== 0 || focusedAppDelegate.xBehavior.running)
169− : false
170−
171− function indexOf(appId) {
172− for (var i = 0; i < spreadRepeater.count; i++) {
173− if (spreadRepeater.itemAt(i).application.appId == appId) {
174− return i;
175− }
176− }
177− return -1;
178− }
179−
180− // Is more stable than "spreadView.shiftedContentX === 0" as it filters out noise caused by
181− // Flickable.contentX changing due to resizes.
182− property bool fullyShowingFocusedApp: true
183−
184− function reset() {
185− // The app that's about to go to foreground has to be focused, otherwise
186− // it would leave us in an inconsistent state.
187− if (!MirFocusController.focusedSurface && spreadRepeater.count > 0) {
188− spreadRepeater.itemAt(0).focus = true;
189− }
190−
191− spreadView.selectedIndex = -1;
192− spreadView.phase = 0;
193− spreadView.contentX = -spreadView.shift;
194− }
195−
196− onHighlightIndexChanged: {
197− spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
198− }
199− }
200− Timer {
201− id: fullyShowingFocusedAppUpdateTimer
202− interval: 100
203− onTriggered: {
204− priv.fullyShowingFocusedApp = spreadView.shiftedContentX === 0;
205− }
206− }
207−
208− Instantiator {
209− model: root.applicationManager
210− delegate: QtObject {
211− property var stateBinding: Binding {
212− target: model.application
213− property: "requestedState"
214− value: (!root.suspended && model.application && priv.focusedAppId === model.application.appId)
215− ? ApplicationInfoInterface.RequestedRunning
216− : ApplicationInfoInterface.RequestedSuspended
217− }
218−
219− property var lifecycleBinding: Binding {
220− target: model.application
221− property: "exemptFromLifecycle"
222− value: model.application
223− ? (!model.application.isTouchApp || isExemptFromLifecycle(model.application.appId))
224− : false
225− }
226− }
227− }
228−
229− Binding {
230− target: MirFocusController
231− property: "focusedSurface"
232− value: priv.focusedAppDelegate ? priv.focusedAppDelegate.focusedSurface : null
233− when: root.parent && !spreadRepeater.startingUp
234− }
235−
236− Flickable {
237− id: spreadView
238− objectName: "spreadView"
239− anchors.fill: parent
240− interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0
241− contentWidth: spreadRow.width - shift
242− contentX: -shift
243−
244− // This indicates when the spreadView is active. That means, all the animations
245− // are activated and tiles need to line up for the spread.
246− readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging || !root.focusFirstApp
247−
248− // The flickable needs to fill the screen in order to get touch events all over.
249− // However, we don't want to the user to be able to scroll back all the way. For
250− // that, the beginning of the gesture starts with a negative value for contentX
251− // so the flickable wants to pull it into the view already. "shift" tunes the
252− // distance where to "lock" the content.
253− readonly property real shift: width / 2
254− readonly property real shiftedContentX: contentX + shift
255−
256− property int tileDistance: width / 4
257−
258− // Those markers mark the various positions in the spread (ratio to screen width from right to left):
259− // 0 - 1: following finger, snap back to the beginning on release
260− property real positionMarker1: 0.2
261− // 1 - 2: curved snapping movement, snap to app 1 on release
262− property real positionMarker2: 0.3
263− // 2 - 3: movement follows finger, snaps back to app 1 on release
264− property real positionMarker3: 0.35
265− // passing 3, we detach movement from the finger and snap to 4
266− property real positionMarker4: 0.9
267−
268− // This is where the first app snaps to when bringing it in from the right edge.
269− property real snapPosition: 0.7
270−
271− // Phase of the animation:
272− // 0: Starting from right edge, a new app (index 1) comes in from the right
273− // 1: The app has reached the first snap position.
274− // 2: The list is dragged further and snaps into the spread view when entering phase 2
275− property int phase: 0
276−
277− property int selectedIndex: -1
278− property int draggedDelegateCount: 0
279− property int closingIndex: -1
280−
281− // <FIXME-contentX> Workaround Flickable's behavior of bringing contentX back between valid boundaries
282− // when resized. The proper way to fix this is refactoring PhoneStage so that it doesn't
283− // rely on having Flickable.contentX keeping an out-of-bounds value when it's set programatically
284− // (as opposed to having contentX reaching an out-of-bounds value through dragging, which will trigger
285− // the Flickable.boundsBehavior upon release).
286− onContentXChanged: {
287− if (!undoContentXReset()) {
288− forceItToRemainStillIfBeingResized();
289− }
290− }
291− onShiftChanged: { forceItToRemainStillIfBeingResized(); }
292− function forceItToRemainStillIfBeingResized() {
293− if (root.beingResized && contentX != -spreadView.shift) {
294− contentX = -spreadView.shift;
295− }
296− }
297− function undoContentXReset() {
298− if (contentWidth <= 0) {
299− contentWidthOnLastContentXChange = contentWidth;
300− lastContentX = contentX;
301− return false;
302− }
303−
304− if (contentWidth !== contentWidthOnLastContentXChange
305− && lastContentX === -shift && contentX === 0) {
306− // Flickable is resetting contentX because contentWidth has changed. Undo it.
307− contentX = -shift;
308− return true;
309− }
310−
311− contentWidthOnLastContentXChange = contentWidth;
312− lastContentX = contentX;
313− return false;
314− }
315− property real contentWidthOnLastContentXChange: -1
316− property real lastContentX: 0
317− // </FIXME-contentX>
318−
319− Behavior on contentX {
320− enabled: root.altTabPressed
321− UbuntuNumberAnimation {}
322− }
323−
324− onShiftedContentXChanged: {
325− if (root.beingResized) {
326− // Flickabe.contentX wiggles during resizes. Don't react to it.
327− return;
328− }
329−
330− switch (phase) {
331− case 0:
332− // the "spreadEnabled" part is because when code does "phase = 0; contentX = -shift" to
333− // dismiss the spread because spreadEnabled went to false, for some reason, during tests,
334− // Flickable might jump in and change contentX value back, causing the code below to do
335− // "phase = 1" which will make the spread stay.
336− // It sucks that we have no control whatsoever over whether or when Flickable animates its
337− // contentX.
338− if (root.spreadEnabled && shiftedContentX > width * positionMarker2) {
339− phase = 1;
340− }
341− break;
342− case 1:
343− if (shiftedContentX < width * positionMarker2) {
344− phase = 0;
345− } else if (shiftedContentX >= width * positionMarker4 && !spreadDragArea.dragging) {
346− phase = 2;
347− }
348− break;
349− }
350− fullyShowingFocusedAppUpdateTimer.restart();
351− }
352−
353− function snap() {
354− if (shiftedContentX < positionMarker1 * width) {
355− snapAnimation.targetContentX = -shift;
356− snapAnimation.start();
357− } else if (shiftedContentX < positionMarker2 * width) {
358− snapTo(1);
359− } else if (shiftedContentX < positionMarker3 * width) {
360− snapTo(1);
361− } else if (phase < 2){
362− snapToSpread();
363− root.opened();
364− }
365− }
366−
367− function snapToSpread() {
368− // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
369− snapAnimation.targetContentX = (root.width * spreadView.positionMarker4) + 1 - spreadView.shift;
370− snapAnimation.start();
371− }
372−
373− function snapTo(index) {
374− if (!root.altTabEnabled) {
375− // Reset to start instead
376− snapAnimation.targetContentX = -shift;
377− snapAnimation.start();
378− return;
379− }
380− if (topLevelSurfaceList.count <= index) {
381− // In case we're trying to snap to some non existing app, lets snap back to the first one
382− index = 0;
383− }
384− spreadView.selectedIndex = index;
385− // If we're not in full spread mode yet, always unwind to start pos
386− // otherwise unwind up to progress 0 of the selected index
387− if (spreadView.phase < 2) {
388− snapAnimation.targetContentX = -shift;
389− } else {
390− snapAnimation.targetContentX = -shift + index * spreadView.tileDistance;
391− }
392− snapAnimation.start();
393− }
394−
395− // In case the applicationManager already holds an app when starting up we're missing animations
396− // Make sure we end up in the same state
397− Component.onCompleted: {
398− spreadView.contentX = -spreadView.shift
399− priv.animateX = true;
400− snapAnimation.complete();
401− }
402−
403− SequentialAnimation {
404− id: snapAnimation
405− property int targetContentX: -spreadView.shift
406−
407− UbuntuNumberAnimation {
408− target: spreadView
409− property: "contentX"
410− to: snapAnimation.targetContentX
411− duration: UbuntuAnimation.FastDuration
412− }
413−
414− ScriptAction {
415− script: {
416− if (spreadView.selectedIndex >= 0) {
417− var delegate = spreadRepeater.itemAt(spreadView.selectedIndex)
418− delegate.focus = true;
419−
420− spreadView.selectedIndex = -1;
421− spreadView.phase = 0;
422− spreadView.contentX = -spreadView.shift;
423− }
424− }
425− }
426− }
427−
428− MouseArea {
429− id: spreadRow
430− // This width controls how much the spread can be flicked left/right. It's composed of:
431− // tileDistance * app count (with a minimum of 3 apps, in order to also allow moving 1 and 2 apps a bit)
432− // + some constant value (still scales with the screen width) which looks good and somewhat fills the screen
433− width: Math.max(3, topLevelSurfaceList.count) * spreadView.tileDistance + (spreadView.width - spreadView.tileDistance) * 1.5
434− height: parent.height
435− Behavior on width {
436− enabled: spreadView.closingIndex >= 0
437− UbuntuNumberAnimation {}
438− }
439− onWidthChanged: {
440− if (spreadView.closingIndex >= 0) {
441− spreadView.contentX = Math.min(spreadView.contentX, width - spreadView.width - spreadView.shift);
442− }
443− }
444−
445− x: spreadView.contentX
446−
447− onClicked: {
448− if (root.altTabEnabled) {
449− spreadView.snapTo(0);
450− }
451− }
452−
453− TopLevelSurfaceRepeater {
454− id: spreadRepeater
455− objectName: "spreadRepeater"
456− model: topLevelSurfaceList
457−
458− onItemRemoved: {
459− // Unless we're closing the app ourselves,
460− // lets make sure the spread doesn't mess up by the changing app list.
461− if (spreadView.closingIndex == -1) {
462− spreadView.phase = 0;
463− spreadView.contentX = -spreadView.shift;
464− }
465− focusTopMostApp();
466− }
467− function focusTopMostApp() {
468− if (spreadRepeater.count > 0) {
469− var topmostDelegate = spreadRepeater.itemAt(0);
470− topmostDelegate.focus = true;
471− }
472− }
473−
474− delegate: TransformedSpreadDelegate {
475− id: appDelegate
476− objectName: "spreadDelegate_" + model.id
477− startAngle: 45
478− endAngle: 5
479− startScale: root.startScale
480− endScale: root.endScale
481− startDistance: spreadView.tileDistance
482− endDistance: units.gu(.5)
483− width: spreadView.width
484− height: spreadView.height
485− selected: spreadView.selectedIndex == index
486− otherSelected: spreadView.selectedIndex >= 0 && !selected
487− interactive: !spreadView.interactive && spreadView.phase === 0
488− && priv.fullyShowingFocusedApp && root.interactive && focus
489− swipeToCloseEnabled: spreadView.interactive && root.interactive && !snapAnimation.running
490− maximizedAppTopMargin: root.maximizedAppTopMargin
491− dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
492− focusFirstApp: root.focusFirstApp
493− highlightShown: root.altTabPressed && index === priv.highlightIndex
494−
495− Component.onCompleted: {
496− // NB: We're differentiating if this delegate was created in response to a new entry in the model
497− // or if the Repeater is just populating itself with delegates to match the model it received.
498− if (!spreadRepeater.startingUp) {
499− // a top level window is always the focused one when it first appears, unfocusing
500− // any preexisting one
501− //
502− // new items are appended and must be manually brought to front.
503− // that's how it *must* be in order to get the animation for new
504− // surfaces working
505− claimFocus();
506− }
507− }
508−
509− onFocusChanged: {
510− if (focus && !spreadRepeater.startingUp) {
511− priv.focusedAppDelegate = appDelegate;
512− // If we're orphan (!parent) it means this stage is no longer the current one
513− // and will be deleted shortly. So we should no longer have a say over the model
514− if (root.parent) {
515− topLevelSurfaceList.raiseId(model.id);
516− }
517− }
518− }
519− function claimFocus() {
520− if (spreadView.phase > 0) {
521− spreadView.snapTo(model.index);
522− } else {
523− appDelegate.focus = true;
524− }
525− }
526− Connections {
527− target: model.surface
528− onFocusRequested: claimFocus()
529− }
530− Connections {
531− target: model.application
532− onFocusRequested: {
533− if (!model.surface) {
534− // when an app has no surfaces, we assume there's only one entry representing it:
535− // this delegate.
536− claimFocus();
537− } else {
538− // if the application has surfaces, focus request should be at surface-level.
539− }
540− }
541− }
542−
543− z: !spreadView.active ? -1 : behavioredIndex
544−
545− x: {
546− // focused app is always positioned at 0 except when following left edge drag
547− if (isFocused) {
548− if (root.inverseProgress > 0 && spreadView.phase === 0) {
549− return root.inverseProgress;
550− }
551− return 0;
552− }
553− if (!spreadView.active && !spreadDragArea.dragging) {
554− return 0;
555− }
556−
557− // Otherwise line up for the spread
558− return spreadView.width + spreadIndex * spreadView.tileDistance;
559− }
560−
561− application: model.application
562− surface: model.surface
563− closeable: true
564−
565− property real behavioredIndex: index
566− Behavior on behavioredIndex {
567− enabled: spreadView.closingIndex >= 0
568− UbuntuNumberAnimation {
569− id: appXAnimation
570− onRunningChanged: {
571− if (!running) {
572− spreadView.closingIndex = -1;
573− }
574− }
575− }
576− }
577−
578− property var xBehavior: xBehavior
579− Behavior on x {
580− enabled: root.spreadEnabled &&
581− !spreadView.active &&
582− !snapAnimation.running &&
583− !spreadDragArea.pressed &&
584− priv.animateX &&
585− !root.beingResized
586− UbuntuNumberAnimation {
587− id: xBehavior
588− duration: UbuntuAnimation.BriskDuration
589− }
590− }
591−
592− // Each tile has a different progress value running from 0 to 1.
593− // 0: means the tile is at the right edge.
594− // 1: means the tile has finished the main animation towards the left edge.
595− // >1: after the main animation has finished, tiles will continue to move very slowly to the left
596− progress: {
597− var tileProgress = (spreadView.shiftedContentX - behavioredIndex * spreadView.tileDistance) / spreadView.width;
598− // Tile 1 needs to move directly from the beginning...
599− if (root.focusFirstApp && behavioredIndex == 1 && spreadView.phase < 2) {
600− tileProgress += spreadView.tileDistance / spreadView.width;
601− }
602− // Limiting progress to ~0 and 1.7 to avoid binding calculations when tiles are not
603− // visible.
604− // < 0 : The tile is outside the screen on the right
605− // > 1.7: The tile is *very* close to the left edge and covered by other tiles now.
606− // Using 0.0001 to differentiate when a tile should still be visible (==0)
607− // or we can hide it (< 0)
608− tileProgress = Math.max(-0.0001, Math.min(1.7, tileProgress));
609− return tileProgress;
610− }
611−
612− // This mostly is the same as progress, just adds the snapping to phase 1 for tiles 0 and 1
613− animatedProgress: {
614− if (spreadView.phase == 0 && index <= priv.firstSpreadIndex) {
615− if (progress < spreadView.positionMarker1) {
616− return progress;
617− } else if (progress < spreadView.positionMarker1 + 0.05){
618− // p : 0.05 = x : pm2
619− return spreadView.positionMarker1 + (progress - spreadView.positionMarker1) * (spreadView.positionMarker2 - spreadView.positionMarker1) / 0.05
620− } else {
621− return spreadView.positionMarker2;
622− }
623− }
624− return progress;
625− }
626−
627− // Hide tile when progress is such that it will be off screen.
628− property bool occluded: {
629− if (spreadView.active && (progress >= 0 && progress < 1.7)) return false;
630− else if (!spreadView.active && isFocused) return false;
631− else if (xBehavior.running) return false;
632− else if (z <= 1 && priv.focusedAppDelegateIsDislocated) return false;
633− return true;
634− }
635−
636− visible: Powerd.status == Powerd.On &&
637− !greeter.fullyShown &&
638− !occluded
639−
640− shellOrientationAngle: root.shellOrientationAngle
641− shellOrientation: root.shellOrientation
642− orientations: root.orientations
643−
644− onClicked: {
645− if (root.altTabEnabled && spreadView.phase == 2) {
646− spreadView.snapTo(index);
647− }
648− }
649−
650− onDraggedChanged: {
651− if (dragged) {
652− spreadView.draggedDelegateCount++;
653− } else {
654− spreadView.draggedDelegateCount--;
655− }
656− }
657−
658− onClosed: {
659− spreadView.closingIndex = index;
660− if (appDelegate.surface) {
661− appDelegate.surface.close();
662− } else if (appDelegate.application) {
663− root.applicationManager.stopApplication(appDelegate.application.appId);
664− } else {
665− // should never happen
666− console.warn("Can't close topLevelSurfaceList entry as it has neither"
667− + " a surface nor an application");
668− }
669− }
670−
671− Binding {
672− target: root
673− when: index == 0
674− property: "mainAppWindowOrientationAngle"
675− value: appWindowOrientationAngle
676− }
677− Binding {
678− target: priv
679− when: index == 0
680− property: "focusedAppOrientationChangesEnabled"
681− value: orientationChangesEnabled
682− }
683−
684− StagedFullscreenPolicy {
685− id: fullscreenPolicy
686− surface: model.surface
687− }
688−
689− Connections {
690− target: root
691− onStageAboutToBeUnloaded: fullscreenPolicy.active = false
692− }
693− }
694− } // Repeater {
695− }
696− }
697−
698− //eat touch events during the right edge gesture
699− MouseArea {
700− objectName: "eventEaterArea"
701− anchors.fill: parent
702− enabled: spreadDragArea.dragging
703− }
704−
705− SwipeArea {
706− id: spreadDragArea
707− objectName: "spreadDragArea"
708− direction: Direction.Leftwards
709− enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
710−
711− anchors { top: parent.top; right: parent.right; bottom: parent.bottom; }
712− width: root.dragAreaWidth
713−
714− property var gesturePoints: new Array()
715−
716− onTouchPositionChanged: {
717− if (dragging) {
718− // Gesture recognized. Let's move the spreadView with the finger
719− var dragX = Math.min(touchPosition.x + width, width); // Prevent dragging rightwards
720− dragX = -dragX + spreadDragArea.width - spreadView.shift;
721− // Don't allow dragging further than the animation crossing with phase2's animation
722− var maxMovement = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
723−
724− spreadView.contentX = Math.min(dragX, maxMovement);
725− } else {
726− // Initial touch. Let's reset the spreadView to the starting position.
727− spreadView.phase = 0;
728− spreadView.contentX = -spreadView.shift;
729− }
730−
731− gesturePoints.push(touchPosition.x);
732− }
733−
734− onDraggingChanged: {
735− if (dragging) {
736− // A potential edge-drag gesture has started. Start recording it
737− gesturePoints = [];
738− } else {
739− // Ok. The user released. Find out if it was a one-way movement.
740− var oneWayFlick = true;
741− var smallestX = spreadDragArea.width;
742− for (var i = 0; i < gesturePoints.length; i++) {
743− if (gesturePoints[i] >= smallestX) {
744− oneWayFlick = false;
745− break;
746− }
747− smallestX = gesturePoints[i];
748− }
749− gesturePoints = [];
750−
751− if (oneWayFlick && spreadView.shiftedContentX > units.gu(2) &&
752− spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
753− // If it was a short one-way movement, do the Alt+Tab switch
754− // no matter if we didn't cross positionMarker1 yet.
755− spreadView.snapTo(1);
756− } else if (!dragging) {
757− // otherwise snap to the closest snap position we can find
758− // (might be back to start, to app 1 or to spread)
759− spreadView.snap();
760− }
761− }
762− }
763− }
764−
765− EdgeBarrier {
766− id: edgeBarrier
767−
768− // NB: it does its own positioning according to the specified edge
769− edge: Qt.RightEdge
770−
771− onPassed: {
772− spreadView.snapToSpread();
773− }
774− material: Component {
775− Item {
776− Rectangle {
777− width: parent.height
778− height: parent.width
779− rotation: 90
780− anchors.centerIn: parent
781− gradient: Gradient {
782− GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
783− GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
784− }
785− }
786− }
787− }
788− }
789−}
qml/Stage/SpreadDelegate.qmldeleted−424
@@ -1,424 +0,0 @@
1−/*
2− * Copyright 2014-2016 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17− * Daniel d'Andrada <daniel.dandrada@canonical.com>
18− */
19−
20−import QtQuick 2.4
21−import QtQuick.Window 2.2
22−import Ubuntu.Components 1.3
23−import "../Components"
24−
25−FocusScope {
26− id: root
27−
28− // to be read from outside
29− readonly property bool dragged: dragArea.moving
30− signal clicked()
31− signal closed()
32− readonly property alias appWindowOrientationAngle: appWindowWithShadow.orientationAngle
33− readonly property alias appWindowRotation: appWindowWithShadow.rotation
34− readonly property alias orientationChangesEnabled: appWindow.orientationChangesEnabled
35− property int supportedOrientations: application ? application.supportedOrientations :
36− Qt.PortraitOrientation
37− | Qt.LandscapeOrientation
38− | Qt.InvertedPortraitOrientation
39− | Qt.InvertedLandscapeOrientation
40− readonly property alias focusedSurface: appWindow.focusedSurface
41−
42− // to be set from outside
43− property bool interactive: true
44− property bool dropShadow: true
45− property real maximizedAppTopMargin
46− property alias swipeToCloseEnabled: dragArea.enabled
47− property bool closeable
48− property alias application: appWindow.application
49− property alias surface: appWindow.surface
50− property int shellOrientationAngle
51− property int shellOrientation
52− property QtObject orientations
53− property bool highlightShown: false
54−
55− // overrideable from outside
56− property alias fullscreen: appWindow.fullscreen
57−
58− function matchShellOrientation() {
59− if (!root.application)
60− return;
61− appWindowWithShadow.orientationAngle = root.shellOrientationAngle;
62− }
63−
64− function animateToShellOrientation() {
65− if (!root.application)
66− return;
67−
68− if (root.application.rotatesWindowContents) {
69− appWindowWithShadow.orientationAngle = root.shellOrientationAngle;
70− } else {
71− orientationChangeAnimation.start();
72− }
73− }
74−
75− OrientationChangeAnimation {
76− id: orientationChangeAnimation
77− objectName: "orientationChangeAnimation"
78− spreadDelegate: root
79− background: background
80− window: appWindowWithShadow
81− screenshot: appWindowScreenshotWithShadow
82− }
83−
84− QtObject {
85− id: priv
86− objectName: "spreadDelegatePriv"
87− property bool startingUp: true
88− }
89−
90− Component.onCompleted: { finishStartUpTimer.start(); }
91− Timer { id: finishStartUpTimer; interval: 400; onTriggered: priv.startingUp = false }
92−
93− // JS version of QPlatformScreen::angleBetween C++ implementation.
94− // So don't ask me how it works because I don't know.
95− // Calling Screen.angleBetween from within a Binding component doesn't work for some reason.
96− function angleBetween(a, b) {
97− if (a == b)
98− return 0;
99−
100− var ia = Math.log(a) / Math.LN2;
101− var ib = Math.log(b) / Math.LN2;
102−
103− var delta = ia - ib;
104−
105− if (delta < 0)
106− delta = delta + 4;
107−
108− var angles = [ 0, 90, 180, 270 ];
109− return angles[delta];
110− }
111−
112− // Sets the initial orientationAngle of the window, when it first slides into view
113− // (with the splash screen likely being displayed). At that point we just try to
114− // match shell's current orientation. We need a bit of time in this state as the
115− // information we need to decide orientationAngle may take a few cycles to
116− // be set.
117− Binding {
118− target: appWindowWithShadow
119− property: "orientationAngle"
120− when: priv.startingUp
121− value: {
122− var supportedOrientations = root.supportedOrientations;
123−
124− if (supportedOrientations === Qt.PrimaryOrientation) {
125− supportedOrientations = root.orientations.primary;
126− }
127−
128− // If it doesn't support shell's current orientation
129− // then simply pick some arbitraty one that it does support
130− var chosenOrientation = 0;
131− if (supportedOrientations & root.shellOrientation) {
132− chosenOrientation = root.shellOrientation;
133− } else if (supportedOrientations & Qt.PortraitOrientation) {
134− chosenOrientation = root.orientations.portrait;
135− } else if (supportedOrientations & Qt.LandscapeOrientation) {
136− chosenOrientation = root.orientations.landscape;
137− } else if (supportedOrientations & Qt.InvertedPortraitOrientation) {
138− chosenOrientation = root.orientations.invertedPortrait;
139− } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) {
140− chosenOrientation = root.orientations.invertedLandscape;
141− } else {
142− chosenOrientation = root.orientations.primary;
143− }
144−
145− return angleBetween(root.orientations.native_, chosenOrientation);
146− }
147− }
148−
149− Rectangle {
150− id: background
151− color: "black"
152− anchors.fill: parent
153− visible: false
154− }
155−
156− Item {
157− objectName: "displacedAppWindowWithShadow"
158−
159− readonly property real limit: root.height / 4
160−
161− y: root.closeable ? dragArea.distance : elastic(dragArea.distance)
162− width: parent.width
163− height: parent.height
164−
165− function elastic(distance) {
166− var k = distance < 0 ? -limit : limit
167− return k * (1 - Math.pow((k - 1) / k, distance))
168− }
169−
170− Item {
171− id: appWindowWithShadow
172− objectName: "appWindowWithShadow"
173−
174− property int orientationAngle
175−
176− property real transformRotationAngle: 0
177− property real transformOriginX
178− property real transformOriginY
179−
180− property var window: appWindow
181−
182− transform: Rotation {
183− origin.x: appWindowWithShadow.transformOriginX
184− origin.y: appWindowWithShadow.transformOriginY
185− axis { x: 0; y: 0; z: 1 }
186− angle: appWindowWithShadow.transformRotationAngle
187− }
188−
189− state: {
190− if (root.application && root.application.rotatesWindowContents) {
191− return "counterRotate";
192− } else if (orientationChangeAnimation.running) {
193− return "animatingRotation";
194− } else {
195− return "keepSceneRotation";
196− }
197− }
198−
199− // Ensures the given angle is in the form (0,90,180,270)
200− function normalizeAngle(angle) {
201− while (angle < 0) {
202− angle += 360;
203− }
204− return angle % 360;
205− }
206−
207− states: [
208− // A base state containing bindings common to others
209− // Ensures appWindowWithShadow fills the root area.
210− State {
211− name: "fillRootArea"
212− PropertyChanges {
213− target: appWindowWithShadow
214− restoreEntryValues: false
215− width: appWindowWithShadow.rotation == 0 || appWindowWithShadow.rotation == 180 ? root.width : root.height
216− height: appWindowWithShadow.rotation == 0 || appWindowWithShadow.rotation == 180 ? root.height : root.width
217− }
218− },
219− // In this state we stick to our currently set orientationAngle, which may change only due
220− // to calls made to matchShellOrientation() or animateToShellOrientation()
221− State {
222− name: "keepSceneRotation"
223− extend: "fillRootArea"
224− PropertyChanges {
225− target: appWindowWithShadow
226− restoreEntryValues: false
227− rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
228− }
229− },
230− // In this state we counteract any shell rotation so that the window, in scene coordinates,
231− // remains unrotated.
232− // But the splash screen should still obey the set orientationAngle set by shell
233− State {
234− name: "counterRotate"
235− extend: "fillRootArea"
236− PropertyChanges {
237− target: appWindowWithShadow
238− rotation: normalizeAngle(-root.shellOrientationAngle)
239− }
240− PropertyChanges {
241− target: appWindow
242− surfaceOrientationAngle: appWindowWithShadow.orientationAngle
243− splashRotation: appWindowWithShadow.orientationAngle
244− }
245− },
246− // Dummy state.
247− // The animation may indiscriminately break any bindings assigned to appWindowWithShadow rotation,
248− // width or height.
249− State {
250− name: "animatingRotation"
251− }
252− ]
253−
254− anchors.centerIn: parent
255−
256− BorderImage {
257− anchors {
258− fill: appWindow
259− margins: -units.gu(2)
260− }
261− source: "graphics/dropshadow2gu.sci"
262− opacity: root.dropShadow ? .3 : 0
263− Behavior on opacity { UbuntuNumberAnimation {} }
264− }
265−
266− Rectangle {
267− id: selectionHighlight
268− objectName: "selectionHighlight"
269− anchors.fill: appWindow
270− anchors.margins: -units.gu(1)
271− color: "white"
272− opacity: root.highlightShown ? 0.15 : 0
273− antialiasing: true
274− visible: opacity > 0
275− }
276−
277− Rectangle {
278− anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
279− height: units.dp(2)
280− color: theme.palette.normal.focus
281− visible: root.highlightShown
282− antialiasing: true
283− }
284−
285− ApplicationWindow {
286− id: appWindow
287− objectName: "appWindow"
288− focus: true
289− anchors {
290− fill: parent
291− topMargin: appWindow.fullscreen || (application && application.rotatesWindowContents)
292− ? 0 : maximizedAppTopMargin
293− }
294−
295− interactive: root.interactive
296− }
297− }
298− }
299−
300− Item {
301− // mimics appWindowWithShadow. Do the positioning of screenshots of non-fullscreen
302− // app windows
303− id: appWindowScreenshotWithShadow
304− visible: false
305−
306− property real transformRotationAngle: 0
307− property real transformOriginX
308− property real transformOriginY
309−
310− transform: Rotation {
311− origin.x: appWindowScreenshotWithShadow.transformOriginX
312− origin.y: appWindowScreenshotWithShadow.transformOriginY
313− axis { x: 0; y: 0; z: 1 }
314− angle: appWindowScreenshotWithShadow.transformRotationAngle
315− }
316−
317− readonly property Item window: appWindowScreenshot
318− readonly property bool ready: appWindowScreenshot.status === Image.Ready
319−
320− function take() {
321− appWindow.grabToImage(
322− function(result) {
323− appWindowScreenshot.source = result.url;
324− });
325− }
326− function discard() {
327− appWindowScreenshot.source = "";
328− }
329−
330− Image {
331− id: appWindowScreenshot
332− anchors.top: parent.top
333− }
334− }
335−
336− DraggingArea {
337− id: dragArea
338− objectName: "dragArea"
339− anchors.fill: parent
340−
341− property bool moving: false
342− property real distance: 0
343− readonly property int threshold: units.gu(2)
344− property int offset: 0
345−
346− readonly property real minSpeedToClose: units.gu(40)
347−
348− onDragValueChanged: {
349− if (!dragging) {
350− return;
351− }
352− moving = moving || Math.abs(dragValue) > threshold;
353− if (moving) {
354− distance = dragValue + offset;
355− }
356− }
357−
358− onMovingChanged: {
359− if (moving) {
360− offset = (dragValue > 0 ? -threshold: threshold)
361− } else {
362− offset = 0;
363− }
364− }
365−
366− onClicked: {
367− if (!moving) {
368− root.clicked();
369− }
370− }
371−
372− onDragEnd: {
373− if (!root.closeable) {
374− animation.animate("center")
375− return;
376− }
377−
378− // velocity and distance values specified by design prototype
379− if ((dragVelocity < -minSpeedToClose && distance < -units.gu(8)) || distance < -root.height / 2) {
380− animation.animate("up")
381− } else if ((dragVelocity > minSpeedToClose && distance > units.gu(8)) || distance > root.height / 2) {
382− animation.animate("down")
383− } else {
384− animation.animate("center")
385− }
386− }
387−
388− UbuntuNumberAnimation {
389− id: animation
390− objectName: "closeAnimation"
391− target: dragArea
392− property: "distance"
393− property bool requestClose: false
394−
395− function animate(direction) {
396− animation.from = dragArea.distance;
397− switch (direction) {
398− case "up":
399− animation.to = -root.height * 1.5;
400− requestClose = true;
401− break;
402− case "down":
403− animation.to = root.height * 1.5;
404− requestClose = true;
405− break;
406− default:
407− animation.to = 0
408− }
409− animation.start();
410− }
411−
412− onRunningChanged: {
413− if (!running) {
414− dragArea.moving = false;
415− if (requestClose) {
416− root.closed();
417− } else {
418− dragArea.distance = 0;
419− }
420− }
421− }
422− }
423− }
424−}
qml/Stage/SpreadMaths.qmldeleted−164
@@ -1,164 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Utils 0.1
20−
21−Item {
22− id: root
23− anchors { left: parent.left; top: parent.top; margins: units.gu(1) }
24−
25− // Information about the transformed item
26− property int itemIndex: 0
27− property real itemHeight: units.gu(10)
28−
29− // Information about the environment
30− property int totalItems: 0
31− property Item flickable: null
32− property int sceneHeight: units.gu(20)
33−
34− // Spread properties
35− property real spreadHeight: sceneHeight * 0.4
36− property int spreadBottomOffset: sceneHeight * 0.18
37− property int foldingAreaWidth: flickableWidth * 0.2
38− property int maxVisibleItems: 7
39− property int margins: flickableWidth * 0.05
40− property real stackScale: 0.1
41− property int leftEndFoldedAngle: 70
42− property int rightEndFoldedAngle: 65
43− property int unfoldedAngle: 30
44− property int stackWidth: flickableWidth * 0.01
45−
46−
47− // Internal
48− readonly property int flickableWidth: flickable ? flickable.width : 0
49− readonly property int flickableContentWidth: flickable ? flickable.contentWidth: 0
50− readonly property real flickableProgress: flickable ? flickable.contentX / (flickable.contentWidth - flickableWidth) : 0
51−
52− readonly property int contentWidth: flickableWidth - root.margins * 2
53−
54− readonly property int distance: (flickableContentWidth - (margins * 2) - (foldingAreaWidth * 2)) / (totalItems - 2)
55− readonly property int startPos: margins + foldingAreaWidth + (itemIndex - 1) * distance
56− readonly property int linearX: startPos - flickableProgress * (flickableContentWidth - flickableWidth)
57−
58− readonly property int leftFoldingAreaX: margins + foldingAreaWidth
59− readonly property int rightFoldingAreaX: flickableWidth - foldingAreaWidth - margins
60−
61− readonly property real leftFoldingAreaProgress: linearAnimation(leftFoldingAreaX, margins, 0, 1, linearX)
62− readonly property real rightFoldingAreaProgress: linearAnimation(rightFoldingAreaX, flickableWidth - margins, 0, 1, linearX)
63−
64− readonly property real limitedLeftProgress: Math.min(2, leftFoldingAreaProgress)
65− readonly property real limitedRightProgress: Math.min(2, rightFoldingAreaProgress)
66−
67− readonly property real middleSectionProgress: (linearX - margins - foldingAreaWidth) / (flickableWidth - (margins + foldingAreaWidth) * 2)
68−
69− // Output
70− readonly property int animatedX: {
71− if (leftFoldingAreaProgress > 4) { // Stop it at the edge
72− return margins;
73− }
74− if (leftFoldingAreaProgress > 2) { // move it slowly through the stack
75− return linearAnimation(2, 4, margins + stackWidth, margins, leftFoldingAreaProgress)
76− }
77− if (leftFoldingAreaProgress > 1 && itemIndex == 0) {
78− // The leftmost runs faster... make it stop before the stack and wait for others
79− return margins + stackWidth;
80− }
81−
82− if (leftFoldingAreaProgress > 0) { // slow it down in a curve
83− if (itemIndex == 0) { // except if it's the leftmost. that one goes straigt
84− return linearAnimation(0, 1, leftFoldingAreaX, margins + stackWidth, leftFoldingAreaProgress)
85− }
86− return linearAnimation(0, 1, leftFoldingAreaX, margins + stackWidth, leftEasing.value)
87− }
88− // same for the right side stack... mostly... don't need to treat the rightmost special...
89− if (rightFoldingAreaProgress > 4) {
90− return flickableWidth - margins
91− }
92− if (rightFoldingAreaProgress > 2) {
93− return linearAnimation(2, 4, flickableWidth - margins - stackWidth, flickableWidth - margins, rightFoldingAreaProgress)
94− }
95−
96− if (rightFoldingAreaProgress > 0) {
97− return linearAnimation(0, 1, rightFoldingAreaX, flickableWidth - margins - stackWidth, rightEasing.value);
98− }
99−
100− return linearX
101− }
102−
103− readonly property int animatedY: sceneHeight - itemHeight - spreadBottomOffset
104−
105− readonly property real animatedAngle: {
106− if (limitedLeftProgress > 0) {
107− // Leftmost is special...
108− if (index == 0) {
109− if (limitedLeftProgress < 1) {
110− return unfoldedAngle;
111− } else {
112− return linearAnimation(1, 2, unfoldedAngle, leftEndFoldedAngle, limitedLeftProgress)
113− }
114− }
115− return linearAnimation(0, 2, unfoldedAngle, leftEndFoldedAngle, limitedLeftProgress)
116− } else if (limitedRightProgress > 0) {
117− return linearAnimation(0, 1, unfoldedAngle, rightEndFoldedAngle, rightEasing.value)
118− } else {
119− return unfoldedAngle
120− }
121− }
122−
123− readonly property real scale: limitedLeftProgress > 0 ?
124− linearAnimation(0, 1, 1, 1 + stackScale, leftEasing.value)
125− : limitedRightProgress > 0 ?
126− linearAnimation(0, 1, 1, 1 + stackScale, rightEasing.value)
127− : 0.95 + Math.abs(middleSectionProgress - 0.5) * 0.1
128−
129− readonly property real closeIconOffset: (scale - 1) * (-root.spreadHeight / 2)
130−
131− readonly property real tileInfoOpacity: leftFoldingAreaProgress > 0 ?
132− linearAnimation(1, 1.5, 1, 0, leftFoldingAreaProgress)
133− : rightFoldingAreaProgress > 0 ?
134− linearAnimation(1, 1.5, 1, 0, rightFoldingAreaProgress)
135− : 1
136−
137− readonly property bool itemVisible: itemIndex == totalItems - 1 ? true : leftFoldingAreaProgress < 5 && rightFoldingAreaProgress < 5
138− readonly property real shadowOpacity: itemIndex == totalItems -1 ?
139− 1
140− : leftFoldingAreaProgress > 3 ?
141− linearAnimation(3, 3.5, 1, 0, leftFoldingAreaProgress)
142− : rightFoldingAreaProgress > 3 ?
143− linearAnimation(3, 3.5, 1, 0, rightFoldingAreaProgress)
144− : 1
145−
146−
147− // Helpers
148− function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
149− // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
150− return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
151− }
152−
153− EasingCurve {
154− id: leftEasing
155− type: EasingCurve.OutSine
156− progress: limitedLeftProgress / 2 // OutSine starts with twice the speed. slow it down.
157− }
158−
159− EasingCurve {
160− id: rightEasing
161− type: EasingCurve.OutSine
162− progress: limitedRightProgress / 2 // OutSine starts with twice the speed. slow it down.
163− }
164−}
qml/Stage/TabletStage.qmldeleted−1183
@@ -1,1183 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Ubuntu.Gestures 0.1
20−import Unity.Application 0.1
21−import Utils 0.1
22−import Powerd 0.1
23−import "../Components"
24−
25−AbstractStage {
26− id: root
27− objectName: "stages"
28− anchors.fill: parent
29−
30− // <tutorial-hacks> The Tutorial looks into our implementation details
31− property alias sideStageVisible: spreadView.sideStageVisible
32− property alias sideStageWidth: spreadView.sideStageWidth
33− // The stage the currently focused surface is in
34− property int stageFocusedSurface: priv.focusedAppDelegate ? priv.focusedAppDelegate.stage : ApplicationInfoInterface.MainStage
35− // </tutorial-hacks>
36−
37− paintBackground: spreadView.shiftedContentX !== 0
38−
39− // Functions to be called from outside
40− function updateFocusedAppOrientation() {
41− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
42−
43− if (priv.mainStageItemId && mainStageIndex >= 0 && mainStageIndex < spreadRepeater.count) {
44− spreadRepeater.itemAt(mainStageIndex).matchShellOrientation();
45− }
46−
47− for (var i = 0; i < spreadRepeater.count; ++i) {
48−
49− if (i === mainStageIndex) {
50− continue;
51− }
52−
53− var spreadDelegate = spreadRepeater.itemAt(i);
54−
55− var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle;
56− if (delta < 0) { delta += 360; }
57− delta = delta % 360;
58−
59− var supportedOrientations = spreadDelegate.supportedOrientations;
60− if (supportedOrientations === Qt.PrimaryOrientation) {
61− supportedOrientations = spreadDelegate.orientations.primary;
62− }
63−
64− if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) {
65− spreadDelegate.matchShellOrientation();
66− }
67− }
68− }
69− function updateFocusedAppOrientationAnimated() {
70− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
71− if (priv.mainStageItemId && mainStageIndex >= 0 && mainStageIndex < spreadRepeater.count) {
72− spreadRepeater.itemAt(mainStageIndex).animateToShellOrientation();
73− }
74−
75− var sideStageIndex = root.topLevelSurfaceList.indexForId(priv.sideStageItemId);
76− if (sideStageIndex >= 0 && sideStageIndex < spreadRepeater.count) {
77− spreadRepeater.itemAt(sideStageIndex).matchShellOrientation();
78− }
79− }
80−
81− function pushRightEdge(amount) {
82− if (spreadView.contentX == -spreadView.shift) {
83− edgeBarrier.push(amount);
84− }
85− }
86−
87− function closeFocusedDelegate() {
88− if (priv.focusedAppDelegate && priv.focusedAppDelegate.closeable) {
89− priv.focusedAppDelegate.closed();
90− }
91− }
92−
93− orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
94−
95− mainApp: {
96− if (priv.mainStageItemId > 0) {
97− var index = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
98− return root.topLevelSurfaceList.applicationAt(index);
99− } else {
100− return null;
101− }
102− }
103−
104− supportedOrientations: {
105− if (mainApp) {
106− var orientations = mainApp.supportedOrientations;
107− orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation;
108− if (priv.sideStageItemId && !spreadView.surfaceDragging) {
109− // If we have a sidestage app, support Portrait orientation
110− // so that it will switch the sidestage app to mainstage on rotate to portrait
111− orientations |= Qt.PortraitOrientation|Qt.InvertedPortraitOrientation;
112− }
113− return orientations;
114− } else {
115− // we just don't care
116− return Qt.PortraitOrientation |
117− Qt.LandscapeOrientation |
118− Qt.InvertedPortraitOrientation |
119− Qt.InvertedLandscapeOrientation;
120− }
121− }
122−
123− // How far left the stage has been dragged, used externally by tutorial code
124− dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0
125−
126− onWidthChanged: {
127− spreadView.selectedIndex = -1;
128− spreadView.phase = 0;
129− spreadView.contentX = -spreadView.shift;
130− }
131−
132− onAltTabPressedChanged: {
133− if (!spreadEnabled) {
134− return;
135− }
136− if (altTabPressed) {
137− priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
138− spreadView.snapToSpread();
139− } else {
140− for (var i = 0; i < spreadRepeater.count; i++) {
141− if (spreadRepeater.itemAt(i).zIndex === priv.highlightIndex) {
142− spreadView.snapTo(i);
143− return;
144− }
145− }
146− }
147− }
148−
149− FocusScope {
150− focus: root.altTabPressed
151−
152− Keys.onPressed: {
153− switch (event.key) {
154− case Qt.Key_Tab:
155− priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
156− break;
157− case Qt.Key_Backtab:
158− priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
159− break;
160− }
161− }
162− }
163−
164− Connections {
165− target: root.topLevelSurfaceList
166− onListChanged: priv.updateMainAndSideStageIndexes()
167− }
168−
169− QtObject {
170− id: priv
171− objectName: "stagesPriv"
172−
173− function updateMainAndSideStageIndexes() {
174− var choseMainStage = false;
175− var choseSideStage = false;
176−
177− if (!root.topLevelSurfaceList)
178− return;
179−
180− for (var i = 0; i < spreadRepeater.count && (!choseMainStage || !choseSideStage); ++i) {
181− var spreadDelegate = spreadRepeater.itemAt(i);
182− if (sideStage.shown && spreadDelegate.stage == ApplicationInfoInterface.SideStage
183− && !choseSideStage) {
184− priv.sideStageDelegate = spreadDelegate
185− priv.sideStageItemId = root.topLevelSurfaceList.idAt(i);
186− priv.sideStageAppId = root.topLevelSurfaceList.applicationAt(i).appId;
187− choseSideStage = true;
188− } else if (!choseMainStage && spreadDelegate.stage == ApplicationInfoInterface.MainStage) {
189− priv.mainStageDelegate = spreadDelegate;
190− priv.mainStageItemId = root.topLevelSurfaceList.idAt(i);
191− priv.mainStageAppId = root.topLevelSurfaceList.applicationAt(i).appId;
192− choseMainStage = true;
193− }
194− }
195− if (!choseMainStage) {
196− priv.mainStageDelegate = null;
197− priv.mainStageItemId = 0;
198− priv.mainStageAppId = "";
199− }
200− if (!choseSideStage) {
201− priv.sideStageDelegate = null;
202− priv.sideStageItemId = 0;
203− priv.sideStageAppId = "";
204− }
205− }
206−
207− property var focusedAppDelegate: null
208−
209− property bool mainAppOrientationChangesEnabled: false
210−
211− property real landscapeHeight: root.orientations.native_ == Qt.LandscapeOrientation ?
212− root.nativeHeight : root.nativeWidth
213−
214− property bool shellIsLandscape: root.shellOrientation === Qt.LandscapeOrientation
215− || root.shellOrientation === Qt.InvertedLandscapeOrientation
216−
217− property var mainStageDelegate: null
218− property var sideStageDelegate: null
219−
220− property int mainStageItemId: 0
221− property int sideStageItemId: 0
222−
223− property string mainStageAppId: ""
224− property string sideStageAppId: ""
225−
226− property int oldInverseProgress: 0
227−
228− property int highlightIndex: 0
229−
230− property bool focusedAppDelegateIsDislocated: focusedAppDelegate &&
231− (focusedAppDelegate.dragOffset !== 0 || focusedAppDelegate.xTranslateAnimating)
232− function evaluateOneWayFlick(gesturePoints) {
233− // Need to have at least 3 points to recognize it as a flick
234− if (gesturePoints.length < 3) {
235− return false;
236− }
237− // Need to have a movement of at least 2 grid units to recognize it as a flick
238− if (Math.abs(gesturePoints[gesturePoints.length - 1] - gesturePoints[0]) < units.gu(2)) {
239− return false;
240− }
241−
242− var oneWayFlick = true;
243− var smallestX = gesturePoints[0];
244− var leftWards = gesturePoints[1] < gesturePoints[0];
245− for (var i = 1; i < gesturePoints.length; i++) {
246− if ((leftWards && gesturePoints[i] >= smallestX)
247− || (!leftWards && gesturePoints[i] <= smallestX)) {
248− oneWayFlick = false;
249− break;
250− }
251− smallestX = gesturePoints[i];
252− }
253− return oneWayFlick;
254− }
255−
256− onHighlightIndexChanged: {
257− spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
258− }
259−
260− readonly property bool sideStageEnabled: root.shellOrientation == Qt.LandscapeOrientation ||
261− root.shellOrientation == Qt.InvertedLandscapeOrientation
262− }
263−
264− Instantiator {
265− model: root.applicationManager
266− delegate: QtObject {
267− property var stateBinding: Binding {
268− target: model.application
269− property: "requestedState"
270−
271− // NB: the first application clause is just to ensure we never get warnings for trying to access
272− // members of a null variable.
273− value: model.application &&
274− (!root.suspended && (model.application.appId === priv.mainStageAppId
275− || model.application.appId === priv.sideStageAppId))
276− )
277− ? ApplicationInfoInterface.RequestedRunning
278− : ApplicationInfoInterface.RequestedSuspended
279− }
280−
281− property var lifecycleBinding: Binding {
282− target: model.application
283− property: "exemptFromLifecycle"
284− value: model.application
285− ? (!model.application.isTouchApp || isExemptFromLifecycle(model.application.appId))
286− : false
287− }
288− }
289− }
290−
291− Binding {
292− target: MirFocusController
293− property: "focusedSurface"
294− value: priv.focusedAppDelegate ? priv.focusedAppDelegate.focusedSurface : null
295− when: root.parent && !spreadRepeater.startingUp
296− }
297−
298− Flickable {
299− id: spreadView
300− objectName: "spreadView"
301− anchors.fill: parent
302− interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0
303− contentWidth: spreadRow.width - shift
304− contentX: -shift
305−
306− property int tileDistance: units.gu(20)
307−
308− // This indicates when the spreadView is active. That means, all the animations
309− // are activated and tiles need to line up for the spread.
310− readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
311−
312− // The flickable needs to fill the screen in order to get touch events all over.
313− // However, we don't want to the user to be able to scroll back all the way. For
314− // that, the beginning of the gesture starts with a negative value for contentX
315− // so the flickable wants to pull it into the view already. "shift" tunes the
316− // distance where to "lock" the content.
317− readonly property real shift: width / 2
318− readonly property real shiftedContentX: contentX + shift
319−
320− // Phase of the animation:
321− // 0: Starting from right edge, a new app (index 1) comes in from the right
322− // 1: The app has reached the first snap position.
323− // 2: The list is dragged further and snaps into the spread view when entering phase 2
324− property int phase
325−
326− readonly property int phase0Width: sideStageWidth
327− readonly property int phase1Width: sideStageWidth
328−
329− // Those markers mark the various positions in the spread (ratio to screen width from right to left):
330− // 0 - 1: following finger, snap back to the beginning on release
331− readonly property real positionMarker1: 0.2
332− // 1 - 2: curved snapping movement, snap to nextInStack on release
333− readonly property real positionMarker2: sideStageWidth / spreadView.width
334− // 2 - 3: movement follows finger, snaps to phase 2 (full spread) on release
335− readonly property real positionMarker3: 0.6
336− // passing 3, we detach movement from the finger and snap to phase 2 (full spread)
337− readonly property real positionMarker4: 0.8
338−
339− readonly property int startSnapPosition: phase0Width * 0.5
340− readonly property int endSnapPosition: phase0Width * 0.75
341− readonly property real snapPosition: 0.75
342−
343− property int selectedIndex: -1
344− property int draggedDelegateCount: 0
345− property int closingIndex: -1
346− property var selectedDelegate: selectedIndex !== -1 ? spreadRepeater.itemAt(selectedIndex) : null
347−
348− // <FIXME-contentX> Workaround Flickable's behavior of bringing contentX back between valid boundaries
349− // when resized. The proper way to fix this is refactoring PhoneStage so that it doesn't
350− // rely on having Flickable.contentX keeping an out-of-bounds value when it's set programatically
351− // (as opposed to having contentX reaching an out-of-bounds value through dragging, which will trigger
352− // the Flickable.boundsBehavior upon release).
353− onContentXChanged: {
354− if (!undoContentXReset()) {
355− forceItToRemainStillIfBeingResized();
356− }
357− }
358− onShiftChanged: { forceItToRemainStillIfBeingResized(); }
359− function forceItToRemainStillIfBeingResized() {
360− if (root.beingResized && contentX != -spreadView.shift) {
361− contentX = -spreadView.shift;
362− }
363− }
364− function undoContentXReset() {
365− if (contentWidth <= 0) {
366− contentWidthOnLastContentXChange = contentWidth;
367− lastContentX = contentX;
368− return false;
369− }
370−
371− if (contentWidth != contentWidthOnLastContentXChange
372− && lastContentX == -shift && contentX == 0) {
373− // Flickable is resetting contentX because contentWidth has changed. Undo it.
374− contentX = -shift;
375− return true;
376− }
377−
378− contentWidthOnLastContentXChange = contentWidth;
379− lastContentX = contentX;
380− return false;
381− }
382− property real contentWidthOnLastContentXChange: -1
383− property real lastContentX: 0
384− // </FIXME-contentX>
385−
386− property bool animateX: true
387− property bool beingResized: root.beingResized
388− onBeingResizedChanged: {
389− if (beingResized) {
390− // Brace yourselves for impact!
391− selectedIndex = -1;
392− phase = 0;
393− contentX = -shift;
394− }
395− }
396−
397− property real sideStageWidth: units.gu(40)
398−
399− property bool surfaceDragging: triGestureArea.recognisedDrag
400−
401− readonly property bool sideStageVisible: priv.sideStageItemId != 0
402−
403− // In case applicationManager already holds an app when starting up we're missing animations
404− // Make sure we end up in the same state
405− Component.onCompleted: {
406− spreadView.contentX = -spreadView.shift
407− }
408−
409− property int nextInStack: {
410− var mainStageIndex = priv.mainStageDelegate ? priv.mainStageDelegate.index : -1;
411− var sideStageIndex = priv.sideStageDelegate ? priv.sideStageDelegate.index : -1;
412− switch (state) {
413− case "main":
414− if (root.topLevelSurfaceList.count > 1) {
415− return 1;
416− }
417− return -1;
418− case "mainAndOverlay":
419− if (root.topLevelSurfaceList.count <= 2) {
420− return -1;
421− }
422− if (mainStageIndex == 0 || sideStageIndex == 0) {
423− if (mainStageIndex == 1 || sideStageIndex == 1) {
424− return 2;
425− }
426− return 1;
427− }
428− return 0;
429− case "overlay":
430− return 1;
431− }
432− return -1;
433− }
434− property int nextZInStack
435−
436− states: [
437− State {
438− name: "empty"
439− },
440− State {
441− name: "main"
442− },
443− State { // Side Stage only in overlay mode
444− name: "overlay"
445− },
446− State { // Main Stage and Side Stage in overlay mode
447− name: "mainAndOverlay"
448− },
449− State { // Main Stage and Side Stage in split mode
450− name: "mainAndSplit"
451− }
452− ]
453− state: {
454− if ((priv.mainStageItemId && !priv.sideStageItemId) || !priv.sideStageEnabled) {
455− return "main";
456− }
457− if (!priv.mainStageItemId && priv.sideStageItemId) {
458− return "overlay";
459− }
460− if (priv.mainStageItemId && priv.sideStageItemId) {
461− return "mainAndOverlay";
462− }
463− return "empty";
464− }
465−
466− onShiftedContentXChanged: {
467− if (root.beingResized) {
468− // Flickabe.contentX wiggles during resizes. Don't react to it.
469− return;
470− }
471−
472− if (phase === 0) {
473− // the "spreadEnabled" part is because when code does "phase = 0; contentX = -shift" to
474− // dismiss the spread because spreadEnabled went to false, for some reason, during tests,
475− // Flickable might jump in and change contentX value back, causing the code below to do
476− // "phase = 1" which will make the spread stay.
477− // It sucks that we have no control whatsoever over whether or when Flickable animates its
478− // contentX.
479− if (root.spreadEnabled && shiftedContentX > width * positionMarker2) {
480− phase = 1;
481− }
482− }
483−
484− // Do not turn to else if
485− // Sometimes the animation of shiftedContentX is very fast and we need to jump from phase 0 to 1 to 2
486− // in the same onShiftedContentXChanged
487− if (phase === 1) {
488− if (shiftedContentX < width * positionMarker2) {
489− phase = 0;
490− } else if (shiftedContentX >= width * positionMarker4 && !spreadDragArea.dragging) {
491− phase = 2;
492− }
493− }
494− }
495−
496− function snap() {
497− if (shiftedContentX < phase0Width) {
498− snapAnimation.targetContentX = -shift;
499− snapAnimation.start();
500− } else if (shiftedContentX < phase1Width) {
501− snapTo(1);
502− } else {
503− snapToSpread();
504− }
505− }
506−
507− function snapToSpread() {
508− // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
509− snapAnimation.targetContentX = (spreadView.width * spreadView.positionMarker4) + 1 - shift;
510− snapAnimation.start();
511− }
512−
513− function snapTo(index) {
514− snapAnimation.stop();
515− spreadView.selectedIndex = index;
516− snapAnimation.targetContentX = -shift;
517− snapAnimation.start();
518− }
519−
520− // We need to shuffle z ordering a bit in order to keep side stage apps above main stage apps.
521− // We don't want to really reorder them in the model because that allows us to keep track
522− // of the last focused order.
523− function indexToZIndex(index) {
524− // only shuffle when we've got a main and overlay
525− if (state !== "mainAndOverlay") return index;
526−
527− var app = root.topLevelSurfaceList.applicationAt(index);
528− if (!app) {
529− return index;
530− }
531− var stage = spreadRepeater.itemAt(index) ? spreadRepeater.itemAt(index).stage : ApplicationInfoInterface.MainStage;
532−
533− // don't shuffle indexes greater than "actives or next"
534− if (index > 2) return index;
535−
536− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
537−
538− if (index == mainStageIndex) {
539− // Active main stage always at 0
540− return 0;
541− }
542−
543− if (spreadView.nextInStack > 0) {
544− var stageOfNextInStack = spreadRepeater.itemAt(spreadView.nextInStack).stage;
545−
546− if (index === spreadView.nextInStack) {
547− // this is the next app in stack.
548−
549− if (stage === ApplicationInfoInterface.SideStage) {
550− // if the next app in stack is a sidestage app, it must order on top of other side stage app
551− return Math.min(2, root.topLevelSurfaceList.count-1);
552− }
553− return 1;
554− }
555− if (stageOfNextInStack === ApplicationInfoInterface.SideStage) {
556− // if the next app in stack is a sidestage app, it must order on top of other side stage app
557− return 1;
558− }
559− return Math.min(2, root.topLevelSurfaceList.count-1);
560− }
561− return Math.min(index+1, root.topLevelSurfaceList.count-1);
562− }
563−
564− SequentialAnimation {
565− id: snapAnimation
566− property int targetContentX: -spreadView.shift
567−
568− UbuntuNumberAnimation {
569− target: spreadView
570− property: "contentX"
571− to: snapAnimation.targetContentX
572− duration: UbuntuAnimation.FastDuration
573− }
574−
575− ScriptAction {
576− script: {
577− if (spreadView.selectedIndex >= 0) {
578− var newIndex = spreadView.selectedIndex;
579− var application = root.topLevelSurfaceList.applicationAt(newIndex);
580− var spreadDelegate = spreadRepeater.itemAt(newIndex);
581− if (spreadDelegate.stage === ApplicationInfoInterface.SideStage) {
582− sideStage.showNow();
583− }
584− spreadView.selectedIndex = -1;
585− spreadDelegate.focus = true;
586− spreadView.phase = 0;
587− spreadView.contentX = -spreadView.shift;
588− }
589− }
590− }
591− }
592−
593− Behavior on contentX {
594− enabled: root.altTabPressed
595− UbuntuNumberAnimation {}
596− }
597−
598− MouseArea {
599− id: spreadRow
600− x: spreadView.contentX
601− width: spreadView.width + Math.max(spreadView.width, root.topLevelSurfaceList.count * spreadView.tileDistance)
602− height: root.height
603−
604− onClicked: {
605− spreadView.snapTo(0);
606− }
607−
608− DropArea {
609− objectName: "MainStageDropArea"
610− anchors {
611− left: parent.left
612− top: parent.top
613− bottom: parent.bottom
614− }
615− width: spreadView.width - sideStage.width
616− enabled: priv.sideStageEnabled
617−
618− onDropped: {
619− drop.source.spreadDelegate.saveStage(ApplicationInfoInterface.MainStage);
620− drop.source.spreadDelegate.focus = true;
621− }
622− keys: "SideStage"
623− }
624−
625− SideStage {
626− id: sideStage
627− objectName: "sideStage"
628− height: priv.landscapeHeight
629− x: spreadView.width - width
630− z: {
631− if (!priv.mainStageItemId) return 0;
632−
633− if (priv.sideStageItemId && spreadView.nextInStack > 0) {
634− var nextDelegateInStack = spreadRepeater.itemAt(spreadView.nextInStack);
635−
636− if (nextDelegateInStack.stage === ApplicationInfoInterface.MainStage) {
637− // if the next app in stack is a main stage app, put the sidestage on top of it.
638− return 2;
639− }
640− return 1;
641− }
642−
643− return 1;
644− }
645− visible: progress != 0
646− enabled: priv.sideStageEnabled && sideStageDropArea.dropAllowed
647− opacity: priv.sideStageEnabled && !spreadView.active ? 1 : 0
648− Behavior on opacity { UbuntuNumberAnimation {} }
649−
650− onShownChanged: {
651− if (!shown && priv.sideStageDelegate && priv.focusedAppDelegate === priv.sideStageDelegate
652− && priv.mainStageDelegate) {
653− priv.mainStageDelegate.focus = true;
654− } else if (shown && priv.sideStageDelegate) {
655− priv.sideStageDelegate.focus = true;
656− }
657− }
658−
659− DropArea {
660− id: sideStageDropArea
661− objectName: "SideStageDropArea"
662− anchors.fill: parent
663−
664− property bool dropAllowed: true
665−
666− onEntered: {
667− dropAllowed = drag.keys != "Disabled";
668− }
669− onExited: {
670− dropAllowed = true;
671− }
672− onDropped: {
673− if (drop.keys == "MainStage") {
674− drop.source.spreadDelegate.saveStage(ApplicationInfoInterface.SideStage);
675− drop.source.spreadDelegate.focus = true;
676− }
677− }
678− drag {
679− onSourceChanged: {
680− if (!sideStageDropArea.drag.source) {
681− dropAllowed = true;
682− }
683− }
684− }
685− }
686− }
687−
688− TopLevelSurfaceRepeater {
689− id: spreadRepeater
690− objectName: "spreadRepeater"
691− model: root.topLevelSurfaceList
692−
693− onItemAdded: {
694− priv.updateMainAndSideStageIndexes();
695− if (spreadView.phase == 2) {
696− spreadView.snapTo(index);
697− }
698− }
699−
700− onItemRemoved: {
701− priv.updateMainAndSideStageIndexes();
702− // Unless we're closing the app ourselves,
703− // lets make sure the spread doesn't mess up by the changing app list.
704− if (spreadView.closingIndex == -1) {
705− spreadView.phase = 0;
706− spreadView.contentX = -spreadView.shift;
707− }
708− focusTopMostApp();
709− }
710− function focusTopMostApp() {
711− if (spreadRepeater.count > 0) {
712− var topmostDelegate = spreadRepeater.itemAt(0);
713− topmostDelegate.focus = true;
714− }
715− }
716−
717− delegate: TransformedTabletSpreadDelegate {
718− id: spreadTile
719− objectName: "spreadDelegate_" + model.id
720−
721− readonly property int index: model.index
722− width: spreadView.width
723− height: spreadView.height
724− active: model.id == priv.mainStageItemId || model.id == priv.sideStageItemId
725− zIndex: selected && stage == ApplicationInfoInterface.MainStage ? 0 : spreadView.indexToZIndex(index)
726− onZIndexChanged: {
727− if (spreadView.nextInStack == model.index) {
728− spreadView.nextZInStack = zIndex;
729− }
730− }
731− selected: spreadView.selectedIndex == index
732− otherSelected: spreadView.selectedIndex >= 0 && !selected
733− isInSideStage: priv.sideStageItemId == model.id
734− interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
735− swipeToCloseEnabled: spreadView.interactive && !snapAnimation.running
736− maximizedAppTopMargin: root.maximizedAppTopMargin
737− dragOffset: model.id == priv.mainStageItemId && root.inverseProgress > 0
738− && spreadView.phase === 0 ? root.inverseProgress : 0
739− application: model.application
740− surface: model.surface
741− closeable: true
742− highlightShown: root.altTabPressed && priv.highlightIndex == zIndex
743− dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
744−
745− readonly property bool wantsMainStage: stage == ApplicationInfoInterface.MainStage
746−
747−
748− onFocusChanged: {
749− if (focus && !spreadRepeater.startingUp) {
750− priv.focusedAppDelegate = spreadTile;
751− root.topLevelSurfaceList.raiseId(model.id);
752− }
753− if (focus && priv.sideStageEnabled && stage === ApplicationInfoInterface.SideStage) {
754− sideStage.show();
755− }
756− }
757− Connections {
758− target: model.surface
759− onFocusRequested: spreadTile.focus = true;
760− }
761− Connections {
762− target: spreadTile.application
763− onFocusRequested: {
764− if (!model.surface) {
765− // when an app has no surfaces, we assume there's only one entry representing it:
766− // this delegate.
767− spreadTile.focus = true;
768− } else {
769− // if the application has surfaces, focus request should be at surface-level.
770− }
771− }
772− }
773−
774− fullscreen: {
775− if (priv.mainStageDelegate && stage === ApplicationInfoInterface.SideStage) {
776− return priv.mainStageDelegate.fullscreen;
777− } else if (surface) {
778− return surface.state == Mir.FullscreenState;
779− } else if (application) {
780− return application.fullscreen;
781− } else {
782− return false;
783− }
784− }
785−
786− supportedOrientations: {
787− if (application) {
788− var orientations = application.supportedOrientations;
789− if (stage == ApplicationInfoInterface.MainStage) {
790− // When an app is in the mainstage, it always supports Landscape|InvertedLandscape
791− // so that we can drag it from the main stage to the side stage
792− orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation;
793− }
794− return orientations;
795− } else {
796− // we just don't care
797− return Qt.PortraitOrientation |
798− Qt.LandscapeOrientation |
799− Qt.InvertedPortraitOrientation |
800− Qt.InvertedLandscapeOrientation;
801− }
802− }
803−
804− function saveStage(newStage) {
805− stage = newStage;
806− WindowStateStorage.saveStage(application.appId, newStage);
807− }
808−
809− // FIXME: A regular binding doesn't update any more after closing an app.
810− // Using a Binding for now.
811− Binding {
812− target: spreadTile
813− property: "z"
814− value: (!spreadView.active && !active) ? -1 : spreadTile.zIndex
815− }
816− x: spreadView.width
817−
818− property real behavioredZIndex: zIndex
819− Behavior on behavioredZIndex {
820− enabled: spreadView.closingIndex >= 0
821− UbuntuNumberAnimation {}
822− }
823− Connections {
824− target: priv
825− onSideStageEnabledChanged: refreshStage()
826− }
827−
828− property bool _constructing: true;
829− onStageChanged: {
830− if (!_constructing) {
831− priv.updateMainAndSideStageIndexes();
832− }
833− }
834−
835− Component.onCompleted: {
836− // a top level window is always the focused one when it first appears, unfocusing
837− // any preexisting one
838− focus = true;
839− refreshStage();
840− _constructing = false;
841− }
842−
843− function refreshStage() {
844− var newStage = ApplicationInfoInterface.MainStage;
845− if (priv.sideStageEnabled) { // we're in lanscape rotation.
846− if (application && application.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
847− var defaultStage = ApplicationInfoInterface.SideStage; // if application supports portrait, it defaults to sidestage.
848− if (application.supportedOrientations & (Qt.LandscapeOrientation|Qt.InvertedLandscapeOrientation)) {
849− // if it supports lanscape, it defaults to mainstage.
850− defaultStage = ApplicationInfoInterface.MainStage;
851− }
852− newStage = WindowStateStorage.getStage(application.appId, defaultStage);
853− }
854− }
855−
856− stage = newStage;
857− }
858−
859− progress: {
860− var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
861− // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0
862− if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {
863− tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;
864− }
865− return tileProgress;
866− }
867−
868− // TODO: Hiding tile when progress is such that it will be off screen.
869− property bool occluded: {
870− if (spreadView.active && !offScreen) return false;
871− else if (spreadTile.active) return false;
872− else if (xTranslateAnimating) return false;
873− else if (z <= 1 && priv.focusedAppDelegateIsDislocated) return false;
874− return true;
875− }
876−
877− visible: Powerd.status == Powerd.On &&
878− !greeter.fullyShown &&
879− !occluded
880−
881− animatedProgress: {
882− if (spreadView.phase == 0 && (spreadTile.active || spreadView.nextInStack == index)) {
883− if (progress < spreadView.positionMarker1) {
884− return progress;
885− } else if (progress < spreadView.positionMarker1 + snappingCurve.period) {
886− return spreadView.positionMarker1 + snappingCurve.value * 3;
887− } else {
888− return spreadView.positionMarker2;
889− }
890− }
891− return progress;
892− }
893−
894− shellOrientationAngle: root.shellOrientationAngle
895− shellOrientation: root.shellOrientation
896− orientations: root.orientations
897−
898− states: [
899− State {
900− name: "MainStage"
901− when: spreadTile.stage == ApplicationInfoInterface.MainStage
902− },
903− State {
904− name: "SideStage"
905− when: spreadTile.stage == ApplicationInfoInterface.SideStage
906−
907− PropertyChanges {
908− target: spreadTile
909− width: spreadView.sideStageWidth
910− height: priv.landscapeHeight
911−
912− supportedOrientations: Qt.PortraitOrientation
913− shellOrientationAngle: 0
914− shellOrientation: Qt.PortraitOrientation
915− orientations: sideStageOrientations
916− }
917− }
918− ]
919−
920− Orientations {
921− id: sideStageOrientations
922− primary: Qt.PortraitOrientation
923− native_: Qt.PortraitOrientation
924− portrait: root.orientations.portrait
925− invertedPortrait: root.orientations.invertedPortrait
926− landscape: root.orientations.landscape
927− invertedLandscape: root.orientations.invertedLandscape
928− }
929−
930− transitions: [
931− Transition {
932− to: "SideStage"
933− SequentialAnimation {
934− PropertyAction {
935− target: spreadTile
936− properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
937− }
938− ScriptAction {
939− script: {
940− // rotate immediately.
941− spreadTile.matchShellOrientation();
942− if (priv.focusedAppDelegate === spreadTile &&
943− priv.sideStageEnabled && !sideStage.shown) {
944− // Sidestage was focused, so show the side stage.
945− sideStage.show();
946− }
947− }
948− }
949− }
950− },
951− Transition {
952− from: "SideStage"
953− SequentialAnimation {
954− ScriptAction {
955− script: {
956− if (priv.sideStageDelegate === spreadTile &&
957− mainApp && (mainApp.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) == 0) {
958− // The mainstage app did not natively support portrait orientation, so focus the sidestage.
959− spreadTile.focus = true;
960− }
961− }
962− }
963− PropertyAction {
964− target: spreadTile
965− properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
966− }
967− ScriptAction { script: { spreadTile.matchShellOrientation(); } }
968− }
969− }
970− ]
971−
972− onClicked: {
973− if (spreadView.phase == 2) {
974− spreadView.snapTo(index);
975− }
976− }
977−
978− onDraggedChanged: {
979− if (dragged) {
980− spreadView.draggedDelegateCount++;
981− } else {
982− spreadView.draggedDelegateCount--;
983− }
984− }
985−
986− onClosed: {
987− spreadView.closingIndex = index;
988− if (spreadTile.surface) {
989− spreadTile.surface.close();
990− } else if (spreadTile.application) {
991− root.applicationManager.stopApplication(spreadTile.application.appId);
992− } else {
993− // should never happen
994− console.warn("Can't close topLevelSurfaceList entry as it has neither"
995− + " a surface nor an application");
996− }
997− }
998−
999− Binding {
1000− target: root
1001− when: model.id == priv.mainStageItemId
1002− property: "mainAppWindowOrientationAngle"
1003− value: appWindowOrientationAngle
1004− }
1005− Binding {
1006− target: priv
1007− when: model.id == priv.mainStageItemId
1008− property: "mainAppOrientationChangesEnabled"
1009− value: orientationChangesEnabled
1010− }
1011−
1012− EasingCurve {
1013− id: snappingCurve
1014− type: EasingCurve.Linear
1015− period: (spreadView.positionMarker2 - spreadView.positionMarker1) / 3
1016− progress: spreadTile.progress - spreadView.positionMarker1
1017− }
1018−
1019− StagedFullscreenPolicy {
1020− id: fullscreenPolicy
1021− surface: model.surface
1022− }
1023− Connections {
1024− target: root
1025− onStageAboutToBeUnloaded: fullscreenPolicy.active = false
1026− }
1027− }
1028− }
1029− }
1030− }
1031−
1032− TabletSideStageTouchGesture {
1033− id: triGestureArea
1034− anchors.fill: parent
1035− enabled: priv.sideStageEnabled && !spreadView.active
1036−
1037− property Item spreadDelegate
1038−
1039− dragComponent: dragComponent
1040− dragComponentProperties: { "spreadDelegate": spreadDelegate }
1041−
1042− onPressed: {
1043− function matchDelegate(obj) { return String(obj.objectName).indexOf("spreadDelegate") >= 0; }
1044−
1045− var delegateAtCenter = Functions.itemAt(spreadRow, x, y, matchDelegate);
1046− if (!delegateAtCenter) return;
1047−
1048− spreadDelegate = delegateAtCenter;
1049− }
1050−
1051− onClicked: {
1052− if (sideStage.shown) {
1053− sideStage.hide();
1054− } else {
1055− sideStage.show();
1056− }
1057− }
1058−
1059− onDragStarted: {
1060− // If we're dragging to the sidestage.
1061− if (!sideStage.shown) {
1062− sideStage.show();
1063− }
1064− }
1065−
1066− Component {
1067− id: dragComponent
1068− SurfaceContainer {
1069− property Item spreadDelegate
1070−
1071− surface: spreadDelegate ? spreadDelegate.surface : null
1072−
1073− consumesInput: false
1074− interactive: false
1075− resizeSurface: false
1076− focus: false
1077−
1078− width: units.gu(40)
1079− height: units.gu(40)
1080−
1081− Drag.hotSpot.x: width/2
1082− Drag.hotSpot.y: height/2
1083− // only accept opposite stage.
1084− Drag.keys: {
1085− if (!surface) return "Disabled";
1086−
1087− if (spreadDelegate.stage === ApplicationInfo.MainStage) {
1088− if (spreadDelegate.application.supportedOrientations
1089− & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
1090− return "MainStage";
1091− }
1092− return "Disabled";
1093− }
1094− return "SideStage";
1095− }
1096− }
1097− }
1098− }
1099−
1100− //eat touch events during the right edge gesture
1101− MouseArea {
1102− anchors.fill: parent
1103− enabled: spreadDragArea.dragging
1104− }
1105−
1106− SwipeArea {
1107− id: spreadDragArea
1108− objectName: "spreadDragArea"
1109− x: parent.width - root.dragAreaWidth
1110− anchors { top: parent.top; bottom: parent.bottom }
1111− width: root.dragAreaWidth
1112− direction: Direction.Leftwards
1113− enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
1114−
1115− property var gesturePoints: new Array()
1116−
1117− onTouchPositionChanged: {
1118− if (!dragging) {
1119− spreadView.phase = 0;
1120− spreadView.contentX = -spreadView.shift;
1121− }
1122−
1123− if (dragging) {
1124− var dragX = -touchPosition.x + spreadDragArea.width - spreadView.shift;
1125− var maxDrag = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
1126− spreadView.contentX = Math.min(dragX, maxDrag);
1127− }
1128− gesturePoints.push(touchPosition.x);
1129− }
1130−
1131− onDraggingChanged: {
1132− if (dragging) {
1133− // Gesture recognized. Start recording this gesture
1134− gesturePoints = [];
1135− } else {
1136− // Ok. The user released. Find out if it was a one-way movement.
1137− var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
1138− gesturePoints = [];
1139−
1140− if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
1141− // If it was a short one-way movement, do the Alt+Tab switch
1142− // no matter if we didn't cross positionMarker1 yet.
1143− spreadView.snapTo(spreadView.nextInStack);
1144− } else {
1145− if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) {
1146− spreadView.snap();
1147− } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
1148− spreadView.snapTo(spreadView.nextInStack);
1149− } else {
1150− // otherwise snap to the closest snap position we can find
1151− // (might be back to start, to app 1 or to spread)
1152− spreadView.snap();
1153− }
1154− }
1155− }
1156− }
1157− }
1158−
1159− EdgeBarrier {
1160− id: edgeBarrier
1161−
1162− // NB: it does its own positioning according to the specified edge
1163− edge: Qt.RightEdge
1164−
1165− onPassed: {
1166− spreadView.snapToSpread();
1167− }
1168− material: Component {
1169− Item {
1170− Rectangle {
1171− width: parent.height
1172− height: parent.width
1173− rotation: 90
1174− anchors.centerIn: parent
1175− gradient: Gradient {
1176− GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
1177− GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
1178− }
1179− }
1180− }
1181− }
1182− }
1183−}
qml/Stage/TransformedSpreadDelegate.qmldeleted−391
@@ -1,391 +0,0 @@
1−/*
2− * Copyright 2014,2016 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17−*/
18−
19−import QtQuick 2.4
20−import Utils 0.1
21−import Ubuntu.Components 1.3
22−
23−SpreadDelegate {
24− id: root
25−
26− // Set this to true when this tile is selected in the spread. The animation will change to bring the tile to front.
27− property bool selected: false
28− // Set this to true when another tile in the spread is selected. The animation will change to fade this tile out.
29− property bool otherSelected: false
30−
31− // The progress animates the tiles. A value > 0 makes it appear from the right edge. At 1 it reaches the end position.
32− property real progress: 0
33− // This is required to snap tile 1 during phase 1 and 2.
34− property real animatedProgress: 0
35−
36− property real startAngle: 0
37− property real endAngle: 0
38−
39− property real startScale: 1
40− property real endScale: 1
41−
42− // Specific to just one tile
43− property real tile1StartScale: startScale + .4
44− property real tile0SnapAngle: 10
45−
46− property real startDistance: units.gu(5)
47− property real endDistance: units.gu(.5)
48−
49− // Whether first app is displayed entirely vs just on the spread edge
50− property bool focusFirstApp: true
51−
52− // Whether this delegate is displayed to the user outside of the spread
53− readonly property bool isFocused: focusFirstApp && index === 0
54−
55− // Adjusted index for any spread animation calculations
56− readonly property int spreadIndex: index - (focusFirstApp ? 1 : 0)
57−
58− // How far left this delegate has been translated
59− readonly property alias xTranslate: priv.xTranslate
60−
61− onSelectedChanged: {
62− if (selected) {
63− priv.snapshot();
64− }
65− priv.isSelected = selected;
66− }
67−
68− onOtherSelectedChanged: {
69− if (otherSelected) {
70− priv.snapshot();
71− }
72− priv.otherSelected = otherSelected;
73− }
74−
75− Connections {
76− target: spreadView
77− onPhaseChanged: {
78− if (root.focusFirstApp && spreadView.phase == 1) {
79− if (index === 0) {
80− priv.phase2startTranslate = priv.easingAnimation(0, spreadView.positionMarker4, 0, -spreadView.width, spreadView.positionMarker4) + spreadView.width;
81− priv.phase2startAngle = priv.easingAnimation(0, spreadView.positionMarker4, root.startAngle, root.endAngle, spreadView.positionMarker4);
82− priv.phase2startScale = priv.easingAnimation(0, spreadView.positionMarker4, root.startScale, root.endScale, spreadView.positionMarker4);
83− priv.phase2startTopMarginProgress = priv.easingAnimation(0, 1, 0, 1, spreadView.positionMarker4);
84− } else if (index == 1) {
85− // find where the main easing for Tile 1 would be when reaching phase 2
86− var phase2Progress = spreadView.positionMarker4 - spreadView.tileDistance / spreadView.width;
87− priv.phase2startTranslate = priv.easingAnimation(0, phase2Progress, 0, -spreadView.width + root.endDistance, phase2Progress);
88− priv.phase2startAngle = priv.easingAnimation(0, phase2Progress, root.startAngle, root.endAngle, phase2Progress);
89− priv.phase2startScale = priv.easingAnimation(0, phase2Progress, root.startScale, root.endScale, phase2Progress);
90− priv.phase2startTopMarginProgress = priv.easingAnimation(0, 1, 0, spreadView.positionMarker4, phase2Progress);
91− }
92− }
93− }
94− }
95−
96− QtObject {
97− id: priv
98− property bool isSelected: false
99− property bool otherSelected: false
100− property real selectedProgress
101− property real selectedXTranslate
102− property real selectedAngle
103− property real selectedScale
104− property real selectedOpacity
105− property real selectedTopMarginProgress
106−
107− // Those values are needed as target values for the end of phase 1.
108− // As they are static values, lets calculate them once when entering phase 1 instead of calculating them in each animation pass.
109− property real phase2startTranslate
110− property real phase2startAngle
111− property real phase2startScale
112− property real phase2startTopMarginProgress
113−
114− function snapshot() {
115− selectedProgress = root.progress;
116− selectedXTranslate = xTranslate;
117− selectedAngle = angle;
118− selectedScale = scale;
119− selectedOpacity = opacity;
120− selectedTopMarginProgress = topMarginProgress;
121− }
122−
123− function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
124− // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
125− return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
126− }
127−
128− function easingAnimation(startProgress, endProgress, startValue, endValue, progress) {
129− helperEasingCurve.progress = progress - startProgress;
130− helperEasingCurve.period = endProgress - startProgress;
131− return helperEasingCurve.value * (endValue - startValue) + startValue;
132− }
133−
134− // The following blocks handle the animation of the tile in the spread.
135− // At the beginning, each tile is attached at the right edge, outside the screen.
136− // The progress for each tile starts at 0 and it reaches its end position at a progress of 1.
137− // The first phases are handled special for the first 2 tiles. as we do the alt-tab and snapping
138− // in there. Once we reached phase 3, the animation is the same for all tiles.
139− // When a tile is selected, the animation state is snapshotted, and the spreadView is unwound.
140− // All tiles are kept in place and faded out to 0 opacity except
141− // the selected tile, which is animated from the snapshotted position to be fullscreen.
142−
143− readonly property real xTranslate: {
144− if (!spreadView.active) {
145− return 0;
146− }
147−
148− if (otherSelected) {
149− if (spreadView.phase < 2 && root.isFocused) {
150− return linearAnimation(selectedProgress, 0, selectedXTranslate,
151− selectedXTranslate - spreadView.tileDistance, root.progress);
152− }
153−
154− return selectedXTranslate;
155− }
156−
157− if (root.focusFirstApp && index === 0) {
158− if (spreadView.phase == 0) {
159− return Math.min(0, linearAnimation(0, spreadView.positionMarker2,
160− 0, -spreadView.width * .25, root.animatedProgress));
161− } else if (spreadView.phase == 1){
162− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
163− -spreadView.width * .25, priv.phase2startTranslate, root.progress);
164− } else if (!priv.isSelected){ // phase 2
165− // Apply the same animation as with the rest but add spreadView.width to align it with the others.
166− return -easingCurve.value * spreadView.width + spreadView.width;
167− } else {
168− return linearAnimation(selectedProgress, 0, selectedXTranslate, 0, root.progress);
169− }
170− } else if (root.focusFirstApp && index === 1) {
171− if (spreadView.phase == 0 && !priv.isSelected) {
172− return linearAnimation(0, spreadView.positionMarker2,
173− 0, -spreadView.width * spreadView.snapPosition, root.animatedProgress);
174− } else if (spreadView.phase == 1 && !priv.isSelected) {
175− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
176− -spreadView.width * spreadView.snapPosition, priv.phase2startTranslate,
177− root.progress);
178− }
179− }
180−
181− if (priv.isSelected) {
182− // Distance to left edge
183− var targetTranslate = -spreadView.width - (root.spreadIndex * root.startDistance);
184− return linearAnimation(selectedProgress, 0,
185− selectedXTranslate, targetTranslate, root.progress);
186− }
187−
188− // Fix it at the right edge...
189− var rightEdgeOffset = -(root.spreadIndex * root.startDistance);
190− // ...and use our easing to move them to the left. Stop a bit earlier for each tile
191− var animatedEndDistance = linearAnimation(0, 2, root.endDistance, 0, root.progress);
192− return -easingCurve.value * spreadView.width + (index * animatedEndDistance) + rightEdgeOffset;
193−
194− }
195−
196− readonly property real angle: {
197− if (!spreadView.active) {
198− return 0;
199− }
200−
201− if (priv.otherSelected) {
202− return priv.selectedAngle;
203− }
204− if (priv.isSelected) {
205− return linearAnimation(selectedProgress, 0, selectedAngle, 0, root.progress);
206− }
207− if (root.focusFirstApp && index === 0) {
208− if (spreadView.phase == 0) {
209− return Math.max(0, linearAnimation(0, spreadView.positionMarker2,
210− 0, root.tile0SnapAngle, root.animatedProgress));
211− } else if (spreadView.phase == 1) {
212− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
213− root.tile0SnapAngle, phase2startAngle, root.progress);
214− }
215− } else if (root.focusFirstApp && index === 1) {
216− if (spreadView.phase == 0) {
217− return linearAnimation(0, spreadView.positionMarker2, root.startAngle,
218− root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
219− } else if (spreadView.phase == 1) {
220− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
221− root.startAngle * (1-spreadView.snapPosition), priv.phase2startAngle,
222− root.progress);
223− }
224− }
225− return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
226− }
227−
228− readonly property real scale: {
229− if (!spreadView.active) {
230− return 1;
231− }
232− if (priv.otherSelected) {
233− return priv.selectedScale;
234− }
235− if (priv.isSelected) {
236− return linearAnimation(selectedProgress, 0, selectedScale, 1, root.progress);
237− }
238−
239− if (root.focusFirstApp && index === 0) {
240− if (spreadView.phase == 0) {
241− return 1;
242− } else if (spreadView.phase == 1) {
243− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
244− 1, phase2startScale, root.progress);
245− }
246− } else if (root.focusFirstApp && index === 1) {
247− if (spreadView.phase == 0) {
248− var targetScale = tile1StartScale - ((tile1StartScale - 1) * spreadView.snapPosition);
249− return linearAnimation(0, spreadView.positionMarker2,
250− root.tile1StartScale, targetScale, root.animatedProgress);
251− } else if (spreadView.phase == 1) {
252− var startScale = tile1StartScale - ((tile1StartScale - 1) * spreadView.snapPosition);
253− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
254− startScale, priv.phase2startScale, root.progress);
255− }
256− }
257− return root.startScale - easingCurve.value * (root.startScale - root.endScale);
258− }
259−
260− readonly property real opacity: {
261− if (priv.otherSelected) {
262− return linearAnimation (selectedProgress, Math.max(0, selectedProgress - .5),
263− selectedOpacity, 0, root.progress);
264− }
265− if (root.isFocused) {
266− switch (spreadView.phase) {
267− case 0:
268− return linearAnimation(0, spreadView.positionMarker2, 1, .7, root.animatedProgress);
269− case 1:
270− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
271− .7, 1, root.animatedProgress);
272− }
273− }
274−
275− return 1;
276− }
277−
278− readonly property real topMarginProgress: {
279− if (priv.isSelected) {
280− return linearAnimation(selectedProgress, 0, selectedTopMarginProgress, 0, root.progress);
281− }
282−
283− if (root.focusFirstApp && index === 0) {
284− if (spreadView.phase == 0) {
285− return 0;
286− } else if (spreadView.phase == 1) {
287− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
288− 0, priv.phase2startTopMarginProgress, root.progress);
289− }
290− } else if (root.focusFirstApp && index === 1) {
291− if (spreadView.phase == 0) {
292− return 0;
293− } else if (spreadView.phase == 1) {
294− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
295− 0, priv.phase2startTopMarginProgress, root.progress);
296− }
297− }
298−
299− return easingCurve.value;
300− }
301− }
302−
303− transform: [
304− Rotation {
305− origin { x: 0; y: spreadView.height / 2 }
306− axis { x: 0; y: 1; z: 0 }
307− angle: priv.angle
308− },
309−
310− // The next two transformations are to ensure that fullscreen and rotated
311− // windows all have the same size and position as an unrotated (0 degrees)
312− // non-fullscreen window when they're stacked on top of each other on the
313− // far left of the spread.
314− Translate {
315− y: !root.fullscreen && appWindowRotation === 180
316− ? priv.topMarginProgress * maximizedAppTopMargin
317− : 0
318− },
319− Scale {
320− origin {
321− x: appWindowRotation === 270 ? spreadView.width : 0
322− y: spreadView.height
323− }
324−
325− xScale: {
326− switch (appWindowRotation) {
327− case 90:
328− case 270:
329− if (root.fullscreen) {
330− return 1;
331− } else {
332− return 1 + priv.topMarginProgress * maximizedAppTopMargin / spreadView.width;
333− }
334− break;
335− default:
336− return 1;
337− }
338− }
339−
340− yScale: {
341− switch (appWindowRotation) {
342− case 0:
343− if (root.fullscreen) {
344− return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height;
345− } else {
346− return 1;
347− }
348− break;
349− case 90:
350− case 270:
351− return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height;
352− break;
353− default:
354− return 1;
355− }
356− }
357− },
358−
359− Scale {
360− origin { x: 0; y: spreadView.height / 2 }
361− xScale: priv.scale
362− yScale: xScale
363− },
364− Translate {
365− x: priv.xTranslate
366− }
367− ]
368−
369− opacity: spreadView.phase == 2 ? priv.opacity : 1
370−
371− Rectangle {
372− anchors.fill: parent
373− color: "black"
374− opacity: spreadView.phase < 2 ? 1 - priv.opacity : 0
375− }
376−
377− EasingCurve {
378− id: easingCurve
379− type: EasingCurve.OutSine
380− period: 1 - spreadView.positionMarker2
381− progress: root.progress
382− }
383−
384− // This is used as a calculation helper to figure values for progress other than the current one
385− // Do not bind anything to this...
386− EasingCurve {
387− id: helperEasingCurve
388− type: easingCurve.type
389− period: easingCurve.period
390− }
391−}
qml/Stage/TransformedTabletSpreadDelegate.qmldeleted−436
@@ -1,436 +0,0 @@
1−/*
2− * Copyright 2014 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17−*/
18−
19−import QtQuick 2.4
20−import Utils 0.1
21−import Ubuntu.Components 1.3
22−import Unity.Application 0.1
23−
24−SpreadDelegate {
25− id: root
26−
27− // Set this to true when this tile is selected in the spread. The animation will change to bring the tile to front.
28− property bool selected: false
29− // Set this to true when another tile in the spread is selected. The animation will change to fade this tile out.
30− property bool otherSelected: false
31− // Set this to true when this tile a currently active on either the MS or the SS.
32− property bool active: false
33−
34− property int zIndex
35− property real progress: 0
36− property real animatedProgress: 0
37−
38− property real startDistance: units.gu(5)
39− property real endDistance: units.gu(.5)
40−
41− property real startScale: 1.1
42− property real endScale: 0.7
43− property real dragStartScale: startScale + .2
44−
45− property real startAngle: 15
46− property real endAngle: 5
47−
48− property bool isInSideStage: false
49−
50− property int stage: ApplicationInfoInterface.MainStage
51−
52− property int dragOffset: 0
53− readonly property alias xTranslateAnimating: xTranslateAnimation.running
54− readonly property bool offScreen: priv.xTranslate >= 0
55−
56− dropShadow: spreadView.active ||
57− (active
58− && (root.stage == ApplicationInfoInterface.MainStage || !priv.shellIsLandscape)
59− && priv.xTranslate != 0)
60−
61− onSelectedChanged: {
62− if (selected) {
63− priv.snapshot();
64− }
65− priv.isSelected = selected;
66− }
67−
68− onOtherSelectedChanged: {
69− if (otherSelected) {
70− priv.snapshot();
71− }
72− priv.otherSelected = otherSelected;
73− }
74−
75− Connections {
76− target: spreadView
77−
78− onPhaseChanged: {
79− if (spreadView.phase == 1) {
80− var phase2Progress = spreadView.positionMarker4 - (root.zIndex * spreadView.tileDistance / spreadView.width);
81− priv.phase2StartTranslate = priv.easingAnimation(0, 1, 0, -spreadView.width + (root.zIndex * root.endDistance), phase2Progress);
82− priv.phase2StartScale = priv.easingAnimation(0, 1, root.startScale, root.endScale, phase2Progress);
83− priv.phase2StartAngle = priv.easingAnimation(0, 1, root.startAngle, root.endAngle, phase2Progress);
84− priv.phase2StartTopMarginProgress = priv.easingAnimation(0, 1, 0, 1, phase2Progress);
85− }
86− }
87− }
88−
89− // Required to be an item because we're using states on it.
90− Item {
91− id: priv
92−
93− // true if this is the next tile on the stack that comes in when dragging from the right
94− property bool nextInStack: spreadView.nextInStack == model.index
95− // true if the next tile in the stack is the nextInStack one. This one will be moved a bit to the left
96− property bool movedActive: spreadView.nextZInStack == zIndex + 1
97− property real animatedEndDistance: linearAnimation(0, 2, root.endDistance, 0, root.progress)
98−
99− property real phase2StartTranslate
100− property real phase2StartScale
101− property real phase2StartAngle
102− property real phase2StartTopMarginProgress
103−
104− property bool isSelected: false
105− property bool otherSelected: false
106− property real selectedProgress
107− property real selectedXTranslate
108− property real selectedAngle
109− property real selectedScale
110− property real selectedOpacity
111− property real selectedTopMarginProgress
112−
113− function snapshot() {
114− selectedProgress = root.progress;
115− selectedXTranslate = xTranslate;
116− selectedAngle = angle;
117− selectedScale = priv.scale;
118− selectedOpacity = priv.opacityTransform;
119− selectedTopMarginProgress = topMarginProgress;
120− }
121−
122− // This calculates how much negative progress there can be if unwinding the spread completely
123− // the progress for each tile starts at 0 when it crosses the right edge, so the later a tile comes in,
124− // the bigger its negativeProgress can be.
125− property real negativeProgress: {
126− if (nextInStack && spreadView.phase < 2) {
127− return 0;
128− }
129− return -root.zIndex * spreadView.tileDistance / spreadView.width;
130− }
131−
132− function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
133− // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
134− return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
135− }
136−
137− function easingAnimation(startProgress, endProgress, startValue, endValue, progress) {
138− helperEasingCurve.progress = progress - startProgress;
139− helperEasingCurve.period = endProgress - startProgress;
140− return helperEasingCurve.value * (endValue - startValue) + startValue;
141− }
142−
143− Behavior on xTranslate {
144− enabled: !spreadView.active &&
145− !snapAnimation.running &&
146− spreadView.animateX &&
147− !spreadView.beingResized &&
148− priv.state !== "sideStage"
149− UbuntuNumberAnimation {
150− id: xTranslateAnimation
151− duration: UbuntuAnimation.FastDuration
152− }
153− }
154−
155− property real xTranslate: {
156− var newTranslate = 0;
157−
158− // selected app or opposite stage active app.
159− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
160− && spreadView.selectedDelegate.stage !== root.stage)) {
161− if (root.stage == ApplicationInfoInterface.MainStage) {
162− return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.width, root.progress);
163− } else {
164− return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.sideStageWidth, root.progress);
165− }
166− } else if (otherSelected) {
167− return selectedXTranslate;
168− }
169−
170− // The tile should move a bit to the left if a new one comes on top of it, but not for the Side Stage and not
171− // when we're only dragging the side stage in on top of a main stage app
172− var shouldMoveAway = spreadView.nextInStack >= 0 && priv.movedActive && root.stage === ApplicationInfoInterface.MainStage &&
173− topLevelSurfaceList.applicationAt(spreadView.nextInStack).stage === ApplicationInfoInterface.MainStage;
174−
175− if (active) {
176− newTranslate -= root.width
177− // Only do the hide animation for active apps in the mainstage, and not if we only drag the ss in
178− if (spreadView.phase == 0 && shouldMoveAway) {
179− newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress);
180− }
181− newTranslate += root.dragOffset;
182− } else if (!spreadView.active) {
183− newTranslate -= root.width;
184− }
185−
186− if (!spreadView.active) {
187− return newTranslate;
188− }
189−
190− var shadowOffset = units.gu(2);
191−
192− if (spreadView.phase == 0) {
193− if (nextInStack) {
194− if (root.stage == ApplicationInfoInterface.MainStage) {
195− if (spreadView.sideStageVisible && root.progress > 0) {
196− // Move it so it appears from behind the side stage immediately
197− newTranslate += -spreadView.sideStageWidth;
198− }
199− }
200−
201− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
202− // This is when we only drag the side stage in, without rotation or snapping
203− newTranslate = linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth, root.animatedProgress);
204− } else {
205− newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth * spreadView.snapPosition, root.animatedProgress);
206− }
207− } else if (!root.active) {
208− newTranslate += shadowOffset;
209− }
210− }
211−
212− if (spreadView.phase == 1) {
213− if (nextInStack) {
214− if (root.stage == ApplicationInfoInterface.MainStage) {
215− var startValue = -spreadView.sideStageWidth * spreadView.snapPosition + (spreadView.sideStageVisible ? -spreadView.sideStageWidth : 0);
216− newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startValue, priv.phase2StartTranslate, root.animatedProgress);
217− } else {
218− var endValue = -spreadView.width + spreadView.width * root.zIndex / 6;
219− if (!spreadView.sideStageVisible) {
220− newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth, priv.phase2StartTranslate, root.animatedProgress);
221− } else {
222− newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth * spreadView.snapPosition, priv.phase2StartTranslate, root.animatedProgress);
223− }
224− }
225− } else if (root.active) {
226− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
227− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
228− var startTranslate = -root.width + (shouldMoveAway ? -units.gu(4) : 0);
229− newTranslate = linearAnimation(startProgress, endProgress, startTranslate, priv.phase2StartTranslate, root.animatedProgress);
230− } else {
231− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
232− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
233− newTranslate = linearAnimation(startProgress, endProgress, shadowOffset * Math.max(0, zIndex-2), priv.phase2StartTranslate, root.animatedProgress);
234− }
235− }
236−
237− if (spreadView.phase == 2) {
238− if (easingCurve.value == 0 && !nextInStack) {
239− newTranslate = shadowOffset;
240− } else {
241− newTranslate = -easingCurve.value * (spreadView.width - root.zIndex * animatedEndDistance);
242− }
243− }
244−
245− return newTranslate;
246− }
247−
248− property real scale: {
249− if (!spreadView.active) {
250− return 1;
251− }
252−
253− // selected app or opposite stage active app.
254− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
255− && spreadView.selectedDelegate.stage !== root.stage)) {
256− return linearAnimation(selectedProgress, negativeProgress, selectedScale, 1, root.progress);
257− } else if (otherSelected) {
258− return selectedScale;
259− }
260−
261− if (spreadView.phase == 0) {
262− if (nextInStack) {
263− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
264− return 1;
265− } else {
266− var targetScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
267− return linearAnimation(0, spreadView.positionMarker2, root.dragStartScale, targetScale, root.animatedProgress);
268− }
269− } else {
270− return 1;
271− }
272− }
273−
274− if (spreadView.phase == 1) {
275− if (nextInStack) {
276− var startScale = 1;
277− if (root.stage !== ApplicationInfoInterface.SideStage || spreadView.sideStageVisible) {
278− startScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
279− }
280− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startScale, priv.phase2StartScale, root.animatedProgress);
281− }
282− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
283− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
284− return linearAnimation(startProgress, endProgress, 1, priv.phase2StartScale, root.animatedProgress);
285− }
286−
287− if (spreadView.phase == 2) {
288− return root.startScale - easingCurve.value * (root.startScale - root.endScale);
289− }
290−
291− return 1;
292− }
293−
294− property real angle: {
295− if (!spreadView.active) {
296− return 0;
297− }
298−
299− // selected app or opposite stage active app.
300− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
301− && spreadView.selectedDelegate.stage !== root.stage)) {
302− return linearAnimation(selectedProgress, negativeProgress, selectedAngle, 0, root.progress);
303− } else if (otherSelected) {
304− return selectedAngle;
305− }
306−
307− // The tile should rotate a bit when another one comes on top, but not when only dragging the side stage in
308− var shouldMoveAway = spreadView.nextInStack == -1 ||
309− spreadView.nextInStack >= 0 && priv.movedActive &&
310− (topLevelSurfaceList.applicationAt(spreadView.nextInStack).stage === ApplicationInfoInterface.MainStage ||
311− root.stage == ApplicationInfoInterface.SideStage);
312−
313− if (spreadView.phase == 0) {
314− if (nextInStack) {
315− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
316− return 0;
317− } else {
318− return linearAnimation(0, spreadView.positionMarker2, root.startAngle, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
319− }
320− }
321− if (shouldMoveAway) {
322− return linearAnimation(0, spreadView.positionMarker2, 0, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
323− }
324− }
325− if (spreadView.phase == 1) {
326− if (nextInStack) {
327− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
328− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, 0, priv.phase2StartAngle, root.animatedProgress);
329− } else {
330− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, root.startAngle * (1-spreadView.snapPosition), priv.phase2StartAngle, root.animatedProgress);
331− }
332− }
333− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
334− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
335− var startAngle = shouldMoveAway ? root.startAngle * (1-spreadView.snapPosition) : 0;
336− return linearAnimation(startProgress, endProgress, startAngle, priv.phase2StartAngle, root.progress);
337− }
338− if (spreadView.phase == 2) {
339− return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
340− }
341−
342− return 0;
343− }
344−
345− property real opacityTransform: {
346− // animate opacity for items not snapping into view.
347− if (spreadView.phase !== 2) return 1;
348− if (root.isSelected) return 1;
349−
350− if (otherSelected) {
351− if (root.active && spreadView.selectedDelegate
352− && spreadView.selectedDelegate.stage !== root.stage) {
353− return 1;
354− }
355− return linearAnimation(selectedProgress, negativeProgress, selectedOpacity, 0, root.progress);
356− }
357− return 1;
358− }
359−
360− property real topMarginProgress: {
361− // selected app or opposite stage active app.
362− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
363− && spreadView.selectedDelegate.stage !== root.stage)) {
364− return linearAnimation(selectedProgress, negativeProgress, selectedTopMarginProgress, 0, root.progress);
365− }
366−
367− if (spreadView.phase == 0) {
368− return 0;
369− } else if (spreadView.phase == 1) {
370− if (nextInStack) {
371− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
372− 0, 1, root.progress);
373− }
374− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
375− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
376− return linearAnimation(startProgress, endProgress, 0, 1, root.progress);
377− }
378− return 1;
379− }
380−
381− states: [
382− State {
383− name: "sideStage";
384− when: root.isInSideStage && spreadView.shiftedContentX == 0 && spreadView.phase == 0
385− PropertyChanges {
386− target: priv;
387− xTranslate: -spreadView.sideStageWidth + spreadView.sideStageWidth * (1-sideStage.progress)
388− }
389− }
390− ]
391− }
392−
393− transform: [
394− Rotation {
395− origin { x: 0; y: spreadView.height / 2 }
396− axis { x: 0; y: 1; z: 0 }
397− angle: priv.angle
398− },
399− Scale {
400− origin { x: 0; y: spreadView.height / 2 }
401− xScale: priv.scale
402− yScale: xScale
403− },
404− Scale {
405− origin { x: 0; y: (spreadView.height * priv.scale) + maximizedAppTopMargin * 3 }
406− xScale: 1
407− yScale: fullscreen ? 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height : 1
408− },
409− Translate {
410− x: priv.xTranslate
411− }
412− ]
413− opacity: priv.opacityTransform
414−
415− UbuntuNumberAnimation {
416− id: fadeBackInAnimation
417− target: root
418− property: "opacity"
419− duration: UbuntuAnimation.SlowDuration
420− from: 0
421− to: 1
422− }
423−
424− EasingCurve {
425− id: easingCurve
426− type: EasingCurve.OutSine
427− period: 1
428− progress: root.progress
429− }
430−
431− EasingCurve {
432− id: helperEasingCurve
433− type: easingCurve.type
434− period: easingCurve.period
435− }
436−}
tests/qmltests/Stage/tst_SpreadDelegate.qmldeleted−423
@@ -1,423 +0,0 @@
1−/*
2− * Copyright 2014-2016 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import QtTest 1.0
19−import Unity.Test 0.1 as UT
20−import ".."
21−import "../../../qml/Components"
22−import "../../../qml/Stages"
23−import Ubuntu.Components 1.3
24−import Ubuntu.Components.ListItems 1.3 as ListItem
25−import Unity.Application 0.1
26−
27−Rectangle {
28− color: "red"
29− id: root
30− width: fakeShell.shortestDimension + controls.width
31− height: fakeShell.longestDimension
32−
33− property QtObject fakeApplication: null
34−
35− Item {
36− id: fakeShell
37−
38− readonly property real shortestDimension: units.gu(40)
39− readonly property real longestDimension: units.gu(70)
40−
41− width: landscape ? longestDimension : shortestDimension
42− height: landscape ? shortestDimension : longestDimension
43−
44− x: landscape ? (height - width) / 2 : 0
45− y: landscape ? (width - height) / 2 : 0
46−
47− property bool landscape: orientationAngle == 90 || orientationAngle == 270
48− property int orientationAngle: shellOrientationAngleSelector.value
49−
50− rotation: orientationAngle
51−
52− Loader {
53− id: spreadDelegateLoader
54− width: parent.width
55− height: parent.height
56−
57− active: false
58− property bool itemDestroyed: false
59− sourceComponent: SpreadDelegate {
60− anchors.fill: parent
61− swipeToCloseEnabled: swipeToCloseCheckbox.checked
62− closeable: closeableCheckbox.checked
63− application: fakeApplication
64− surface: fakeApplication && fakeApplication.surfaceList.count > 0 ? fakeApplication.surfaceList.get(0) : null
65− shellOrientationAngle: shellOrientationAngleSelector.value
66− shellOrientation: {
67− switch (shellOrientationAngleSelector.value) {
68− case 0:
69− return Qt.PortraitOrientation;
70− case 90:
71− return Qt.InvertedLandscapeOrientation;
72− case 180:
73− return Qt.InvertedPortraitOrientation;
74− default: // 270
75− return Qt.LandscapeOrientation;
76− }
77− }
78−
79− orientations: Orientations {
80− // the default values will do
81− }
82−
83− maximizedAppTopMargin: units.gu(3)
84− Component.onDestruction: {
85− spreadDelegateLoader.itemDestroyed = true;
86− }
87− Component.onCompleted: {
88− spreadDelegateLoader.itemDestroyed = false;
89− }
90− }
91− }
92− }
93−
94− Rectangle {
95− id: controls
96− color: "white"
97− x: fakeShell.shortestDimension
98− width: units.gu(30)
99− anchors {
100− top: parent.top
101− bottom: parent.bottom
102− }
103−
104− Column {
105− anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
106− spacing: units.gu(1)
107− Button {
108− id: loadWithWeatherApp
109− text: "Load with ubuntu-weather-app"
110− onClicked: { testCase.restartWithApp("ubuntu-weather-app"); }
111− }
112− Button {
113− id: loadWithGalleryApp
114− text: "Load with gallery-app"
115− onClicked: { testCase.restartWithApp("gallery-app"); }
116− }
117− Row {
118− anchors { left: parent.left; right: parent.right }
119− CheckBox { id: swipeToCloseCheckbox; checked: false; }
120− Label { text: "swipeToCloseEnabled" }
121− }
122− Row {
123− anchors { left: parent.left; right: parent.right }
124− CheckBox { id: closeableCheckbox; checked: false }
125− Label { text: "closeable" }
126− }
127− ListItem.ItemSelector {
128− id: shellOrientationAngleSelector
129− anchors { left: parent.left; right: parent.right }
130− text: "shellOrientationAngle"
131− model: ["0", "90", "180", "270"]
132− property int value: selectedIndex * 90
133− }
134− Button {
135− id: matchShellButton
136− text: "matchShellOrientation()"
137− onClicked: { spreadDelegateLoader.item.matchShellOrientation(); }
138− }
139− Button {
140− id: animateToShellButton
141− text: "animateToShellOrientation()"
142− onClicked: { spreadDelegateLoader.item.animateToShellOrientation(); }
143− }
144− }
145− }
146−
147− UT.UnityTestCase {
148− id: testCase
149− name: "SpreadDelegate"
150− when: windowShown
151−
152− SignalSpy {
153− id: spyClosedSignal
154− target: spreadDelegateLoader.item
155− signalName: "closed"
156− }
157−
158− property var dragArea
159− property Item spreadDelegate: spreadDelegateLoader.item
160−
161− function init() {
162− }
163−
164− function cleanup() {
165− unloadSpreadDelegate();
166− spyClosedSignal.clear();
167− shellOrientationAngleSelector.selectedIndex = 0;
168− root.fakeApplication = null;
169− killApps();
170− }
171−
172− function restartWithApp(appId) {
173− if (spreadDelegateLoader.active) {
174− unloadSpreadDelegate();
175− }
176− if (root.fakeApplication) {
177− ApplicationManager.stopApplication(root.fakeApplication.appId);
178− }
179−
180− root.fakeApplication = ApplicationManager.startApplication(appId);
181− spreadDelegateLoader.active = true;
182− tryCompare(spreadDelegateLoader, "status", Loader.Ready);
183−
184− dragArea = findInvisibleChild(spreadDelegate, "dragArea");
185− dragArea.__dateTime = fakeDateTime;
186− }
187−
188− function unloadSpreadDelegate() {
189− spreadDelegateLoader.active = false;
190− tryCompare(spreadDelegateLoader, "status", Loader.Null);
191− tryCompare(spreadDelegateLoader, "item", null);
192− // Loader.status might be Loader.Null and Loader.item might be null but the Loader
193− // item might still be alive. So if we set Loader.active back to true
194− // again right now we will get the very same Shell instance back. So no reload
195− // actually took place. Likely because Loader waits until the next event loop
196− // iteration to do its work. So to ensure the reload, we will wait until the
197− // Shell instance gets destroyed.
198− tryCompare(spreadDelegateLoader, "itemDestroyed", true);
199−
200− }
201−
202− function waitUntilAppWindowIsFullyLoaded() {
203− var appWindowStateGroup = findInvisibleChild(spreadDelegate, "applicationWindowStateGroup");
204− tryCompareFunction(function() { return appWindowStateGroup.state === "surface" }, true);
205− waitUntilTransitionsEnd(appWindowStateGroup);
206−
207− var priv = findInvisibleChild(spreadDelegate, "spreadDelegatePriv");
208− verify(priv);
209− tryCompare(priv, "startingUp", false);
210− }
211−
212− function rotateShellTo(angle) {
213− shellOrientationAngleSelector.selectedIndex = angle / 90;
214− }
215−
216− function waitUntilRotationAnimationStops() {
217− var orientationChangeAnimation = findInvisibleChild(spreadDelegate, "orientationChangeAnimation");
218− verify(orientationChangeAnimation);
219− tryCompare(orientationChangeAnimation, "running", false);
220− }
221−
222− function checkAppWindowTransformationMatchesRotation(appWindow, angle) {
223−
224− var topLeftX = 0;
225− var topLeftY = 0;
226− var bottomRightX = 0;
227− var bottomRightY = 0;
228−
229− switch (angle) {
230− case 0:
231− topLeftX = 0;
232− topLeftY = 0;
233− bottomRightX = fakeShell.shortestDimension;
234− bottomRightY = fakeShell.longestDimension;
235− break;
236− case 90:
237− topLeftX = fakeShell.shortestDimension;
238− topLeftY = 0;
239− bottomRightX = 0;
240− bottomRightY = fakeShell.longestDimension;
241− break;
242− default:
243− // TODO implement 180 and 270 once we need them
244− verify(false);
245− }
246−
247− var appWindowTopLeftInRootCoords = appWindow.mapToItem(root, 0, 0);
248−
249− if (appWindowTopLeftInRootCoords.x !== topLeftX) {
250− qtest_fail("appWindow topLeft.x ("+appWindowTopLeftInRootCoords.x+")"
251− +" doesn't match expectations ("+topLeftX+").", 1);
252− }
253− if (appWindowTopLeftInRootCoords.y !== topLeftY) {
254− qtest_fail("appWindow topLeft.y ("+appWindowTopLeftInRootCoords.y+")"
255− +" doesn't match expectations ("+topLeftY+").", 1);
256− }
257−
258− var appWindowBottomRightInRootCoords = appWindow.mapToItem(root, appWindow.width,
259− appWindow.height);
260− compare(appWindowBottomRightInRootCoords.x, bottomRightX);
261− compare(appWindowBottomRightInRootCoords.y, bottomRightY);
262−
263− if (appWindowBottomRightInRootCoords.x !== bottomRightX) {
264− qtest_fail("appWindow bottomRight.x ("+appWindowBottomRightInRootCoords.x+")"
265− +" doesn't match expectations ("+bottomRightX+").", 1);
266− }
267− if (appWindowBottomRightInRootCoords.y !== bottomRightY) {
268− qtest_fail("appWindow bottomRight.y ("+appWindowBottomRightInRootCoords.y+")"
269− +" doesn't match expectations ("+bottomRightY+").", 1);
270− }
271− }
272−
273− function test_swipeToClose_data() {
274− return [
275− {tag: "swipeToClose=true closeable=true -> appWindow moves away",
276− swipeToClose: true, closeable: true },
277−
278− {tag: "swipeToClose=true closeable=false -> appWindow bounces back",
279− swipeToClose: true, closeable: false },
280−
281− {tag: "swipeToClose=false -> appWindow stays put",
282− swipeToClose: false, closeable: true },
283− ]
284− }
285−
286− function test_swipeToClose(data) {
287− loadWithGalleryApp.clicked();
288− var displacedAppWindowWithShadow = findChild(spreadDelegateLoader.item, "displacedAppWindowWithShadow");
289−
290− verify(displacedAppWindowWithShadow.y === 0);
291−
292− swipeToCloseCheckbox.checked = data.swipeToClose;
293− closeableCheckbox.checked = data.closeable;
294−
295− var dragDistance = spreadDelegateLoader.item.height * 0.8;
296− var touchX = spreadDelegateLoader.item.width / 2;
297− var fromY = spreadDelegateLoader.item.height * 0.9;
298− var toY = fromY - dragDistance;
299− touchFlick(spreadDelegateLoader.item,
300− touchX /* fromX */, fromY, touchX /* toX */, toY,
301− true /* beginTouch */, false /* endTouch */, dragArea.minSpeedToClose * 1.1 /* speed */);
302−
303− if (data.swipeToClose) {
304− verify(displacedAppWindowWithShadow.y < 0);
305− var threshold = findChild(spreadDelegateLoader.item, "dragArea").threshold
306− if (data.closeable) {
307− // Verify that the delegate started moving exactly "threshold" after the finger movement
308− // and did not jump up to the finger, but lags the threshold behind
309− compare(Math.abs(Math.abs(displacedAppWindowWithShadow.y) - dragDistance), threshold);
310− } else {
311− verify(Math.abs(Math.abs(displacedAppWindowWithShadow.y) - dragDistance) > threshold);
312− }
313−
314− touchRelease(spreadDelegateLoader.item, touchX, toY - units.gu(1));
315−
316− waitForCloseAnimationToFinish();
317−
318− if (data.closeable) {
319− verify(spyClosedSignal.count === 1);
320− } else {
321− verify(spyClosedSignal.count === 0);
322− tryCompare(displacedAppWindowWithShadow, "y", 0);
323− }
324−
325− } else {
326− verify(displacedAppWindowWithShadow.y === 0);
327−
328− touchRelease(spreadDelegateLoader.item, touchX, toY);
329− }
330− }
331−
332− function test_loadingLandscapeOnlyAppWhenShellInPortrait() {
333− loadWithWeatherApp.clicked();
334−
335− var appWindow = findChild(spreadDelegate, "appWindow");
336− verify(appWindow);
337−
338− // It must have landscape dimensions as it does not support portrait
339− tryCompare(appWindow, "width", fakeShell.height);
340− tryCompare(appWindow, "height", fakeShell.width - spreadDelegate.maximizedAppTopMargin);
341− }
342−
343− function test_keepsSceneTransformationWhenShellRotates_data() {
344− return [
345− {tag: "0", selectedIndex: 0},
346− {tag: "90", selectedIndex: 1},
347− {tag: "180", selectedIndex: 2},
348− {tag: "270", selectedIndex: 3}
349− ];
350− }
351− function test_keepsSceneTransformationWhenShellRotates(data) {
352− loadWithGalleryApp.clicked();
353−
354− waitUntilAppWindowIsFullyLoaded();
355−
356− var appWindowWithShadow = findChild(spreadDelegate, "appWindowWithShadow");
357− verify(appWindowWithShadow);
358−
359− compare(appWindowWithShadow.state, "keepSceneRotation");
360−
361− shellOrientationAngleSelector.selectedIndex = data.selectedIndex;
362−
363− // must keep same aspect ratio
364− compare(appWindowWithShadow.width, fakeShell.shortestDimension);
365− compare(appWindowWithShadow.height, fakeShell.longestDimension);
366−
367−
368− // and scene transformation must be the identity (ie, no rotation or translation)
369− checkAppWindowTransformationMatchesRotation(appWindowWithShadow, 0);
370− }
371−
372− function waitForCloseAnimationToFinish() {
373− var closeAnimation = findInvisibleChild(spreadDelegateLoader.item, "closeAnimation");
374− wait(closeAnimation.duration * 1.5);
375− tryCompare(closeAnimation, "running", false);
376− }
377−
378− function test_showHighLight() {
379− loadWithGalleryApp.clicked();
380− var highlightRect = findChild(spreadDelegateLoader.item, "selectionHighlight")
381− tryCompare(highlightRect, "visible", false)
382− spreadDelegateLoader.item.highlightShown = true;
383− tryCompare(highlightRect, "visible", true)
384− }
385−
386− /*
387− Checks that the ApplicationWindow position, size and rotation is correct after
388− a sequence of shell rotations folowed by rotations (immediate or not) to match them
389− */
390− function test_animateToShellThenMatchShell() {
391− loadWithGalleryApp.clicked();
392− waitUntilAppWindowIsFullyLoaded();
393−
394− var appWindowWithShadow = findChild(spreadDelegate, "appWindowWithShadow");
395− verify(appWindowWithShadow);
396−
397− // appWindow transformation is 0 relative to display
398− checkAppWindowTransformationMatchesRotation(appWindowWithShadow, 0);
399−
400− rotateShellTo(90);
401−
402− // appWindow transformation remains 0 relative to display
403− checkAppWindowTransformationMatchesRotation(appWindowWithShadow, 0);
404−
405− animateToShellButton.clicked();
406− waitUntilRotationAnimationStops();
407−
408− // appWindow transformation is now 90 relative to display, just like shell
409− checkAppWindowTransformationMatchesRotation(appWindowWithShadow, 90);
410−
411− rotateShellTo(0);
412−
413− // appWindow transformation is remains 90 relative to display.
414− checkAppWindowTransformationMatchesRotation(appWindowWithShadow, 90);
415−
416− matchShellButton.clicked();
417−
418− // appWindow transformation is back to 0 relative to display, just like shell
419− checkAppWindowTransformationMatchesRotation(appWindowWithShadow, 0);
420−
421− }
422− }
423−}