[gnome-shell] popupMenu: add alternate menu item



commit 610c2b59872029bceb0279b24dc9637a85f54968
Author: Ray Strode <rstrode redhat com>
Date:   Mon Feb 21 15:25:56 2011 -0500

    popupMenu: add alternate menu item
    
    This is special menu item that can alternate
    between two choices when you hit the alt key.
    
    It will be useful for getting a hybrid
    suspend/power off menu item.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=636680

 data/theme/gnome-shell.css |    4 ++
 js/ui/popupMenu.js         |  101 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+), 0 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 7476390..248bb0c 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -140,6 +140,10 @@ StTooltip StLabel {
     height: 1em;
 }
 
+.popup-alternating-menu-item:alternate {
+    font-weight: bold;
+}
+
 .popup-slider-menu-item {
     height: 1em;
     min-width: 15em;
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index 00cc020..0a26ba7 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -328,6 +328,107 @@ PopupSeparatorMenuItem.prototype = {
     }
 };
 
+const PopupAlternatingMenuItemState = {
+    DEFAULT: 0,
+    ALTERNATIVE: 1
+}
+
+function PopupAlternatingMenuItem() {
+    this._init.apply(this, arguments);
+}
+
+PopupAlternatingMenuItem.prototype = {
+    __proto__: PopupBaseMenuItem.prototype,
+
+    _init: function(text, alternateText, params) {
+        PopupBaseMenuItem.prototype._init.call(this, params);
+        this.actor.add_style_class_name('popup-alternating-menu-item');
+
+        this._text = text;
+        this._alternateText = alternateText;
+        this.label = new St.Label({ text: text });
+        this.state = PopupAlternatingMenuItemState.DEFAULT;
+        this.addActor(this.label);
+
+        this.actor.connect('notify::mapped', Lang.bind(this, this._onMapped));
+    },
+
+    _onMapped: function() {
+        if (this.actor.mapped) {
+            this._capturedEventId = global.stage.connect('captured-event',
+                                                         Lang.bind(this, this._onCapturedEvent));
+            this._updateStateFromModifiers();
+        } else {
+            if (this._capturedEventId != 0) {
+                global.stage.disconnect(this._capturedEventId);
+                this._capturedEventId = 0;
+            }
+        }
+    },
+
+    _setState: function(state) {
+        if (this.state != state) {
+            if (state == PopupAlternatingMenuItemState.ALTERNATIVE && !this._canAlternate())
+                return;
+
+            this.state = state;
+            this._updateLabel();
+        }
+    },
+
+    _updateStateFromModifiers: function() {
+        let [x, y, mods] = global.get_pointer();
+        let state;
+
+        if ((mods & Clutter.ModifierType.MOD1_MASK) == 0) {
+            state = PopupAlternatingMenuItemState.DEFAULT;
+        } else {
+            state = PopupAlternatingMenuItemState.ALTERNATIVE;
+        }
+
+        this._setState(state);
+    },
+
+    _onCapturedEvent: function(actor, event) {
+        if (event.type() != Clutter.EventType.KEY_PRESS &&
+            event.type() != Clutter.EventType.KEY_RELEASE)
+            return false;
+
+        let key = event.get_key_symbol();
+
+        if (key == Clutter.KEY_Alt_L || key == Clutter.KEY_Alt_R)
+            this._updateStateFromModifiers();
+
+        return false;
+    },
+
+    _updateLabel: function() {
+        if (this.state == PopupAlternatingMenuItemState.ALTERNATIVE) {
+            this.actor.add_style_pseudo_class('alternate');
+            this.label.set_text(this._alternateText);
+        } else {
+            this.actor.remove_style_pseudo_class('alternate');
+            this.label.set_text(this._text);
+        }
+    },
+
+    _canAlternate: function() {
+        if (this.state == PopupAlternatingMenuItemState.DEFAULT && !this._alternateText)
+            return false;
+        return true;
+    },
+
+    updateText: function(text, alternateText) {
+        this._text = text;
+        this._alternateText = alternateText;
+
+        if (!this._canAlternate())
+            this._setState(PopupAlternatingMenuItemState.DEFAULT);
+
+        this._updateLabel();
+    }
+};
+
 function PopupSliderMenuItem() {
     this._init.apply(this, arguments);
 }



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