on xenial help sign in
improve mouse interaction with CoverFlip
e7794e3Michael Zanetti
qml/Stages/CoverFlipDelegate.qmlnew file+6
@@ -0,0 +1,6 @@
1+import QtQuick 2.0
2+
3+Rectangle {
4+ width: 100
5+ height: 62
6+}
qml/Stages/PhoneStage.qml+89−50
@@ -215,17 +215,47 @@ Item {
215 anchors.fill: root
215 anchors.fill: root
216 blockInput: coverFlip.visible
216 blockInput: coverFlip.visible
217 }
217 }
218−// MouseArea {
218+ MouseArea {
219−// anchors.fill: root
219+ anchors.fill: root
220−// enabled: coverFlip.visible
220+ enabled: coverFlip.visible
221−// property int oldMouseX
221+ property int oldMouseX
222−
222+ property int startX
223+
224+ property bool isDrag: false
225+
226+ onPressed: {
227+ isDrag = false
223−// onPressed: oldMouseX = mouseX
228+ oldMouseX = mouseX
229+ startX = mouseX
230+ }
231+
224−// onMouseXChanged: {
232+ onMouseXChanged: {
225−// coverFlip.progress += (oldMouseX - mouseX) * .001
233+ var diff = (oldMouseX - mouseX) * .001;
234+ coverFlip.progress = Math.max(.8, coverFlip.progress + diff);
226−// oldMouseX = mouseX
235+ oldMouseX = mouseX
236+ print("mousex changed", mouseX - startX)
237+ if (Math.abs(mouseX - startX) > units.gu(.5)) {
238+ isDrag = true;
239+ }
240+ }
241+ onClicked: {
242+ // From Qt docs:
243+ // "A click is defined as a press followed by a release, both inside the
244+ // MouseArea (pressing, moving outside the MouseArea, and then moving back
245+ // inside and releasing is also considered a click)."
246+ // This means, that pressing, moving the coverFlip around and then releasing
247+ // will still be threated as a click. Let's add our own logic to not activate
248+ // a tile if the user just wants to drag stuff around.
249+ if (isDrag) {
250+ return;
251+ }
252+
253+ var index = Math.floor(mouseX / coverFlip.tileWidth)
254+ index = Math.min(tileRepeater.count - 1, index)
255+ print("clicked item", index)
256+ coverFlip.selectItem(index);
227−// }
257+ }
228−// }
258+ }
229
259
230 Row {
260 Row {
231 id: coverFlip
261 id: coverFlip
@@ -236,19 +266,28 @@ Item {
236 property real progress: 0
266 property real progress: 0
237 property int maxAngle: 45
267 property int maxAngle: 45
238 property real minScale: .6
268 property real minScale: .6
269+ property bool animatingBack: false
270+
271+ property real tileWidth: Math.max(units.gu(2), root.width - (coverFlip.progress * root.width))
272+
239// onProgressChanged: print("CoverFlip progress changed", progress)
273// onProgressChanged: print("CoverFlip progress changed", progress)
274+ onXChanged: print("coverflip x changed", x)
240
275
241 function snap() {
276 function snap() {
242 if (coverFlip.progress < 0.25) {
277 if (coverFlip.progress < 0.25) {
243 snapAnimation.targetProgress = 0
278 snapAnimation.targetProgress = 0
244− } else if (coverFlip.progress < 0.75) {
279+ } else if (coverFlip.progress < 0.6) {
245 snapAnimation.targetProgress = 0.5
280 snapAnimation.targetProgress = 0.5
246 } else {
281 } else {
247− snapAnimation.targetProgress = 1;
282+ snapAnimation.targetProgress = .8;
248 }
283 }
249 snapAnimation.start();
284 snapAnimation.start();
250 }
285 }
251
286
287+ function selectItem(index) {
288+ tileRepeater.itemAt(index).select();
289+ }
290+
252 SequentialAnimation {
291 SequentialAnimation {
253 id: snapAnimation
292 id: snapAnimation
254 property var targetProgress
293 property var targetProgress
@@ -269,15 +308,21 @@ Item {
269 }
308 }
270
309
271 Repeater {
310 Repeater {
311+ id: tileRepeater
272 model: ApplicationManager
312 model: ApplicationManager
273
313
274 Item {
314 Item {
275 height: parent.height
315 height: parent.height
276− width: Math.max(root.width / ApplicationManager.count, appImage.implicitWidth - (coverFlip.progress * appImage.implicitWidth))
316+ width: coverFlip.tileWidth
317+
318+ function select() {
319+ switchToAppAnimation.start();
320+ }
277
321
278 Image {
322 Image {
279 id: appImage
323 id: appImage
280− height: parent.height
324+ anchors { left: parent.left; bottom: parent.bottom }
325+ width: root.width
281 source: ApplicationManager.get(index).screenshot
326 source: ApplicationManager.get(index).screenshot
282 scale: 1
327 scale: 1
283
328
@@ -289,29 +334,37 @@ Item {
289 axis { x: 0; y: 1; z: 0 }
334 axis { x: 0; y: 1; z: 0 }
290 angle: {
335 angle: {
291 var newAngle = 0;
336 var newAngle = 0;
292− switch (index) {
337+ if (coverFlip.animatingBack) {
293− case 0:
294− if (appImage.progress < .5) {
295− newAngle = appImage.progress * coverFlip.maxAngle;
296− } else {
297− newAngle = (appImage.progress - .5) * coverFlip.maxAngle * 2;
298− }
299− break;
300− case 1:
301− if (appImage.progress < .5) {
302− newAngle = coverFlip.maxAngle - (appImage.progress * coverFlip.maxAngle * 2);
303− } else {
304− newAngle = (appImage.progress - .5) * coverFlip.maxAngle * 2;
305− }
306− break;
307− default:
308 newAngle = Math.min(appImage.progress, .75) * coverFlip.maxAngle;
338 newAngle = Math.min(appImage.progress, .75) * coverFlip.maxAngle;
339+ } else {
340+ switch (index) {
341+ case 0:
342+ if (appImage.progress < .5) {
343+ newAngle = appImage.progress * coverFlip.maxAngle;
344+ } else {
345+ newAngle = (appImage.progress - .5) * coverFlip.maxAngle * 2;
346+ }
347+ break;
348+ case 1:
349+ if (appImage.progress < .5) {
350+ newAngle = coverFlip.maxAngle - (appImage.progress * coverFlip.maxAngle * 2);
351+ } else {
352+ newAngle = (appImage.progress - .5) * coverFlip.maxAngle * 2;
353+ }
354+ break;
355+ default:
356+ newAngle = Math.min(appImage.progress, .75) * coverFlip.maxAngle;
357+ }
309 }
358 }
310 return Math.min(newAngle, coverFlip.maxAngle);
359 return Math.min(newAngle, coverFlip.maxAngle);
311 }
360 }
312 },
361 },
313 Translate {
362 Translate {
314 x: {
363 x: {
364+ if (coverFlip.animatingBack) {
365+ return 0;
366+ }
367+
315 switch (index) {
368 switch (index) {
316 case 1:
369 case 1:
317 if (appImage.progress < .5) {
370 if (appImage.progress < .5) {
@@ -342,37 +395,23 @@ Item {
342 ]
395 ]
343
396
344 }
397 }
345− MouseArea {
346− anchors.fill: parent
347−
348− property int oldMouseX
349−
350− onPressed: oldMouseX = mouseX
351− onMouseXChanged: {
352− coverFlip.progress += (oldMouseX - mouseX) * .001
353− oldMouseX = mouseX
354− }
355−
356− onClicked: {
357− print("clicked item", index)
358− switchToAppAnimation.start();
359− }
360− }
361
398
362 SequentialAnimation {
399 SequentialAnimation {
363 id: switchToAppAnimation
400 id: switchToAppAnimation
401+ PropertyAction { target: coverFlip; property: "animatingBack"; value: true }
364 ParallelAnimation {
402 ParallelAnimation {
365− UbuntuNumberAnimation { target: appImage; property: "progress"; to: 0 }
403+ UbuntuNumberAnimation { target: coverFlip; property: "progress"; to: 0 }
366− UbuntuNumberAnimation { target: appImage; property: "x"; to: -width * index }
404+ UbuntuNumberAnimation { target: coverFlip; property: "x"; to: -root.width * index }
367 }
405 }
368 ScriptAction {
406 ScriptAction {
369 script: {
407 script: {
370 ApplicationManager.focusApplication(ApplicationManager.get(index).appId);
408 ApplicationManager.focusApplication(ApplicationManager.get(index).appId);
371 coverFlip.progress = 0;
409 coverFlip.progress = 0;
410+ coverFlip.x = 0;
411+ coverFlip.animatingBack = false;
372 appImage.x = 0;
412 appImage.x = 0;
373 }
413 }
374 }
414 }
375−
376 }
415 }
377 }
416 }
378 }
417 }