[gnome-shell] status/network: Add NMSectionItem subclass



commit ad1a32749eea154aac789d53363dd2410b8482e4
Author: Florian Müllner <fmuellner gnome org>
Date:   Tue Aug 2 14:04:46 2022 +0200

    status/network: Add NMSectionItem subclass
    
    The class implements a menu item that contains a section which
    can be collapsed into a submenu.
    
    It is very common for network devices to only have one associated
    connection, so hiding away a single item in a submenu is fairly
    inconvenient.
    
    This class will address this, by only using a submenu when it is
    actually needed.
    
    Although the main issue it addresses is that menus (including
    sections) aren't GObjects. This gives us a GObject that can
    be added to a menu, and that can itself contain other menu
    items.
    
    Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2407>

 js/ui/status/network.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)
---
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index 394fd074e7..4d5f737888 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -200,6 +200,78 @@ const NMMenuItem = GObject.registerClass({
     }
 });
 
+/**
+ * Item that contains a section, and can be collapsed
+ * into a submenu
+ */
+const NMSectionItem = GObject.registerClass({
+    Properties: {
+        'use-submenu': GObject.ParamSpec.boolean('use-submenu', '', '',
+            GObject.ParamFlags.READWRITE,
+            false),
+    },
+}, class NMSectionItem extends NMMenuItem {
+    constructor() {
+        super({
+            activate: false,
+            can_focus: false,
+        });
+
+        this._useSubmenu = false;
+
+        // Turn into an empty container with no padding
+        this.styleClass = '';
+        this.setOrnament(PopupMenu.Ornament.HIDDEN);
+
+        // Add intermediate section; we need this for submenu support
+        this._mainSection = new PopupMenu.PopupMenuSection();
+        this.add_child(this._mainSection.actor);
+
+        this._submenuItem = new PopupMenu.PopupSubMenuMenuItem('', true);
+        this._mainSection.addMenuItem(this._submenuItem);
+        this._submenuItem.hide();
+
+        this.section = new PopupMenu.PopupMenuSection();
+        this._mainSection.addMenuItem(this.section);
+
+        // Represents the item as a whole when shown
+        this.bind_property('name',
+            this._submenuItem.label, 'text',
+            GObject.BindingFlags.DEFAULT);
+        this.bind_property('icon-name',
+            this._submenuItem.icon, 'icon-name',
+            GObject.BindingFlags.DEFAULT);
+    }
+
+    _setParent(parent) {
+        super._setParent(parent);
+        this._mainSection._setParent(parent);
+
+        parent?.connect('menu-closed',
+            () => this._mainSection.emit('menu-closed'));
+    }
+
+    get use_submenu() {
+        return this._useSubmenu;
+    }
+
+    set use_submenu(useSubmenu) {
+        if (this._useSubmenu === useSubmenu)
+            return;
+
+        this._useSubmenu = useSubmenu;
+        this._submenuItem.visible = useSubmenu;
+
+        if (useSubmenu) {
+            this._mainSection.box.remove_child(this.section.actor);
+            this._submenuItem.menu.box.add_child(this.section.actor);
+        } else {
+            this._submenuItem.menu.box.remove_child(this.section.actor);
+            this._mainSection.box.add_child(this.section.actor);
+        }
+    }
+});
+
 const NMConnectionItem = GObject.registerClass(
 class NMConnectionItem extends NMMenuItem {
     constructor(section, connection) {


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