@@ -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 }
@@ -153,11 +158,55 @@ FocusScope {
153158 pixelAligned: true
154159 interactive: !navigationShown
155160
156− property Item expandedCategoryItem: null
161+ property string expandedCategoryId: ""
162+ property int runMaximizeAfterSizeChanges: 0
157163
158164 readonly property bool pageHeaderTotallyVisible: scopeView.showPageHeader &&
159165 ((headerItemShownHeight == 0 && categoryView.contentY <= categoryView.originY) || (headerItemShownHeight == pageHeaderLoader.item.height))
160166
167+ onExpandedCategoryIdChanged: {
168+ var firstCreated = firstCreatedIndex();
169+ var shrinkingAny = false;
170+ var shrinkHeightDifference = 0;
171+ for (var i = 0; i < createdItemCount(); ++i) {
172+ var baseItem = item(firstCreated + i);
173+ if (baseItem.expandable) {
174+ var shouldExpand = baseItem.category === expandedCategoryId;
175+ if (shouldExpand != baseItem.expanded) {
176+
177+ var animate = false;
178+ if (!subPageLoader.open) {
179+ var animateShrinking = !shouldExpand && baseItem.y + baseItem.item.collapsedHeight + baseItem.seeAll.height < categoryView.height;
180+ var animateGrowing = shouldExpand && baseItem.y + baseItem.height < categoryView.height;
181+ animate = shrinkingAny || animateShrinking || animateGrowing;
182+ }
183+
184+ if (!shouldExpand) {
185+ shrinkingAny = true;
186+ shrinkHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
187+ }
188+
189+ if (shouldExpand && !subPageLoader.open) {
190+ if (!shrinkingAny) {
191+ categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAll.height);
192+ } else {
193+ // If the space that shrkinking is smaller than the one we need to grow we'll call maximizeVisibleArea
194+ // after the shrink/grow animation ends
195+ var growHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
196+ if (growHeightDifference > shrinkHeightDifference) {
197+ runMaximizeAfterSizeChanges = 2;
198+ } else {
199+ runMaximizeAfterSizeChanges = 0;
200+ }
201+ }
202+ }
203+
204+ baseItem.expand(shouldExpand, animate);
205+ }
206+ }
207+ }
208+ }
209+
161210 delegate: ListItems.Base {
162211 id: baseItem
163212 objectName: "dashCategory" + category
@@ -176,6 +225,7 @@ FocusScope {
176225 readonly property string category: categoryId
177226 readonly property string headerLink: model.headerLink
178227 readonly property var item: rendererLoader.item
228+ readonly property var seeAll: seeAll
179229
180230 function expand(expand, animate) {
181231 heightBehaviour.enabled = animate;
@@ -195,13 +245,13 @@ FocusScope {
195245 // This can happen with the VJ that doesn't know how height it will be on creation
196246 // so doesn't set expandable until a bit too late for onLoaded
197247 if (expandable) {
198− var shouldExpand = baseItem === categoryView.expandedCategoryItem;
248+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
199249 baseItem.expand(shouldExpand, false /*animate*/);
200250 }
201251 }
202252
203− onHeightChanged: rendererLoader.updateDelegateCreationRange();
204− onYChanged: rendererLoader.updateDelegateCreationRange();
253+ onHeightChanged: rendererLoader.updateRanges();
254+ onYChanged: rendererLoader.updateRanges();
205255
206256 Loader {
207257 id: rendererLoader
@@ -216,9 +266,23 @@ FocusScope {
216266 id: heightBehaviour
217267 enabled: false
218268 animation: UbuntuNumberAnimation {
269+ duration: UbuntuAnimation.FastDuration
219270 onRunningChanged: {
220271 if (!running) {
221272 heightBehaviour.enabled = false
273+ if (categoryView.runMaximizeAfterSizeChanges > 0) {
274+ categoryView.runMaximizeAfterSizeChanges--;
275+ if (categoryView.runMaximizeAfterSizeChanges == 0) {
276+ var firstCreated = categoryView.firstCreatedIndex();
277+ for (var i = 0; i < categoryView.createdItemCount(); ++i) {
278+ var baseItem = categoryView.item(firstCreated + i);
279+ if (baseItem.category === categoryView.expandedCategoryId) {
280+ categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAll.height);
281+ break;
282+ }
283+ }
284+ }
285+ }
222286 }
223287 }
224288 }
@@ -246,10 +310,10 @@ FocusScope {
246310 item.objectName = Qt.binding(function() { return categoryId })
247311 item.scopeStyle = scopeView.scopeStyle;
248312 if (baseItem.expandable) {
249− var shouldExpand = baseItem === categoryView.expandedCategoryItem;
313+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
250314 baseItem.expand(shouldExpand, false /*animate*/);
251315 }
252− updateDelegateCreationRange();
316+ updateRanges();
253317 if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
254318 // Yeah, hackish :/
255319 cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
@@ -304,13 +368,25 @@ FocusScope {
304368 }
305369 }
306370 }
307− onOriginYChanged: rendererLoader.updateDelegateCreationRange();
308− onContentYChanged: rendererLoader.updateDelegateCreationRange();
309− onHeightChanged: rendererLoader.updateDelegateCreationRange();
310− onContentHeightChanged: rendererLoader.updateDelegateCreationRange();
371+ onOriginYChanged: rendererLoader.updateRanges();
372+ onContentYChanged: rendererLoader.updateRanges();
373+ onHeightChanged: rendererLoader.updateRanges();
374+ onContentHeightChanged: rendererLoader.updateRanges();
375+ }
376+ Connections {
377+ target: scopeView
378+ onIsCurrentChanged: rendererLoader.updateRanges();
379+ }
380+ Connections {
381+ target: holdingList
382+ onMovingChanged: if (!moving) rendererLoader.updateRanges();
311383 }
312384
313− function updateDelegateCreationRange() {
385+ function updateRanges() {
386+ if (holdingList && holdingList.moving) {
387+ return;
388+ }
389+
314390 if (categoryView.moving) {
315391 // Do not update the range if we are overshooting up or down, since we'll come back
316392 // to the stable position and delete/create items without any reason
@@ -322,10 +398,18 @@ FocusScope {
322398 }
323399 }
324400
401+ if (item && item.hasOwnProperty("visibleRangeBegin")) {
402+ item.visibleRangeBegin = Math.max(-baseItem.y, 0)
403+ item.visibleRangeEnd = item.visibleRangeBegin + Math.min(categoryView.height, rendererLoader.height)
404+ }
405+
325406 if (item && item.hasOwnProperty("displayMarginBeginning")) {
326407 // TODO do we need item.originY here, test 1300302 once we have a silo
327408 // and we can run it on the phone
328− if (baseItem.y + baseItem.height <= 0) {
409+ if (scopeView.isCurrent) {
410+ item.displayMarginBeginning = 1073741823;
411+ item.displayMarginEnd = 1073741823;
412+ } else if (baseItem.y + baseItem.height <= 0) {
329413 // Not visible (item at top of the list viewport)
330414 item.displayMarginBeginning = -baseItem.height;
331415 item.displayMarginEnd = 0;
@@ -334,9 +418,9 @@ FocusScope {
334418 item.displayMarginBeginning = 0;
335419 item.displayMarginEnd = -baseItem.height;
336420 } else {
337− item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
338− item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
339− - categoryView.height + baseItem.y, 0)
421+ item.displayMarginBeginning = Math.round(-Math.max(-baseItem.y, 0));
422+ item.displayMarginEnd = -Math.round(Math.max(baseItem.height - seeAll.height
423+ - categoryView.height + baseItem.y, 0));
340424 }
341425 }
342426 }
@@ -353,10 +437,11 @@ FocusScope {
353437 height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(4) : 0
354438
355439 onClicked: {
356− if (categoryView.expandedCategoryItem !== baseItem) {
357− categoryView.expandedCategoryItem = baseItem;
440+ if (categoryView.expandedCategoryId !== baseItem.category) {
441+ categoryView.expandedCategoryId = baseItem.category;
442+ floatingSeeLess.companionBase = baseItem;
358443 } else {
359− categoryView.expandedCategoryItem = null;
444+ categoryView.expandedCategoryId = "";
360445 }
361446 }
362447
@@ -456,7 +541,7 @@ FocusScope {
456541 objectName: "floatingSeeLess"
457542
458543 property Item companionTo: companionBase ? companionBase.seeAllButton : null
459− property Item companionBase: categoryView.expandedCategoryItem
544+ property Item companionBase: null
460545 property bool showBecausePosition: false
461546 property real yOffset: 0
462547
@@ -468,7 +553,7 @@ FocusScope {
468553 height: seeLessLabel.font.pixelSize + units.gu(4)
469554 visible: companionTo && showBecausePosition
470555
471− onClicked: categoryView.expandedCategoryItem = null;
556+ onClicked: categoryView.expandedCategoryId = "";
472557
473558 function updateVisibility() {
474559 var companionPos = companionTo.mapToItem(floatingSeeLess, 0, 0);
@@ -477,6 +562,10 @@ FocusScope {
477562 var posToBase = floatingSeeLess.mapToItem(companionBase, 0, -yOffset).y;
478563 yOffset = Math.max(0, companionBase.item.collapsedHeight - posToBase);
479564 yOffset = Math.min(yOffset, height);
565+
566+ if (!showBecausePosition && categoryView.expandedCategoryId === "") {
567+ companionBase = null;
568+ }
480569 }
481570
482571 Label {