[gnome-shell/wip/paging-release: 27/38] Make the grid responsive to size reescaling icons and adapting spacing. That's a good start for resp



commit 27240eaae7794a4e2b1dc460f826089048f5fc5b
Author: Carlos Soriano <carlos soriano89 gmail com>
Date:   Thu Jul 25 20:35:06 2013 +0200

    Make the grid responsive to size reescaling icons and adapting spacing.
    That's a good start for responsive widgets!
    
    Also rework the pagination indicators with Allan feedback

 data/theme/gnome-shell.css             |    6 +-
 data/theme/page-indicator-active.svg   |    8 +-
 data/theme/page-indicator-inactive.svg |   10 +-
 js/ui/appDisplay.js                    |   70 ++++++++-----
 js/ui/iconGrid.js                      |  172 ++++++++++++++++++++++++--------
 5 files changed, 186 insertions(+), 80 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 751ef3e..d02957a 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -881,7 +881,7 @@ StScrollBar StButton#vhandle:active {
 
 .icon-grid .overview-icon-with-label,
 .icon-grid .overview-icon {
-    icon-size: 96px;
+    icon-size: 76px;
 }
 
 .app-display {
@@ -918,8 +918,8 @@ StScrollBar StButton#vhandle:active {
 }
 
 .pages-indicator {
-       spacing: 40px;
-       padding: 0px, 25px 0px, 0px;
+       spacing: 35px;
+       padding: 0px, 20px 0px, 0px;
 }
 
 .app-folder-icon {
diff --git a/data/theme/page-indicator-active.svg b/data/theme/page-indicator-active.svg
index b64c91b..38b720f 100644
--- a/data/theme/page-indicator-active.svg
+++ b/data/theme/page-indicator-active.svg
@@ -9,8 +9,8 @@
    xmlns="http://www.w3.org/2000/svg";
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
-   width="24"
-   height="24"
+   width="18"
+   height="18"
    id="svg4703"
    version="1.1"
    inkscape:version="0.48.4 r9939"
@@ -52,9 +52,9 @@
      id="layer1"
      inkscape:label="Layer 1"
      inkscape:groupmode="layer"
-     transform="translate(0,8)">
+     transform="translate(0,2)">
     <path
-       transform="matrix(1.0013282,0,0,1.1462573,-2079.7699,-728.26471)"
+       transform="matrix(0.72823872,0,0,0.8336417,-1512.2872,-525.55618)"
        d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 
-10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
        sodipodi:ry="9.5964489"
        sodipodi:rx="10.985409"
diff --git a/data/theme/page-indicator-inactive.svg b/data/theme/page-indicator-inactive.svg
index 2f0b6e7..3048f56 100644
--- a/data/theme/page-indicator-inactive.svg
+++ b/data/theme/page-indicator-inactive.svg
@@ -9,8 +9,8 @@
    xmlns="http://www.w3.org/2000/svg";
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
-   width="24"
-   height="24"
+   width="18"
+   height="18"
    id="svg5266"
    version="1.1"
    inkscape:version="0.48.4 r9939"
@@ -52,16 +52,16 @@
      id="layer1"
      inkscape:label="Layer 1"
      inkscape:groupmode="layer"
-     transform="translate(0,8)">
+     transform="translate(0,2)">
     <path
        sodipodi:type="arc"
-       
style="fill:#ffffff;fill-opacity:0;stroke:#ffffff;stroke-width:2.93356276000000005;stroke-miterlimit:4;stroke-opacity:0.39215686000000000;stroke-dasharray:none"
+       
style="fill:#ffffff;fill-opacity:0;stroke:#ffffff;stroke-width:2.93356276;stroke-miterlimit:4;stroke-opacity:0.39215686;stroke-dasharray:none"
        id="path5274"
        sodipodi:cx="2088.9954"
        sodipodi:cy="638.83099"
        sodipodi:rx="10.985409"
        sodipodi:ry="9.5964489"
        d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 
-10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
-       transform="matrix(0.87616219,0,0,1.0029752,-1818.2988,-636.73159)" />
+       transform="matrix(0.63720887,0,0,0.72943648,-1322.1264,-458.98661)" />
   </g>
 </svg>
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index bb25ebb..fff331a 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -72,7 +72,10 @@ const AlphabeticalView = new Lang.Class({
     _init: function() {
         this._grid = new IconGrid.IconGrid({ xAlign: St.Align.MIDDLE,
                                              usePagination: true,
-                                             columnLimit: MAX_COLUMNS });
+                                             columnLimit: MAX_COLUMNS,
+                                             minRows: MIN_ROWS,
+                                             minColumns: MIN_COLUMNS,
+                                             useSurroundingSpacing: true});
 
         // Standard hack for ClutterBinLayout
         this._grid.actor.x_expand = true;
@@ -118,7 +121,7 @@ const AlphabeticalView = new Lang.Class({
             let id = this._getItemId(this._allItems[i]);
             if (!id)
                 continue;
-            this._grid.addItem(this._items[id].actor);
+            this._grid.addItem(this._items[id]);
         }
     }
 });
