[gnome-shell/wip/paging-release: 2/90] Pagging with St.ScrollView



commit 22cbe51e67c7df79c03b81341a32f59e16f59815
Author: Carlos Soriano <csoriano src gnome org>
Date:   Fri Jun 14 11:58:50 2013 +0200

    Pagging with St.ScrollView

 js/ui/appDisplay.js |  221 ++++++++++++++++++++++++++++++++++++++-------------
 js/ui/iconGrid.js   |   90 +++++++++++++++------
 2 files changed, 231 insertions(+), 80 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 41ecddc..bc54180 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -36,7 +36,7 @@ const FOLDER_SUBICON_FRACTION = .4;
 
 
 // Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
-function _loadCategory(dir, view) {
+function _loadCategory(dir, list) {
     let iter = dir.iter();
     let appSystem = Shell.AppSystem.get_default();
     let nextType;
@@ -45,11 +45,11 @@ function _loadCategory(dir, view) {
             let entry = iter.get_entry();
             let app = appSystem.lookup_app_by_tree_entry(entry);
             if (!entry.get_app_info().get_nodisplay())
-                view.addApp(app);
+                list.addApp(app);
         } else if (nextType == GMenu.TreeItemType.DIRECTORY) {
             let itemDir = iter.get_directory();
             if (!itemDir.get_is_nodisplay())
-                _loadCategory(itemDir, view);
+                _loadCategory(itemDir, list);
         }
     }
 };
