on xenial help sign in
make flicking AND clicking work
commite48b96b91d3def4c663c7c87b7df2f27ab48f03a authorMichael Zanetti <michael.zanetti@canonical.com> dateWed 15 Jan 2014, 11:33 (13 years ago) parent354cdc9
1 file changed+290−287
qml/Stages/PhoneStage.qml+290−287
qml/Stages/PhoneStage.qml+290−287
@@ -221,347 +221,350 @@ Item {
221221 anchors.fill: root
222222 blockInput: coverFlip.visible
223223 }
224+
224225 Flickable {
225226 id: coverFlickable
226227 anchors.fill: root
227228 contentHeight: height
228− contentWidth: width * ApplicationManager.count
229+ contentWidth: width * ApplicationManager.count * 0.5
229230 flickableDirection: Qt.Horizontal
230231 enabled: coverFlip.visible
231232
232233 onContentXChanged: {
233−// print("contentX changed", contentX)
234234 var progress = contentX / width
235235 if (progress > coverFlip.progressMarker1) {
236236 progress += progress - coverFlip.progressMarker1
237237 }
238238
239239 coverFlip.progress = progress;
240−// print("progress is", coverFlip.progress)
241240 }
242− }
243−
244− Row {
245− id: coverFlip
246− height: parent.height
247− x: 0
248− visible: progress > 0
249−
250− property real progress: 0
251− property real startAngle: 45
252− property int endAngle: 10
253−
254− property real maxScale: 1.4
255− property real minScale: .6
256−
257− // Markers: relative screen position from left to right
258− // marks the line where first application is finished moving in from the right
259− property real progressMarker1: 0.5
260−
261− property real tileDistance: 0.1
262−
263− property bool animatingBack: false
264−
265− property real tileWidth: root.width
266−
267− property real oldProgress: 0
268− onProgressChanged: {
269− if (oldProgress <= coverFlip.progressMarker1 && progress > coverFlip.progressMarker1) {
270− ApplicationManager.focusApplication(ApplicationManager.get(1).appId)
271− } else if (oldProgress >= coverFlip.progressMarker1 && progress <= coverFlip.progressMarker1) {
272− ApplicationManager.focusApplication(ApplicationManager.get(1).appId)
241+ Row {
242+ id: coverFlip
243+ height: parent.height
244+ // The MouseAreas on the AppImages need to be children of the flickable in order to make focus stealing
245+ // for flicking vs. clicking work correctly.
246+ // However, for the animation calculations to become easier we don't want the row to move so we don't
247+ // always have to take contentX into account. So lets just compensate the flickable's movement here.
248+ x: coverFlickable.contentX
249+ visible: progress > 0
250+
251+ property real progress: 0
252+ property real startAngle: 45
253+ property int endAngle: 10
254+
255+ property real maxScale: 1.4
256+ property real minScale: .6
257+
258+ // Markers: relative screen position from left to right
259+ // marks the line where first application is finished moving in from the right
260+ property real progressMarker1: 0.5
261+
262+ property real tileDistance: 0.1
263+
264+ property bool animatingBack: false
265+
266+ property real tileWidth: root.width
267+
268+ property real oldProgress: 0
269+ onProgressChanged: {
270+ if (oldProgress <= coverFlip.progressMarker1 && progress > coverFlip.progressMarker1) {
271+ ApplicationManager.focusApplication(ApplicationManager.get(1).appId)
272+ } else if (oldProgress >= coverFlip.progressMarker1 && progress <= coverFlip.progressMarker1) {
273+ ApplicationManager.focusApplication(ApplicationManager.get(1).appId)
274+ }
275+ oldProgress = progress;
273276 }
274− oldProgress = progress;
275− }
276277
277− function snap() {
278− if (coverFlip.progress < 0.25) {
279− snapAnimation.targetContentX = 0
280− } else if (coverFlip.progress < 0.6) {
281− snapAnimation.targetContentX = root.width * coverFlip.progressMarker1
282− } else {
283− if (ApplicationManager.count == 3) {
284− snapAnimation.targetContentX = root.width * .8;
278+ function snap() {
279+ if (coverFlip.progress < 0.25) {
280+ snapAnimation.targetContentX = 0
281+ } else if (coverFlip.progress < 0.6) {
282+ snapAnimation.targetContentX = root.width * coverFlip.progressMarker1
285283 } else {
286− snapAnimation.targetContentX = root.width * .9;
284+ if (ApplicationManager.count == 3) {
285+ snapAnimation.targetContentX = root.width * .8;
286+ } else {
287+ snapAnimation.targetContentX = root.width * .9;
288+ }
287289 }
290+ snapAnimation.start();
288291 }
289− snapAnimation.start();
290− }
291292
292− function selectItem(index) {
293− tileRepeater.itemAt(index).select();
294− }
293+ function selectItem(index) {
294+ tileRepeater.itemAt(index).select();
295+ }
295296
296− SequentialAnimation {
297− id: snapAnimation
298− property var targetContentX
297+ SequentialAnimation {
298+ id: snapAnimation
299+ property var targetContentX
299300
300− UbuntuNumberAnimation {
301− target: coverFlickable
302− properties: "contentX"
303− to: snapAnimation.targetContentX
304− }
305− ScriptAction {
306− script: {
307− if (snapAnimation.targetContentX == root.width * coverFlip.progressMarker1) {
308− coverFlickable.contentX = 0;
301+ UbuntuNumberAnimation {
302+ target: coverFlickable
303+ properties: "contentX"
304+ to: snapAnimation.targetContentX
305+ }
306+ ScriptAction {
307+ script: {
308+ if (snapAnimation.targetContentX == root.width * coverFlip.progressMarker1) {
309+ coverFlickable.contentX = 0;
310+ }
309311 }
310312 }
311313 }
312− }
313314
314− Repeater {
315− id: tileRepeater
316− model: ApplicationManager
317−
318− Item {
319− height: parent.height
320− width: coverFlip.tileWidth
321−
322− Image {
323− id: appImage
324− anchors { left: parent.left; bottom: parent.bottom }
325− width: root.width
326− source: ApplicationManager.get(index).screenshot
327− scale: 1
328−
329− // This is the main progress, of the gesture, the same for every tile
330− property real progress: coverFlip.progress
331− // The progress, translated for the second stage of the animation, after the first app switch has happened
332− // Additionally it speeds it up a bit, depending on the distance of the tile
333− property real translatedProgress: appImage.progress - coverFlip.progressMarker1 - (coverFlip.tileDistance * (index-1))
334−
335− // Is this tile selected by a click?
336− property bool isSelected: false
337− // We need to remember some values when app is selected to be able to animate it to the foreground
338− property real selectedXTranslation: 0
339− property real selectedTranslatedProgress: 0
340− property real selectedAngle: 0
341− property real selectedXScale: 0
342−
343− function select() {
344− print("selecting item, current translation:", appImage.xTranslation)
345− appImage.selectedXTranslation = appImage.xTranslation;
346− appImage.selectedAngle = appImage.angle;
347− appImage.selectedXScale = appImage.xScale;
348− appImage.selectedTranslatedProgress = appImage.translatedProgress;
349− print("set selected x translation", appImage.selectedXTranslation)
350− appImage.isSelected = true;
351− switchToAppAnimation.start();
352− }
315+ Repeater {
316+ id: tileRepeater
317+ model: ApplicationManager
318+
319+ Item {
320+ height: parent.height
321+ width: coverFlip.tileWidth
322+
323+ Image {
324+ id: appImage
325+ anchors { left: parent.left; bottom: parent.bottom }
326+ width: root.width
327+ source: ApplicationManager.get(index).screenshot
328+ scale: 1
329+
330+ // This is the main progress, of the gesture, the same for every tile
331+ property real progress: coverFlip.progress
332+ // The progress, translated for the second stage of the animation, after the first app switch has happened
333+ // Additionally it speeds it up a bit, depending on the distance of the tile
334+ property real translatedProgress: appImage.progress - coverFlip.progressMarker1 - (coverFlip.tileDistance * (index-1))
335+
336+ // Is this tile selected by a click?
337+ property bool isSelected: false
338+ // We need to remember some values when app is selected to be able to animate it to the foreground
339+ property real selectedXTranslation: 0
340+ property real selectedTranslatedProgress: 0
341+ property real selectedAngle: 0
342+ property real selectedXScale: 0
343+
344+ function select() {
345+ print("selecting item, current translation:", appImage.xTranslation)
346+ appImage.selectedXTranslation = appImage.xTranslation;
347+ appImage.selectedAngle = appImage.angle;
348+ appImage.selectedXScale = appImage.xScale;
349+ appImage.selectedTranslatedProgress = appImage.translatedProgress;
350+ print("set selected x translation", appImage.selectedXTranslation)
351+ appImage.isSelected = true;
352+ switchToAppAnimation.start();
353+ }
353354
354− property int xTranslation: {
355− var xTranslate = 0;
356− var minXTranslate = -index * root.width + index * units.dp(3);
357− switch (index) {
358− case 0:
359− if (appImage.progress < coverFlip.progressMarker1) {
360− var progress = appImage.progress
361− var progressDiff = coverFlip.progressMarker1
362− var translateDiff = -root.width * 0.25
363− // progress : progressDiff = translate : translateDiff
364− xTranslate = progress * translateDiff / progressDiff
365− }
366− break;
367− case 1:
368− if (appImage.progress < coverFlip.progressMarker1) {
369− var progress = appImage.progress;
370− var progressDiff = coverFlip.progressMarker1;
371− var translateDiff = -root.width;
372− // progress : progressDiff = translate : translateDiff
373− xTranslate = progress * translateDiff / progressDiff;
355+ property int xTranslation: {
356+ var xTranslate = 0;
357+ var minXTranslate = -index * root.width + index * units.dp(3);
358+ switch (index) {
359+ case 0:
360+ if (appImage.progress < coverFlip.progressMarker1) {
361+ var progress = appImage.progress
362+ var progressDiff = coverFlip.progressMarker1
363+ var translateDiff = -root.width * 0.25
364+ // progress : progressDiff = translate : translateDiff
365+ xTranslate = progress * translateDiff / progressDiff
366+ }
374367 break;
368+ case 1:
369+ if (appImage.progress < coverFlip.progressMarker1) {
370+ var progress = appImage.progress;
371+ var progressDiff = coverFlip.progressMarker1;
372+ var translateDiff = -root.width;
373+ // progress : progressDiff = translate : translateDiff
374+ xTranslate = progress * translateDiff / progressDiff;
375+ break;
376+ }
377+ // Intentionally no break here...
378+ default:
379+ if (appImage.progress > coverFlip.progressMarker1) {
380+ xTranslate = xTranslateEasing.value * xTranslateEasing.period;
381+
382+ // make sure we stop at the left screen edge
383+ // xTranslate = Math.max(xTranslate, minXTranslate)
384+ break;
385+ }
375386 }
376− // Intentionally no break here...
377− default:
378− if (appImage.progress > coverFlip.progressMarker1) {
379− xTranslate = xTranslateEasing.value * xTranslateEasing.period;
380−
381− // make sure we stop at the left screen edge
382−// xTranslate = Math.max(xTranslate, minXTranslate)
383− break;
387+ if (appImage.isSelected) {
388+ var newTranslate = selectedXTranslateEasing.value * selectedXTranslateEasing.period
389+ xTranslate = appImage.selectedXTranslation + newTranslate;
384390 }
385− }
386− if (appImage.isSelected) {
387− var newTranslate = selectedXTranslateEasing.value * selectedXTranslateEasing.period
388− xTranslate = appImage.selectedXTranslation + newTranslate;
389− }
390391
391− return xTranslate;
392− }
392+ return xTranslate;
393+ }
393394
394− property real angle: {
395− var newAngle = 0;
396− switch (index) {
397− case 0:
398− if (appImage.progress <= coverFlip.progressMarker1) {
399− var progress = appImage.progress;
400− var angleDiff = coverFlip.endAngle;
401− var progressDiff = coverFlip.progressMarker1;
402− // progress : progressDiff = angle : angleDiff
403− newAngle = progress * angleDiff / progressDiff;
404− } else {
405− var progress = appImage.progress - coverFlip.progressMarker1;
406− var angleDiff = coverFlip.endAngle;
407− var progressDiff = 1 - coverFlip.progressMarker1;
408− // progress : progressDiff = angle : angleDiff
409− newAngle = progress * angleDiff / progressDiff;
410− newAngle = Math.min(coverFlip.endAngle, newAngle);
411− }
412− break;
413− case 1:
414− if (appImage.progress < coverFlip.progressMarker1) {
415− var progress = coverFlip.progress;
416− var angleDiff = coverFlip.startAngle;
417− var progressDiff = coverFlip.progressMarker1;
418− // progress : progressDiff = angle : angleDiff
419− var angle = progress * angleDiff / progressDiff;
420− newAngle = coverFlip.startAngle - angle;
395+ property real angle: {
396+ var newAngle = 0;
397+ switch (index) {
398+ case 0:
399+ if (appImage.progress <= coverFlip.progressMarker1) {
400+ var progress = appImage.progress;
401+ var angleDiff = coverFlip.endAngle;
402+ var progressDiff = coverFlip.progressMarker1;
403+ // progress : progressDiff = angle : angleDiff
404+ newAngle = progress * angleDiff / progressDiff;
405+ } else {
406+ var progress = appImage.progress - coverFlip.progressMarker1;
407+ var angleDiff = coverFlip.endAngle;
408+ var progressDiff = 1 - coverFlip.progressMarker1;
409+ // progress : progressDiff = angle : angleDiff
410+ newAngle = progress * angleDiff / progressDiff;
411+ newAngle = Math.min(coverFlip.endAngle, newAngle);
412+ }
421413 break;
422− }
423− // Intentionally no break here...
424− default:
425−// var progress = appImage.progress;
426−// var angleDiff = coverFlip.startAngle - coverFlip.endAngle;
427−//// var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
428−// var progressDiff = index
429−// // progress : progressDiff = angle : angleDiff
430−// newAngle = progress * angleDiff / progressDiff;
431−// newAngle = Math.max(coverFlip.endAngle, coverFlip.startAngle - newAngle)
414+ case 1:
415+ if (appImage.progress < coverFlip.progressMarker1) {
416+ var progress = coverFlip.progress;
417+ var angleDiff = coverFlip.startAngle;
418+ var progressDiff = coverFlip.progressMarker1;
419+ // progress : progressDiff = angle : angleDiff
420+ var angle = progress * angleDiff / progressDiff;
421+ newAngle = coverFlip.startAngle - angle;
422+ break;
423+ }
424+ // Intentionally no break here...
425+ default:
426+ // var progress = appImage.progress;
427+ // var angleDiff = coverFlip.startAngle - coverFlip.endAngle;
428+ //// var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
429+ // var progressDiff = index
430+ // // progress : progressDiff = angle : angleDiff
431+ // newAngle = progress * angleDiff / progressDiff;
432+ // newAngle = Math.max(coverFlip.endAngle, coverFlip.startAngle - newAngle)
433+
434+ newAngle = coverFlip.startAngle - (angleEasing.value * angleEasing.period);
432435
433− newAngle = coverFlip.startAngle - (angleEasing.value * angleEasing.period);
436+ // make sure we stop at the left screen edge
437+ newAngle = Math.max(newAngle, coverFlip.endAngle);
434438
435− // make sure we stop at the left screen edge
436− newAngle = Math.max(newAngle, coverFlip.endAngle);
439+ }
440+ if (appImage.isSelected) {
441+ var selectedAngleTranslate = selectedAngleEasing.value * selectedAngleEasing.period
442+ print("selectedAngle", appImage.selectedAngle, "translate", selectedAngleTranslate)
443+ newAngle = appImage.selectedAngle - selectedAngleTranslate;
444+ }
437445
438− }
439− if (appImage.isSelected) {
440− var selectedAngleTranslate = selectedAngleEasing.value * selectedAngleEasing.period
441− print("selectedAngle", appImage.selectedAngle, "translate", selectedAngleTranslate)
442− newAngle = appImage.selectedAngle - selectedAngleTranslate;
446+ return newAngle;
443447 }
444448
445− return newAngle;
446− }
447−
448− property real xScale: {
449− var scale = 1;
450−
451− switch (index) {
452− case 0:
453− if (appImage.progress > coverFlip.progressMarker1) {
454− var scaleDiff = coverFlip.maxScale - 1;
455− var progressDiff = 1.5 - coverFlip.progressMarker1;
456− // progress : progressDiff = scale : scaleDiff
457− scale = 1 - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff;
458− }
459− break;
460− case 1:
461− if (appImage.progress < coverFlip.progressMarker1) {
462− var scaleDiff = coverFlip.maxScale - 1
463− var progressDiff = coverFlip.progressMarker1
464− // progress : progressDiff = scale : scaleDiff
465− scale = coverFlip.maxScale - (appImage.progress * scaleDiff / progressDiff);
449+ property real xScale: {
450+ var scale = 1;
451+
452+ switch (index) {
453+ case 0:
454+ if (appImage.progress > coverFlip.progressMarker1) {
455+ var scaleDiff = coverFlip.maxScale - 1;
456+ var progressDiff = 1.5 - coverFlip.progressMarker1;
457+ // progress : progressDiff = scale : scaleDiff
458+ scale = 1 - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff;
459+ }
466460 break;
461+ case 1:
462+ if (appImage.progress < coverFlip.progressMarker1) {
463+ var scaleDiff = coverFlip.maxScale - 1
464+ var progressDiff = coverFlip.progressMarker1
465+ // progress : progressDiff = scale : scaleDiff
466+ scale = coverFlip.maxScale - (appImage.progress * scaleDiff / progressDiff);
467+ break;
468+ }
469+ // Intentionally no break
470+ default:
471+ // var scaleDiff = coverFlip.maxScale - coverFlip.minScale
472+ //// var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
473+ // var progressDiff = index
474+ // // progress : progressDiff = scale : scaleDiff
475+ // scale = coverFlip.maxScale - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff
476+ // break;
477+
478+ scale = coverFlip.maxScale - scaleEasing.value * scaleEasing.period;
467479 }
468− // Intentionally no break
469− default:
470−// var scaleDiff = coverFlip.maxScale - coverFlip.minScale
471−//// var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
472−// var progressDiff = index
473−// // progress : progressDiff = scale : scaleDiff
474−// scale = coverFlip.maxScale - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff
475−// break;
476−
477− scale = coverFlip.maxScale - scaleEasing.value * scaleEasing.period;
478− }
479480
480− if (appImage.isSelected) {
481− var selectedScaleTranslate = selectedScaleEasing.value * selectedScaleEasing.period
482− scale = appImage.selectedXScale + selectedScaleTranslate;
483− }
481+ if (appImage.isSelected) {
482+ var selectedScaleTranslate = selectedScaleEasing.value * selectedScaleEasing.period
483+ scale = appImage.selectedXScale + selectedScaleTranslate;
484+ }
484485
485− return Math.min(coverFlip.maxScale, Math.max(coverFlip.minScale, scale));
486− }
486+ return Math.min(coverFlip.maxScale, Math.max(coverFlip.minScale, scale));
487+ }
487488
488489
489− EasingCurve {
490− id: xTranslateEasing
491− type: EasingCurve.OutQuad
492− period: index * -width
493− progress: appImage.translatedProgress
494− }
495− EasingCurve {
496− id: selectedXTranslateEasing
497− type: EasingCurve.Linear
498− period: xTranslateEasing.period - appImage.selectedXTranslation
499− progress: appImage.selectedTranslatedProgress - xTranslateEasing.progress
500− }
501− EasingCurve {
502− id: angleEasing
503− type: EasingCurve.InQuad
504− period: coverFlip.startAngle - coverFlip.endAngle
505− progress: appImage.translatedProgress
506− }
507− EasingCurve {
508− id: selectedAngleEasing
509− type: EasingCurve.Linear
510− period: appImage.selectedAngle
511− progress: appImage.selectedTranslatedProgress - angleEasing.progress
512− }
513− EasingCurve {
514− id: scaleEasing
515− type: EasingCurve.Linear
516− period: coverFlip.maxScale - coverFlip.minScale
517− progress: appImage.translatedProgress
518− }
519− EasingCurve {
520− id: selectedScaleEasing
521− type: EasingCurve.Linear
522− period: 1 - appImage.selectedXScale
523− progress: appImage.selectedTranslatedProgress - scaleEasing.progress
524− }
525−
526− transform: [
527− Rotation {
528− origin { x: 0; y: coverFlip.height / 2 }
529− axis { x: 0; y: 1; z: 0 }
530− angle: appImage.angle
531− },
532− Translate {
533− x: appImage.xTranslation
534− },
535− Scale {
536− origin { x: appImage.xTranslation; y: root.height / 2 - (root.height - appImage.height)}
537− xScale: appImage.xScale
538− yScale: xScale
490+ EasingCurve {
491+ id: xTranslateEasing
492+ type: EasingCurve.OutQuad
493+ period: index * -width
494+ progress: appImage.translatedProgress
495+ }
496+ EasingCurve {
497+ id: selectedXTranslateEasing
498+ type: EasingCurve.Linear
499+ period: xTranslateEasing.period - appImage.selectedXTranslation
500+ progress: appImage.selectedTranslatedProgress - xTranslateEasing.progress
501+ }
502+ EasingCurve {
503+ id: angleEasing
504+ type: EasingCurve.InQuad
505+ period: coverFlip.startAngle - coverFlip.endAngle
506+ progress: appImage.translatedProgress
507+ }
508+ EasingCurve {
509+ id: selectedAngleEasing
510+ type: EasingCurve.Linear
511+ period: appImage.selectedAngle
512+ progress: appImage.selectedTranslatedProgress - angleEasing.progress
513+ }
514+ EasingCurve {
515+ id: scaleEasing
516+ type: EasingCurve.Linear
517+ period: coverFlip.maxScale - coverFlip.minScale
518+ progress: appImage.translatedProgress
519+ }
520+ EasingCurve {
521+ id: selectedScaleEasing
522+ type: EasingCurve.Linear
523+ period: 1 - appImage.selectedXScale
524+ progress: appImage.selectedTranslatedProgress - scaleEasing.progress
539525 }
540− ]
541526
542− MouseArea {
543− anchors.fill: parent
544− onClicked: {
545− print("clicked on index", index)
546− appImage.select()
527+ transform: [
528+ Rotation {
529+ origin { x: 0; y: coverFlip.height / 2 }
530+ axis { x: 0; y: 1; z: 0 }
531+ angle: appImage.angle
532+ },
533+ Translate {
534+ x: appImage.xTranslation
535+ },
536+ Scale {
537+ origin { x: appImage.xTranslation; y: root.height / 2 - (root.height - appImage.height)}
538+ xScale: appImage.xScale
539+ yScale: xScale
540+ }
541+ ]
542+
543+ MouseArea {
544+ anchors.fill: parent
545+ onClicked: {
546+ print("clicked on index", index)
547+ appImage.select()
548+ }
547549 }
548550 }
549− }
550551
551− SequentialAnimation {
552− id: switchToAppAnimation
553− ParallelAnimation {
554− UbuntuNumberAnimation { target: coverFlickable; property: "contentX"; to: 0}
555− }
556− ScriptAction {
557− script: {
558− ApplicationManager.focusApplication(ApplicationManager.get(index).appId);
559− appImage.isSelected = false;
560− coverFlip.progress = 0;
552+ SequentialAnimation {
553+ id: switchToAppAnimation
554+ ParallelAnimation {
555+ UbuntuNumberAnimation { target: coverFlickable; property: "contentX"; to: 0}
556+ }
557+ ScriptAction {
558+ script: {
559+ ApplicationManager.focusApplication(ApplicationManager.get(index).appId);
560+ appImage.isSelected = false;
561+ coverFlip.progress = 0;
562+ }
561563 }
562564 }
563565 }
564566 }
565567 }
566568 }
569+
567570}