[gnome-shell] popupMenu: Create and insert menu items that don't have actions yet



commit c0afe7260a5882763d7b25d9b2b206528ccb866f
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Apr 19 21:27:15 2013 -0400

    popupMenu: Create and insert menu items that don't have actions yet
    
    Instead of recreating the entire model, which can be expensive... but
    keep them insensitive for now. This also matches what GTK+ does.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=698427

 js/ui/popupMenu.js |  137 ++++++++++++++++++++++++++++------------------------
 1 files changed, 73 insertions(+), 64 deletions(-)
---
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index b9d6e83..11c3ab5 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -1820,39 +1820,8 @@ const RemoteMenu = new Lang.Class({
         this.parent();
     },
 
-    _createMenuItem: function(model, index) {
-        let labelValue = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null);
-        let label = labelValue ? labelValue.deep_unpack() : '';
-        // remove all underscores that are not followed by another underscore
-        label = label.replace(/_([^_])/, '$1');
-
-        let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION);
-        if (section_link) {
-            let item = new PopupMenuSection();
-            if (label) {
-                let title = new PopupMenuItem(label, { reactive: false,
-                                                       style_class: 'popup-subtitle-menu-item' });
-                item._titleMenuItem = title;
-                title._ignored = true;
-                item.addMenuItem(title);
-            }
-            this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item);
-            return [item, true, ''];
-        }
-
-        let submenu_link = model.get_item_link(index, Gio.MENU_LINK_SUBMENU);
-
-        if (submenu_link) {
-            let item = new PopupSubMenuMenuItem(label);
-            this._modelChanged(submenu_link, 0, 0, submenu_link.get_n_items(), item.menu);
-            return [item, false, ''];
-        }
-
-        let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack();
-        if (!this.actionGroup.has_action(action_id)) {
-            // the action may not be there yet, wait for action-added
-            return [null, false, 'action-added'];
-        }
+    _actionAdded: function(model, item, index) {
+        let action_id = item.action_id;
 
         if (!this._actions[action_id])
             this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id),
@@ -1862,8 +1831,6 @@ const RemoteMenu = new Lang.Class({
         let action = this._actions[action_id];
         let target, destroyId, specificSignalId;
 
-        let item = new PopupMenuItem(label);
-
         if (action.state) {
             // Docs have get_state_hint(), except that the DBus protocol
             // has no provision for it (so ShellApp does not implement it,
@@ -1891,7 +1858,7 @@ const RemoteMenu = new Lang.Class({
                 break;
             default:
                 log('Action "%s" has state of type %s, which is not supported'.format(action_id, 
action.state.get_type_string()));
-                return [null, false, 'action-state-changed'];
+                return [null, false];
             }
         } else {
             target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null);
@@ -1912,8 +1879,57 @@ const RemoteMenu = new Lang.Class({
                 action.items.splice(pos, 1);
         }));
 
-        return [item, false, ''];
-    }, 
+        return [item, false];
+    },
+
+    _createMenuItem: function(model, index) {
+        let labelValue = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null);
+        let label = labelValue ? labelValue.deep_unpack() : '';
+        // remove all underscores that are not followed by another underscore
+        label = label.replace(/_([^_])/, '$1');
+
+        let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION);
+        if (section_link) {
+            let item = new PopupMenuSection();
+            if (label) {
+                let title = new PopupMenuItem(label, { reactive: false,
+                                                       style_class: 'popup-subtitle-menu-item' });
+                item._titleMenuItem = title;
+                title._ignored = true;
+                item.addMenuItem(title);
+            }
+            this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item);
+            return [item, true];
+        }
+
+        let submenu_link = model.get_item_link(index, Gio.MENU_LINK_SUBMENU);
+
+        if (submenu_link) {
+            let item = new PopupSubMenuMenuItem(label);
+            this._modelChanged(submenu_link, 0, 0, submenu_link.get_n_items(), item.menu);
+            return [item, false];
+        }
+
+        let item = new PopupMenuItem(label);
+        let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack();
+        item.actor.can_focus = item.actor.reactive = false;
+
+        item.action_id = action_id;
+
+        if (this.actionGroup.has_action(action_id)) {
+            this._actionAdded(model, item, index);
+            return [item, false];
+        }
+
+        let signalId = this.actionGroup.connect('action-added', Lang.bind(this, function(actionGroup, 
actionName) {
+            actionGroup.disconnect(signalId);
+            if (this._actions[actionName]) return;
+
+            this._actionAdded(model, item, index);
+        }));
+
+        return [item, false];
+    },
 
     _modelChanged: function(model, position, removed, added, target) {
         let j, k;
@@ -1945,35 +1961,28 @@ const RemoteMenu = new Lang.Class({
         }
 
         for (j = j0, k = k0; j < j0 + added; j++, k++) {
-            let [item, addSeparator, changeSignal] = this._createMenuItem(model, j);
-
-            if (item) {
-                // separators must be added in the parent to make autohiding work
-                if (addSeparator) {
-                    let separator = new PopupSeparatorMenuItem();
-                    item.separators.push(separator);
-                    separator._ignored = true;
-                    target.addMenuItem(separator, k+1);
-                    k++;
-                }
+            let [item, addSeparator] = this._createMenuItem(model, j);
 
-                target.addMenuItem(item, k);
+            if (!item)
+                continue;
 
-                if (addSeparator) {
-                    let separator = new PopupSeparatorMenuItem();
-                    item.separators.push(separator);
-                    separator._ignored = true;
-                    target.addMenuItem(separator, k+1);
-                    k++;
-                }
-            } else if (changeSignal) {
-                let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function(actionGroup, 
actionName) {
-                    actionGroup.disconnect(signalId);
-                    if (this._actions[actionName]) return;
+            // separators must be added in the parent to make autohiding work
+            if (addSeparator) {
+                let separator = new PopupSeparatorMenuItem();
+                item.separators.push(separator);
+                separator._ignored = true;
+                target.addMenuItem(separator, k+1);
+                k++;
+            }
 
-                    // force a full update
-                    this._modelChanged(model, 0, -1, model.get_n_items(), target);
-                }));
+            target.addMenuItem(item, k);
+
+            if (addSeparator) {
+                let separator = new PopupSeparatorMenuItem();
+                item.separators.push(separator);
+                separator._ignored = true;
+                target.addMenuItem(separator, k+1);
+                k++;
             }
         }
 


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