@@ -349,12 +352,7 @@ const AppPages = new Lang.Class({
         let availWidth = box.x2 - box.x1;
         let availHeight = box.y2 - box.y1;
         // Update grid dinamyc spacing based on display width
-        let spacing = this._grid.maxSpacingForWidthHeight(availWidth, availHeight, MIN_COLUMNS, MIN_ROWS, 
true);
-        this._grid.top_padding = spacing;
-        this._grid.bottom_padding = spacing;
-        this._grid.left_padding = spacing;
-        this._grid.right_padding = spacing;
-        this._grid.setSpacing(spacing);
+        this._grid.calculateResponsiveGrid(availWidth, availHeight);
         // Update folder views
         for(let id in this._folderIcons) {
             this._folderIcons[id].onUpdatedDisplaySize(width, height);
@@ -611,7 +609,8 @@ const PaginationIconIndicator = new Lang.Class({
                                      can_focus: true });
         this.actor.connect('clicked', Lang.bind(this, this._onClicked));
         this.actor._delegate = this;
-        this.actor.set_size(24, 24);
+        //Background image is 18x18 but it is a svg, so we have to put a size
+        this.actor.set_size(18, 18);
         this._parent = parent;
         this.actor._index = index;
     },
@@ -793,7 +792,10 @@ const FrequentView = new Lang.Class({
     _init: function() {
         this._grid = new IconGrid.IconGrid({ xAlign: St.Align.MIDDLE,
                                              fillParent: true,
-                                             columnLimit: MAX_COLUMNS });
+                                             columnLimit: MAX_COLUMNS,
+                                             minRows: MIN_ROWS,
+                                             minColumns: MIN_COLUMNS,
+                                             useSurroundingSpacing: true });
         this.actor = new St.Widget({ style_class: 'frequent-apps',
                                      x_expand: true, y_expand: true });
         this.actor.add_actor(this._grid.actor);
@@ -811,7 +813,7 @@ const FrequentView = new Lang.Class({
             if (!mostUsed[i].get_app_info().should_show())
                 continue;
             let appIcon = new AppIcon(mostUsed[i]);
-            this._grid.addItem(appIcon.actor, -1);
+            this._grid.addItem(appIcon, -1);
         }
     },
     
@@ -825,12 +827,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;
-        let spacing = this._grid.maxSpacingForWidthHeight(availWidth, availHeight, MIN_COLUMNS, MIN_ROWS, 
true);
-        this._grid.top_padding = spacing;
-        this._grid.bottom_padding = spacing;
-        this._grid.left_padding = spacing;
-        this._grid.right_padding = spacing;
-        this._grid.setSpacing(spacing);
+        this._grid.calculateResponsiveGrid(availWidth, availHeight);
     }
 });
 
