on xenial help sign in
Implement proper updateRanges for horizontal items (i.e. Carousel, Horizontal List)
3181a02Albert Astals
qml/Components/Carousel.qml+6−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−import QtQuick 2.0
17+import QtQuick 2.3
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import "carousel.js" as CarouselJS
19import "carousel.js" as CarouselJS
20
20
@@ -38,6 +38,8 @@ Item {
38 property alias tileAspectRatio: listView.tileAspectRatio
38 property alias tileAspectRatio: listView.tileAspectRatio
39 /// Used to cache some delegates for performance reasons. See the ListView documentation for details
39 /// Used to cache some delegates for performance reasons. See the ListView documentation for details
40 property alias cacheBuffer: listView.cacheBuffer
40 property alias cacheBuffer: listView.cacheBuffer
41+ property alias displayMarginBeginning: listView.displayMarginBeginning
42+ property alias displayMarginEnd: listView.displayMarginEnd
41 /// Width of the "draw buffer" in pixel. The drawBuffer is an additional area at start/end where
43 /// Width of the "draw buffer" in pixel. The drawBuffer is an additional area at start/end where
42 /// items drawn, even if it is not in the visible area.
44 /// items drawn, even if it is not in the visible area.
43 /// cacheBuffer controls only the to retain delegates outside the visible area (and is used on top of the drawBuffer)
45 /// cacheBuffer controls only the to retain delegates outside the visible area (and is used on top of the drawBuffer)
@@ -51,6 +53,8 @@ Item {
51 readonly property alias currentItem: listView.currentItem
53 readonly property alias currentItem: listView.currentItem
52 /// exposes the distance to the next row (only one row in carousel, so it's the topMargins)
54 /// exposes the distance to the next row (only one row in carousel, so it's the topMargins)
53 readonly property alias verticalSpacing: listView.verticalMargin
55 readonly property alias verticalSpacing: listView.verticalMargin
56+ /// the width of the internal list
57+ readonly property alias innerWidth: listView.width
54
58
55 implicitHeight: listView.tileHeight * selectedItemScaleFactor
59 implicitHeight: listView.tileHeight * selectedItemScaleFactor
56 opacity: listView.highlightIndex === -1 ? 1 : 0.6
60 opacity: listView.highlightIndex === -1 ? 1 : 0.6
qml/Dash/CardCarousel.qml+6−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@ DashRenderer {
23
23
24 expandedHeight: carousel.implicitHeight + units.gu(6)
24 expandedHeight: carousel.implicitHeight + units.gu(6)
25 collapsedHeight: expandedHeight
25 collapsedHeight: expandedHeight
26+ growsVertically: false
27+ innerWidth: carousel.innerWidth
26
28
27 Carousel {
29 Carousel {
28 id: carousel
30 id: carousel
@@ -32,7 +34,9 @@ DashRenderer {
32 // and push others back.
34 // and push others back.
33 minimumTileWidth: cardTool.cardWidth / selectedItemScaleFactor
35 minimumTileWidth: cardTool.cardWidth / selectedItemScaleFactor
34 selectedItemScaleFactor: cardTool.carouselSelectedItemScaleFactor
36 selectedItemScaleFactor: cardTool.carouselSelectedItemScaleFactor
35− cacheBuffer: 1404 // 18px * 13gu * 6
37+ cacheBuffer: cardCarousel.cacheBuffer
38+ displayMarginBeginning: cardCarousel.displayMarginBeginning
39+ displayMarginEnd: cardCarousel.displayMarginEnd
36 model: cardCarousel.model
40 model: cardCarousel.model
37
41
38 property real fontScale: 1 / selectedItemScaleFactor
42 property real fontScale: 1 / selectedItemScaleFactor
qml/Dash/CardHorizontalList.qml+7−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−import QtQuick 2.2
17+import QtQuick 2.3
18import Ubuntu.Components 1.1
18import Ubuntu.Components 1.1
19import "../Components"
19import "../Components"
20
20
@@ -23,6 +23,8 @@ DashRenderer {
23
23
24 expandedHeight: cardTool.cardHeight + units.gu(2)
24 expandedHeight: cardTool.cardHeight + units.gu(2)
25 collapsedHeight: expandedHeight
25 collapsedHeight: expandedHeight
26+ growsVertically: false
27+ innerWidth: Math.max(0, listView.width)
26 clip: true
28 clip: true
27
29
28 ListView {
30 ListView {
@@ -36,6 +38,9 @@ DashRenderer {
36 spacing: units.gu(1)
38 spacing: units.gu(1)
37 model: root.model
39 model: root.model
38 orientation: ListView.Horizontal
40 orientation: ListView.Horizontal
41+ cacheBuffer: root.cacheBuffer
42+ displayMarginBeginning: root.displayMarginBeginning
43+ displayMarginEnd: root.displayMarginEnd
39
44
40 delegate: Loader {
45 delegate: Loader {
41 id: loader
46 id: loader
qml/Dash/DashRenderer.qml+6−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -31,6 +31,11 @@ Item {
31
31
32 property real originY: 0
32 property real originY: 0
33
33
34+ property bool growsVertically: true
35+
36+ // If growsVertically the width of the item inside the renderer
37+ property real innerWidth: 0
38+
34 // The model to renderer
39 // The model to renderer
35 property var model
40 property var model
36
41
qml/Dash/GenericScopeView.qml+91−48
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013-2014 Canonical, Ltd.
2+ * Copyright (C) 2013-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -401,59 +401,102 @@ FocusScope {
401 }
401 }
402
402
403 if (item && item.hasOwnProperty("displayMarginBeginning")) {
403 if (item && item.hasOwnProperty("displayMarginBeginning")) {
404+ if (item.growsVertically) {
404− // A item view creates its delegates synchronously from
405+ // A item view creates its delegates synchronously from
405− // -displayMarginBeginning
406+ // -displayMarginBeginning
406− // to
407+ // to
407− // height + displayMarginEnd
408+ // height + displayMarginEnd
408− // Around that area it adds the cacheBuffer area where delegates are created async
409+ // Around that area it adds the cacheBuffer area where delegates are created async
409− //
410+ //
410− // We adjust displayMarginBeginning and displayMarginEnd so
411+ // We adjust displayMarginBeginning and displayMarginEnd so
411− // * In non visible scopes nothing is considered visible and we set cacheBuffer
412+ // * In non visible scopes nothing is considered visible and we set cacheBuffer
412− // so that creates the items that would be in the viewport asynchronously
413+ // so that creates the items that would be in the viewport asynchronously
413− // * For the current scope set the visible range to the viewport and then
414+ // * For the current scope set the visible range to the viewport and then
414− // use cacheBuffer to create extra items for categoryView.height * 1.5
415+ // use cacheBuffer to create extra items for categoryView.height * 1.5
415− // to make scrolling nicer by mantaining a higher number of
416+ // to make scrolling nicer by mantaining a higher number of
416− // cached items
417+ // cached items
417− // * For non current but visible scopes (i.e. when the user changes from one scope
418+ // * For non current but visible scopes (i.e. when the user changes from one scope
418− // to the next, we set the visible range to the viewport so
419+ // to the next, we set the visible range to the viewport so
419− // items are not culled (invisible) but still use no cacheBuffer
420+ // items are not culled (invisible) but still use no cacheBuffer
420− // (it will be set once the scope is the current one)
421+ // (it will be set once the scope is the current one)
421− var displayMarginBeginning = baseItem.y;
422+ var displayMarginBeginning = baseItem.y;
422− displayMarginBeginning = -Math.max(-displayMarginBeginning, 0);
423+ displayMarginBeginning = -Math.max(-displayMarginBeginning, 0);
423− displayMarginBeginning = -Math.min(-displayMarginBeginning, baseItem.height);
424+ displayMarginBeginning = -Math.min(-displayMarginBeginning, baseItem.height);
424− displayMarginBeginning = Math.round(displayMarginBeginning);
425+ displayMarginBeginning = Math.round(displayMarginBeginning);
425− var displayMarginEnd = -baseItem.height + seeAll.height + categoryView.height - baseItem.y;
426+ var displayMarginEnd = -baseItem.height + seeAll.height + categoryView.height - baseItem.y;
426− displayMarginEnd = -Math.max(-displayMarginEnd, 0);
427+ displayMarginEnd = -Math.max(-displayMarginEnd, 0);
427− displayMarginEnd = -Math.min(-displayMarginEnd, baseItem.height);
428+ displayMarginEnd = -Math.min(-displayMarginEnd, baseItem.height);
428− displayMarginEnd = Math.round(displayMarginEnd);
429+ displayMarginEnd = Math.round(displayMarginEnd);
430+
429− if (scopeView.isCurrent || scopeView.visibleToParent) {
431+ if (scopeView.isCurrent || scopeView.visibleToParent) {
430− item.displayMarginBeginning = displayMarginBeginning;
432+ item.displayMarginBeginning = displayMarginBeginning;
431− item.displayMarginEnd = displayMarginEnd;
433+ item.displayMarginEnd = displayMarginEnd;
432− if (holdingList && holdingList.moving) {
434+ if (holdingList && holdingList.moving) {
433− // If we are moving we need to reset the cache buffer of the
435+ // If we are moving we need to reset the cache buffer of the
434− // view that was not visible (i.e. !wasCurrentOnMoveStart) to 0 since
436+ // view that was not visible (i.e. !wasCurrentOnMoveStart) to 0 since
435− // otherwise the cache buffer we had set to preload the items of the
437+ // otherwise the cache buffer we had set to preload the items of the
436− // visible range will trigger some item creations and we want move to
438+ // visible range will trigger some item creations and we want move to
437− // be as smooth as possible meaning no need creations
439+ // be as smooth as possible meaning no need creations
438− if (!wasCurrentOnMoveStart) {
440+ if (!wasCurrentOnMoveStart) {
441+ item.cacheBuffer = 0;
442+ }
443+ } else {
439− item.cacheBuffer = 0;
444+ item.cacheBuffer = categoryView.height * 1.5;
440 }
445 }
441 } else {
446 } else {
442− item.cacheBuffer = categoryView.height * 1.5;
447+ var visibleRange = baseItem.height + displayMarginEnd + displayMarginBeginning;
448+ if (visibleRange < 0) {
449+ item.displayMarginBeginning = displayMarginBeginning;
450+ item.displayMarginEnd = displayMarginEnd;
451+ item.cacheBuffer = 0;
452+ } else {
453+ // This should be visibleRange/2 in each of the properties
454+ // but some item views still (like GridView) like creating sync delegates even if
455+ // the visible range is 0 so let's make sure the visible range is negative
456+ item.displayMarginBeginning = displayMarginBeginning - visibleRange;
457+ item.displayMarginEnd = displayMarginEnd - visibleRange;
458+ item.cacheBuffer = visibleRange;
459+ }
443 }
460 }
444 } else {
461 } else {
445− var visibleRange = baseItem.height + displayMarginEnd + displayMarginBeginning;
462+ var buffer = wasCurrentOnMoveStart ? categoryView.height * 1.5 : 0;
446− if (visibleRange < 0) {
463+ var onViewport = baseItem.y + baseItem.height > 0 &&
464+ baseItem.y < categoryView.height;
465+ var onBufferViewport = baseItem.y + baseItem.height > -buffer &&
466+ baseItem.y < categoryView.height + buffer;
467+ if (!onBufferViewport) {
468+ // If not on the buffered viewport, don't load anything
447− item.displayMarginBeginning = displayMarginBeginning;
469+ item.displayMarginBeginning = 0;
448− item.displayMarginEnd = displayMarginEnd;
470+ item.displayMarginEnd = -item.innerWidth;
449 item.cacheBuffer = 0;
471 item.cacheBuffer = 0;
450 } else {
472 } else {
451− // This should be visibleRange/2 in each of the properties
473+ if (onViewport && (scopeView.isCurrent || scopeView.visibleToParent)) {
452− // but some item views still (like GridView) like creating sync delegates even if
474+ // If on the buffered viewport and the viewport and the on a visible scope
453− // the visible range is 0 so let's make sure the visible range is negative
475+ // Set displayMargin so that cards are rendered
476+ // And if not moving the parent list also give it some extra asynchronously
477+ // buffering
478+ item.displayMarginBeginning = 0;
479+ item.displayMarginEnd = 0;
480+ if (holdingList && holdingList.moving) {
481+ // If we are moving we need to reset the cache buffer of the
482+ // view that was not visible (i.e. !wasCurrentOnMoveStart) to 0 since
483+ // otherwise the cache buffer we had set to preload the items of the
484+ // visible range will trigger some item creations and we want move to
485+ // be as smooth as possible meaning no need creations
486+ if (!wasCurrentOnMoveStart) {
487+ item.cacheBuffer = 0;
488+ }
489+ } else {
490+ item.cacheBuffer = baseItem.width * 1.5;
491+ }
492+ } else {
493+ // If on the buffered viewport but either not in the real viewport
494+ // or in the viewport of the non current scope, use displayMargin + cacheBuffer
495+ // to render asynchronously the width of cards
454− item.displayMarginBeginning = displayMarginBeginning - visibleRange;
496+ item.displayMarginBeginning = 0;
455− item.displayMarginEnd = displayMarginEnd - visibleRange;
497+ item.displayMarginEnd = -item.innerWidth;
456− item.cacheBuffer = visibleRange;
498+ item.cacheBuffer = item.innerWidth;
499+ }
457 }
500 }
458 }
501 }
459 }
502 }