[gnome-shell/wip/paging-release: 13/43] New collection implementation, contained inside parent view
- From: Carlos Soriano <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/paging-release: 13/43] New collection implementation, contained inside parent view
- Date: Tue, 13 Aug 2013 19:11:51 +0000 (UTC)
commit 0467851129d807fbf6e33f922dfa3e9ec62a5070
Author: Carlos Soriano <carlos soriano89 gmail com>
Date: Tue Aug 13 13:20:12 2013 +0200
New collection implementation, contained inside parent view
testing
js/ui/appDisplay.js | 219 +++++++++++++++++++++++++++++++--------------------
js/ui/iconGrid.js | 173 ++++++++++++++++++++++++----------------
2 files changed, 238 insertions(+), 154 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 5128b44..f113c03 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -30,6 +30,8 @@ const Util = imports.misc.util;
const MAX_APPLICATION_WORK_MILLIS = 75;
const MENU_POPUP_TIMEOUT = 600;
const MAX_COLUMNS = 6;
+const MIN_COLUMNS = 4;
+const MIN_ROWS = 4;
const INACTIVE_GRID_OPACITY = 77;
const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.15;
@@ -199,6 +201,11 @@ const AppPages = new Lang.Class({
addFolderPopup: function(popup) {
this._parent.addFolderPopup(popup);
},
+
+ removeFolderPopUp: function(popup) {
+ this._parent.removeFolderPopUp(popup);
+ },
+
/**
* Pan view with items to make space for the folder view.
* @param folderNVisibleRowsAtOnce this parameter tell how many rows the folder view has, but,
@@ -206,7 +213,6 @@ const AppPages = new Lang.Class({
* enough space to show the folder view.
*/
makeSpaceForPopUp: function(iconActor, side, folderNVisibleRowsAtOnce) {
- global.log("#### makeSpaceForPopUp ####");
let rowsUp = [];
let rowsDown = [];
let mainIconYPosition = iconActor.actor.y;
@@ -215,7 +221,6 @@ const AppPages = new Lang.Class({
let isMainIconRow = false;
let rows = this._grid.pageRows(currentPage);
this._translatedRows = rows;
- //global.log(" ROWS " + rows);
for(let rowIndex in rows) {
isMainIconRow = mainIconYPosition == rows[rowIndex][0].y;
if(isMainIconRow)
@@ -256,7 +261,6 @@ const AppPages = new Lang.Class({
}
this._panViewForFolderView(rowsUp, rowsDown, panViewUpNRows, panViewDownNRows, iconActor);
this.updateIconOpacities(true);
- global.log("#### END makeSpaceForPopUp ####");
},
returnSpaceToOriginalPosition: function() {
@@ -286,18 +290,14 @@ const AppPages = new Lang.Class({
for(let rowId in rowsUp) {
for(let childrenId in rowsUp[rowId]) {
rowsUp[rowId][childrenId].translate_y = 0;
- //global.log("children up y " + rowsUp[rowId][childrenId].translate_y);
let tweenerParams = { translate_y: - 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);
+ tweenerParams['onComplete'] = Lang.bind(iconActor,
iconActor.onCompleteMakeSpaceForPopUp);
}
Tweener.addTween(rowsUp[rowId][childrenId], tweenerParams);
- //rowsUp[rowId][childrenId].translate_y = - height;
- //rowsUp[rowId][childrenId].queue_relayout();
- //global.log("after children up y " + rowsUp[rowId][childrenId].translate_y);
}
}
}
@@ -306,7 +306,6 @@ const AppPages = new Lang.Class({
let height = rowHeight * panViewDownNRows;
for(let rowId in rowsDown) {
for(let childrenId in rowsDown[rowId]) {
- //global.log("children down y " + rowsDown[rowId][childrenId].translate_y);
rowsDown[rowId][childrenId].translate_y = 0;
let tweenerParams = { translate_y: height,
time: POPUP_FOLDER_VIEW_ANIMATION,
@@ -315,9 +314,6 @@ const AppPages = new Lang.Class({
tweenerParams['onComplete'] = Lang.bind(iconActor,
iconActor.onCompleteMakeSpaceForPopUp);
}
Tweener.addTween(rowsDown[rowId][childrenId], tweenerParams);
- //rowsDown[rowId][childrenId].translate_y = height;
- //rowsDown[rowId][childrenId].queue_relayout();
- //global.log("after children down y " + rowsDown[rowId][childrenId].translate_y);
}
}
}
@@ -417,10 +413,12 @@ const PaginationScrollView = new Lang.Class({
},
vfunc_allocate: function(box, flags) {
+
box = this.get_parent().allocation;
this.set_allocation(box, flags);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
+ //FIXME
let childBox = new Clutter.ActorBox();
childBox.x1 = 0;
childBox.y1 = 0;
@@ -527,13 +525,18 @@ const PaginationScrollView = new Lang.Class({
addFolderPopup: function(popup) {
this._stack.add_actor(popup.actor);
- popup.connect('open-state-changed', Lang.bind(this,
+ popup.openStateId = popup.connect('open-state-changed', Lang.bind(this,
function(popup, isOpen) {
this._eventBlocker.reactive = isOpen;
this._currentPopup = isOpen ? popup : null;
}));
},
+ removeFolderPopUp: function(popup) {
+ popup.disconnect(popup.openStateId);
+ this._stack.remove_child(popup.actor);
+ },
+
_onPan: function(action) {
this._clickAction.release();
if(this._pages.displayingPopup)
@@ -568,6 +571,7 @@ const PaginationScrollView = new Lang.Class({
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
this._pages.onUpdatedDisplaySize(availWidth, availHeight);
+ //this.invalidatePagination = true;
}
});
@@ -846,9 +850,9 @@ const ControlsBoxLayout = Lang.Class({
const AppDisplayActor = new Lang.Class({
Name: 'AppDisplayActor',
- Extends: Clutter.BoxLayout,
+ Extends: Clutter.BinLayout,
- vfunc_allocate: function (actor, box, flags) {
+ vfunc_allocate: function (actor, box, flags) {
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
// Prepare children of all views for the upcomming allocation, calculate all
@@ -907,12 +911,13 @@ const AppDisplay = new Lang.Class({
this.actor = new St.Widget({ style_class: 'app-display',
x_expand: true, y_expand: true });
- this._actorLayout = new AppDisplayActor({vertical: true});
- this.actor.set_layout_manager(this._actorLayout);
- this._actorLayout.connect('allocated-size-changed', Lang.bind(this, this._onUpdatedDisplaySize));
+ this._viewStackLayout = new AppDisplayActor();
+ this.actor.set_layout_manager(new Clutter.BoxLayout({vertical: true}));
+ this._viewStackLayout.connect('allocated-size-changed', Lang.bind(this, this._onUpdatedDisplaySize));
- this._viewStack = new St.Widget({ layout_manager: new Clutter.BinLayout(),
+ this._viewStack = new St.Widget({
x_expand: true, y_expand: true });
+ this._viewStack.set_layout_manager(this._viewStackLayout);
//FIXME
this.actor.add_actor(this._viewStack, { expand: true });
let layout = new ControlsBoxLayout({ homogeneous: true });
@@ -1095,20 +1100,21 @@ const AppSearchProvider = new Lang.Class({
const FolderView = new Lang.Class({
Name: 'FolderView',
- _init: function(parentView) {
+ _init: function() {
this._grid = new IconGrid.IconGrid({ xAlign: St.Align.MIDDLE,
columnLimit: MAX_COLUMNS });
- this._parentView = parentView;
this.actor = new St.ScrollView({overlay_scrollbars: true});
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
- this._box = new St.BoxLayout({vertical:true, reactive: true});
+ this._box = new St.BoxLayout({vertical: true, reactive: true});
this._widget = new St.Widget({layout_manager: new Clutter.BinLayout()});
this._widget.add_child(this._grid.actor);
this._box.add_actor(this._widget);
this.actor.add_actor(this._box);
this._items = {};
this._allItems = [];
+
+ this._boxPointerOffsets = {};
},
_getItemId: function(item) {
@@ -1124,6 +1130,9 @@ const FolderView = new Lang.Class({
},
addApp: function(app) {
+ //FIXME
+ if(this._allItems.length > 1)
+ return;
this._addItem(app);
},
@@ -1179,12 +1188,27 @@ const FolderView = new Lang.Class({
this._appDisplayWidth = width;
this._appDisplayHeight = height;
// Update grid dinamyc spacing based on display width
- let itemWidth = this._grid._hItemSize * MAX_COLUMNS;
- let emptyArea = width - itemWidth;
- let spacing;
- spacing = Math.max(this._grid._spacing, emptyArea / ( 2 * MAX_COLUMNS));
- spacing = Math.round(spacing);
+ let spacing = this._grid.maxSpacingForWidthHeight(width, height, MIN_COLUMNS, MIN_ROWS, true);
this._grid.setSpacing(spacing);
+ if(!Object.keys(this._boxPointerOffsets).length)
+ return;
+ //WE put the normal padding as spacing as we have in the main grid to do well the calculations for
used rows, used columns etc, since
+ // it is the behaviour we want to emulate. After that we will put the correct padding
fromcalculations of the boxpointer offsets, to ensure
+ //the boxpointer will be contained in side the view
+ this._grid.top_padding = spacing;
+ this._grid.bottom_padding = spacing;
+ this._grid.left_padding = spacing;
+ this._grid.right_padding = spacing;
+ let boxPointerTotalOffset;
+ if(this.nRowsDisplayedAtOnce() == this.maxRowsDisplayedAtOnce())
+ boxPointerTotalOffset = this._boxPointerOffsets['arrowHeight'] +
this._boxPointerOffsets['padding'] * 2 + this._boxPointerOffsets['closeButtonOverlap'];
+ else
+ boxPointerTotalOffset = this._boxPointerOffsets['arrowHeight'] +
this._boxPointerOffsets['padding'] * 2;
+ let offsetForEachSide = Math.ceil(boxPointerTotalOffset / 2);
+ this._grid.top_padding = spacing - offsetForEachSide;
+ this._grid.bottom_padding = spacing - offsetForEachSide;
+ this._grid.left_padding = spacing - offsetForEachSide;
+ this._grid.right_padding = spacing - offsetForEachSide;
},
_containerBox: function() {
@@ -1200,14 +1224,12 @@ const FolderView = new Lang.Class({
let box = this._containerBox();
let availWidthPerPage = box.x2 - box.x1;
let maxUsedWidth = this._grid.usedWidth(availWidthPerPage);
- global.log("maxUsedWidth " + maxUsedWidth);
return maxUsedWidth;
},
usedHeight: function() {
// Then calculate the real maxUsedHeight
- global.log("this.nRowsDisplayedAtOnce() " + this.nRowsDisplayedAtOnce());
- return this._grid.usedHeightForNRows(this.nRowsDisplayedAtOnce());
+ return this._grid.usedHeightForNRows(this.nRowsDisplayedAtOnce()) + this._grid.top_padding +
this._grid.bottom_padding;
},
nRowsDisplayedAtOnce: function() {
@@ -1224,10 +1246,22 @@ const FolderView = new Lang.Class({
let box = this._containerBox();
let availHeightPerPage = box.y2 - box.y1;
let availWidthPerPage = box.x2 - box.x1;
+ //FIXME
let maxRowsPerPage = this._grid.rowsForHeight(availHeightPerPage);
//Then, we can only show that rows least one.
maxRowsPerPage -= 1;
return maxRowsPerPage;
+ },
+
+ updateBoxPointerOffsets: function(arrowHeight, padding, closeButtonOverlap) {
+ // We have to ensure the close button doesn't go outside the allocation, so
+ // if we are using all the possible rows, means the boxpointer goes until
+ // the boundary of allocation, and then we have to take into account the close button
+ // overlap and least it from padding
+ this._boxPointerOffsets['arrowHeight'] = arrowHeight;
+ this._boxPointerOffsets['padding'] = padding;
+ this._boxPointerOffsets['closeButtonOverlap'] = closeButtonOverlap;
+
}
});
@@ -1245,7 +1279,13 @@ const FolderIcon = new Lang.Class({
y_fill: true });
this.actor._delegate = this;
this._parentView = parentView;
-
+ // when changing screen resolution or during clutter false allocations
+ // we have to tell folder view that the calculated values of boxpointer arrow side, position, etc
+ // are not correct (since the allocated size of pagination changed)
+ // For that problem we calculate everything again and apply it maintaining current popup.
+ this.invalidatePopUp = false;
+ this._boxPointerOffsets = {};
+
let label = this._dir.get_name();
this.icon = new IconGrid.BaseIcon(label,
{ createIcon: Lang.bind(this, this._createIcon) });
@@ -1278,76 +1318,71 @@ const FolderIcon = new Lang.Class({
_updatePopupPosition: function() {
if(this._popup) {
// Position the popup above or below the source icon
- if (this._side == St.Side.BOTTOM) {
- global.log("Bottom " + this.actor.y);
+ if (this._boxPointerArrowside == St.Side.BOTTOM) {
let closeButtonOffset = -this._popup.closeButton.translation_y;
- let y = this.actor.y - this._popup.actor.fixed_height;
- global.log("Bottom " + this._popup.actor.fixed_height);
+ // FLORIAN REVIEW
+ // We have to use this function, since this._popup.actor.height not always return a good
value (32 px??)
+ // and then all this calculation of position fails. To solve this in this function we
calculate the used height with the grid
+ // since we knoe all of the properties of grid. Then we add the padding, arrowheigth etc of
boxpointer, and we have the
+ // used height of the popup
+ let y = this.actor.y - this._popUpHeight();
let yWithButton = y - closeButtonOffset;
this._popup.parentOffset = yWithButton < 0 ? -yWithButton : 0;
this._popup.actor.y = Math.max(y, closeButtonOffset);
+ this._popup.actor.y = y
} else {
this._popup.actor.y = this.actor.y + this.actor.height;
}
}
},
- _popUpWidth: function() {
+ _popUpGridWidth: function() {
return this.view.usedWidth();
},
- _popUpHeight: function() {
- /*
- * To maintain the grid of the collection aligned to the main grid, we have to
- * make the same spacing to each element of the collection as the main grid has, except
- * for the last row which has to take less space, since the grid of collection is inside a view with
padding (the popup)
- * and, the arrow of the popup is rising some pixels the collection, we have to calculate how much
real spacing
- * we have to let under/above the last/first arrow to make let the collection grid aligned with the
main grid
- */
- let arrowHeight = this._popup._boxPointer.actor.get_theme_node().get_length('-arrow-rise');
- let popupPadding = this._popup._boxPointer.bin.get_theme_node().get_length('padding');
- //It will be negative value, so we have to rest it, instead of plust it.
- let closeButtonOverlap =
this._popup.closeButton.get_theme_node().get_length('-shell-close-overlap-y');
- let closeButtonHeight = this._popup.closeButton.height;
- global.log("BUTTON OFFSET " + closeButtonOverlap);
+ _popUpGridHeight: function() {
let usedHeight = this.view.usedHeight();
- // If we want it corrected aligned with the main grid the calculation will be: usedHeight -
popupPadding - arrowHeight
- // but, if we do that and the popup needs all the height, the popup will remain outside the
allocation and then clipped. so:
- if(this.view.nRowsDisplayedAtOnce() == this.view.maxRowsDisplayedAtOnce())
- usedHeight = usedHeight - popupPadding * 2 - arrowHeight + closeButtonOverlap;
- else
- usedHeight = usedHeight - popupPadding - arrowHeight;
- return usedHeight;
-
+ return usedHeight;
+ },
+
+ _popUpHeight: function() {
+ let usedHeight = this.view.usedHeight() + this._boxPointerOffsets['arrowHeight'] +
this._boxPointerOffsets['padding'] * 2;
+ return usedHeight;
},
makeSpaceForPopUp: function() {
- this._parentView.makeSpaceForPopUp(this, this._side, this.view.nRowsDisplayedAtOnce());
+ this._parentView.makeSpaceForPopUp(this, this._boxPointerArrowside,
this.view.nRowsDisplayedAtOnce());
},
returnSpaceToOriginalPosition: function() {
- global.log("Original position");
this._parentView.returnSpaceToOriginalPosition();
},
onCompleteMakeSpaceForPopUp: function() {
- //Mainloop.timeout_add(0.1, Lang.bind(this, function() {
this._popup.popup();
},
+ _calculateBoxPointerArrowSide: function() {
+ let absoluteActorYPosition = this.actor.get_transformed_position()[1];
+ let spaceTop = absoluteActorYPosition;
+ let spaceBottom = this.actor.get_stage().height - (absoluteActorYPosition + this.actor.height);
+ return spaceTop > spaceBottom ? St.Side.BOTTOM : St.Side.TOP;
+ },
+
_ensurePopup: function() {
- if(this._popup){
+ if(this._popup && !this.invalidatePopUp){
this.makeSpaceForPopUp();
return;
} else {
- let absoluteActorYPosition = this.actor.get_transformed_position()[1];
- let spaceTop = absoluteActorYPosition;
- let spaceBottom = this.actor.get_stage().height - (absoluteActorYPosition + this.actor.height);
- global.log("absoluteActorYPosition " + absoluteActorYPosition);
- this._side = spaceTop > spaceBottom ? St.Side.BOTTOM : St.Side.TOP;
- global.log("this._side " + this._side);
- this._popup = new AppFolderPopup(this, this._side);
- this._parentView.addFolderPopup(this._popup);
+
+ this._boxPointerArrowside = this._calculateBoxPointerArrowSide();
+ let firstCreationPopup = this._popup ? false : true;
+ if(!this._popup) {
+ this._popup = new AppFolderPopup(this, this._boxPointerArrowside);
+ this._parentView.addFolderPopup(this._popup);
+ } else
+ this._popup.updateBoxPointer(this._boxPointerArrowside);
+ // FLORIAN REVIEW
/**
* Why we need that: AppDiplay update width for the spacing for all
* views Allview and frequent view and folder views calcualte spacing
@@ -1376,7 +1411,14 @@ const FolderIcon = new Lang.Class({
* Solution: ensure style of the grid just after we add it to the parent
* and before the calculation of the position.
*/
+
this.view._grid.actor.ensure_style();
+ this._boxPointerOffsets['arrowHeight'] =
this._popup._boxPointer.actor.get_theme_node().get_length('-arrow-rise');
+ this._boxPointerOffsets['padding'] =
this._popup._boxPointer.bin.get_theme_node().get_length('padding');
+ //It will be negative value, so we have to substract it, instead of plust it.
+ this._boxPointerOffsets['closeButtonOverlap'] = -
this._popup.closeButton.get_theme_node().get_length('-shell-close-overlap-y');
+
+ this.view.updateBoxPointerOffsets(this._boxPointerOffsets['arrowHeight'],
this._boxPointerOffsets['padding'], this._boxPointerOffsets['closeButtonOverlap']);
this.view.onUpdatedDisplaySize(this._displayWidth, this._displayHeight);
/*
@@ -1385,7 +1427,7 @@ const FolderIcon = new Lang.Class({
* icons than necesary to full the row. In that manner the popup will be
* more eye pleasant, fulling the parent view
*/
- this.view.actor.set_width(this._popUpWidth());
+ this.view.actor.set_width(this._popUpGridWidth());
/*
* A folder view can only be, at a maximum, one row less than the parent
@@ -1393,20 +1435,21 @@ const FolderIcon = new Lang.Class({
* then calculate the maxUsedHeigth and the current Used height, if it
* is more, strech to the maxUsedHeight
*/
- let usedHeight = this._popUpHeight();
- global.log("Used height " + usedHeight);
- this.view.actor.set_height(this._popUpHeight());
- this._popup.actor.fixed_height = this._popup.actor.height;
-
+ let usedHeight = this._popUpGridHeight();
+ this.view.actor.set_height(this._popUpGridHeight());
+ this._updatePopupPosition();
this.makeSpaceForPopUp();
- this._popup.connect('open-state-changed', Lang.bind(this,
- function(popup, isOpen) {
- if (!isOpen) {
- this.actor.checked = false;
- this.returnSpaceToOriginalPosition();
- }
- }));
+ if(firstCreationPopup) {
+ this._popup.connect('open-state-changed', Lang.bind(this,
+ function(popup, isOpen) {
+ if (!isOpen) {
+ this.actor.checked = false;
+ this.returnSpaceToOriginalPosition();
+ }
+ }));
+ }
+ this.invalidatePopUp = false;
}
},
@@ -1414,6 +1457,7 @@ const FolderIcon = new Lang.Class({
this._displayWidth = width;
this._displayHeight = height;
this.view.onUpdatedDisplaySize(width, height);
+ this.invalidatePopUp = true;
},
});
@@ -1493,7 +1537,7 @@ const AppFolderPopup = new Lang.Class({
this.actor.show();
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
this._boxPointer.setArrowActor(this._source.actor);
- this._boxPointer.show(BoxPointer.PopupAnimation.FADE);
+ this._boxPointer.show(BoxPointer.PopupAnimation.FADE | BoxPointer.PopupAnimation.SLIDE);
this._isOpen = true;
this.emit('open-state-changed', true);
@@ -1503,9 +1547,14 @@ const AppFolderPopup = new Lang.Class({
if (!this._isOpen)
return;
- this._boxPointer.hide(BoxPointer.PopupAnimation.FADE);
+ this._boxPointer.hide(BoxPointer.PopupAnimation.FADE | BoxPointer.PopupAnimation.SLIDE);
this._isOpen = false;
this.emit('open-state-changed', false);
+ },
+
+ updateBoxPointer: function (side) {
+ this._arrowSide = side;
+ this._boxPointer._arrowSide = side;
}
});
Signals.addSignalMethods(AppFolderPopup.prototype);
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 3060019..a7c6e27 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -187,9 +187,15 @@ const IconGrid = new Lang.Class({
this._fillParent = params.fillParent;
this._usePagination = params.usePagination;
+ this.top_padding = 0;
+ this.bottom_padding = 0;
+ this.right_padding = 0;
+ this.left_padding = 0;
+
if(this._usePagination) {
this._nPages = 0;
- //Set this variable properly before allocate function is called
+ // Set this variable properly pointing to the scrollView containing the grid
+ // before allocate function is called
this._viewForPageSize = null;
this._firstPagesItems = [];
}
@@ -206,7 +212,6 @@ const IconGrid = new Lang.Class({
this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._grid.connect('allocate', Lang.bind(this, this._allocate));
-
},
_getPreferredWidth: function (grid, forHeight, alloc) {
@@ -218,14 +223,13 @@ const IconGrid = new Lang.Class({
let nChildren = this._grid.get_n_children();
let nColumns = this._colLimit ? Math.min(this._colLimit,
nChildren)
- : nChildren;
- let spacing = this._fixedSpacing ? this._fixedSpacing : this._spacing;
- let totalSpacing = Math.max(0, nColumns - 1) * spacing;
+ : nChildren;
+ let totalSpacing = Math.max(0, nColumns - 1) * this.getSpacing();
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
// need higher level design
- alloc.min_size = this._hItemSize;
- alloc.natural_size = nColumns * this._hItemSize + totalSpacing;
+ alloc.min_size = this._hItemSize + this.left_padding + this.right_padding;
+ alloc.natural_size = nColumns * this._hItemSize + totalSpacing + this.left_padding +
this.right_padding;
},
_getVisibleChildren: function() {
@@ -249,8 +253,7 @@ const IconGrid = new Lang.Class({
} else {
[nColumns, ] = this._computeLayout(forWidth);
}
-
- let spacing = this._fixedSpacing ? this._fixedSpacing : this._spacing;
+ let spacing = this.getSpacing();
let nRows;
if (nColumns > 0)
@@ -260,11 +263,10 @@ const IconGrid = new Lang.Class({
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
let totalSpacing = Math.max(0, nRows - 1) * spacing;
- let height = nRows * this._vItemSize + totalSpacing;
-
+ let height = nRows * this._vItemSize + totalSpacing + this.top_padding + this.bottom_padding;
if(this._usePagination && this._nPages) {
- alloc.min_size = this._rowsPerPage * this._spacePerRow * this._nPages +
this._spaceBetweenPagesTotal;
- alloc.natural_size = this._rowsPerPage * this._spacePerRow * this._nPages +
this._spaceBetweenPagesTotal;
+ alloc.min_size = this.usedHeightPerPage() * this._nPages + this._spaceBetweenPagesTotal;
+ alloc.natural_size = this.usedHeightPerPage() * this._nPages + this._spaceBetweenPagesTotal;
return;
}
alloc.min_size = height;
@@ -282,14 +284,13 @@ const IconGrid = new Lang.Class({
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
- let spacing = this._fixedSpacing ? this._fixedSpacing : this._spacing;
- let [nColumns, usedWidth] = this._computeLayout(availWidth);
+ let spacing = this.getSpacing();
+ let [nColumns, usedWidth] = this._computeLayout(availWidth);
if(this._usePagination) {
- // ScrollView height
+ // Calculate icongrid box inside the scrollView
let parentBox = this._viewForPageSize.allocation;
let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
let customBox = this._grid.get_theme_node().get_content_box(gridBox);
- let availWidth = customBox.x2 - customBox.x1;
let availHeightPerPage = customBox.y2 - customBox.y1;
let nRows;
if (nColumns > 0)
@@ -302,10 +303,6 @@ const IconGrid = new Lang.Class({
this._calculatePaginationValues(availHeightPerPage, nColumns, nRows);
if(oldNPages != this._nPages) {
this.emit('n-pages-changed', this._nPages);
- /*Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
- this._grid.queue_relayout();
- return false;
- }));*/
}
}
let leftPadding;
@@ -319,13 +316,12 @@ const IconGrid = new Lang.Class({
case St.Align.END:
leftPadding = availWidth - usedWidth;
}
-
- let x = box.x1 + leftPadding;
- let y = box.y1;
+
+ let x = box.x1 + leftPadding + this.left_padding;
+ let y = box.y1 + this.top_padding;
let columnIndex = 0;
let rowIndex = 0;
-
- if(children.length > 0) {
+ if(this._usePagination && children.length > 0) {
this._firstPagesItems = [children[0]];
}
for (let i = 0; i < children.length; i++) {
@@ -336,7 +332,7 @@ const IconGrid = new Lang.Class({
}
if(!this._usePagination) {
if (this._rowLimit && rowIndex >= this._rowLimit ||
- this._fillParent && childBox.y2 >= availHeight) {
+ this._fillParent && childBox.y2 > availHeight - this.bottom_padding) {
this._grid.set_skip_paint(children[i], true);
} else {
children[i].allocate(childBox, flags);
@@ -357,13 +353,13 @@ const IconGrid = new Lang.Class({
y += this._vItemSize + spacing;
if(this._usePagination) {
if((i + 1) % this._childrenPerPage == 0) {
- y+= this._spaceBetweenPages;
+ y+= this._spaceBetweenPages + this.top_padding;
if(i < children.length) {
this._firstPagesItems.push(children[i+1]);
}
}
}
- x = box.x1 + leftPadding;
+ x = box.x1 + leftPadding + this.left_padding;
} else {
x += this._hItemSize + spacing;
}
@@ -372,14 +368,16 @@ const IconGrid = new Lang.Class({
},
_calculatePaginationValues: function (availHeightPerPage, nColumns, nRows) {
- let spacing = this._fixedSpacing ? this._fixedSpacing : this._spacing;
+ let spacing = this.getSpacing();
this._spacePerRow = this._vItemSize + spacing;
+ // We want to contain the grid inside the parent box with padding
+ availHeightPerPage -= this.top_padding + this.bottom_padding;
this._rowsPerPage = Math.floor(availHeightPerPage / this._spacePerRow);
// Check if deleting spacing from bottom there's enough space for another row
let spaceWithOneMoreRow = (this._rowsPerPage + 1) * this._spacePerRow - spacing;
this._rowsPerPage = spaceWithOneMoreRow <= availHeightPerPage? this._rowsPerPage + 1 :
this._rowsPerPage;
this._nPages = Math.ceil(nRows / this._rowsPerPage);
- this._spaceBetweenPages = availHeightPerPage - (this._rowsPerPage * (this._vItemSize + spacing));
+ this._spaceBetweenPages = availHeightPerPage - (this._rowsPerPage * (this._vItemSize + spacing) -
spacing);
this._spaceBetweenPagesTotal = this._spaceBetweenPages * (this._nPages);
this._childrenPerPage = nColumns * this._rowsPerPage;
},
@@ -396,6 +394,7 @@ const IconGrid = new Lang.Class({
let childBox = new Clutter.ActorBox();
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
+ //FIXME not defined box????????
let _x = box.x2 - (x + width);
childBox.x1 = Math.floor(_x - childXSpacing);
} else {
@@ -406,7 +405,30 @@ const IconGrid = new Lang.Class({
childBox.y2 = childBox.y1 + height;
return childBox;
},
-
+
+ _computeLayout: function (forWidth) {
+ let nColumns = 0;
+ let usedWidth = this.left_padding + this.right_padding;
+ let spacing = this.getSpacing();
+ while ((this._colLimit == null || nColumns < this._colLimit) &&
+ (usedWidth + this._hItemSize <= forWidth)) {
+ usedWidth += this._hItemSize + spacing;
+ nColumns += 1;
+ }
+
+ if (nColumns > 0)
+ usedWidth -= spacing;
+ return [nColumns, usedWidth];
+ },
+
+ _onStyleChanged: function() {
+ let themeNode = this.actor.get_theme_node();
+ this._spacing = themeNode.get_length('spacing');
+ this._hItemSize = themeNode.get_length('-shell-grid-horizontal-item-size') || ICON_SIZE;
+ this._vItemSize = themeNode.get_length('-shell-grid-vertical-item-size') || ICON_SIZE;
+ this._grid.queue_relayout();
+ },
+
childrenInRow: function(rowWidth) {
return this._computeLayout(rowWidth)[0];
},
@@ -414,7 +436,7 @@ const IconGrid = new Lang.Class({
getRowLimit: function() {
return this._rowLimit;
},
-
+
nUsedRows: function(forWidth) {
let children = this._getVisibleChildren();
let nColumns;
@@ -423,7 +445,6 @@ const IconGrid = new Lang.Class({
} else {
[nColumns, ] = this._computeLayout(forWidth);
}
-
let nRows;
if (nColumns > 0)
nRows = Math.ceil(children.length / nColumns);
@@ -433,8 +454,9 @@ const IconGrid = new Lang.Class({
nRows = Math.min(nRows, this._rowLimit);
return nRows;
},
-
+
rowsForHeight: function(forHeight) {
+ forHeight -= this.top_padding + this.bottom_padding;
let spacePerRow = this._vItemSize + this.getSpacing();
let rowsPerPage = Math.floor(forHeight / spacePerRow);
// Check if deleting spacing from bottom there's enough space for another row
@@ -442,42 +464,24 @@ const IconGrid = new Lang.Class({
rowsPerPage = spaceWithOneMoreRow <= forHeight? rowsPerPage + 1 : rowsPerPage;
return rowsPerPage;
},
-
+
+ /**
+ * Don't take into account paddings
+ */
usedHeightForNRows: function(nRows) {
let spacePerRow = this.rowHeight();
- return spacePerRow * nRows;
+ return spacePerRow * nRows - this.getSpacing();
},
-
+
+ usedHeightPerPage: function() {
+ return this._rowsPerPage * this._spacePerRow - this.getSpacing() + this.top_padding +
this.bottom_padding;
+ },
+
usedWidth: function(forWidth) {
let childrenInRow = this.childrenInRow(forWidth);
let usedWidth = childrenInRow * (this._hItemSize + this.getSpacing());
usedWidth -= this.getSpacing();
- return usedWidth;
- },
-
- _computeLayout: function (forWidth) {
- let nColumns = 0;
- let usedWidth = 0;
- let spacing = this._fixedSpacing ? this._fixedSpacing : this._spacing;
-
- while ((this._colLimit == null || nColumns < this._colLimit) &&
- (usedWidth + this._hItemSize <= forWidth)) {
- usedWidth += this._hItemSize + spacing;
- nColumns += 1;
- }
-
- if (nColumns > 0)
- usedWidth -= spacing;
-
- return [nColumns, usedWidth];
- },
-
- _onStyleChanged: function() {
- let themeNode = this.actor.get_theme_node();
- this._spacing = themeNode.get_length('spacing');
- this._hItemSize = themeNode.get_length('-shell-grid-horizontal-item-size') || ICON_SIZE;
- this._vItemSize = themeNode.get_length('-shell-grid-vertical-item-size') || ICON_SIZE;
- this._grid.queue_relayout();
+ return usedWidth + this.left_padding + this.right_padding;
},
removeAll: function() {
@@ -510,20 +514,51 @@ const IconGrid = new Lang.Class({
throw new Error('Invalid page number ' + pageNumber);
}
let childBox = this._firstPagesItems[pageNumber].get_allocation_box();
- return [childBox.x1, childBox.y1];
+ return [childBox.x1 - this.top_padding, childBox.y1 - this.top_padding];
},
setSpacing: function(spacing) {
this._fixedSpacing = spacing;
- /*Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
- this._grid.queue_relayout();
- return false;
- }));*/
},
getSpacing: function() {
return this._fixedSpacing ? this._fixedSpacing : this._spacing;
},
+ /**
+ * This functions is intended to use before iconGrid allocation, to know how much spacing can we have at
the grid
+ * but also to set manually the top/bottom rigth/left padding accordnly to the spacing calculated here.
+ * To take into account the spacing also for before the first row and for after the last row mark
usingSurroundingSpacing true
+ * This function doesn't take into account the dynamic padding rigth now, since in fact we want to
calculate also that.
+ */
+ maxSpacingForWidthHeight: function(availWidth, availHeight, minColumns, minRows,
usingSurroundingSpacing) {
+ // Maximum spacing will be the icon item size. It doesn't make any sense to have more spacing than
items.
+ let maxSpacing = Math.floor(Math.min(this._vItemSize, this._hItemSize));
+ let minEmptyVerticalArea = (availHeight - minRows * this._vItemSize);
+ let minEmptyHorizontalArea = (availWidth - minColumns * this._hItemSize);
+ let spacing;
+ if(usingSurroundingSpacing) {
+ // minRows + 1 because we want to put spacing before the first row, so it is like we have one
more row
+ // to divide the empty space
+ let maxSpacingForRows = Math.floor(minEmptyVerticalArea / (minRows +1));
+ let maxSpacingForColumns = Math.floor(minEmptyHorizontalArea / (minColumns +1));
+ let spacingToEnsureMinimums = Math.min(maxSpacingForRows, maxSpacingForColumns);
+ let spacingNotTooBig = Math.min(spacingToEnsureMinimums, maxSpacing);
+ spacing = Math.max(this._spacing, spacingNotTooBig);
+ } else {
+ //We don't want spacing if there's only one row, it will be touching the boundary.
+ if(minRows == 1) {
+ let maxSpacingForRows = 0;
+ let maxSpacingForColumns = 0;
+ } else {
+ let maxSpacingForRows = Math.floor(minEmptyVerticalArea / (minRows - 1));
+ let maxSpacingForColumns = Math.floor(minEmptyHorizontalArea / (minColumns - 1));
+ }
+ let spacingToEnsureMinimums = Math.min(maxSpacingForRows, maxSpacingForColumns);
+ let spacingNotTooBig = Math.min(spacingToEnsureMinimums, maxSpacing);
+ spacing = Math.max(this._spacing, spacingNotTooBig);
+ }
+ return spacing;
+ },
pageRows: function(pageNumber) {
let pagePosition = this.getPagePosition(pageNumber);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]