power: Implement new power menu design

This is a part of the new system status design, see
https://wiki.gnome.org/GnomeShell/Design/Guidelines/SystemStatus/
for design details.

https://bugzilla.gnome.org/show_bug.cgi?id=704368
This commit is contained in:
Jasper St. Pierre 2013-05-22 14:19:00 -04:00
parent 22c8be6645
commit 37a316e66c
2 changed files with 54 additions and 45 deletions

View File

@ -225,10 +225,6 @@ StScrollBar StButton#vhandle:active {
font-weight: bold; font-weight: bold;
} }
.popup-device-menu-item {
spacing: .5em;
}
.popup-status-menu-item { .popup-status-menu-item {
font-weight: normal; font-weight: normal;
color: #999; color: #999;
@ -247,10 +243,6 @@ StScrollBar StButton#vhandle:active {
icon-size: 1.09em; icon-size: 1.09em;
} }
.popup-battery-percentage {
padding-left: 24px;
}
/* Switches */ /* Switches */
.toggle-switch { .toggle-switch {
width: 65px; width: 65px;

View File

@ -2,9 +2,9 @@
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const St = imports.gi.St;
const UPower = imports.gi.UPowerGlib; const UPower = imports.gi.UPowerGlib;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
@ -37,51 +37,67 @@ const Indicator = new Lang.Class({
return; return;
} }
this._proxy.connect('g-properties-changed', this._proxy.connect('g-properties-changed',
Lang.bind(this, this._devicesChanged)); Lang.bind(this, this._sync));
this._devicesChanged(); this._sync();
})); }));
this.item = new PopupMenu.PopupMenuItem('', { reactive: false }); this._item = new PopupMenu.PopupSubMenuMenuItem(_("Battery"), true);
this._primaryPercentage = new St.Label({ style_class: 'popup-battery-percentage' }); this._item.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
this.item.addActor(this._primaryPercentage, { align: St.Align.END }); this.menu.addMenuItem(this._item);
this.menu.addMenuItem(this.item);
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._sessionUpdated();
}, },
_readPrimaryDevice: function() { _sessionUpdated: function() {
let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
this.menu.setSensitive(sensitive);
},
_statusForDevice: function(device) {
let [device_id, device_type, icon, percentage, state, seconds] = device;
if (state == UPower.DeviceState.FULLY_CHARGED)
return _("Fully Charged");
let time = Math.round(seconds / 60);
if (time == 0) {
// 0 is reported when UPower does not have enough data
// to estimate battery life
return _("Estimating…");
}
let minutes = time % 60;
let hours = Math.floor(time / 60);
if (state == UPower.DeviceState.DISCHARGING) {
// Translators: this is <hours>:<minutes> Remaining (<percentage>)
return _("%d\u2236%d Remaining (%d%%)".format(hours, minutes, percentage));
}
if (state == UPower.DeviceState.CHARGING) {
// Translators: this is <hours>:<minutes> Until Full (<percentage>)
return _("%d\u2236%d Until Full (%d%%)".format(hours, minutes, percentage));
}
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
return _("Estimating…");
},
_syncStatusLabel: function() {
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) { this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
if (error) { if (error) {
this.item.actor.hide(); this._item.actor.hide();
return; return;
} }
let [[device_id, device_type, icon, percentage, state, seconds]] = result; let [device] = result;
let [device_id, device_type] = device;
if (device_type == UPower.DeviceKind.BATTERY) { if (device_type == UPower.DeviceKind.BATTERY) {
let time = Math.round(seconds / 60); this._item.status.text = this._statusForDevice(device);
if (time == 0) { this._item.actor.show();
// 0 is reported when UPower does not have enough data
// to estimate battery life
this.item.label.text = _("Estimating…");
} else {
let minutes = time % 60;
let hours = Math.floor(time / 60);
let timestring;
if (time >= 60) {
if (minutes == 0) {
timestring = ngettext("%d hour remaining", "%d hours remaining", hours).format(hours);
} else {
/* TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining" */
let template = _("%d %s %d %s remaining");
timestring = template.format (hours, ngettext("hour", "hours", hours), minutes, ngettext("minute", "minutes", minutes));
}
} else
timestring = ngettext("%d minute remaining", "%d minutes remaining", minutes).format(minutes);
this.item.label.text = timestring;
}
this._primaryPercentage.text = C_("percent of battery remaining", "%d%%").format(Math.round(percentage));
this.item.actor.show();
} else { } else {
this.item.actor.hide(); this._item.actor.hide();
} }
})); }));
}, },
@ -93,14 +109,15 @@ const Indicator = new Lang.Class({
if (icon) { if (icon) {
let gicon = Gio.icon_new_for_string(icon); let gicon = Gio.icon_new_for_string(icon);
this.setGIcon(gicon); this.setGIcon(gicon);
this._item.icon.gicon = gicon;
hasIcon = true; hasIcon = true;
} }
this.mainIcon.visible = hasIcon; this.mainIcon.visible = hasIcon;
this.actor.visible = hasIcon; this.actor.visible = hasIcon;
}, },
_devicesChanged: function() { _sync: function() {
this._syncIcon(); this._syncIcon();
this._readPrimaryDevice(); this._syncStatusLabel();
} }
}); });