[gnome-shell/wip/carlosg/osk-emoji-and-keypad: 1/3] appDisplay: Separate PageIndicators to a separate file



commit 5dff54c078258c38d329023cf4a1ac6bec68a749
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Jan 22 12:10:51 2019 +0100

    appDisplay: Separate PageIndicators to a separate file
    
    In order to cater for emoji panel usage, we want something like PageIndicators
    except:
    - It should have horizontal disposition
    - It should not be animatable (?)
    - It should not be reactive
    
    Separated PageIndicators into a base, non-animated widget, and an
    AnimatedPageIndicators that can be used on appDisplay.js. Reactiveness is
    set through an extra method, and layout is set as a construct argument.

 js/js-resources.gresource.xml |   1 +
 js/ui/appDisplay.js           | 117 ++--------------------------------
 js/ui/pageIndicators.js       | 142 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+), 113 deletions(-)
---
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index a3dd2be08..8532aaf45 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -78,6 +78,7 @@
     <file>ui/overview.js</file>
     <file>ui/overviewControls.js</file>
     <file>ui/padOsd.js</file>
+    <file>ui/pageIndicators.js</file>
     <file>ui/panel.js</file>
     <file>ui/panelMenu.js</file>
     <file>ui/pointerWatcher.js</file>
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 1a3533cab..23ec4df70 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -19,6 +19,7 @@ const IconGrid = imports.ui.iconGrid;
 const Main = imports.ui.main;
 const Overview = imports.ui.overview;
 const OverviewControls = imports.ui.overviewControls;
+const PageIndicators = imports.ui.pageIndicators;
 const PopupMenu = imports.ui.popupMenu;
 const Tweener = imports.ui.tweener;
 const Workspace = imports.ui.workspace;
@@ -245,116 +246,6 @@ class BaseAppView {
 };
 Signals.addSignalMethods(BaseAppView.prototype);
 
