[gnome-shell/gbsneto/icon-grid-part4] appDisplay: Allow editing folder names



commit fd771022432578cdef084ce4b73161fe8b73f7f0
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Sep 2 22:17:08 2019 -0300

    appDisplay: Allow editing folder names
    
    Add a new popover with a regular entry + button to rename
    folders. The layout is similar to other GNOME applications.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/696

 data/theme/gnome-shell-sass/_common.scss |   7 ++
 js/ui/appDisplay.js                      | 175 ++++++++++++++++++++++++++++++-
 2 files changed, 178 insertions(+), 4 deletions(-)
---
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
index 8731ba48d9..846ec3dc96 100644
--- a/data/theme/gnome-shell-sass/_common.scss
+++ b/data/theme/gnome-shell-sass/_common.scss
@@ -611,6 +611,13 @@ StScrollBar {
   }
 
 
+// Rename popup
+
+.rename-folder-popup-box {
+  spacing: 6px;
+  margin: 12px;
+}
+
 // Background menu
 .background-menu { -boxpointer-gap: 4px; -arrow-rise: 0px; }
 
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 21aebc1ab8..0eb456886f 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -1438,6 +1438,13 @@ var FolderIcon = class FolderIcon {
         this._itemDragEndId = Main.overview.connect(
             'item-drag-end', this._onDragEnd.bind(this));
 
+        this._popupTimeoutId = 0;
+
+        this.actor.connect('leave-event', this._onLeaveEvent.bind(this));
+        this.actor.connect('button-press-event', this._onButtonPress.bind(this));
+        this.actor.connect('touch-event', this._onTouchEvent.bind(this));
+        this.actor.connect('popup-menu', this._popupRenamePopup.bind(this));
+
         this.actor.connect('clicked', this.open.bind(this));
         this.actor.connect('destroy', this.onDestroy.bind(this));
         this.actor.connect('notify::mapped', () => {
@@ -1462,9 +1469,12 @@ var FolderIcon = class FolderIcon {
 
         if (this._popup)
             this._popup.actor.destroy();
+
+        this._removeMenuTimeout();
     }
 
     open() {
+        this._removeMenuTimeout();
         this._ensurePopup();
         this.view.actor.vscroll.adjustment.value = 0;
         this._openSpaceForPopup();
@@ -1627,6 +1637,62 @@ var FolderIcon = class FolderIcon {
         this._popupInvalidated = false;
     }
 
+    _removeMenuTimeout() {
+        if (this._popupTimeoutId > 0) {
+            Mainloop.source_remove(this._popupTimeoutId);
+            this._popupTimeoutId = 0;
+        }
+    }
+
+    _setPopupTimeout() {
+        this._removeMenuTimeout();
+        this._popupTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT, () => {
+            this._popupTimeoutId = 0;
+            this._popupRenamePopup();
+            return GLib.SOURCE_REMOVE;
+        });
+        GLib.Source.set_name_by_id(this._popupTimeoutId,
+                                   '[gnome-shell] this._popupRenamePopup');
+    }
+
+    _onLeaveEvent(_actor, _event) {
+        this.actor.fake_release();
+        this._removeMenuTimeout();
+    }
+
+    _onButtonPress(_actor, event) {
+        let button = event.get_button();
+        if (button == 1) {
+            this._setPopupTimeout();
+        } else if (button == 3) {
+            this._popupRenamePopup();
+            return Clutter.EVENT_STOP;
+        }
+        return Clutter.EVENT_PROPAGATE;
+    }
+
+    _onTouchEvent(actor, event) {
+        if (event.type() == Clutter.EventType.TOUCH_BEGIN)
+            this._setPopupTimeout();
+
+        return Clutter.EVENT_PROPAGATE;
+    }
+
+    _popupRenamePopup() {
+        this._removeMenuTimeout();
+        this.actor.fake_release();
+
+        if (!this._renamePopup) {
+            this._renamePopup = new RenameFolderPopup(this,
+                                                      this._folder,
+                                                      this._parentView);
+            this._parentView.addFolderPopup(this._renamePopup);
+        }
+
+        this.actor.set_hover(true);
+        this._renamePopup.popup();
+    }
+
     adaptToSize(width, height) {
         this._parentAvailableWidth = width;
         this._parentAvailableHeight = height;
@@ -1637,11 +1703,112 @@ var FolderIcon = class FolderIcon {
 };
 Signals.addSignalMethods(FolderIcon.prototype);
 
-var RenameFolderPopup = GObject.registerClass(
-class RenameFolderPopup extends BoxPointer.BoxPointer {
-    _init(folder) {
+var RenameFolderPopup = class RenameFolderPopup {
+    constructor(source, folder, parentView) {
+        this.actor = new BoxPointer.BoxPointer(St.Side.BOTTOM, {
+            x_align: St.Align.START,
+        });
+        this.actor.style_class = 'popup-menu popup-menu-boxpointer';
+
+        this._source = source;
+        this._folder = folder;
+        this._parentView = parentView;
+
+        this._isOpen = false;
+
+        let box = new St.BoxLayout({ style_class: 'rename-folder-popup-box'});
+        this.actor.bin.set_child(box);
+
+        // Entry
+        this._entry = new St.Entry({
+            x_expand: true,
+            width: 200,
+        });
+        box.add_child(this._entry);
+
+        this._entry.clutter_text.connect('notify::text',
+                                         this._validate.bind(this));
+        this._entry.clutter_text.connect('activate',
+                                         this._updateFolderName.bind(this));
+
+        // Rename button
+        this._button = new St.Button({
+            style_class: 'button',
+            reactive: true,
+            button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
+            can_focus: true,
+            label: _("Rename"),
+        });
+        box.add_child(this._button);
+
+        this._button.connect('clicked', this._updateFolderName.bind(this));
+
+        this._grabHelper = new GrabHelper.GrabHelper(this.actor, {
+            actionMode: Shell.ActionMode.POPUP
+        });
+        this._grabHelper.addActor(Main.layoutManager.overviewGroup);
     }
-});
+
+    popup() {
+        if (this._isOpen)
+            return;
+
+        this._isOpen = this._grabHelper.grab({
+            actor: this.actor,
+            onUngrab: this.popdown.bind(this),
+        });
+
+        if (!this._isOpen)
+            return;
+
+        this.actor.setPosition(this._source.actor, 0.5);
+
+        let folderName = _getFolderName(this._folder);
+
+        this._entry.text = folderName;
+        this._entry.clutter_text.set_selection(0, folderName.length);
+
+        this.actor.open(BoxPointer.PopupAnimation.FADE | BoxPointer.PopupAnimation.SLIDE);
+
+        this.emit('open-state-changed', true);
+    }
+
+    popdown() {
+        if (!this._isOpen)
+            return;
+
+        this._grabHelper.ungrab({ actor: this.actor });
+
+        this.actor.close(BoxPointer.PopupAnimation.FADE | BoxPointer.PopupAnimation.SLIDE);
+        this._isOpen = false;
+
+        this.emit('open-state-changed', false);
+    }
+
+    _validFolderName() {
+        let folderName = _getFolderName(this._folder);
+        let newFolderName = this._entry.text.trim();
+
+        return newFolderName.length > 0 && newFolderName != folderName;
+    }
+
+    _validate() {
+        let validName = this._validFolderName();
+
+        this._button.reactive = validName;
+    }
+
+    _updateFolderName() {
+        if (!this._validFolderName())
+            return;
+
+        let newFolderName = this._entry.text.trim();
+        this._folder.set_string('name', newFolderName);
+        this._folder.set_boolean('translate', false);
+        this.popdown();
+    }
+};
+Signals.addSignalMethods(RenameFolderPopup.prototype);
 
 var AppFolderPopup = class AppFolderPopup {
     constructor(source, side) {


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