[gnome-shell/wip/carlosg/appgrid-navigation: 27/29] js/appDisplay: Implement side page previews while DnDing




commit e95a9f693ccff697aa7d9a6fad57e5d1d9efd734
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Feb 3 12:51:17 2021 +0100

    js/appDisplay: Implement side page previews while DnDing
    
    When DnDing an icon, we show both previous/next page, and optionally
    a "placeholder" actor to allow creating new pages. These sides on the
    scrollview are drop targets themselves, allowing to drop an app onto
    the next/prev page without further navigation.
    
    Still, preserve the checks to maybe switch to prev/next page without
    finishing the DnD operation, for finer grained operations.

 data/theme/gnome-shell-sass/widgets/_app-grid.scss |  8 ++++
 js/ui/appDisplay.js                                | 52 +++++++++++++++++++++-
 2 files changed, 58 insertions(+), 2 deletions(-)
---
diff --git a/data/theme/gnome-shell-sass/widgets/_app-grid.scss 
b/data/theme/gnome-shell-sass/widgets/_app-grid.scss
index 051dbc239e..19c3ee5a4b 100644
--- a/data/theme/gnome-shell-sass/widgets/_app-grid.scss
+++ b/data/theme/gnome-shell-sass/widgets/_app-grid.scss
@@ -137,3 +137,11 @@ $app_grid_fg_color: #fff;
   border-radius: 99px;
   icon-size: $app_icon_size * 0.5;
 }
+
+.dnd-placeholder {
+  background: rgba(255,255,255,0.25);
+  width: 80px;
+
+  &:ltr { border-radius: 15px 0px 0px 15px; }
+  &:rtl { border-radius: 0px 15px 15px 0px; }
+}
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index a9433fddb5..67026e598f 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -55,6 +55,7 @@ var SidePages = {
     NONE: 0,
     PREVIOUS: 1 << 0,
     NEXT: 1 << 1,
+    EMPTY_PLACEHOLDER: 1 << 2,
 };
 
 function _getCategories(info) {
@@ -153,6 +154,7 @@ var BaseAppView = GObject.registerClass({
             enable_mouse_scrolling: false,
         });
         this._scrollView.set_policy(St.PolicyType.EXTERNAL, St.PolicyType.NEVER);
+        this._scrollView._delegate = this;
 
         this._canScroll = true; // limiting scrolling speed
         this._scrollTimeoutId = 0;
@@ -184,12 +186,32 @@ var BaseAppView = GObject.registerClass({
             this._scrollView.event(event, false);
         });
 
+        // "Empty page" DnD indicator
+        this._emptyPageIndicator = new St.Widget({
+            opacity: 0,
+            reactive: false,
+            visible: false,
+            x_expand: true,
+            y_expand: true,
+            x_align: Clutter.ActorAlign.END,
+            y_align: Clutter.ActorAlign.FILL,
+        });
+        this._emptyPageIndicator.add_style_class_name('dnd-placeholder');
+        this._emptyPageIndicator._delegate = this;
+
+        let scrollContainer = new St.Widget({
+            layout_manager: new Clutter.BinLayout(),
+            clip_to_allocation: true,
+        });
+        scrollContainer.add_child(this._scrollView);
+        scrollContainer.add_child(this._emptyPageIndicator);
+
         this._box = new St.BoxLayout({
             vertical: true,
             x_expand: true,
             y_expand: true,
         });
-        this._box.add_child(this._scrollView);
+        this._box.add_child(scrollContainer);
         this._box.add_child(this._pageIndicators);
 
         // Swipe
@@ -572,6 +594,7 @@ var BaseAppView = GObject.registerClass({
             dragMotion: this._onDragMotion.bind(this),
         };
         DND.addDragMonitor(this._dragMonitor);
+        this._slideSidePages(SidePages.PREVIOUS | SidePages.NEXT | SidePages.EMPTY_PLACEHOLDER);
     }
 
     _onDragMotion(dragEvent) {
@@ -588,6 +611,16 @@ var BaseAppView = GObject.registerClass({
 
         this._maybeMoveItem(dragEvent);
 
+        this._dropPage = this._pageForCoords(dragEvent.x, dragEvent.y);
+        if (this._dropPage) {
+            if (this._dropPage === SidePages.NEXT || this._grid.currentPage !== 0) {
+                return DND.DragMotionResult.MOVE_DROP;
+            } else {
+                this._dropPage = null;
+                return DND.DragMotionResult.NO_DROP;
+            }
+        }
+
         return DND.DragMotionResult.CONTINUE;
     }
 
@@ -598,12 +631,15 @@ var BaseAppView = GObject.registerClass({
         }
 
         this._resetOvershoot();
+        this._slideSidePages(SidePages.NONE);
+        this._dropPage = null;
     }
 
     _onDragCancelled() {
         // At this point, the positions aren't stored yet, thus _redisplay()
         // will move all items to their original positions
         this._redisplay();
+        this._slideSidePages(SidePages.NONE);
     }
 
     _canAccept(source) {
@@ -627,6 +663,13 @@ var BaseAppView = GObject.registerClass({
 
             this._moveItem(source, page, position);
             this._removeDelayedMove();
+        } else if (this._dropPage) {
+            const page = (this._dropPage === SidePages.NEXT)
+                  ? this._grid.currentPage + 1
+                  : this._grid.currentPage - 1;
+
+            this._moveItem(source, page, 1);
+            this.goToPage(page);
         }
 
         return true;
@@ -982,7 +1025,12 @@ var BaseAppView = GObject.registerClass({
                 this._nextPageAdjustmentId = this._nextPageAdjustment.connect('notify::value', () => {
                     let translationX = (1 - this._nextPageAdjustment.value) * 100;
                     translationX = rtl ? -translationX : translationX;
-                    if (this._grid.currentPage < this._grid.nPages - 1) {
+                    if ((pages & SidePages.EMPTY_PLACEHOLDER) !== 0 &&
+                        this._grid.currentPage === this._grid.nPages - 1) {
+                        this._emptyPageIndicator.visible = true;
+                        this._emptyPageIndicator.translation_x = translationX;
+                        this._emptyPageIndicator.opacity = this._nextPageAdjustment.value * 255;
+                    } else if (this._grid.currentPage < this._grid.nPages - 1) {
                         const items = this._grid.layout_manager.getItemsAtPage(this._grid.currentPage + 1);
                         items.forEach(item => (item.translation_x = translationX));
                     }


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