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




commit 9d599aae5b4fc9685b931b8346719ec56d207462
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                                | 45 +++++++++++++++++++++-
 2 files changed, 52 insertions(+), 1 deletion(-)
---
diff --git a/data/theme/gnome-shell-sass/widgets/_app-grid.scss 
b/data/theme/gnome-shell-sass/widgets/_app-grid.scss
index 76358d1988..9b85468064 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: #fff;
+  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 df7f928c27..9dfed27150 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -52,6 +52,7 @@ var SidePages = {
     NONE: 0,
     PREVIOUS: 1 << 0,
     NEXT: 1 << 1,
+    EMPTY_PLACEHOLDER: 1 << 2,
 }
 
 function _getCategories(info) {
@@ -161,6 +162,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;
@@ -244,6 +246,14 @@ var BaseAppView = GObject.registerClass({
         this._dragCancelledId = 0;
 
         this.connect('destroy', this._onDestroy.bind(this));
+
+        this._emptyPageIndicator = new St.Widget({
+            opacity: 0,
+            reactive: false,
+            visible: false,
+        });
+        this._emptyPageIndicator.add_style_class_name('dnd-placeholder');
+        this.add_actor(this._emptyPageIndicator);
     }
 
     _onDestroy() {
@@ -586,6 +596,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) {
@@ -602,6 +613,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;
     }
 
@@ -612,12 +633,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) {
@@ -641,6 +665,11 @@ var BaseAppView = GObject.registerClass({
 
             this._moveItem(source, page, position);
             this._removeDelayedMove();
+        } else if (this._dropPage) {
+            if (this._dropPage == SidePages.NEXT)
+                this._moveItem(source, this._grid.currentPage + 1, 1);
+            else if (this._dropPage == SidePages.PREVIOUS)
+                this._moveItem(source, this._grid.currentPage - 1, 1);
         }
 
         return true;
@@ -908,6 +937,16 @@ var BaseAppView = GObject.registerClass({
         this.adaptToSize(width, height);
 
         super.vfunc_allocate(box);
+
+        this._emptyPageIndicator.set_height(this._grid.get_height());
+        const rtl = this.get_text_direction() === Clutter.TextDirection.RTL;
+        if (rtl) {
+            this._emptyPageIndicator.set_position (0, this._grid.get_y());
+        } else {
+            this._emptyPageIndicator.set_position (
+                width - this._emptyPageIndicator.width,
+                this._grid.get_y());
+        }
     }
 
     vfunc_map() {
@@ -994,7 +1033,11 @@ var BaseAppView = GObject.registerClass({
 
                 const rtl = this.get_text_direction() === Clutter.TextDirection.RTL;
                 this._nextPageAdjustmentId = this._nextPageAdjustment.connect('notify::value', () => {
-                    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.opacity = this._nextPageAdjustment.value * 128;
+                    } else if (this._grid.currentPage < this._grid.nPages - 1) {
                         let items = this._grid.layout_manager.getItemsAtPage(this._grid.currentPage + 1);
                         items.forEach(item => {
                             item.translation_x = (1 - this._nextPageAdjustment.value) * 100;


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