[gnome-shell/wip/exalm/dots] pageIndicators: Redesign and add position-based animation



commit 9ec420a0e82a3677ab12d2e17785919cfb5a4fc0
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date:   Fri Nov 22 03:24:46 2019 +0500

    pageIndicators: Redesign and add position-based animation
    
    Remove setCurrentPage() function, introduce setCurrentPosition() instead,
    which allows to have fractional positions.
    
    Draw dots via Cairo, introduce css properties for controlling dot size and
    color in active and inactive state, interpolate between states depending on
    the position.
    
    Make inactive dots smaller, filled and slightly transparent, as opposed to
    larger and fully opaque active dot. Make dots smaller overall, remove
    borders.
    
    Make it impossible to "uncheck" the active dot.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1932
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/843

 data/theme/gnome-shell-sass/_common.scss | 28 ++++++++++++-------
 js/ui/appDisplay.js                      |  9 +++---
 js/ui/keyboard.js                        | 13 ++++++++-
 js/ui/pageIndicators.js                  | 48 ++++++++++++++++++++++++++------
 4 files changed, 74 insertions(+), 24 deletions(-)
---
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
index b600830115..49bd3c0b20 100644
--- a/data/theme/gnome-shell-sass/_common.scss
+++ b/data/theme/gnome-shell-sass/_common.scss
@@ -1549,20 +1549,24 @@ StScrollBar {
   }
 
   .page-indicator {
-    padding: 15px 20px;
+    padding: 7px 16px;
 
     .page-indicator-icon {
       width: 12px;
       height: 12px;
-      background-color: transparent;
-      border: 2px solid rgba(255, 255, 255, 0.4);
-      border-radius: 12px;
+      -page-indicator-inactive-radius: 4px;
+      -page-indicator-active-radius: 6px;
+      -page-indicator-inactive-color: rgba(255, 255, 255, 0.5);
+      -page-indicator-active-color: white;
+    }
+
+    &:hover .page-indicator-icon {
+      -page-indicator-inactive-color: white;
     }
 
-    &:hover .page-indicator-icon { border-color: white; }
-    &:active .page-indicator-icon { border: none; margin: 2px; background-color: white; }
-    &:checked .page-indicator-icon,
-    &:checked:active .page-indicator-icon { background-color: white;}
+    &:active .page-indicator-icon {
+      -page-indicator-inactive-radius: 3px;
+    }
   }
 
   .no-frequent-applications-label { @extend %status_text; }