@@ -60,6 +60,7 @@ const AlphabeticalView = new Lang.Class({
 
     _init: function() {
         this._grid = new IconGrid.IconGrid({ xAlign: St.Align.MIDDLE,
+                                             
                                              columnLimit: MAX_COLUMNS });
 
         // Standard hack for ClutterBinLayout
@@ -161,6 +162,11 @@ const AllViewLayout = new Lang.Class({
     Extends: Clutter.BinLayout,
 
     vfunc_get_preferred_height: function(container, forWidth) {
+        if(this.parentSize)
+            {
+            return this.parentSize;
+            }
+        global.log("Parent size " + this.parentSize);
         let minBottom = 0;
         let naturalBottom = 0;
 
@@ -180,33 +186,134 @@ const AllViewLayout = new Lang.Class({
     }
 });
 
-const AllView = new Lang.Class({
-    Name: 'AllView',
+const AppPage = new Lang.Class({
+    Name: 'AppPage',
     Extends: AlphabeticalView,
-
+    
     _init: function() {
         this.parent();
-
         this._grid.actor.y_align = Clutter.ActorAlign.START;
-        this._grid.actor.y_expand = true;
+        this._grid.actor.y_expand = false;
+        this.actor = this._grid.actor;
+    },
+
+    _getItemId: function(item) {
+        if (item instanceof Shell.App)
+            return item.get_id();
+        else if (item instanceof GMenu.TreeDirectory)
+            return item.get_menu_id();
+        else
+            return null;
+    },
+    
+    _createItemIcon: function(item) {
+        if (item instanceof Shell.App)
+            return new AppIcon(item);
+        else if (item instanceof GMenu.TreeDirectory)
+            return new FolderIcon(item, this);
+        else
+            return null;
+    },
+
+    _compareItems: function(itemA, itemB) {
+        // bit of a hack: rely on both ShellApp and GMenuTreeDirectory
+        // having a get_name() method
+        let nameA = GLib.utf8_collate_key(itemA.get_name(), -1);
+        let nameB = GLib.utf8_collate_key(itemB.get_name(), -1);
+        return (nameA > nameB) ? 1 : (nameA < nameB ? -1 : 0);
+    },
+    
+    addItem: function(item) {
+        this._addItem(item);
+    }
+});
+
+const PaginationScrollView = new Lang.Class({
+    Name: 'PaginationScrollView',
+    Extends: St.ScrollView,
+    
+    _init: function(params) {
+        
+    },
+
+    vfunc_allocate: function(box, flags) {
+        this.set_allocation(box, flags);
+        global.log("ALLOCATION DONE!!!");
+    }
+});
 
-        let box = new St.BoxLayout({ vertical: true });
-        this._stack = new St.Widget({ layout_manager: new AllViewLayout() });
-        this._stack.add_actor(this._grid.actor);
+
+const AllView = new Lang.Class({
+    Name: 'AllView',
+    Extends: St.ScrollView,
+    
+    _init: function() {
+        this.parent({ 
+            x_fill: true,
+            y_fill: false,
+            y_align: St.Align.START,
+            x_expand: true,
+            y_expand: true,
+            overlay_scrollbars: true,
+            style_class: 'all-apps vfade' });
+        this._actorLayoutManager = new AllViewLayout();
+        this.actor = this;
+        global.log(" SERAAA?? " + this.actor.scroll_to_point);
+        this._box = new St.BoxLayout({vertical: true});
+        this._widgetLayoutManager = new AllViewLayout();
+        
+        
+        this._widgetForLayout = new St.Widget({ layout_manager:  this._widgetLayoutManager });
+        this._page = new AppPage();       
+        this._widgetForLayout.add_actor(this._page.actor);
+        this._box.add_actor(this._widgetForLayout);
+        this.actor.add_actor(this._box); 
+        //this.clip_to_allocation = true;
+        //this.actor.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
+        /*let box = new St.BoxLayout({ vertical: true });
+        this._stack = new St.Widget();*/
+        
+        /*this._stack.add_actor(this._page.actor);
         this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
         this._stack.add_actor(this._eventBlocker);
-        box.add(this._stack, { y_align: St.Align.START, expand: true });
+        box.add(this._stack, { y_align: St.Align.START, expand: true });*/
 
-        this.actor = new St.ScrollView({ x_fill: true,
+        /*this.actor = new St.ScrollView({ x_fill: true,
                                          y_fill: false,
                                          y_align: St.Align.START,
                                          x_expand: true,
                                          y_expand: true,
                                          overlay_scrollbars: true,
-                                         style_class: 'all-apps vfade' });
-        this.actor.add_actor(box);
-        this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
-        let action = new Clutter.PanAction({ interpolate: true });
+                                         style_class: 'all-apps vfade' });*/
+        
+        /*this._widgetForLayout2 = new St.Widget({ layout_manager: new AllViewLayout() });
+        this._widgetForLayout2.add_actor(this._page2.actor);
+        this._textLabel = new St.Label({text: "HOLAAA"});
+        this._textLabel2 = new St.Label({text: "HOLAAA"});
+        this._box.add_actor(this._textLabel);
+        this._box.add_actor(this._widgetForLayout);
+        
+        
+        this._box.add(this._textLabel2);
+        this._box.add(this._widgetForLayout2);*/
+        
+        
+        /*this.actor = new St.Bin({ style_class: 'all-apps vfade',
+            x_fill: true,
+            y_fill: false,
+            y_align: St.Align.START, x_expand: true, y_expand: true});
+
+        this.actor.add_actor(this._page.actor);*/
+        //this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
+        
+        
+        this._pageControl = new St.Widget();
+        
+        /*this.actor = new St.Widget({ style_class: 'frequent-apps',
+            x_expand: true, y_expand: true });*/
+              
+        
+       /* let action = new Clutter.PanAction({ interpolate: true });
         action.connect('pan', Lang.bind(this, this._onPan));
         this.actor.add_action(action);
 
@@ -220,59 +327,50 @@ const AllView = new Lang.Class({
             if (!this._currentPopup.actor.contains(actor))
                 this._currentPopup.popdown();
         }));
-        this._eventBlocker.add_action(this._clickAction);
+        this._eventBlocker.add_action(this._clickAction);*/
+        global.log("PPP visible items after init " + this._page._grid.visibleItemsCount());
     },
-
+    
+    vfunc_allocate: function(box, flags) {
+        this.set_allocation(box, flags);
+        global.log("ALLOCATIONS!!!!!!");
+        global.log("Allocation width "+ this.clip_rect.size.width);
+        global.log("Allocation heithg "+ this.clip_rect.size.height);
+        global.log("Allocation box "+ [box.x2 - box.x1, box.y2 - box.y1]);
+        let availWidth = box.x2 - box.x1;
+        let availHeight = box.y2 - box.y1;
+        this._page._grid.parentSize = [availWidth, availHeight];
+        this._widgetLayoutManager.parentSize = [availWidth, availHeight];
+        this._actorLayoutManager.parentSize = [availWidth, availHeight];
+        this._box.allocate(box, flags);
+    },
+    
     _onPan: function(action) {
+        /*
         this._clickAction.release();
 
         let [dist, dx, dy] = action.get_motion_delta(0);
         let adjustment = this.actor.vscroll.adjustment;
-        adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
+        adjustment.value -= (dy / this.actor.height) * adjustment.page_size;*/
         return false;
     },
 
-    _getItemId: function(item) {
-        if (item instanceof Shell.App)
-            return item.get_id();
-        else if (item instanceof GMenu.TreeDirectory)
-            return item.get_menu_id();
-        else
-            return null;
-    },
-
-    _createItemIcon: function(item) {
-        if (item instanceof Shell.App)
-            return new AppIcon(item);
-        else if (item instanceof GMenu.TreeDirectory)
-            return new FolderIcon(item, this);
-        else
-            return null;
-    },
-
-    _compareItems: function(itemA, itemB) {
-        // bit of a hack: rely on both ShellApp and GMenuTreeDirectory
-        // having a get_name() method
-        let nameA = GLib.utf8_collate_key(itemA.get_name(), -1);
-        let nameB = GLib.utf8_collate_key(itemB.get_name(), -1);
-        return (nameA > nameB) ? 1 : (nameA < nameB ? -1 : 0);
-    },
-
     addApp: function(app) {
-        let appIcon = this._addItem(app);
-        if (appIcon)
+        let appIcon = this._page.addItem(app);
+        /*if (appIcon)
             appIcon.actor.connect('key-focus-in',
-                                  Lang.bind(this, this._ensureIconVisible));
+                                  Lang.bind(this, this._ensureIconVisible));*/
     },
 
     addFolder: function(dir) {
-        let folderIcon = this._addItem(dir);
-        if (folderIcon)
+        let folderIcon = this._page.addItem(dir);
+        /*if (folderIcon)
             folderIcon.actor.connect('key-focus-in',
-                                     Lang.bind(this, this._ensureIconVisible));
+                                     Lang.bind(this, this._ensureIconVisible));*/
     },
 
     addFolderPopup: function(popup) {
+        /*
         this._stack.add_actor(popup.actor);
         popup.connect('open-state-changed', Lang.bind(this,
             function(popup, isOpen) {
@@ -285,12 +383,12 @@ const AllView = new Lang.Class({
                 } else {
                     this._grid.actor.y = 0;
                 }
-            }));
+            }));*/
     },
 
-    _ensureIconVisible: function(icon) {
+    /*_ensureIconVisible: function(icon) {
         Util.ensureActorVisibleInScrollView(this.actor, icon);
-    },
+    },*/
 
     _updateIconOpacities: function(folderOpen) {
         for (let id in this._items) {
@@ -299,6 +397,15 @@ const AllView = new Lang.Class({
             else
                 this._items[id].actor.opacity = 255;
         }
+    },
+    
+    removeAll: function() {
+        this._page.removeAll();
+    },
+
+    loadGrid: function() {
+        this._page.loadGrid();
+        global.log("ZZZ visible items after load grid " + this._page._grid.visibleItemsCount());
     }
 });
 
@@ -312,6 +419,8 @@ const FrequentView = new Lang.Class({
         this.actor = new St.Widget({ style_class: 'frequent-apps',
                                      x_expand: true, y_expand: true });
         this.actor.add_actor(this._grid.actor);
+        
+        //global.log("Frequent visible items " + this._grid.visibleItemsCount());
 
         this._usage = Shell.AppUsage.get_default();
     },
@@ -328,6 +437,8 @@ const FrequentView = new Lang.Class({
             let appIcon = new AppIcon(mostUsed[i]);
             this._grid.addItem(appIcon.actor, -1);
         }
+        global.log("Frequent visible items after " + this._grid.visibleItemsCount());
+        //global.log("Current frequent apps number "+mostUsed.length);
     }
 });
 
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 416e659..67f5689 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -196,6 +196,7 @@ 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));
+        this._currentPage = 0;
     },
 
     _getPreferredWidth: function (grid, forHeight, alloc) {
@@ -231,6 +232,7 @@ const IconGrid = new Lang.Class({
             return;
 
         let children = this._getVisibleChildren();
+        //global.log("Num children visible"  + children.length);
         let nColumns, spacing;
         if (forWidth < 0) {
             nColumns = children.length;
@@ -246,13 +248,19 @@ const IconGrid = new Lang.Class({
             nRows = 0;
         if (this._rowLimit)
             nRows = Math.min(nRows, this._rowLimit);
+        //global.log("Rows "+nRows);
+        //global.log("Columns "+nColumns);
         let totalSpacing = Math.max(0, nRows - 1) * spacing;
         let height = nRows * this._vItemSize + totalSpacing;
+        //global.log("Heigth "+height);
         alloc.min_size = height;
         alloc.natural_size = height;
     },
 
     _allocate: function (grid, box, flags) {
+        let firstTime = true;
+        let maxChildsPerPage = 0;
+        let spacingBetweenPages = 0;
         if (this._fillParent) {
             // Reset the passed in box to fill the parent
             let parentBox = this.actor.get_parent().allocation;
@@ -261,11 +269,14 @@ const IconGrid = new Lang.Class({
         }
 
         let children = this._getVisibleChildren();
+        //global.log("Allocate visible children " + children.length);
         let availWidth = box.x2 - box.x1;
         let availHeight = box.y2 - box.y1;
-
+        //global.log("Allocate availHeigth " + availHeight);
+        //global.log("Allocate availWidth " + availWidth);
         let [nColumns, usedWidth, spacing] = this._computeLayout(availWidth);
-
+        //global.log("Allocate nColumnds " + nColumns);
+        //global.log("Allocate usedWidth " + nColumns);
         let leftPadding;
         switch(this._xAlign) {
             case St.Align.START:
@@ -282,32 +293,29 @@ const IconGrid = new Lang.Class({
         let y = box.y1;
         let columnIndex = 0;
         let rowIndex = 0;
+        let count1 = 0;
+        let count2 = 0;
         for (let i = 0; i < children.length; i++) {
-            let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight]
-                = children[i].get_preferred_size();
-
-            /* Center the item in its allocation horizontally */
-            let width = Math.min(this._hItemSize, childNaturalWidth);
-            let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
-            let height = Math.min(this._vItemSize, childNaturalHeight);
-            let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
-
-            let childBox = new Clutter.ActorBox();
-            if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
-                let _x = box.x2 - (x + width);
-                childBox.x1 = Math.floor(_x - childXSpacing);
-            } else {
-                childBox.x1 = Math.floor(x + childXSpacing);
-            }
-            childBox.y1 = Math.floor(y + childYSpacing);
-            childBox.x2 = childBox.x1 + width;
-            childBox.y2 = childBox.y1 + height;
-
+            let childBox = this._calculateChildrenBox(children[i], x, y);
+            
             if (this._rowLimit && rowIndex >= this._rowLimit ||
-                this._fillParent && childBox.y2 > availHeight) {
-                this._grid.set_skip_paint(children[i], true);
+                 childBox.y2 > availHeight || this.parentSize && (childBox.y2 > this.parentSize[1]) ) {
+                if(firstTime && this.parentSize) {
+                    maxChildsPerPage = count2;
+                    firstTime = false;
+                    spacingBetweenPages = this.parentSize[1] - ( children[i-1].y + 
children[i-1].size.height);
+                    y+= spacingBetweenPages;
+                    global.log("Spacing between pages " + spacingBetweenPages);
+                  //Recalculate child box
+                  childBox = this._calculateChildrenBox(children[i], x, y);  
+                }
+                
+                count1 += 1;
+                children[i].allocate(childBox, flags);
+                this._grid.set_skip_paint(children[i], false);
             } else {
                 children[i].allocate(childBox, flags);
+                count2 += 1;
                 this._grid.set_skip_paint(children[i], false);
             }
 
@@ -319,15 +327,47 @@ const IconGrid = new Lang.Class({
 
             if (columnIndex == 0) {
                 y += this._vItemSize + spacing;
+                if(!firstTime && count1 % maxChildsPerPage == 0)
+                    {
+                        y+= spacingBetweenPages;
+                    }
                 x = box.x1 + leftPadding;
             } else {
                 x += this._hItemSize + spacing;
             }
         }
+        /*global.log("Final count 1 " + count1);
+        global.log("Final count 2 " + count2);
+        global.log("Final n children " + this._grid.get_n_children());
+        global.log("Final n skip " + this._grid.get_n_skip_paint());*/
+        global.log("Allocation final visible count " + this.visibleItemsCount());
     },
 
+    _calculateChildrenBox: function(child, x, y) {
+        let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight]
+        = child.get_preferred_size();
+
+        /* Center the item in its allocation horizontally */
+        let width = Math.min(this._hItemSize, childNaturalWidth);
+        let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
+        let height = Math.min(this._vItemSize, childNaturalHeight);
+        let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
+    
+        let childBox = new Clutter.ActorBox();
+        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
+            let _x = box.x2 - (x + width);
+            childBox.x1 = Math.floor(_x - childXSpacing);
+        } else {
+            childBox.x1 = Math.floor(x + childXSpacing);
+        }
+        childBox.y1 = Math.floor(y + childYSpacing);
+        childBox.x2 = childBox.x1 + width;
+        childBox.y2 = childBox.y1 + height;
+        return childBox;
+    },
+    
     childrenInRow: function(rowWidth) {
-        return this._computeLayout(rowWidth)[0];
+        return this._computeLayout(rowWidth)[0]
     },
 
     getRowLimit: function() {


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