[gnome-shell/wip/paging-release2: 12/14] AppDisplay: Make space on grid to fit collection when opening
- From: Carlos Soriano <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/paging-release2: 12/14] AppDisplay: Make space on grid to fit collection when opening
- Date: Thu, 22 Aug 2013 10:48:25 +0000 (UTC)
commit 88e831be4e2e4da202446bf0e8aa2ab962a1087d
Author: Carlos Soriano <carlos soriano89 gmail com>
Date: Tue Jul 9 15:11:03 2013 +0200
AppDisplay: Make space on grid to fit collection when opening
Add properly functions in AllView and FolderView to animate
the FolderView popup opening.
js/ui/appDisplay.js | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++-
js/ui/iconGrid.js | 30 ++++++++-
2 files changed, 182 insertions(+), 7 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index d66613e..6f0f2cb 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -34,7 +34,7 @@ const MIN_COLUMNS = 4;
const MIN_ROWS = 4;
const INACTIVE_GRID_OPACITY = 77;
-const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.15;
+const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.40;
const FOLDER_SUBICON_FRACTION = .4;
const MAX_APPS_PAGES = 20;
@@ -44,6 +44,8 @@ const MAX_APPS_PAGES = 20;
const PAGE_SWITCH_TRESHOLD = 0.2;
const PAGE_SWITCH_TIME = 0.3;
+const POPUP_FOLDER_VIEW_ANIMATION = 0.25;
+
// Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
function _loadCategory(dir, view) {
let iter = dir.iter();
@@ -344,6 +346,8 @@ const AllView = new Lang.Class({
// we have to tell pagination that the adjustment is not correct (since the allocated size of
pagination changed)
// For that problem we return to the first page of pagination.
this.invalidatePagination = false;
+ this._popupExpansionNeeded = true;
+ this.displayingPopup = false;
// Always start at page 0 when we enter and quit overview
Main.overview.connect('hidden', Lang.bind(this, function() {this.goToPage(0, true);}));
},
@@ -356,6 +360,10 @@ const AllView = new Lang.Class({
},
goToPage: function(pageNumber, updateIndicators, action) {
+ if (this._currentPage != pageNumber && this.displayingPopup && this._currentPopup)
+ this._currentPopup.popdown();
+ else if(this.displayingPopup && this._currentPopup)
+ return;
this.viewGoToPage(pageNumber, action);
if (updateIndicators)
this.indicatorsGoToPage(pageNumber);
@@ -416,7 +424,130 @@ const AllView = new Lang.Class({
return Math.abs(currentScrollPosition - this._grid.getPagePosition(pageNumber)[1]);
},
+ /**
+ * Pan view with items to make space for the folder view.
+ * @param folderNVisibleRowsAtOnce this parameter tell how many rows the folder view has, but,
+ * it is already constrained to be at maximum of main grid rows least one, to ensure we have
+ * enough space to show the folder view popup.
+ */
+ makeSpaceForPopUp: function(iconActor, side, folderNVisibleRowsAtOnce) {
+ let rowsUp = [];
+ let rowsDown = [];
+ let mainIconYPosition = iconActor.actor.y;
+ let mainIconRowReached = false;
+ let isMainIconRow = false;
+ let rows = this._grid.pageRows(this._currentPage);
+ this._translatedRows = rows;
+ for (let rowIndex in rows) {
+ isMainIconRow = mainIconYPosition == rows[rowIndex][0].y;
+ if (isMainIconRow)
+ mainIconRowReached = true;
+ if ( !mainIconRowReached)
+ rowsUp.push(rows[rowIndex]);
+ else {
+ if (isMainIconRow) {
+ if (side == St.Side.BOTTOM)
+ rowsDown.push(rows[rowIndex]);
+ else
+ rowsUp.push(rows[rowIndex]);
+ } else
+ rowsDown.push(rows[rowIndex]);
+ }
+ }
+ //The last page can have space without rows
+ let emptyRows = this._grid.rowsPerPage() - rows.length ;
+ let panViewUpNRows = 0;
+ let panViewDownNRows = 0;
+ if(side == St.Side.BOTTOM) {
+ // There's not need to pan view down
+ if (rowsUp.length >= folderNVisibleRowsAtOnce)
+ panViewUpNRows = folderNVisibleRowsAtOnce;
+ else {
+ panViewUpNRows = rowsUp.length;
+ panViewDownNRows = folderNVisibleRowsAtOnce - rowsUp.length;
+ }
+ } else {
+ // There's not need to pan view up
+ if (rowsDown.length + emptyRows >= folderNVisibleRowsAtOnce)
+ panViewDownNRows = folderNVisibleRowsAtOnce;
+ else {
+ panViewDownNRows = rowsDown.length + emptyRows;
+ panViewUpNRows = folderNVisibleRowsAtOnce - rowsDown.length - emptyRows;
+ }
+ }
+ this._updateIconOpacities(true);
+ // Especial case, last page and no rows below the icon of the folder, no rows down neither rows up,
+ // we call directly the popup
+ if (panViewDownNRows > 0 && rowsDown.length == 0 && rowsUp.length == 0) {
+ this.displayingPopup = true;
+ this._popupExpansionNeeded = false;
+ iconActor.onCompleteMakeSpaceForPopUp();
+ } else {
+ this._popupExpansionNeeded = true;
+ this._panViewForFolderView(rowsUp, rowsDown, panViewUpNRows, panViewDownNRows, iconActor);
+ }
+ },
+
+ returnSpaceToOriginalPosition: function() {
+ this._updateIconOpacities(false);
+ if (!this._popupExpansionNeeded) {
+ this.displayingPopup = false;
+ return;
+ }
+ if (this._translatedRows) {
+ for (let rowId in this._translatedRows) {
+ for (let childrenId in this._translatedRows[rowId]) {
+ if (this._translatedRows[rowId][childrenId]._translateY) {
+ let tweenerParams = { _translateY: 0,
+ time: POPUP_FOLDER_VIEW_ANIMATION,
+ onUpdate: function() {this.queue_relayout();},
+ transition: 'easeInOutQuad',
+ onComplete: Lang.bind(this, function(){ this.displayingPopup =
false; }) };
+ Tweener.addTween(this._translatedRows[rowId][childrenId], tweenerParams);
+ }
+ }
+ }
+ }
+ },
+
+ _panViewForFolderView: function(rowsUp, rowsDown, panViewUpNRows, panViewDownNRows, iconActor) {
+ let rowHeight = this._grid.rowHeight();
+ if (panViewUpNRows > 0) {
+ this.displayingPopup = true;
+ let height = rowHeight * panViewUpNRows;
+ for (let rowId in rowsUp) {
+ for (let childrenId in rowsUp[rowId]) {
+ rowsUp[rowId][childrenId]._translateY = 0;
+ let tweenerParams = { _translateY: - height,
+ time: POPUP_FOLDER_VIEW_ANIMATION,
+ onUpdate: function() { this.queue_relayout(); },
+ transition: 'easeInOutQuad' };
+ if ((rowId == rowsUp.length - 1) && (childrenId == rowsUp[rowId].length - 1))
+ tweenerParams['onComplete'] = Lang.bind(iconActor,
iconActor.onCompleteMakeSpaceForPopUp);
+ Tweener.addTween(rowsUp[rowId][childrenId], tweenerParams);
+ }
+ }
+ }
+ if (panViewDownNRows > 0) {
+ this.displayingPopup = true;
+ let height = rowHeight * panViewDownNRows;
+ for (let rowId in rowsDown) {
+ for (let childrenId in rowsDown[rowId]) {
+ rowsDown[rowId][childrenId]._translateY = 0;
+ let tweenerParams = { _translateY: height,
+ time: POPUP_FOLDER_VIEW_ANIMATION,
+ onUpdate: function() { this.queue_relayout(); } };
+ if ((rowId == rowsDown.length - 1) && (childrenId == rowsDown[rowId].length - 1))
+ tweenerParams['onComplete'] = Lang.bind(iconActor,
iconActor.onCompleteMakeSpaceForPopUp);
+ Tweener.addTween(rowsDown[rowId][childrenId], tweenerParams);
+ }
+ }
+ }
+ },
+
_onScroll: function(actor, event) {
+ if(this.displayingPopup)
+ return;
let direction = event.get_scroll_direction();
let nextPage;
if (direction == Clutter.ScrollDirection.UP)
@@ -432,6 +563,8 @@ const AllView = new Lang.Class({
},
_onPan: function(action) {
+ if (this.displayingPopup)
+ return;
this._clickAction.release();
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this._verticalAdjustment;
@@ -440,6 +573,8 @@ const AllView = new Lang.Class({
},
_onPanEnd: function(action) {
+ if (this.displayingPopup)
+ return;
let diffCurrentPage = this._diffToPage(this._currentPage);
if (diffCurrentPage > this._paginationView.height * PAGE_SWITCH_TRESHOLD) {
if (action.get_velocity(0)[2] > 0 && this._currentPage > 0)
@@ -1065,7 +1200,6 @@ const FolderIcon = new Lang.Class({
this.actor.connect('clicked', Lang.bind(this,
function() {
this._ensurePopup();
- this._popup.toggle();
this.view.setScrollToStart();
}));
this.actor.connect('notify::mapped', Lang.bind(this,
@@ -1073,6 +1207,9 @@ const FolderIcon = new Lang.Class({
if (!this.actor.mapped && this._popup)
this._popup.popdown();
}));
+ this.actor.connect('notify::allocation', Lang.bind(this, function() {
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, this._updatePopupPosition));
+ }));
},
_createIcon: function(size) {
@@ -1094,6 +1231,18 @@ const FolderIcon = new Lang.Class({
return usedHeight;
},
+ makeSpaceForPopUp: function() {
+ this._parentView.makeSpaceForPopUp(this, this._boxPointerArrowside,
this.view.nRowsDisplayedAtOnce());
+ },
+
+ returnSpaceToOriginalPosition: function() {
+ this._parentView.returnSpaceToOriginalPosition();
+ },
+
+ onCompleteMakeSpaceForPopUp: function() {
+ this._popup.popup();
+ },
+
_calculateBoxPointerArrowSide: function() {
let absoluteActorYPosition = this.actor.get_transformed_position()[1];
let spaceTop = absoluteActorYPosition;
@@ -1179,8 +1328,10 @@ const FolderIcon = new Lang.Class({
},
_ensurePopup: function() {
- if (this._popup && !this.invalidatePopUp)
+ if (this._popup && !this.invalidatePopUp){
+ this.makeSpaceForPopUp();
return;
+ }
this._boxPointerArrowside = this._calculateBoxPointerArrowSide();
if (!this._popup) {
this._popup = new AppFolderPopup(this, this._boxPointerArrowside);
@@ -1189,12 +1340,14 @@ const FolderIcon = new Lang.Class({
function(popup, isOpen) {
if (!isOpen) {
this.actor.checked = false;
+ this.returnSpaceToOriginalPosition();
}
}));
} else
this._popup.updateBoxPointer(this._boxPointerArrowside);
this._updatePopUpSize();
this._updatePopupPosition();
+ this.makeSpaceForPopUp();
this.invalidatePopUp = false;
},
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 4c8eb3b..6a6475e 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -329,6 +329,10 @@ const IconGrid = new Lang.Class({
childBox.y1 = Math.floor(y + childYSpacing);
childBox.x2 = childBox.x1 + width;
childBox.y2 = childBox.y1 + height;
+ if(child._translateY) {
+ childBox.y1 += child._translateY;
+ childBox.y2 += child._translateY;
+ }
return childBox;
},
@@ -369,10 +373,6 @@ const IconGrid = new Lang.Class({
return children;
},
- childrenInRow: function(rowWidth) {
- return this._computeLayout(rowWidth)[0];
- },
-
getRowLimit: function() {
return this._rowLimit;
},
@@ -588,6 +588,28 @@ const PaginatedIconGrid = new Lang.Class({
}
},
+ rowsPerPage: function() {
+ return this._rowsPerPage;
+ },
+
+ pageRows: function(pageNumber) {
+ let pagePosition = this.getPagePosition(pageNumber);
+ let currentRowItemsYPosition = pagePosition;
+ let rows = [];
+ let currentItem = this._getVisibleChildren()[pageNumber * this._childrenPerPage];
+ let children = this._grid.get_children();
+ let index = pageNumber * this._childrenPerPage;
+ for (let rowIndex = 0; rowIndex < this._rowsPerPage && index < children.length; rowIndex++) {
+ rows[rowIndex] = [];
+ while (index < children.length && children[index].y == currentItem.y) {
+ rows[rowIndex].push(children[index]);
+ index++;
+ }
+ currentItem = children[index];
+ }
+ return rows;
+ },
+
_availableHeightPerPageForItems: function() {
let spacePerRow = this._vItemSize + this._getSpacing();
return this._rowsPerPage * spacePerRow - this._getSpacing() + this.top_padding + this.bottom_padding;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]