@@ -1118,7 +1115,10 @@ const FolderView = new Lang.Class({
 
     _init: function() {
         this._grid = new IconGrid.IconGrid({ xAlign: St.Align.MIDDLE,
-            columnLimit: MAX_COLUMNS });
+                                             columnLimit: MAX_COLUMNS,
+                                             minRows: MIN_ROWS,
+                                             minColumns: MIN_COLUMNS,
+                                             useSurroundingSpacing: true});
         // If it not expand, the parent doesn't take into account its preferred_width when allocating
         // the second time it allocates, so we apply the "Standard hack for ClutterBinLayout"
         this._grid.actor.x_expand = true;
@@ -1196,7 +1196,7 @@ const FolderView = new Lang.Class({
             let id = this._getItemId(this._allItems[i]);
             if (!id)
                 continue;
-            this._grid.addItem(this._items[id].actor);
+            this._grid.addItem(this._items[id]);
         }
     },
     
@@ -1204,14 +1204,14 @@ const FolderView = new Lang.Class({
         this._appDisplayWidth = width;
         this._appDisplayHeight = height;
         // Update grid dinamyc spacing based on display width
-        let spacing = this._grid.maxSpacingForWidthHeight(width, height, MIN_COLUMNS, MIN_ROWS, true);
-        this._grid.setSpacing(spacing);
+        this._grid.calculateResponsiveGrid(width, height);
+        
         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 from 
calculations of the boxpointer offsets, to ensure
         //the boxpointer will be contained inside the view
-        this._parentSpacing = spacing;
+        let spacing = this._grid.getSpacing();
         
         let boxPointerTotalOffset = this._boxPointerOffsets['arrowHeight'] + 
this._boxPointerOffsets['padding'] * 2 + this._boxPointerOffsets['closeButtonOverlap'];
         let offsetForEachSide = Math.ceil(boxPointerTotalOffset / 2);
@@ -1245,7 +1245,7 @@ const FolderView = new Lang.Class({
     
     usedHeight: function() {
         // Then calculate the real maxUsedHeight
-        return this._grid.usedHeightForNRows(this.nRowsDisplayedAtOnce()) + this._grid.top_padding + 
this._grid.bottom_padding;
+        return this._grid.usedHeightForNRows(this.nRowsDisplayedAtOnce());
     },   
     
     nRowsDisplayedAtOnce: function() {
@@ -1320,7 +1320,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;
 
@@ -1344,8 +1344,16 @@ const FolderIcon = new Lang.Class({
         }));
     },
 
-    _createIcon: function(size) {
-        return this.view.createFolderIcon(size, this);
+    _createIcon: function(iconSize) {
+        return this.view.createFolderIcon(iconSize, this);
+    },
+    
+    getIconSize: function() {
+        return this.icon.iconSize;
+    },
+    
+    setIconSize: function(size) {
+        this.icon.setIconSize(size);
     },
     
     _popUpGridWidth: function() {
@@ -1423,6 +1431,7 @@ const FolderIcon = new Lang.Class({
 
         this.view.updateBoxPointerOffsets(this._boxPointerOffsets['arrowHeight'], 
this._boxPointerOffsets['padding'], this._boxPointerOffsets['closeButtonOverlap']);
         this.view.onUpdatedDisplaySize(this._displayWidth, this._displayHeight);
+        
         /*
          * Always make the grid (and therefore the boxpointer) to be the max
          * width it can be if it use full icon rows, althougth there's less
@@ -1611,6 +1620,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);
 
@@ -1657,6 +1667,14 @@ const AppIcon = new Lang.Class({
     _createIcon: function(iconSize) {
         return this.app.create_icon_texture(iconSize);
     },
+    
+    getIconSize: function() {
+        return this.icon.iconSize;
+    },
+    
+    setIconSize: function(size) {
+        this.icon.setIconSize(size);
+    },
 
     _removeMenuTimeout: function() {
         if (this._menuTimeoutId > 0) {
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 376178c..17675c5 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -9,8 +9,8 @@ const Signals = imports.signals;
 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',
@@ -70,6 +70,7 @@ const BaseIcon = new Lang.Class({
         let iconSize = availHeight;
         let [iconMinHeight, iconNatHeight] = this._iconBin.get_preferred_height(-1);
         let [iconMinWidth, iconNatWidth] = this._iconBin.get_preferred_width(-1);
+        
         let preferredHeight = iconNatHeight;
 
         let childBox = new Clutter.ActorBox();
@@ -133,7 +134,6 @@ const BaseIcon = new Lang.Class({
 
         if (size == this.iconSize)
             return;
-
         this._createIconTexture(size);
     },
 
@@ -142,7 +142,6 @@ const BaseIcon = new Lang.Class({
             this.icon.destroy();
         this.iconSize = size;
         this.icon = this.createIcon(this.iconSize);
-
         this._iconBin.child = this.icon;
 
         // The icon returned by createIcon() might actually be smaller than
@@ -188,14 +187,20 @@ const IconGrid = new Lang.Class({
     _init: function(params) {
         params = Params.parse(params, { rowLimit: null,
                                         columnLimit: null,
+                                        minRows: 1,
+                                        minColumns: 1,
                                         fillParent: false,
                                         xAlign: St.Align.MIDDLE,
-                                        usePagination: false});
+                                        usePagination: false,
+                                        useSurroundingSpacing: true});
         this._rowLimit = params.rowLimit;
         this._colLimit = params.columnLimit;
+        this._minRows = params.minRows;
+        this._minColumns = params.minColumns;
         this._xAlign = params.xAlign;
         this._fillParent = params.fillParent;
         this._usePagination = params.usePagination;
+        this._useSurroundingSpacing = params.useSurroundingSpacing;
         
         this.top_padding = 0;
         this.bottom_padding = 0;
@@ -211,10 +216,11 @@ const IconGrid = new Lang.Class({
         }
         this.actor = new St.BoxLayout({ style_class: 'icon-grid',
                                         vertical: true });
-
+        this._items = [];
         // 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));
@@ -238,8 +244,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.left_padding + this.right_padding;
-        alloc.natural_size = nColumns * this._hItemSize + totalSpacing + this.left_padding + 
this.right_padding;
+        alloc.min_size = this.getHItemSize() + this.left_padding + this.right_padding;
+        alloc.natural_size = nColumns * this.getHItemSize() + totalSpacing + this.left_padding + 
this.right_padding;
     },
 
     _getVisibleChildren: function() {
@@ -273,7 +279,7 @@ 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 + this.top_padding + this.bottom_padding;     
+        let height = nRows * this.getVItemSize() + totalSpacing + this.top_padding + this.bottom_padding;    
 
         if(this._usePagination && this._nPages) {
             alloc.min_size =  this.usedHeightPerPage() * this._nPages + this._spaceBetweenPagesTotal;
             alloc.natural_size = this.usedHeightPerPage() * this._nPages + this._spaceBetweenPagesTotal;
@@ -317,6 +323,10 @@ const IconGrid = new Lang.Class({
             // maybe the number of pages doesn't change
             if(oldNPages != this._nPages || oldHeightUsedPerPage != this.usedHeightPerPage()) {
                 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;
@@ -364,7 +374,7 @@ const IconGrid = new Lang.Class({
             }
 
             if (columnIndex == 0) {
-                y += this._vItemSize + spacing;
+                y += this.getVItemSize() + spacing;
                 if(this._usePagination) {
                     if((i + 1) % this._childrenPerPage == 0) {
                         y+= this._spaceBetweenPages + this.top_padding;
@@ -375,14 +385,14 @@ const IconGrid = new Lang.Class({
                 }
                 x = box.x1 + leftPadding + this.left_padding;
             } else {
-                x += this._hItemSize + spacing;
+                x += this.getHItemSize() + spacing;
             }
         }       
     },
     
     _calculatePaginationValues: function (availHeightPerPage, nColumns, nRows) {
         let spacing = this.getSpacing();
-        this._spacePerRow = this._vItemSize + spacing;
+        this._spacePerRow = this.getVItemSize() + 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);
@@ -390,7 +400,7 @@ const IconGrid = new Lang.Class({
         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) - 
spacing);
+        this._spaceBetweenPages = availHeightPerPage - (this._rowsPerPage * (this.getVItemSize() + spacing) 
- spacing);
         this._spaceBetweenPagesTotal = this._spaceBetweenPages * (this._nPages);
         this._childrenPerPage = nColumns * this._rowsPerPage;
     },
@@ -400,9 +410,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();
@@ -424,8 +434,8 @@ const IconGrid = new Lang.Class({
         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;
+               (usedWidth + this.getHItemSize() <= forWidth)) {
+            usedWidth += this.getHItemSize() + spacing;
             nColumns += 1;
         }
 
@@ -442,7 +452,7 @@ const IconGrid = new Lang.Class({
         this._grid.queue_relayout();
     },
 
-    childrenInRow: function(rowWidth) {
+    columnsForWidth: function(rowWidth) {
         return this._computeLayout(rowWidth)[0];
     },
 
@@ -470,7 +480,7 @@ const IconGrid = new Lang.Class({
 
     rowsForHeight: function(forHeight) {
         forHeight -= this.top_padding + this.bottom_padding;
-        let spacePerRow = this._vItemSize + this.getSpacing();
+        let spacePerRow = this.getVItemSize() + this.getSpacing();
         let rowsPerPage = Math.floor(forHeight / spacePerRow);
         // Check if deleting spacing from bottom there's enough space for another row
         let spaceWithOneMoreRow = (rowsPerPage + 1) * spacePerRow - this.getSpacing();
@@ -478,12 +488,9 @@ const IconGrid = new Lang.Class({
         return rowsPerPage;
     },
 
-    /**
-     * Don't take into account paddings
-     */
     usedHeightForNRows: function(nRows) {
         let spacePerRow = this.rowHeight();
-        return spacePerRow * nRows - this.getSpacing();
+        return spacePerRow * nRows - this.getSpacing() + this.top_padding + this.bottom_padding;
     },
 
     usedHeightPerPage: function() {
@@ -491,21 +498,29 @@ const IconGrid = new Lang.Class({
     },
 
     usedWidth: function(forWidth) {
-        let childrenInRow = this.childrenInRow(forWidth);
-        let usedWidth = childrenInRow  * (this._hItemSize + this.getSpacing());
+        let columnsForWidth = this.columnsForWidth(forWidth);
+        let usedWidth = columnsForWidth  * (this.getHItemSize() + this.getSpacing());
+        usedWidth -= this.getSpacing();
+        return usedWidth + this.left_padding + this.right_padding;
+    },
+    
+    usedWidthForNColumns: function(columns) {
+        let usedWidth = columns  * (this.getHItemSize() + this.getSpacing());
         usedWidth -= this.getSpacing();
         return usedWidth + this.left_padding + this.right_padding;
     },
 
     removeAll: function() {
+        this._items = [];
         this._grid.destroy_all_children();
     },
 
-    addItem: function(actor, index) {
+    addItem: function(item, index) {
+        this._items.push(item);
         if (index !== undefined)
-            this._grid.insert_child_at_index(actor, index);
+            this._grid.insert_child_at_index(item.actor, index);
         else
-            this._grid.add_actor(actor);
+            this._grid.add_actor(item.actor);
     },
 
     getItemAtIndex: function(index) {
@@ -537,33 +552,43 @@ const IconGrid = new Lang.Class({
     getSpacing: function() {
         return this._fixedSpacing ? this._fixedSpacing : this._spacing;
     },
+    
+    getHItemSize: function() {
+        return this._fixedHItemSize ? this._fixedHItemSize : this._hItemSize;
+    },
+    
+    getVItemSize: function() {
+        return this._fixedVItemSize ? this._fixedVItemSize : this._vItemSize;
+    },
+
     /**
-     * This functions is intended to use before iconGrid allocation, to know how much spacing can we have at 
the grid
+     * This function 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) {
+    maxSpacingForWidthHeight: function(availWidth, availHeight) {
         // 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 maxSpacing = Math.floor(Math.min(this.getVItemSize(), this.getHItemSize()));
+        let minEmptyVerticalArea = (availHeight - this._minRows * this.getVItemSize());
+        let minEmptyHorizontalArea = (availWidth - this._minColumns * this.getHItemSize());
         let spacing;
-        if(usingSurroundingSpacing) {
+        if(this._useSurroundingSpacing) {
             // 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 maxSpacingForRows = Math.floor(minEmptyVerticalArea / (this._minRows +1));
+            let maxSpacingForColumns = Math.floor(minEmptyHorizontalArea / (this._minColumns +1));
             let spacingToEnsureMinimums = Math.min(maxSpacingForRows, maxSpacingForColumns);
             let spacingNotTooBig = Math.min(spacingToEnsureMinimums, maxSpacing);
             spacing = Math.max(this._spacing, spacingNotTooBig);
         } else {
-            if(minRows == 1) {
-                let maxSpacingForRows = Math.floor(minEmptyVerticalArea / minRows);
-                let maxSpacingForColumns = Math.floor(minEmptyHorizontalArea / minColumns);
+            let maxSpacingForRows, maxSpacingForColumns;
+            if(this._minRows == 1) {
+                maxSpacingForRows = Math.floor(minEmptyVerticalArea / this._minRows);
+                maxSpacingForColumns = Math.floor(minEmptyHorizontalArea / this._minColumns);
             } else {
-                let maxSpacingForRows = Math.floor(minEmptyVerticalArea / (minRows - 1));
-                let maxSpacingForColumns = Math.floor(minEmptyHorizontalArea / (minColumns - 1));
+                maxSpacingForRows = Math.floor(minEmptyVerticalArea / (this._minRows - 1));
+                maxSpacingForColumns = Math.floor(minEmptyHorizontalArea / (this._minColumns - 1));
             }
             let spacingToEnsureMinimums = Math.min(maxSpacingForRows, maxSpacingForColumns);
             let spacingNotTooBig = Math.min(spacingToEnsureMinimums, maxSpacing);
@@ -572,6 +597,69 @@ const IconGrid = new Lang.Class({
         return spacing;
     },
     
+    calculateResponsiveGrid: function(availWidth, availHeight) {
+        this._fixedHItemSize = this._hItemSize;
+        this._fixedVItemSize = this._vItemSize;
+        let spacing = this.maxSpacingForWidthHeight(availWidth, availHeight);
+        this.setSpacing(spacing);
+        if(this._useSurroundingSpacing)
+            this.top_padding = this.bottom_padding = this.right_padding = this.left_padding = spacing;
+
+        let count = 0;
+        if(this.columnsForWidth(availWidth) < this._minColumns || this.rowsForHeight(availHeight) < 
this._minRows) {
+            let neededWidth, neededHeight;
+            if(this._useSurroundingSpacing)
+                neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth ;
+            else
+                neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth ;
+
+            if(this._useSurroundingSpacing)
+                neededHeight = this.usedHeightForNRows(this._minRows) - availHeight;
+            else
+                neededHeight = this.usedHeightForNRows(this._minRows) - availHeight ;
+
+            if(neededWidth > neededHeight) {
+                let neededSpaceForEachItem = Math.ceil(neededWidth / this._minColumns);
+                this._fixedHItemSize = this._hItemSize - neededSpaceForEachItem;
+                this._fixedVItemSize = this._vItemSize - neededSpaceForEachItem;
+            } else {
+                let neededSpaceForEachItem = Math.ceil(neededHeight / this._minRows);
+                this._fixedHItemSize = this._hItemSize - neededSpaceForEachItem;
+                this._fixedVItemSize = this._vItemSize - neededSpaceForEachItem;
+            }
+            
+            if(this._fixedHItemSize < MIN_ICON_SIZE)
+                this._fixedHItemSize = MIN_ICON_SIZE;
+            if(this._fixedVItemSize < MIN_ICON_SIZE)
+                this._fixedVItemSize = MIN_ICON_SIZE;
+            
+            let spacing = this.maxSpacingForWidthHeight(availWidth, availHeight);
+            this.setSpacing(spacing);
+            if(this._useSurroundingSpacing)
+                this.top_padding = this.bottom_padding = this.right_padding = this.left_padding = spacing;
+        }
+        
+        let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, 
this._vItemSize);
+        this.updateChildrenScale(scale);
+    },
+    /**
+     * FLORIAN REVIEW
+     * We are supossing that the this._items contain some item that we can set its size. 
+     * Also, we suposse that they are icons, and the original size is ICON_SIZE, to let the good icon size 
when updating the size.
+     * Also, we supose that we need a Meta.later, since when we call calculateResponsiveGrid that calls 
updateChildrenScale
+     * we are inside the allocation of the AppDisplay, and modifinyg icon size can cause allocation cycles
+     * So this functions is not intentded to be called outside this class, lets think a little about that. 
Now reescaling icons
+     * works fine at least.
+     */
+    updateChildrenScale: function(scale) {
+        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
+            for(let i in this._items) {
+                let newIconSize = Math.floor(ICON_SIZE * scale);
+                this._items[i].setIconSize(newIconSize);
+            }
+        }));
+    },
+    
     pageRows: function(pageNumber) {
         let pagePosition = this.getPagePosition(pageNumber);
         let currentRowItemsYPosition = pagePosition;
@@ -594,7 +682,7 @@ const IconGrid = new Lang.Class({
     },
     
     rowHeight: function() {
-        return this._vItemSize + this.getSpacing();
+        return this.getVItemSize() + this.getSpacing();
     }
     
 });


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