2010-06-22 21:02:26 +00:00
|
|
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
|
2010-10-07 18:15:51 +00:00
|
|
|
const Clutter = imports.gi.Clutter;
|
2011-02-08 19:53:43 +00:00
|
|
|
const Gtk = imports.gi.Gtk;
|
2011-08-22 21:19:13 +00:00
|
|
|
const Signals = imports.signals;
|
2010-06-22 21:02:26 +00:00
|
|
|
const St = imports.gi.St;
|
2011-02-08 19:53:43 +00:00
|
|
|
|
2010-06-22 21:02:26 +00:00
|
|
|
const Lang = imports.lang;
|
|
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
|
|
|
|
function Button(menuAlignment) {
|
|
|
|
this._init(menuAlignment);
|
|
|
|
}
|
|
|
|
|
|
|
|
Button.prototype = {
|
|
|
|
_init: function(menuAlignment) {
|
|
|
|
this.actor = new St.Bin({ style_class: 'panel-button',
|
|
|
|
reactive: true,
|
2010-10-07 18:15:51 +00:00
|
|
|
can_focus: true,
|
2010-06-22 21:02:26 +00:00
|
|
|
x_fill: true,
|
|
|
|
y_fill: false,
|
|
|
|
track_hover: true });
|
|
|
|
this.actor._delegate = this;
|
|
|
|
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
2011-02-08 19:53:43 +00:00
|
|
|
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
|
2011-07-30 17:24:24 +00:00
|
|
|
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
|
|
|
|
this.menu.actor.add_style_class_name('panel-menu');
|
2010-06-22 21:02:26 +00:00
|
|
|
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
|
2011-02-08 19:53:43 +00:00
|
|
|
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
|
2011-08-28 03:44:04 +00:00
|
|
|
Main.uiGroup.add_actor(this.menu.actor);
|
2010-06-22 21:02:26 +00:00
|
|
|
this.menu.actor.hide();
|
|
|
|
},
|
|
|
|
|
|
|
|
_onButtonPress: function(actor, event) {
|
2011-04-02 16:35:03 +00:00
|
|
|
if (!this.menu.isOpen) {
|
|
|
|
// Setting the max-height won't do any good if the minimum height of the
|
|
|
|
// menu is higher then the screen; it's useful if part of the menu is
|
|
|
|
// scrollable so the minimum height is smaller than the natural height
|
2011-06-13 13:54:05 +00:00
|
|
|
let monitor = Main.layoutManager.primaryMonitor;
|
2011-04-02 16:35:03 +00:00
|
|
|
this.menu.actor.style = ('max-height: ' +
|
|
|
|
Math.round(monitor.height - Main.panel.actor.height) +
|
|
|
|
'px;');
|
|
|
|
}
|
2010-06-22 21:02:26 +00:00
|
|
|
this.menu.toggle();
|
|
|
|
},
|
|
|
|
|
2011-02-08 19:53:43 +00:00
|
|
|
_onSourceKeyPress: function(actor, event) {
|
2010-10-07 18:15:51 +00:00
|
|
|
let symbol = event.get_key_symbol();
|
|
|
|
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
|
|
|
|
this.menu.toggle();
|
|
|
|
return true;
|
2011-02-08 19:53:43 +00:00
|
|
|
} else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) {
|
|
|
|
this.menu.close();
|
|
|
|
return true;
|
2010-10-07 18:15:51 +00:00
|
|
|
} else if (symbol == Clutter.KEY_Down) {
|
|
|
|
if (!this.menu.isOpen)
|
|
|
|
this.menu.toggle();
|
2011-02-08 19:53:43 +00:00
|
|
|
this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false);
|
2010-10-07 18:15:51 +00:00
|
|
|
return true;
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
2011-02-08 19:53:43 +00:00
|
|
|
_onMenuKeyPress: function(actor, event) {
|
|
|
|
let symbol = event.get_key_symbol();
|
|
|
|
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
|
|
|
|
let focusManager = St.FocusManager.get_for_stage(global.stage);
|
|
|
|
let group = focusManager.get_group(this.actor);
|
|
|
|
if (group) {
|
|
|
|
let direction = (symbol == Clutter.KEY_Left) ? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
|
|
|
|
group.navigate_focus(this.actor, direction, false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
2010-06-22 21:02:26 +00:00
|
|
|
_onOpenStateChanged: function(menu, open) {
|
2010-11-03 17:30:08 +00:00
|
|
|
if (open)
|
2011-02-08 18:46:05 +00:00
|
|
|
this.actor.add_style_pseudo_class('active');
|
2010-11-03 17:30:08 +00:00
|
|
|
else
|
2011-02-08 18:46:05 +00:00
|
|
|
this.actor.remove_style_pseudo_class('active');
|
2011-08-22 21:19:13 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function() {
|
|
|
|
this.actor._delegate = null;
|
|
|
|
|
|
|
|
this.menu.destroy();
|
|
|
|
this.actor.destroy();
|
|
|
|
|
|
|
|
this.emit('destroy');
|
2010-06-22 21:02:26 +00:00
|
|
|
}
|
2010-06-22 21:06:17 +00:00
|
|
|
};
|
2011-08-22 21:19:13 +00:00
|
|
|
Signals.addSignalMethods(Button.prototype);
|
2010-06-22 21:06:17 +00:00
|
|
|
|
|
|
|
/* SystemStatusButton:
|
|
|
|
*
|
|
|
|
* This class manages one System Status indicator (network, keyboard,
|
|
|
|
* volume, bluetooth...), which is just a PanelMenuButton with an
|
|
|
|
* icon and a tooltip
|
|
|
|
*/
|
|
|
|
function SystemStatusButton() {
|
|
|
|
this._init.apply(this, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
SystemStatusButton.prototype = {
|
|
|
|
__proto__: Button.prototype,
|
|
|
|
|
|
|
|
_init: function(iconName,tooltipText) {
|
2011-02-09 17:27:00 +00:00
|
|
|
Button.prototype._init.call(this, 0.0);
|
2010-09-26 15:18:26 +00:00
|
|
|
this._iconActor = new St.Icon({ icon_name: iconName,
|
|
|
|
icon_type: St.IconType.SYMBOLIC,
|
|
|
|
style_class: 'system-status-icon' });
|
|
|
|
this.actor.set_child(this._iconActor);
|
2010-06-22 21:06:17 +00:00
|
|
|
this.setTooltip(tooltipText);
|
|
|
|
},
|
|
|
|
|
|
|
|
setIcon: function(iconName) {
|
2010-09-26 15:18:26 +00:00
|
|
|
this._iconActor.icon_name = iconName;
|
|
|
|
},
|
|
|
|
|
|
|
|
setGIcon: function(gicon) {
|
|
|
|
this._iconActor.gicon = gicon;
|
2010-06-22 21:06:17 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
setTooltip: function(text) {
|
|
|
|
if (text != null) {
|
|
|
|
this.tooltip = text;
|
|
|
|
this.actor.has_tooltip = true;
|
|
|
|
this.actor.tooltip_text = text;
|
|
|
|
} else {
|
|
|
|
this.actor.has_tooltip = false;
|
|
|
|
this.tooltip = null;
|
|
|
|
}
|
|
|
|
}
|
2010-09-26 15:18:26 +00:00
|
|
|
};
|