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
This commit is contained in:
Ray Strode 2011-02-21 15:25:56 -05:00
parent 3c66455112
commit 610c2b5987
2 changed files with 105 additions and 0 deletions

View File

@ -140,6 +140,10 @@ StTooltip StLabel {
height: 1em; height: 1em;
} }
.popup-alternating-menu-item:alternate {
font-weight: bold;
}
.popup-slider-menu-item { .popup-slider-menu-item {
height: 1em; height: 1em;
min-width: 15em; min-width: 15em;

View File

@ -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() { function PopupSliderMenuItem() {
this._init.apply(this, arguments); this._init.apply(this, arguments);
} }