Unity 8
SpreadDelegate.qml
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  * Daniel d'Andrada <daniel.dandrada@canonical.com>
18  */
19 
20 import QtQuick 2.0
21 import Ubuntu.Components 1.1
22 import "../Components"
23 
24 FocusScope {
25  id: root
26 
27  // to be read from outside
28  readonly property bool dragged: dragArea.moving
29  signal clicked()
30  signal closed()
31 
32  // to be set from outside
33  property bool interactive: true
34  property bool dropShadow: true
35  property real maximizedAppTopMargin
36  property alias swipeToCloseEnabled: dragArea.enabled
37  property bool closeable
38  property alias application: appWindow.application
39  property int orientation
40 
41  Item {
42  objectName: "appWindowWithShadow"
43 
44  readonly property real limit: root.height / 4
45 
46  y: root.closeable ? dragArea.distance : elastic(dragArea.distance)
47  width: parent.width
48  height: parent.height
49 
50  function elastic(distance) {
51  var k = distance < 0 ? -limit : limit
52  return k * (1 - Math.pow((k - 1) / k, distance))
53  }
54 
55  BorderImage {
56  anchors {
57  fill: appWindow
58  margins: -units.gu(2)
59  }
60  source: "graphics/dropshadow2gu.sci"
61  opacity: root.dropShadow ? .3 : 0
62  Behavior on opacity { UbuntuNumberAnimation {} }
63  }
64 
65  ApplicationWindow {
66  id: appWindow
67  objectName: application ? "appWindow_" + application.appId : "appWindow_null"
68  focus: true
69  anchors {
70  fill: parent
71  topMargin: appWindow.fullscreen ? 0 : maximizedAppTopMargin
72  }
73 
74  interactive: root.interactive
75  orientation: root.orientation
76  }
77  }
78 
79  DraggingArea {
80  id: dragArea
81  objectName: "dragArea"
82  anchors.fill: parent
83 
84  property bool moving: false
85  property real distance: 0
86  readonly property int threshold: units.gu(2)
87  property int offset: 0
88 
89  readonly property real minSpeedToClose: units.gu(40)
90 
91  onDragValueChanged: {
92  if (!dragging) {
93  return;
94  }
95  moving = moving || Math.abs(dragValue) > threshold;
96  if (moving) {
97  distance = dragValue + offset;
98  }
99  }
100 
101  onMovingChanged: {
102  if (moving) {
103  offset = (dragValue > 0 ? -threshold: threshold)
104  } else {
105  offset = 0;
106  }
107  }
108 
109  onClicked: {
110  if (!moving) {
111  root.clicked();
112  }
113  }
114 
115  onDragEnd: {
116  if (!root.closeable) {
117  animation.animate("center")
118  return;
119  }
120 
121  // velocity and distance values specified by design prototype
122  if ((dragVelocity < -minSpeedToClose && distance < -units.gu(8)) || distance < -root.height / 2) {
123  animation.animate("up")
124  } else if ((dragVelocity > minSpeedToClose && distance > units.gu(8)) || distance > root.height / 2) {
125  animation.animate("down")
126  } else {
127  animation.animate("center")
128  }
129  }
130 
131  UbuntuNumberAnimation {
132  id: animation
133  objectName: "closeAnimation"
134  target: dragArea
135  property: "distance"
136  property bool requestClose: false
137 
138  function animate(direction) {
139  animation.from = dragArea.distance;
140  switch (direction) {
141  case "up":
142  animation.to = -root.height * 1.5;
143  requestClose = true;
144  break;
145  case "down":
146  animation.to = root.height * 1.5;
147  requestClose = true;
148  break;
149  default:
150  animation.to = 0
151  }
152  animation.start();
153  }
154 
155  onRunningChanged: {
156  if (!running) {
157  dragArea.moving = false;
158  if (requestClose) {
159  root.closed();
160  } else {
161  dragArea.distance = 0;
162  }
163  }
164  }
165  }
166  }
167 }