[gnome-shell/wip/paging-release: 3/11] Added pages indicators



commit 537dba3ba5fad42c8f319a8ecdfa1efde47e5c41
Author: Carlos Soriano <carlos soriano89 gmail com>
Date:   Mon Aug 12 19:09:43 2013 +0200

    Added pages indicators
    
    AllView: pagination indicator reworked
    
    pagesindicator css: change spacing
    
    PaginationIconIndicator: change icon name
    
    AllView, indicator layout, paginationScrollView: fixed allocation cycle hidding actors of indicators
    
    IndicatorLayout: fixed allocation
    
    No more hacking to Indicator
    
    before implementing with StBin
    
    Indicator with Shell.GenericContainer
    
    testing allocation issues with visual glitchs
    
    yeah....Shell.GenericContainer works fine for skipping painting
    actors...
    
    fixed frequent apps css spacing calculation, since the box passed didn't
    take into account the grid spacing in updateDisplaySize, which is the
    widget which has the right padding
    
    Makefile.am : Added indicators svg
    
    Added good page indicators
    
    Forgot the indicators
    
    Fixed indicator layout growing
    
    New pagination indicators

 data/Makefile.am                       |    2 +
 data/theme/gnome-shell.css             |   18 ++-
 data/theme/page-indicator-active.svg   |   67 +++++++++
 data/theme/page-indicator-inactive.svg |   67 +++++++++
 js/ui/appDisplay.js                    |  237 +++++++++++++++++++++++++-------
 js/ui/iconGrid.js                      |   30 +----
 6 files changed, 339 insertions(+), 82 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index ece7925..3126e27 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -41,6 +41,8 @@ dist_theme_DATA =                             \
        theme/message-tray-background.png       \
        theme/more-results.svg                  \
        theme/noise-texture.png                 \
+       theme/page-indicator-active.svg \
+       theme/page-indicator-inactive.svg       \
        theme/panel-button-border.svg           \
        theme/panel-button-highlight-narrow.svg \
        theme/panel-button-highlight-wide.svg   \
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index c1a3fcc..b08cbcf 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -900,9 +900,23 @@ StScrollBar StButton#vhandle:active {
 
 .search-display > StBoxLayout,
 .all-apps,
-.frequent-apps > StBoxLayout {
+.frequent-apps > StBoxLayout{
     /* horizontal padding to make sure scrollbars or dash don't overlap content */
-    padding: 8px 88px;
+    padding: 10px 88px;
+}
+
+.pages-icon-indicator {
+       background-image: url(page-indicator-inactive.svg);
+}
+
+.pages-icon-indicator:hover,
+.pages-icon-indicator:checked{
+       background-image: url(page-indicator-active.svg);
+}
+
+.pages-indicator {
+       spacing: 40px;
+       padding: 0px, 25px 0px, 0px;
 }
 
 .app-folder-icon {
diff --git a/data/theme/page-indicator-active.svg b/data/theme/page-indicator-active.svg
new file mode 100644
index 0000000..38b720f
--- /dev/null
+++ b/data/theme/page-indicator-active.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   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="18"
+   height="18"
+   id="svg4703"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="page-indicator-active.svg">
+  <defs
+     id="defs4705" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="22.197802"
+     inkscape:cx="2.1522887"
+     inkscape:cy="16.782904"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1021"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata4708">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,2)">
+    <path
+       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"
+       sodipodi:cy="638.83099"
+       sodipodi:cx="2088.9954"
+       id="path4711"
+       style="fill:#fdffff;fill-opacity:0.94117647;stroke:none"
+       sodipodi:type="arc" />
+  </g>
+</svg>
diff --git a/data/theme/page-indicator-inactive.svg b/data/theme/page-indicator-inactive.svg
new file mode 100644
index 0000000..3048f56
--- /dev/null
+++ b/data/theme/page-indicator-inactive.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   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="18"
+   height="18"
+   id="svg5266"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="page-indicator-inactive.svg">
+  <defs
+     id="defs5268" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.313709"
+     inkscape:cx="13.381365"
+     inkscape:cy="17.859535"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1021"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata5271">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,2)">
+    <path
+       sodipodi:type="arc"
+       
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.63720887,0,0,0.72943648,-1322.1264,-458.98661)" />
+  </g>
+</svg>
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index c2db284..c4ffec2 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -322,6 +322,38 @@ const PaginationScrollView = new Lang.Class({
         child.allocate(childBox, flags);
     },
 
+   vfunc_get_preferred_height: function (forWidht) {
+        let parentBox = this.get_parent().allocation;
+        let gridBox = this.get_theme_node().get_content_box(parentBox);
+        let availWidth = gridBox.x2 - gridBox.x1;
+        let availHeight = gridBox.y2 - gridBox.y1;
+        return [0, 0];
+    },
+
+    vfunc_get_preferred_width: function(forHeight) {
+        let parentBox = this.get_parent().allocation;
+        let gridBox = this.get_theme_node().get_content_box(parentBox);
+        let availWidth = gridBox.x2 - gridBox.x1;
+        let availHeight = gridBox.y2 - gridBox.y1;
+        return [0, 0];
+    },
+    
+    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;
+        let childBox = new Clutter.ActorBox();
+        // Get the boxLayout inside scrollView
+        let child = this.get_children()[2];
+        childBox.x1 = 0;
+        childBox.y1 = 0;
+        childBox.x2 = availWidth;
+        childBox.y2 = availHeight;   
+
+        child.allocate(childBox, flags);
+    },
+
     vfunc_get_preferred_height: function (container, forWidht) {
         return [0, 0];
     },