-var PageIndicatorsActor = GObject.registerClass(
-class PageIndicatorsActor extends St.BoxLayout {
-    _init() {
-        super._init({ style_class: 'page-indicators',
-                      vertical: true,
-                      x_expand: true, y_expand: true,
-                      x_align: Clutter.ActorAlign.END,
-                      y_align: Clutter.ActorAlign.CENTER,
-                      reactive: true,
-                      clip_to_allocation: true });
-    }
-
-    vfunc_get_preferred_height(forWidth) {
-        // We want to request the natural height of all our children as our
-        // natural height, so we chain up to St.BoxLayout, but we only request 0
-        // as minimum height, since it's not that important if some indicators
-        // are not shown
-        let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
-        return [0, natHeight];
-    }
-});
-
-class PageIndicators {
-    constructor() {
-        this.actor = new PageIndicatorsActor();
-        this._nPages = 0;
-        this._currentPage = undefined;
-
-        this.actor.connect('notify::mapped', () => {
-            this.animateIndicators(IconGrid.AnimationDirection.IN);
-        });
-    }
-
-    setNPages(nPages) {
-        if (this._nPages == nPages)
-            return;
-
-        let diff = nPages - this._nPages;
-        if (diff > 0) {
-            for (let i = 0; i < diff; i++) {
-                let pageIndex = this._nPages + i;
-                let indicator = new St.Button({ style_class: 'page-indicator',
-                                                button_mask: St.ButtonMask.ONE |
-                                                             St.ButtonMask.TWO |
-                                                             St.ButtonMask.THREE,
-                                                toggle_mode: true,
-                                                checked: pageIndex == this._currentPage });
-                indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
-                indicator.connect('clicked', () => {
-                    this.emit('page-activated', pageIndex);
-                });
-                this.actor.add_actor(indicator);
-            }
-        } else {
-            let children = this.actor.get_children().splice(diff);
-            for (let i = 0; i < children.length; i++)
-                children[i].destroy();
-        }
-        this._nPages = nPages;
-        this.actor.visible = (this._nPages > 1);
-    }
-
-    setCurrentPage(currentPage) {
-        this._currentPage = currentPage;
-
-        let children = this.actor.get_children();
-        for (let i = 0; i < children.length; i++)
-            children[i].set_checked(i == this._currentPage);
-    }
-
-    animateIndicators(animationDirection) {
-        if (!this.actor.mapped)
-            return;
-
-        let children = this.actor.get_children();
-        if (children.length == 0)
-            return;
-
-        for (let i = 0; i < this._nPages; i++)
-            Tweener.removeTweens(children[i]);
-
-        let offset;
-        if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
-            offset = -children[0].width;
-        else
-            offset = children[0].width;
-
-        let isAnimationIn = animationDirection == IconGrid.AnimationDirection.IN;
-        let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
-                                    INDICATORS_ANIMATION_DELAY_OUT;
-        let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
-        let totalAnimationTime = baseTime + delay * this._nPages;
-        let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
-                                      INDICATORS_ANIMATION_MAX_TIME_OUT;
-        if (totalAnimationTime > maxTime)
-            delay -= (totalAnimationTime - maxTime) / this._nPages;
-
-        for (let i = 0; i < this._nPages; i++) {
-            children[i].translation_x = isAnimationIn ? offset : 0;
-            Tweener.addTween(children[i],
-                             { translation_x: isAnimationIn ? 0 : offset,
-                               time: baseTime + delay * i,
-                               transition: 'easeInOutQuad',
-                               delay: isAnimationIn ? VIEWS_SWITCH_ANIMATION_DELAY : 0
-                             });
-        }
-    }
-};
-Signals.addSignalMethods(PageIndicators.prototype);
-
 var AllView = class AllView extends BaseAppView {
     constructor() {
         super({ usePagination: true }, null);
@@ -373,13 +264,13 @@ var AllView = class AllView extends BaseAppView {
                                     St.PolicyType.EXTERNAL);
         this._adjustment = this._scrollView.vscroll.adjustment;
 
-        this._pageIndicators = new PageIndicators();
+        this._pageIndicators = new PageIndicators.AnimatedPageIndicators();
         this._pageIndicators.connect('page-activated',
             (indicators, pageIndex) => {
                 this.goToPage(pageIndex);
             });
-        this._pageIndicators.actor.connect('scroll-event', this._onScroll.bind(this));
-        this.actor.add_actor(this._pageIndicators.actor);
+        this._pageIndicators.connect('scroll-event', this._onScroll.bind(this));
+        this.actor.add_actor(this._pageIndicators);
 
         this.folderIcons = [];
 
diff --git a/js/ui/pageIndicators.js b/js/ui/pageIndicators.js
new file mode 100644
index 000000000..134606c44
--- /dev/null
+++ b/js/ui/pageIndicators.js
@@ -0,0 +1,142 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
+const St = imports.gi.St;
+
+const Tweener = imports.ui.tweener;
+const { ANIMATION_TIME_OUT, ANIMATION_MAX_DELAY_OUT_FOR_ITEM, AnimationDirection } = imports.ui.iconGrid;
+
+var INDICATORS_BASE_TIME = 0.25;
+var INDICATORS_BASE_TIME_OUT = 0.125;
+var INDICATORS_ANIMATION_DELAY = 0.125;
+var INDICATORS_ANIMATION_DELAY_OUT = 0.0625;
+var INDICATORS_ANIMATION_MAX_TIME = 0.75;
+var SWITCH_TIME = 0.4;
+var INDICATORS_ANIMATION_MAX_TIME_OUT =
+    Math.min (SWITCH_TIME,
+              ANIMATION_TIME_OUT + ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
+
+var ANIMATION_DELAY = 0.1;
+
+var PageIndicators = GObject.registerClass({
+    Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } }
+}, class PageIndicators extends St.BoxLayout {
+    _init(vertical = true) {
+        super._init({ style_class: 'page-indicators',
+                      vertical,
+                      x_expand: true, y_expand: true,
+                      x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
+                      y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
+                      reactive: true,
+                      clip_to_allocation: true });
+        this._nPages = 0;
+        this._currentPage = undefined;
+        this._reactive = true;
+        this._reactive = true;
+    }
+
+    vfunc_get_preferred_height(forWidth) {
+        // We want to request the natural height of all our children as our
+        // natural height, so we chain up to St.BoxLayout, but we only request 0
+        // as minimum height, since it's not that important if some indicators
+        // are not shown
+        let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
+        return [0, natHeight];
+    }
+
+    setReactive(reactive) {
+        let children = this.get_children();
+        for (let i = 0; i < children.length; i++)
+            children[i].reactive = reactive;
+
+        this._reactive = reactive;
+    }
+
+    setNPages(nPages) {
+        if (this._nPages == nPages)
+            return;
+
+        let diff = nPages - this._nPages;
+        if (diff > 0) {
+            for (let i = 0; i < diff; i++) {
+                let pageIndex = this._nPages + i;
+                let indicator = new St.Button({ style_class: 'page-indicator',
+                                                button_mask: St.ButtonMask.ONE |
+                                                             St.ButtonMask.TWO |
+                                                             St.ButtonMask.THREE,
+                                                toggle_mode: true,
+                                                reactive: this._reactive,
+                                                checked: pageIndex == this._currentPage });
+                indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
+                indicator.connect('clicked', () => {
+                    this.emit('page-activated', pageIndex);
+                });
+                this.add_actor(indicator);
+            }
+        } else {
+            let children = this.get_children().splice(diff);
+            for (let i = 0; i < children.length; i++)
+                children[i].destroy();
+        }
+        this._nPages = nPages;
+        this.visible = (this._nPages > 1);
+    }
+
+    setCurrentPage(currentPage) {
+        this._currentPage = currentPage;
+
+        let children = this.get_children();
+        for (let i = 0; i < children.length; i++)
+            children[i].set_checked(i == this._currentPage);
+    }
+});
+
+var AnimatedPageIndicators = GObject.registerClass(
+class AnimatedPageIndicators extends PageIndicators {
+    _init() {
+        super._init(true);
+
+        this.connect('notify::mapped', () => {
+            this.animateIndicators(AnimationDirection.IN);
+        });
+    }
+
+    animateIndicators(animationDirection) {
+        if (!this.mapped)
+            return;
+
+        let children = this.get_children();
+        if (children.length == 0)
+            return;
+
+        for (let i = 0; i < this._nPages; i++)
+            Tweener.removeTweens(children[i]);
+
+        let offset;
+        if (this.get_text_direction() == Clutter.TextDirection.RTL)
+            offset = -children[0].width;
+        else
+            offset = children[0].width;
+
+        let isAnimationIn = animationDirection == AnimationDirection.IN;
+        let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
+                                    INDICATORS_ANIMATION_DELAY_OUT;
+        let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
+        let totalAnimationTime = baseTime + delay * this._nPages;
+        let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
+                                      INDICATORS_ANIMATION_MAX_TIME_OUT;
+        if (totalAnimationTime > maxTime)
+            delay -= (totalAnimationTime - maxTime) / this._nPages;
+
+        for (let i = 0; i < this._nPages; i++) {
+            children[i].translation_x = isAnimationIn ? offset : 0;
+           Tweener.addTween(children[i], {
+                translation_x: isAnimationIn ? 0 : offset,
+                time: baseTime + delay * i,
+                transition: 'easeInOutQuad',
+                delay: isAnimationIn ? ANIMATION_DELAY : 0
+            });
+        }
+    }
+});


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