@@ -1762,8 +1766,12 @@ StScrollBar {
         padding: 4px 4px;
 
         .page-indicator-icon {
-            width: 6px;
-            height: 6px
+            width: 8px;
+            height: 8px;
+            -page-indicator-inactive-radius: 3px;
+            -page-indicator-active-radius: 4px;
+            -page-indicator-inactive-color: rgba(255, 255, 255, 0.5);
+            -page-indicator-active-color: white;
         }
     }
 }
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 929caa12bd..f540c1fb6a 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -315,6 +315,9 @@ var AllView = GObject.registerClass({
         this._scrollView.set_policy(St.PolicyType.NEVER,
                                     St.PolicyType.EXTERNAL);
         this._adjustment = this._scrollView.vscroll.adjustment;
+        this._adjustment.connect('notify::value', (adj) => {
+            this._pageIndicators.setCurrentPosition(adj.value / adj.page_size);
+        });
 
         this._pageIndicators = new PageIndicators.AnimatedPageIndicators();
         this._pageIndicators.connect('page-activated',
@@ -561,7 +564,7 @@ var AllView = GObject.registerClass({
 
         if (!this.mapped) {
             this._adjustment.value = this._grid.getPageY(pageNumber);
-            this._pageIndicators.setCurrentPage(pageNumber);
+            this._pageIndicators.setCurrentPosition(pageNumber);
             this._grid.currentPage = pageNumber;
             return;
         }
@@ -597,8 +600,6 @@ var AllView = GObject.registerClass({
             mode: Clutter.AnimationMode.EASE_OUT_QUAD,
             duration: time,
         });
-
-        this._pageIndicators.setCurrentPage(pageNumber);
     }
 
     _diffToPage(pageNumber) {
@@ -754,7 +755,7 @@ var AllView = GObject.registerClass({
                 this._adjustment.value = 0;
                 this._grid.currentPage = 0;
                 this._pageIndicators.setNPages(this._grid.nPages());
-                this._pageIndicators.setCurrentPage(0);
+                this._pageIndicators.setCurrentPosition(0);
                 return GLib.SOURCE_REMOVE;
             });
         }
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index c6984cc36d..594db72385 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -920,9 +920,14 @@ var EmojiSelection = GObject.registerClass({
         this.add_child(this._pageIndicator);
         this._pageIndicator.setReactive(false);
 
+        this._emojiPager.connect('notify::delta', (pager) => {
+            this._updateIndicatorPosition();
+        });
+
         let bottomRow = this._createBottomRow();
         this.add_child(bottomRow);
 
+        this._curPage = 0;
         this._emojiPager.setCurrentPage(0);
     }
 
@@ -937,8 +942,9 @@ var EmojiSelection = GObject.registerClass({
     }
 
     _onPageChanged(sectionLabel, page, nPages) {
+        this._curPage = page;
         this._pageIndicator.setNPages(nPages);
-        this._pageIndicator.setCurrentPage(page);
+        this._updateIndicatorPosition();
 
         for (let i = 0; i < this._sections.length; i++) {
             let sect = this._sections[i];
@@ -946,6 +952,11 @@ var EmojiSelection = GObject.registerClass({
         }
     }
 
+    _updateIndicatorPosition() {
+        this._pageIndicator.setCurrentPosition(this._curPage -
+            this._emojiPager.delta / this._emojiPager.width);
+    }
+
     _findSection(emoji) {
         for (let i = 0; i < this._sections.length; i++) {
             if (this._sections[i].first == emoji)
diff --git a/js/ui/pageIndicators.js b/js/ui/pageIndicators.js
index 825aafcf74..121f02b763 100644
--- a/js/ui/pageIndicators.js
+++ b/js/ui/pageIndicators.js
@@ -2,6 +2,7 @@
 /* exported PageIndicators, AnimatedPageIndicators */
 
 const { Clutter, GLib, GObject, Meta, St } = imports.gi;
+const Cairo = imports.cairo;
 
 const { ANIMATION_TIME_OUT, ANIMATION_MAX_DELAY_OUT_FOR_ITEM, AnimationDirection } = imports.ui.iconGrid;
 
@@ -32,7 +33,7 @@ var PageIndicators = GObject.registerClass({
             clip_to_allocation: true,
         });
         this._nPages = 0;
-        this._currentPage = undefined;
+        this._currentPosition = 0;
         this._reactive = true;
         this._reactive = true;
     }
@@ -66,10 +67,11 @@ var PageIndicators = GObject.registerClass({
                                                 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' });
+                                                reactive: this._reactive });
+                indicator.child = new St.DrawingArea({ style_class: 'page-indicator-icon' });
+                indicator.child.connect('repaint', () => {
+                    this.drawIndicatorIcon(indicator.child, pageIndex);
+                });
                 indicator.connect('clicked', () => {
                     this.emit('page-activated', pageIndex);
                 });
@@ -84,12 +86,40 @@ var PageIndicators = GObject.registerClass({
         this.visible = this._nPages > 1;
     }
 
-    setCurrentPage(currentPage) {
-        this._currentPage = currentPage;
+    drawIndicatorIcon(widget, index) {
+        let node = widget.get_theme_node();
+
+        let inactiveRadius = node.get_length('-page-indicator-inactive-radius');
+        let activeRadius = node.get_length('-page-indicator-active-radius');
+
+        let activeColor = node.get_color('-page-indicator-active-color');
+        let inactiveColor = node.get_color('-page-indicator-inactive-color');
+
+        let progress = Math.max(1 - Math.abs(this._currentPosition - index), 0);
+        let radius = inactiveRadius + (activeRadius - inactiveRadius) * progress;
+        let color = inactiveColor.interpolate(activeColor, progress);
+
+        let cr = widget.get_context();
+        cr.setOperator(Cairo.Operator.SOURCE);
+
+        cr.arc(widget.width / 2, widget.height / 2, radius, 0, Math.PI * 2);
+
+        Clutter.cairo_set_source_color(cr, color);
+        cr.fill();
+
+        cr.$dispose();
+    }
+
+    setCurrentPosition(currentPosition) {
+        this._currentPosition = currentPosition;
 
         let children = this.get_children();
-        for (let i = 0; i < children.length; i++)
-            children[i].set_checked(i == this._currentPage);
+        for (let i = 0; i < children.length; i++) {
+            let progress = Math.max(1 - Math.abs(currentPosition - i), 0);
+
+            let child = children[i].child;
+            child.queue_repaint();
+        }
     }
 });
 


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