[gnome-shell/wip/paging-release2: 22/22] iconGrid: Also adapt icon size to available space



commit 66f64cb7bdfbc7f39598aff2f072639407eeaede
Author: Carlos Soriano <carlos soriano89 gmail com>
Date:   Thu Aug 15 10:38:17 2013 +0200

    iconGrid: Also adapt icon size to available space
    
    Similar to adapting the spacing dynamically to the available
    space we already do, scale down icon sizes if the grid is too
    small to fit the requested minimum number of rows/columns.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706081

 js/ui/appDisplay.js |   18 ++++----
 js/ui/iconGrid.js   |  112 +++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 91 insertions(+), 39 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index def1a2e..08f2497 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -586,10 +586,9 @@ const AllView = new Lang.Class({
         let oldNPages = this._grid.nPages();
 
         this._updateAdjustment(availHeight);
-        this._grid.updateSpacingForSize(availWidth, availHeight);
-        this._grid.computePages(availWidth, availHeight);
-        // Make sure the view doesn't have a bad adjustment value after screen size changes
-        // and therefore the pages computation.
+
+        this._grid.adaptToSize(availWidth, availHeight);
+
         if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != 
this._grid.nPages()) {
             this._verticalAdjustment.value = 0;
             Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
@@ -641,7 +640,7 @@ const FrequentView = new Lang.Class({
         box = this._grid.actor.get_theme_node().get_content_box(box);
         let availWidth = box.x2 - box.x1;
         let availHeight = box.y2 - box.y1;
-        this._grid.updateSpacingForSize(availWidth, availHeight);
+        this._grid.adaptToSize(availWidth, availHeight);
     }
 });
 
@@ -974,7 +973,7 @@ const FolderView = new Lang.Class({
         this._parentAvailableWidth = width;
         this._parentAvailableHeight = height;
 
-        this._grid.updateSpacingForSize(width, height);
+        this._grid.adaptToSize(width, height);
 
         // Set extra padding to avoid popup or close button being cut off
         this._grid.topPadding = Math.max(this._grid.topPadding - this._offsetForEachSide, 0);
@@ -1037,7 +1036,7 @@ const FolderIcon = new Lang.Class({
 
         let label = this._dir.get_name();
         this.icon = new IconGrid.BaseIcon(label,
-                                          { createIcon: Lang.bind(this, this._createIcon) });
+                                          { createIcon: Lang.bind(this, this._createIcon), setSizeManually: 
true });
         this.actor.set_child(this.icon.actor);
         this.actor.label_actor = this.icon.label;
 
@@ -1058,8 +1057,8 @@ const FolderIcon = new Lang.Class({
             }));
     },
 
-    _createIcon: function(size) {
-        return this.view.createFolderIcon(size, this);
+    _createIcon: function(iconSize) {
+        return this.view.createFolderIcon(iconSize, this);
     },
 
     _popupHeight: function() {
@@ -1263,6 +1262,7 @@ const AppIcon = new Lang.Class({
             iconParams = {};
 
         iconParams['createIcon'] = Lang.bind(this, this._createIcon);
+        iconParams['setSizeManually'] = true;
         this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
         this.actor.set_child(this.icon.actor);
 
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index ccb67b4..fa7486f 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -3,12 +3,13 @@
 const Clutter = imports.gi.Clutter;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
+const Meta = imports.gi.Meta;
 
 const Lang = imports.lang;
 const Params = imports.misc.params;
 
-const ICON_SIZE = 48;
-
+const ICON_SIZE = 96;
+const MIN_ICON_SIZE = 16;
 
 const BaseIcon = new Lang.Class({
     Name: 'BaseIcon',
@@ -205,6 +206,7 @@ const IconGrid = new Lang.Class({
         // Pulled from CSS, but hardcode some defaults here
         this._spacing = 0;
         this._hItemSize = this._vItemSize = ICON_SIZE;
+        this._fixedHItemSize = this._fixedVItemSize = undefined;
         this._grid = new Shell.GenericContainer();
         this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
         this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
@@ -228,8 +230,8 @@ const IconGrid = new Lang.Class({
         // 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 + this.leftPadding + this.rightPadding;
-        alloc.natural_size = nColumns * this._hItemSize + totalSpacing + this.leftPadding + 
this.rightPadding;
+        alloc.min_size = this._getHItemSize() + this.leftPadding + this.rightPadding;
+        alloc.natural_size = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + 
this.rightPadding;
     },
 
     _getVisibleChildren: function() {
@@ -261,7 +263,7 @@ const IconGrid = new Lang.Class({
         if (this._rowLimit)
             nRows = Math.min(nRows, this._rowLimit);
         let totalSpacing = Math.max(0, nRows - 1) * this._getSpacing();
-        let height = nRows * this._vItemSize + totalSpacing + this.topPadding + this.bottomPadding;
+        let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
         alloc.min_size = height;
         alloc.natural_size = height;
     },
@@ -314,10 +316,10 @@ const IconGrid = new Lang.Class({
             }
 
             if (columnIndex == 0) {
-                y += this._vItemSize + spacing;
+                y += this._getVItemSize() + spacing;
                 x = box.x1 + leftEmptySpace + this.leftPadding;
             } else {
-                x += this._hItemSize + spacing;
+                x += this._getHItemSize() + spacing;
             }
         }
     },
@@ -327,9 +329,9 @@ const IconGrid = new Lang.Class({
              child.get_preferred_size();
 
         /* Center the item in its allocation horizontally */
-        let width = Math.min(this._hItemSize, childNaturalWidth);
+        let width = Math.min(this._getHItemSize(), childNaturalWidth);
         let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
-        let height = Math.min(this._vItemSize, childNaturalHeight);
+        let height = Math.min(this._getVItemSize(), childNaturalHeight);
         let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
 
         let childBox = new Clutter.ActorBox();
@@ -359,8 +361,8 @@ const IconGrid = new Lang.Class({
         let spacing = this._getSpacing();
 
         while ((this._colLimit == null || nColumns < this._colLimit) &&
-               (usedWidth + this._hItemSize <= forWidth)) {
-            usedWidth += this._hItemSize + spacing;
+               (usedWidth + this._getHItemSize() <= forWidth)) {
+            usedWidth += this._getHItemSize() + spacing;
             nColumns += 1;
         }
 
@@ -379,7 +381,7 @@ const IconGrid = new Lang.Class({
     },
 
     rowHeight: function() {
-        return this._vItemSize + this._getSpacing();
+        return this._getVItemSize() + this._getSpacing();
     },
 
     nRows: function(forWidth) {
@@ -392,15 +394,19 @@ const IconGrid = new Lang.Class({
     },
 
     rowsForHeight: function(forHeight) {
-        return Math.floor((forHeight -(this.topPadding + this.bottomPadding) + this._getSpacing()) / 
(this._vItemSize + this._getSpacing()));
+        return Math.floor((forHeight - (this.topPadding + this.bottomPadding) + this._getSpacing()) / 
(this._getVItemSize() + this._getSpacing()));
     },
 
     usedHeightForNRows: function(nRows) {
-        return (this._vItemSize + this._getSpacing()) * nRows - this._getSpacing() + this.topPadding + 
this.bottomPadding;
+        return (this._getVItemSize() + this._getSpacing()) * nRows - this._getSpacing() + this.topPadding + 
this.bottomPadding;
     },
 
     usedWidth: function(forWidth) {
-        let usedWidth = this.columnsForWidth(forWidth) * (this._hItemSize + this._getSpacing());
+        return this.usedWidthForNColumns(this.columnsForWidth(forWidth));
+    },
+
+    usedWidthForNColumns: function(columns) {
+        let usedWidth = columns  * (this._getHItemSize() + this._getSpacing());
         usedWidth -= this._getSpacing();
         return usedWidth + this.leftPadding + this.rightPadding;
     },
@@ -439,13 +445,17 @@ const IconGrid = new Lang.Class({
         return this._fixedSpacing ? this._fixedSpacing : this._spacing;
     },
 
-    /**
-     * This function must to be called before iconGrid allocation,
-     * to know how much spacing can the grid has
-     */
-    updateSpacingForSize: function(availWidth, availHeight) {
-        let maxEmptyVArea = availHeight - this._minRows * this._vItemSize;
-        let maxEmptyHArea = availWidth - this._minColumns * this._hItemSize;
+    _getHItemSize: function() {
+        return this._fixedHItemSize ? this._fixedHItemSize : this._hItemSize;
+    },
+
+    _getVItemSize: function() {
+        return this._fixedVItemSize ? this._fixedVItemSize : this._vItemSize;
+    },
+
+    _updateSpacingForSize: function(availWidth, availHeight) {
+        let maxEmptyVArea = availHeight - this._minRows * this._getVItemSize();
+        let maxEmptyHArea = availWidth - this._minColumns * this._getHItemSize();
         let maxHSpacing, maxVSpacing;
 
         if (this._padWithSpacing) {
@@ -467,13 +477,51 @@ const IconGrid = new Lang.Class({
 
         let maxSpacing = Math.min(maxHSpacing, maxVSpacing);
         // Limit spacing to the item size
-        maxSpacing = Math.min(maxSpacing, Math.min(this._vItemSize, this._hItemSize));
-        // The minimum spacing, regardless of whether it satisfies the row/column minima,
+        maxSpacing = Math.min(maxSpacing, Math.min(this._getVItemSize(), this._getHItemSize()));
+        // The minimum spacing, regardless of whether it satisfies the row/columng minima,
         // is the spacing we get from CSS.
         let spacing = Math.max(this._spacing, maxSpacing);
         this.setSpacing(spacing);
         if (this._padWithSpacing)
             this.topPadding = this.rightPadding = this.bottomPadding = this.leftPadding = spacing;
+    },
+
+    /**
+     * This function must to be called before iconGrid allocation,
+     * to know how much spacing can the grid has
+     */
+    adaptToSize: function(availWidth, availHeight) {
+        this._fixedHItemSize = this._hItemSize;
+        this._fixedVItemSize = this._vItemSize;
+        this._updateSpacingForSize(availWidth, availHeight);
+        let spacing = this._getSpacing();
+
+        if (this.columnsForWidth(availWidth) < this._minColumns || this.rowsForHeight(availHeight) < 
this._minRows) {
+            let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth ;
+            let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight ;
+
+            let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns)
+                                                                  : Math.ceil(neededHeight / this._minRows);
+            this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE);
+            this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE);
+
+            if (this._fixedHItemSize < MIN_ICON_SIZE)
+                this._fixedHItemSize = MIN_ICON_SIZE;
+            if (this._fixedVItemSize < MIN_ICON_SIZE)
+                this._fixedVItemSize = MIN_ICON_SIZE;
+
+            this._updateSpacingForSize(availWidth, availHeight);
+        }
+        let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, 
this._vItemSize);
+        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { 
this._updateChildrenScale(scale); }));
+    },
+
+    // Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up 
+    _updateChildrenScale: function(scale) {
+        for (let i in this._items) {
+            let newIconSize = Math.floor(ICON_SIZE * scale);
+            this._items[i].icon.setIconSize(newIconSize);
+        }
     }
 });
 
@@ -535,17 +583,16 @@ const PaginatedIconGrid = new Lang.Class({
                 rowIndex++;
             }
             if (columnIndex == 0) {
-                y += this._vItemSize + spacing;
+                y += this._getVItemSize() + spacing;
                 if ((i + 1) % this._childrenPerPage == 0)
-                    y += this._spaceBetweenPages - spacing  + this.bottomPadding + this.topPadding;
+                    y +=  this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
                 x = box.x1 + leftEmptySpace + this.leftPadding;
-            } else {
-                x += this._hItemSize + spacing;
-            }
+            } else
+                x += this._getHItemSize() + spacing;
         }
     },
 
-    computePages: function (availWidthPerPage, availHeightPerPage) {
+    _computePages: function (availWidthPerPage, availHeightPerPage) {
         let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
         let nRows;
         let children = this._getVisibleChildren();
@@ -564,6 +611,11 @@ const PaginatedIconGrid = new Lang.Class({
         this._childrenPerPage = nColumns * this._rowsPerPage;
     },
 
+    adaptToSize: function(availWidth, availHeight) {
+        this.parent(availWidth, availHeight);
+        this._computePages(availWidth, availHeight);
+    },
+
     rowsPerPage: function() {
         return this._rowsPerPage;
     },


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]