@@ -38,6 +38,7 @@ FocusScope {
3838 property int paginationCount: 0
3939 property int paginationIndex: 0
4040 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
41+ property var holdingList: null
4142
4243 property var scopeStyle: ScopeStyle {
4344 style: scope ? scope.customizations : {}
@@ -47,6 +48,10 @@ FocusScope {
4748
4849 signal backClicked()
4950
51+ onScopeChanged: {
52+ floatingSeeLess.companionBase = null;
53+ }
54+
5055 function positionAtBeginning() {
5156 categoryView.positionAtBeginning()
5257 }
@@ -152,11 +157,55 @@ FocusScope {
152157 forceNoClip: subPageLoader.open
153158 pixelAligned: true
154159
155− property Item expandedCategoryItem: null
160+ property string expandedCategoryId: ""
161+ property int runMaximizeAfterSizeChanges: 0
156162
157163 readonly property bool pageHeaderTotallyVisible: scopeView.showPageHeader &&
158164 ((headerItemShownHeight == 0 && categoryView.contentY <= categoryView.originY) || (headerItemShownHeight == pageHeaderLoader.item.height))
159165
166+ onExpandedCategoryIdChanged: {
167+ var firstCreated = firstCreatedIndex();
168+ var shrinkingAny = false;
169+ var shrinkHeightDifference = 0;
170+ for (var i = 0; i < createdItemCount(); ++i) {
171+ var baseItem = item(firstCreated + i);
172+ if (baseItem.expandable) {
173+ var shouldExpand = baseItem.category === expandedCategoryId;
174+ if (shouldExpand != baseItem.expanded) {
175+
176+ var animate = false;
177+ if (!subPageLoader.open) {
178+ var animateShrinking = !shouldExpand && baseItem.y + baseItem.item.collapsedHeight + baseItem.seeAll.height < categoryView.height;
179+ var animateGrowing = shouldExpand && baseItem.y + baseItem.height < categoryView.height;
180+ animate = shrinkingAny || animateShrinking || animateGrowing;
181+ }
182+
183+ if (!shouldExpand) {
184+ shrinkingAny = true;
185+ shrinkHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
186+ }
187+
188+ if (shouldExpand && !subPageLoader.open) {
189+ if (!shrinkingAny) {
190+ categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAll.height);
191+ } else {
192+ // If the space that shrkinking is smaller than the one we need to grow we'll call maximizeVisibleArea
193+ // after the shrink/grow animation ends
194+ var growHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
195+ if (growHeightDifference > shrinkHeightDifference) {
196+ runMaximizeAfterSizeChanges = 2;
197+ } else {
198+ runMaximizeAfterSizeChanges = 0;
199+ }
200+ }
201+ }
202+
203+ baseItem.expand(shouldExpand, animate);
204+ }
205+ }
206+ }
207+ }
208+
160209 delegate: ListItems.Base {
161210 id: baseItem
162211 objectName: "dashCategory" + category
@@ -175,6 +224,7 @@ FocusScope {
175224 readonly property string category: categoryId
176225 readonly property string headerLink: model.headerLink
177226 readonly property var item: rendererLoader.item
227+ readonly property var seeAll: seeAll
178228
179229 function expand(expand, animate) {
180230 heightBehaviour.enabled = animate;
@@ -194,13 +244,13 @@ FocusScope {
194244 // This can happen with the VJ that doesn't know how height it will be on creation
195245 // so doesn't set expandable until a bit too late for onLoaded
196246 if (expandable) {
197− var shouldExpand = baseItem === categoryView.expandedCategoryItem;
247+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
198248 baseItem.expand(shouldExpand, false /*animate*/);
199249 }
200250 }
201251
202− onHeightChanged: rendererLoader.updateDelegateCreationRange();
203− onYChanged: rendererLoader.updateDelegateCreationRange();
252+ onHeightChanged: rendererLoader.updateRanges();
253+ onYChanged: rendererLoader.updateRanges();
204254
205255 Loader {
206256 id: rendererLoader
@@ -215,9 +265,23 @@ FocusScope {
215265 id: heightBehaviour
216266 enabled: false
217267 animation: UbuntuNumberAnimation {
268+ duration: UbuntuAnimation.FastDuration
218269 onRunningChanged: {
219270 if (!running) {
220271 heightBehaviour.enabled = false
272+ if (categoryView.runMaximizeAfterSizeChanges > 0) {
273+ categoryView.runMaximizeAfterSizeChanges--;
274+ if (categoryView.runMaximizeAfterSizeChanges == 0) {
275+ var firstCreated = categoryView.firstCreatedIndex();
276+ for (var i = 0; i < categoryView.createdItemCount(); ++i) {
277+ var baseItem = categoryView.item(firstCreated + i);
278+ if (baseItem.category === categoryView.expandedCategoryId) {
279+ categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAll.height);
280+ break;
281+ }
282+ }
283+ }
284+ }
221285 }
222286 }
223287 }
@@ -245,10 +309,10 @@ FocusScope {
245309 item.objectName = Qt.binding(function() { return categoryId })
246310 item.scopeStyle = scopeView.scopeStyle;
247311 if (baseItem.expandable) {
248− var shouldExpand = baseItem === categoryView.expandedCategoryItem;
312+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
249313 baseItem.expand(shouldExpand, false /*animate*/);
250314 }
251− updateDelegateCreationRange();
315+ updateRanges();
252316 if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
253317 // Yeah, hackish :/
254318 cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
@@ -303,13 +367,25 @@ FocusScope {
303367 }
304368 }
305369 }
306− onOriginYChanged: rendererLoader.updateDelegateCreationRange();
307− onContentYChanged: rendererLoader.updateDelegateCreationRange();
308− onHeightChanged: rendererLoader.updateDelegateCreationRange();
309− onContentHeightChanged: rendererLoader.updateDelegateCreationRange();
370+ onOriginYChanged: rendererLoader.updateRanges();
371+ onContentYChanged: rendererLoader.updateRanges();
372+ onHeightChanged: rendererLoader.updateRanges();
373+ onContentHeightChanged: rendererLoader.updateRanges();
374+ }
375+ Connections {
376+ target: scopeView
377+ onIsCurrentChanged: rendererLoader.updateRanges();
378+ }
379+ Connections {
380+ target: holdingList
381+ onMovingChanged: if (!moving) rendererLoader.updateRanges();
310382 }
311383
312− function updateDelegateCreationRange() {
384+ function updateRanges() {
385+ if (holdingList && holdingList.moving) {
386+ return;
387+ }
388+
313389 if (categoryView.moving) {
314390 // Do not update the range if we are overshooting up or down, since we'll come back
315391 // to the stable position and delete/create items without any reason
@@ -321,10 +397,18 @@ FocusScope {
321397 }
322398 }
323399
400+ if (item && item.hasOwnProperty("visibleRangeBegin")) {
401+ item.visibleRangeBegin = Math.max(-baseItem.y, 0)
402+ item.visibleRangeEnd = item.visibleRangeBegin + Math.min(categoryView.height, rendererLoader.height)
403+ }
404+
324405 if (item && item.hasOwnProperty("displayMarginBeginning")) {
325406 // TODO do we need item.originY here, test 1300302 once we have a silo
326407 // and we can run it on the phone
327− if (baseItem.y + baseItem.height <= 0) {
408+ if (scopeView.isCurrent) {
409+ item.displayMarginBeginning = 1073741823;
410+ item.displayMarginEnd = 1073741823;
411+ } else if (baseItem.y + baseItem.height <= 0) {
328412 // Not visible (item at top of the list viewport)
329413 item.displayMarginBeginning = -baseItem.height;
330414 item.displayMarginEnd = 0;
@@ -333,9 +417,9 @@ FocusScope {
333417 item.displayMarginBeginning = 0;
334418 item.displayMarginEnd = -baseItem.height;
335419 } else {
336− item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
337− item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
338− - categoryView.height + baseItem.y, 0)
420+ item.displayMarginBeginning = Math.round(-Math.max(-baseItem.y, 0));
421+ item.displayMarginEnd = -Math.round(Math.max(baseItem.height - seeAll.height
422+ - categoryView.height + baseItem.y, 0));
339423 }
340424 }
341425 }
@@ -352,10 +436,11 @@ FocusScope {
352436 height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(4) : 0
353437
354438 onClicked: {
355− if (categoryView.expandedCategoryItem !== baseItem) {
356− categoryView.expandedCategoryItem = baseItem;
439+ if (categoryView.expandedCategoryId !== baseItem.category) {
440+ categoryView.expandedCategoryId = baseItem.category;
441+ floatingSeeLess.companionBase = baseItem;
357442 } else {
358− categoryView.expandedCategoryItem = null;
443+ categoryView.expandedCategoryId = "";
359444 }
360445 }
361446
@@ -455,7 +540,7 @@ FocusScope {
455540 objectName: "floatingSeeLess"
456541
457542 property Item companionTo: companionBase ? companionBase.seeAllButton : null
458− property Item companionBase: categoryView.expandedCategoryItem
543+ property Item companionBase: null
459544 property bool showBecausePosition: false
460545 property real yOffset: 0
461546
@@ -467,7 +552,7 @@ FocusScope {
467552 height: seeLessLabel.font.pixelSize + units.gu(4)
468553 visible: companionTo && showBecausePosition
469554
470− onClicked: categoryView.expandedCategoryItem = null;
555+ onClicked: categoryView.expandedCategoryId = "";
471556
472557 function updateVisibility() {
473558 var companionPos = companionTo.mapToItem(floatingSeeLess, 0, 0);
@@ -476,6 +561,10 @@ FocusScope {
476561 var posToBase = floatingSeeLess.mapToItem(companionBase, 0, -yOffset).y;
477562 yOffset = Math.max(0, companionBase.item.collapsedHeight - posToBase);
478563 yOffset = Math.min(yOffset, height);
564+
565+ if (!showBecausePosition && categoryView.expandedCategoryId === "") {
566+ companionBase = null;
567+ }
479568 }
480569
481570 Label {