[gnome-shell/wip/paging-release2: 6/12] AppDisplay: Add and rework pan action response



commit 71e2979b6aa0d2caa5bd7d3e38ec08ab8d8849f1
Author: Carlos Soriano <carlos soriano89 gmail com>
Date:   Mon Aug 12 16:36:45 2013 +0200

    AppDisplay: Add and rework pan action response
    
    Add pan action to AllView and rework it to take
    into account the velocity the user gives to the action

 js/ui/appDisplay.js |   67 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 65 insertions(+), 2 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 1d02b81..d69bff8 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -39,7 +39,10 @@ const FOLDER_SUBICON_FRACTION = .4;
 
 const MAX_APPS_PAGES = 20;
 
-const PAGE_SWITCH_TIME = 0.25;
+//fraction of page height the finger or mouse must reach before
+//change page
+const PAGE_SWITCH_TRESHOLD = 0.2;
+const PAGE_SWITCH_TIME = 0.3;
 
 // Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
 function _loadCategory(dir, view) {
@@ -306,6 +309,17 @@ const AllView = new Lang.Class({
 
         this._paginationView.connect('scroll-event', Lang.bind(this, this._onScroll));
 
+        let panAction = new Clutter.PanAction({ interpolate: false });
+        panAction.connect('pan', Lang.bind(this, this._onPan));
+        panAction.connect('gesture-cancel', Lang.bind(this, function() {
+            this._onPanEnd(this._panAction);
+        }));
+        panAction.connect('gesture-end', Lang.bind(this, function() {
+            this._onPanEnd(this._panAction);
+        }));
+        this._panAction = panAction;
+        this._paginationView.add_action(panAction);
+
         this._clickAction = new Clutter.ClickAction();
         this._clickAction.connect('clicked', Lang.bind(this, function() {
             if (!this._currentPopup)
@@ -353,16 +367,45 @@ const AllView = new Lang.Class({
         if(!this._grid.nPages())
             return;
 
+        let velocity;
+        if(!action)
+            velocity = 0;
+        else
+            velocity = Math.abs(action.get_velocity(0)[2]);
+        // Tween the change between pages.
+        // If velocity is not specified (i.e. scrolling with mouse wheel),
+        // use the same speed regardless of original position
+        // if velocity is specified, it's in pixels per milliseconds
+        let diffFromPage =  this._diffToPage(pageNumber);
+        let childBox = this._paginationView.get_allocation_box();
+        let totalHeight = childBox.y2 - childBox.y1;
+        let time;
+        // Only take into account the velocity if we change of page, if not,
+        // we returns smoothly with default velocity to the current page
+        if(this._currentPage != pageNumber) {
+            let min_velocity = totalHeight / (PAGE_SWITCH_TIME * 1000);
+            velocity = Math.max(min_velocity, velocity);
+            time = (diffFromPage / velocity) / 1000;
+        } else
+            time = PAGE_SWITCH_TIME * diffFromPage / totalHeight;
+        // Take care when we are changing more than one page, maximum time
+        // regardless the velocity is the default one
+        time = Math.min(time, PAGE_SWITCH_TIME);
         if(pageNumber < this._grid.nPages() && pageNumber >= 0) {
             this._currentPage = pageNumber;
             let params = { value: this._grid.getPagePosition(this._currentPage)[1],
-                           time: PAGE_SWITCH_TIME,
+                           time: time,
                            transition: 'easeOutQuad'
                          };
             Tweener.addTween(this._verticalAdjustment, params);
         }
     },
 
+    _diffToPage: function (pageNumber) {
+        let currentScrollPosition = this._verticalAdjustment.value;
+        return Math.abs(currentScrollPosition - this._grid.getPagePosition(pageNumber)[1]);
+    },
+
     _onScroll: function(actor, event) {
         let direction = event.get_scroll_direction();
         let nextPage;
@@ -378,6 +421,26 @@ const AllView = new Lang.Class({
             }
     },
 
+    _onPan: function(action) {
+        this._clickAction.release();
+        let [dist, dx, dy] = action.get_motion_delta(0);
+        let adjustment = this._verticalAdjustment;
+        adjustment.value -= (dy / this._paginationView.height) * adjustment.page_size;
+        return false;
+    },
+
+    _onPanEnd: function(action) {
+        let diffCurrentPage = this._diffToPage(this._currentPage);
+        if(diffCurrentPage > this._paginationView.height * PAGE_SWITCH_TRESHOLD) {
+            if(action.get_velocity(0)[2] > 0 && this._currentPage > 0) {
+                this.goToPage(this._currentPage - 1, action);
+            } else if(this._currentPage < this._grid.nPages() - 1) {
+                this.goToPage(this._currentPage + 1, action);
+            }
+        } else
+            this.goToPage(this._currentPage, action);
+    },
+
     _onKeyRelease: function(actor, event) {
         if (event.get_key_symbol() == Clutter.KEY_Up) {
             this.goToNextPage();


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