tianbar-0.4.7.0: scripts/power.js
/*
* A plugin to show the power (e.g. battery) state through UPower.
*
* Requires 'jquery' and 'moment' to be available through RequireJS.
*/
define(['jquery', 'moment', './dbus'], function ($, moment, dbus) {
"use strict";
var self = {};
self.HOUR = 3600;
self.TERMINAL_HEIGHT = 6;
self.HEIGHT = 8;
self.WIDTH = 25;
self.FILL_COLOR = null;
self.FILL_LOW_COLOR = 'red';
self.EMPTY_COLOR = 'transparent';
self.SEGMENT_COLOR = '#888';
self.OUTLINE_COLOR = null;
self.DEFAULT_TIME = 4 * self.HOUR;
self.LOW_TIME = self.HOUR / 4;
self.DEVICE_STATE = {
Unknown: 0,
Charging: 1,
Discharging: 2,
Empty: 3,
FullyCharged: 4,
PendingCharge: 5,
PendingDischarge: 6
};
self.DEVICE_TYPE = {
Unknown: 0,
LinePower: 1,
Battery: 2,
UPS: 3,
Monitor: 4,
Mouse: 5,
Keyboard: 6,
PDA: 7,
Phone: 8
};
self.widget = function () {
return $('.widget-power');
};
self.fill_color = function () {
return self.FILL_COLOR || self.widget().css('color');
};
self.outline_color = function () {
return self.OUTLINE_COLOR || self.widget().css('color');
};
self.block = function (width, color, border, leftBorder) {
var result = $('<div />');
result.css({
'display': 'inline-block',
'background-color': color,
'width': width - (border ? 1 : 0),
'height': self.HEIGHT,
'border-top': '1px solid',
'border-bottom': '1px solid',
'border-color': self.outline_color(),
'margin-top': -1,
'margin-bottom': -1
});
if (border) {
result.css({
'padding-right': -1,
'border-right-width': '1px',
'border-right-style': 'solid',
'border-right-color': border,
});
}
if (leftBorder) {
result.css({
'border-left-width': '1px',
'border-left-style': 'solid',
'border-left-color': leftBorder,
});
}
return result;
};
/**
* Format an HTML element displaying the device status.
* @param st {Object} The device status, as returned by UPower
*/
self.formatDevice = function (st) {
if (st.Type == self.DEVICE_TYPE.LinePower) {
return '';
}
var percentage = st.Percentage;
var displayPercentage = percentage;
if (st.State == self.DEVICE_STATE.FullyCharged) {
displayPercentage = 100;
}
var timeToEmpty = st.TimeToEmpty;
var timeToFull = st.TimeToFull;
var haveTTE = timeToEmpty !== 0;
var haveTTF = timeToFull !== 0;
// Sanity checks if one or the other time is missing
if (haveTTE && !haveTTF) {
if (displayPercentage > 0) {
timeToFull = timeToEmpty *
(100 - displayPercentage) / displayPercentage;
} else {
timeToFull = self.DEFAULT_TIME;
}
} else if (haveTTF && !haveTTE) {
if (displayPercentage < 100) {
timeToEmpty = timeToFull *
displayPercentage / (100 - displayPercentage);
} else {
timeToFull = self.DEFAULT_TIME;
}
} else if (!haveTTF && !haveTTE) {
timeToEmpty = self.DEFAULT_TIME * displayPercentage;
timeToFull = self.DEFAULT_TIME * (100 - displayPercentage);
}
var hour_width = self.WIDTH * self.HOUR / (timeToEmpty + timeToFull);
var result = $('<div />').css({
'display': 'inline-block'
});
var fillColor = timeToEmpty > self.LOW_TIME ?
self.fill_color() : self.FILL_LOW_COLOR;
var firstSegment = true;
if (haveTTE) {
for (; timeToEmpty > self.HOUR; timeToEmpty -= self.HOUR) {
result.append(self.block(
hour_width,
fillColor,
self.SEGMENT_COLOR,
firstSegment ? self.outline_color() : null
));
firstSegment = false;
}
}
result.append(self.block(
timeToEmpty / self.HOUR * hour_width,
fillColor,
null,
firstSegment ? self.outline_color() : null
));
if (haveTTF) {
for (; timeToFull > self.HOUR; timeToFull -= self.HOUR) {
result.append(self.block(
hour_width,
self.EMPTY_COLOR,
self.SEGMENT_COLOR
));
}
}
result.append(self.block(
timeToFull / self.HOUR * hour_width,
self.EMPTY_COLOR,
self.OUTLINE_COLOR
));
result.append($('<span>').css({
'display': 'inline-block',
'background-color': self.outline_color(),
'width': 1,
'height': self.TERMINAL_HEIGHT,
'margin-top': (self.HEIGHT - self.TERMINAL_HEIGHT) / 2,
'margin-bottom': (self.HEIGHT - self.TERMINAL_HEIGHT) / 2
}));
var title;
if (st.State === self.DEVICE_STATE.FullyCharged) {
title = '';
} else {
title = percentage + '%';
if (st.TimeToEmpty !== 0) {
title += ' (' + moment.duration(st.TimeToEmpty, 's').humanize() + ')';
}
}
if (st.Type != self.DEVICE_TYPE.Battery) {
title += '\n' + st.Vendor + ' ' + st.Model;
}
title = title.trim();
result.attr('title', title);
if (st.State === self.DEVICE_STATE.Charging) {
result.append('⚡');
}
return result;
};
self.updated = $.Callbacks();
// A map of device paths to device states
self.devices = {};
// Display the status of all the devices
self.display = function () {
// TODO: support updating individual devices
var widget = self.widget();
widget.empty();
$.each(self.devices, function (_, device) {
widget.append(self.formatDevice(device));
});
self.updated.fire();
};
// Refresh the device list and each device status
self.refresh = function () {
dbus.system.call({
'destination': 'org.freedesktop.UPower',
'path': '/org/freedesktop/UPower',
'iface': 'org.freedesktop.UPower',
'member': 'EnumerateDevices',
'body': [
]
}).done(function (devices) {
devices = devices.body[0];
// TODO: support device add and removal
$.each(devices, function(_, device) {
dbus.system.listen(
{ path: device }
).add(function() {
self.refreshDevice(device);
}
);
self.refreshDevice(device);
});
});
};
// Refresh an individual device
self.refreshDevice = function (device) {
dbus.system.call({
'destination': 'org.freedesktop.UPower',
'path': device,
'iface': 'org.freedesktop.DBus.Properties',
'member': 'GetAll',
'body': [
'string:org.freedesktop.UPower.Device',
]
}).done(function (properties) {
properties = properties.body[0];
self.devices[device] = properties;
self.display();
});
};
$(document).ready(function () {
dbus.system.listen(
{ path: '/org/freedesktop/UPower' }
).add(self.refresh);
self.refresh();
});
return self;
});