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



commit a8ebee510c5e1bba3e33b1b33d0c4ed8456a2994
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

 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                    |  239 +++++++++++++++++++++++++-------
 5 files changed, 339 insertions(+), 54 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..b64c91b
--- /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="24"
+   height="24"
+   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,8)">
+    <path
+       transform="matrix(1.0013282,0,0,1.1462573,-2079.7699,-728.26471)"
+       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..2f0b6e7
--- /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="24"
+   height="24"
+   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,8)">
+    <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"
+       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)" />
+  </g>
+</svg>
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index c2db284..b8ff503 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(24, 24);
         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,131 @@ const PaginationIconIndicator = new Lang.Class({
     }
 });
 
+const PaginationIndicator = new Lang.Class({
+    Name:'PaginationIndicator',
+    
+    _init: function(params) {
+        params['y_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 = [this._spacing, availHeight / 2 - totalUsedHeight / 2];
+        for(let i = 0; i < this._nPages; i++) {
+            let childBox = new Clutter.ActorBox();
+            childBox.x1 = 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);
+        }
+    },
+
+    vfunc_set_container: function(container) {
+        if(this._styleChangedId) {
+            this._container.disconnect(this._styleChangedId);
+            this._styleChangedId = 0;
+        }
+        if(container != null)
+            this._styleChangedId = container.connect('style-changed', Lang.bind(this,
+                    function() { this.spacing = this._container.get_theme_node().get_length('spacing'); }));
+        this._container = container;
+    }
+});
 
 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();
+        this._paginationIndicatorLayout._nPages = nPages;
+        let availWidth = box.x2 - box.x1;
+        let availHeight = box.y2 - box.y1;
+        let childBox = new Clutter.ActorBox();
+        let [minWidth, natWidth] = this._paginationIndicator.get_preferred_width(availHeight);
+        childBox.x1 = availWidth - natWidth;
+        childBox.x2 = availWidth;
+        childBox.y1 = 0;
+        childBox.y2 = availHeight;
+
+        this._paginationIndicator.allocate(childBox, flags);
         
-        if(nPages > 1) {
-            for(let i = 0; i < nPages; i++) {
-                this._paginationIndicator.get_child_at_index(i).show();
-            }         
-        }
-        this._paginationIndicator.allocate(box, 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 +629,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 +676,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 +876,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);
+        }
     }
 });
 


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