@@ -346,9 +378,6 @@ const PaginationScrollView = new Lang.Class({
         
         this._pages.setGridParentSize([availWidth, availHeight]);
         child.allocate(childBox, flags);
-        if(this._pages.nPages() > 0) {
-            this._parent.goToPage(0);
-       }
     },
     
     goToPage: function(pageNumber) {
@@ -386,11 +415,6 @@ const PaginationScrollView = new Lang.Class({
                     this._eventBlocker.reactive = isOpen;
                     this._currentPopup = isOpen ? popup : null;
                     this._updateIconOpacities(isOpen);
-                    if (isOpen) {
-                        this._pages._grid.actor.y = popup.parentOffset;
-                    } else {
-                        this._pages._grid.actor.y = 0;
-                    }
                 }));
     },
 
@@ -409,31 +433,19 @@ const PaginationIconIndicator = new Lang.Class({
 
     _init: function(parent, index) {
 
-        this.actor = new St.Button({ style_class: 'show-apps',
-                                        button_mask: St.ButtonMask.ONE || St.ButtonMask.TWO,
-                                        toggle_mode: true,
-                                        can_focus: true });
-        this._icon = new St.Icon({ icon_name: 'view-grid-symbolic',
-                                   icon_size: 32,
-                                   style_class: 'show-apps-icon',
-                                   track_hover: true});
+        this.actor = new St.Button({ style_class: 'pages-icon-indicator',
+                                     button_mask: St.ButtonMask.ONE || St.ButtonMask.TWO,
+                                     toggle_mode: true,
+                                     can_focus: true });
         this.actor.connect('clicked', Lang.bind(this, this._onClicked));
-        this.actor.set_child(this._icon);
         this.actor._delegate = this;
+        this.actor.set_size(18, 18);
         this._parent = parent;
-        this._index = index;
+        this.actor._index = index;
     },
 
-    _createIcon: function(size) {
-        this._icon = new St.Icon({ icon_name: 'view-grid-symbolic',
-                                    icon_size: size,
-                                    style_class: 'show-apps-icon',
-                                    track_hover: true });
-        return this._icon;
-    },
-
-    _onClicked: function(actor, button) {
-        this._parent.goToPage(this._index); 
+    _onClicked: function(actor, button) {        
+        this._parent.goToPage(this.actor._index); 
         return false;
     },
 
@@ -442,49 +454,127 @@ const PaginationIconIndicator = new Lang.Class({
     }
 });
 
+const PaginationIndicator = new Lang.Class({
+    Name:'PaginationIndicator',
+    
+    _init: function(params) {
+        params['y_expand'] = true;
+        params['x_expand'] = true;
+        this.actor = new Shell.GenericContainer(params);
+        this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
+        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
+        this.actor.connect('allocate', Lang.bind(this, this._allocate));
+        this.actor.connect('style-changed', Lang.bind(this, this._styleChanged));
+        this._spacing = 0;
+    },
+    
+    _getPreferredHeight: function(actor, forWidth, alloc) {
+        let [minHeight, natHeight] = this.actor.get_children()[0].get_preferred_height(forWidth);
+        if(this._nPages) {
+            let natHeightPerChild = natHeight + this._spacing;
+            let totalUsedHeight =  this._nPages * natHeightPerChild - this._spacing;
+            let minHeightPerChild = minHeight + this._spacing;
+            minHeight = this._nPages * minHeightPerChild - this._spacing;
+            natHeight = this._nPages * natHeightPerChild - this._spacing;
+        } else
+            minHeight = natHeight = 0;
+        alloc.min_size = 0;
+        alloc.natural_size = natHeight;
+    },
+    
+    _getPreferredWidth: function(actor, forHeight, alloc) {
+        let [minWidth, natWidth] = this.actor.get_children()[0].get_preferred_width(forHeight);
+        let totalWidth = natWidth + this._spacing;
+        alloc.min_size = totalWidth;
+        alloc.natural_size = totalWidth;
+    },
+
+    _allocate: function(actor, box, flags) {
+        let children = this.actor.get_children();
+        for(let i in children)
+            this.actor.set_skip_paint(children[i], true);
+        if(children.length < 1)
+            return;
+        let availHeight = box.y2 - box.y1;
+        let availWidth = box.x2 - box.x1;
+        let [minHeight, natHeight] = children[0].get_preferred_height(availWidth);
+        let heightPerChild = natHeight + this._spacing;
+        let totalUsedHeight =  this._nPages * heightPerChild - this._spacing;
+        let [minWidth, natWidth] = children[0].get_preferred_width(natHeight);
+        let widthPerChild = natWidth + this._spacing * 2;
+        let firstPosition = [availWidth - widthPerChild , availHeight / 2 - totalUsedHeight / 2];
+        for(let i = 0; i < this._nPages; i++) {
+            let childBox = new Clutter.ActorBox();
+            childBox.x1 =  firstPosition[0] ;
+            childBox.x2 = availWidth;
+            childBox.y1 = firstPosition[1] + i * heightPerChild;
+            childBox.y2 = childBox.y1 + heightPerChild;
+            if(childBox.y2 > availHeight)
+                break;
+            children[i].allocate(childBox, flags);
+            this.actor.set_skip_paint(children[i], false);
+        }
+    },
+
+    _styleChanged: function() {
+        this._spacing = this.actor.get_theme_node().get_length('spacing');
+        this.actor.queue_relayout();
+    }
+});
 
 const AllView = new Lang.Class({
     Name: 'AllView',
    
     _init: function() {
-        this._paginationView = new PaginationScrollView(this);
-        let paginationIndicatorLayout = new Clutter.BoxLayout({orientation: Clutter.Orientation.VERTICAL});
-        //FIXME: hardcoded spacing
-        paginationIndicatorLayout.spacing = 40;
-        this._paginationIndicator = new St.Widget({layout_manager: paginationIndicatorLayout, x_align:3, 
y_align: 2, x_expand:true, y_expand:true, style_class: 'pages-indicator'});
-        
+        this._paginationView = new PaginationScrollView(this, {style_class: 'all-apps'});
+        this._paginationIndicator = new PaginationIndicator({style_class: 'pages-indicator'});
+        this._paginationIndicator._nPages = 0;
         let layout = new Clutter.BinLayout();
-
         this.actor = new Shell.GenericContainer({ layout_manager: layout, 
                                                   x_expand:true, y_expand:true });
         layout.add(this._paginationView, 2,2);
-        layout.add(this._paginationIndicator, 2,3);
-
+        if(Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
+            layout.add(this._paginationIndicator.actor, 2,2);
+        else
+            layout.add(this._paginationIndicator.actor, 3,2);
         for(let i = 0; i < MAX_APPS_PAGES; i++) {
             let indicatorIcon = new PaginationIconIndicator(this, i);
             if(i == 0) {
                 indicatorIcon.setChecked(true);
             }
-            indicatorIcon.actor.hide();
-            this._paginationIndicator.add_actor(indicatorIcon.actor);
+            this._paginationIndicator.actor.add_actor(indicatorIcon.actor);
         }
         this.actor.connect('allocate', Lang.bind(this, this._allocate));
     },
-        
+
     _allocate: function(widget, box, flags) {
         let children = this.actor.get_children();
         this._paginationView.allocate(box, flags);
         
         let nPages = this._paginationView.nPages();
-        
-        if(nPages > 1) {
-            for(let i = 0; i < nPages; i++) {
-                this._paginationIndicator.get_child_at_index(i).show();
-            }         
-        }
-        this._paginationIndicator.allocate(box, flags);
+        this._paginationIndicator._nPages = nPages;
+        let availWidth = box.x2 - box.x1;
+        let availHeight = box.y2 - box.y1;
+        let childBox = new Clutter.ActorBox();
+        let alloc = new Object();
+        alloc.min_size = 0;
+        alloc.natural_size = 0;
+        this._paginationIndicator._getPreferredWidth(this._paginationIndicator.actor,  availHeight, alloc);
+        let natWidth = alloc.natural_size;
+        childBox.x1 = 0;
+        childBox.x2 = availWidth;
+        childBox.y1 = 0;
+        childBox.y2 = availHeight;
+        this._paginationIndicator._allocate(this._paginationIndicator.actor, childBox, flags);
     },
-    
+
+    _updatedNPages: function(iconGrid, nPages) {
+        // We don't need a relayout because we already done it at iconGrid
+        // when pages are calculated (and then the signal is emitted before that)");
+        this._paginationIndicator._nPages = nPages;
+        this._paginationView.invalidatePagination = true;
+    },
+
     _onKeyRelease: function(actor, event) {
         if (event.get_key_symbol() == Clutter.KEY_Up) {
             this._paginationView.goToNextPage();
@@ -535,10 +625,25 @@ const AllView = new Lang.Class({
         this._paginationView._pages.loadGrid();
     },
     
-    goToPage: function(index) {
-        this._paginationIndicator.get_child_at_index(this._paginationView.currentPage()).set_checked(false);
-        this._paginationView.goToPage(index);
-        this._paginationIndicator.get_child_at_index(this._paginationView.currentPage()).set_checked(true);
+    goToPage: function(index, action) {
+        // Since it can happens after a relayout, we have to ensure that all is unchecked
+        let indicators = this._paginationIndicator.actor.get_children();
+        for(let index in indicators)
+            indicators[index].set_checked(false);
+        this._paginationView.goToPage(index, action);
+        
this._paginationIndicator.actor.get_child_at_index(this._paginationView.currentPage()).set_checked(true);
+    },
+    
+    onUpdatedDisplaySize: function(width, height) {
+        let box = new Clutter.ActorBox();
+        box.x1 = 0;
+        box.x2 = width;
+        box.y1 = 0;
+        box.y2 = height;
+        box = this.actor.get_theme_node().get_content_box(box);
+        let availWidth = box.x2 - box.x1;
+        let availHeight = box.y2 - box.y1;
+        this._paginationView.onUpdatedDisplaySize(availWidth, availHeight);
     }
 });
 
@@ -567,7 +672,26 @@ const FrequentView = new Lang.Class({
                 continue;
             let appIcon = new AppIcon(mostUsed[i]);
             this._grid.addItem(appIcon.actor, -1);
-        }    }
+        }
+    },
+    
+    onUpdatedDisplaySize: function(width, height) {
+        let box = new Clutter.ActorBox();
+        box.x1 = 0;
+        box.x2 = width;
+        box.y1 = 0;
+        box.y2 = height;
+        box = this.actor.get_theme_node().get_content_box(box);
+        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);
+    }
 });
 
 const Views = {
@@ -748,6 +872,13 @@ const AppDisplay = new Lang.Class({
             if (focused)
                 this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
         }
+    },
+    
+    _onUpdatedDisplaySize: function(actor, width, height) {
+        //FIXME
+        for (let i = 0; i < this._views.length; i++) {
+            this._views[i].view.onUpdatedDisplaySize(width, height);
+        }
     }
 });
 
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 8f4b4d1..1175a84 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -245,7 +245,7 @@ const IconGrid = new Lang.Class({
             nColumns = children.length;
             spacing = this._spacing;
         } else {
-            [nColumns, , spacing] = this._computeLayoutOld(forWidth);
+            [nColumns, , spacing] = this._computeLayout(forWidth);
         }
 
         let nRows;
@@ -285,7 +285,7 @@ const IconGrid = new Lang.Class({
         let children = this._getVisibleChildren();
         let availWidth = box.x2 - box.x1;
         let availHeight = box.y2 - box.y1;
-        let [nColumns, usedWidth, spacing] = this._computeLayoutOld(availWidth);
+        let [nColumns, usedWidth, spacing] = this._computeLayout(availWidth);
         if(this._usePagination) {
             //Recalculate the space between pages with the new spacing
             this._spaceBetweenPages = this._parentSize[1] - (this._rowsPerPage * (this._vItemSize + 
spacing));
@@ -380,32 +380,8 @@ const IconGrid = new Lang.Class({
     getRowLimit: function() {
         return this._rowLimit;
     },
-    
-    _computeLayoutOldOld: function (forWidth) {
-        let nColumns = 0;
-        let usedWidth = 0;
-        let spacing = this._spacing;
-
-        if (this._colLimit) {
-            let itemWidth = this._hItemSize * this._colLimit;
-            let emptyArea = forWidth - itemWidth;
-            spacing = Math.max(this._spacing, emptyArea / (2 * this._colLimit));
-            spacing = Math.round(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, spacing];
-    },
-    
-    _computeLayoutOld: function (forWidth, forHeight) {
+    _computeLayout: function (forWidth, forHeight) {
         let nColumns = 0;
         let usedWidth = 0;
         let spacing = this._spacing;


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