bacfdbbb03
ES6 finally adds standard class syntax to the language, so we can replace our custom Lang.Class framework with the new syntax. Any classes that inherit from GObject will need special treatment, so limit the port to regular javascript classes for now. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/361
207 lines
8.6 KiB
JavaScript
207 lines
8.6 KiB
JavaScript
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
const Atk = imports.gi.Atk;
|
|
const Cairo = imports.cairo;
|
|
const Clutter = imports.gi.Clutter;
|
|
const St = imports.gi.St;
|
|
const Signals = imports.signals;
|
|
|
|
var BarLevel = class {
|
|
constructor(value, params) {
|
|
if (isNaN(value))
|
|
// Avoid spreading NaNs around
|
|
throw TypeError('The bar level value must be a number');
|
|
this._maxValue = 1;
|
|
this._value = Math.max(Math.min(value, this._maxValue), 0);
|
|
this._overdriveStart = 1;
|
|
this._barLevelWidth = 0;
|
|
|
|
if (params == undefined)
|
|
params = {}
|
|
|
|
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
|
|
can_focus: params['canFocus'] || false,
|
|
reactive: params['reactive'] || false,
|
|
accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR });
|
|
this.actor.connect('repaint', this._barLevelRepaint.bind(this));
|
|
this.actor.connect('allocation-changed', (actor, box) => {
|
|
this._barLevelWidth = box.get_width();
|
|
});
|
|
|
|
this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
|
|
this.actor.set_accessible(this._customAccessible);
|
|
|
|
this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this));
|
|
this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this));
|
|
this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this));
|
|
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
|
|
|
|
this.connect('value-changed', this._valueChanged.bind(this));
|
|
}
|
|
|
|
setValue(value) {
|
|
if (isNaN(value))
|
|
throw TypeError('The bar level value must be a number');
|
|
|
|
this._value = Math.max(Math.min(value, this._maxValue), 0);
|
|
this.actor.queue_repaint();
|
|
}
|
|
|
|
setMaximumValue(value) {
|
|
if (isNaN(value))
|
|
throw TypeError('The bar level max value must be a number');
|
|
|
|
this._maxValue = Math.max(value, 1);
|
|
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
|
|
this.actor.queue_repaint();
|
|
}
|
|
|
|
setOverdriveStart(value) {
|
|
if (isNaN(value))
|
|
throw TypeError('The overdrive limit value must be a number');
|
|
if (value > this._maxValue)
|
|
throw new Error(`Tried to set overdrive value to ${value}, ` +
|
|
`which is a number greater than the maximum allowed value ${this._maxValue}`);
|
|
|
|
this._overdriveStart = value;
|
|
this._value = Math.max(Math.min(value, this._maxValue), 0);
|
|
this.actor.queue_repaint();
|
|
}
|
|
|
|
_barLevelRepaint(area) {
|
|
let cr = area.get_context();
|
|
let themeNode = area.get_theme_node();
|
|
let [width, height] = area.get_surface_size();
|
|
|
|
let barLevelHeight = themeNode.get_length('-barlevel-height');
|
|
let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2;
|
|
let fgColor = themeNode.get_foreground_color();
|
|
|
|
let barLevelColor = themeNode.get_color('-barlevel-background-color');
|
|
let barLevelActiveColor = themeNode.get_color('-barlevel-active-background-color');
|
|
let barLevelOverdriveColor = themeNode.get_color('-barlevel-overdrive-color');
|
|
|
|
let barLevelBorderWidth = Math.min(themeNode.get_length('-barlevel-border-width'), 1);
|
|
let [hasBorderColor, barLevelBorderColor] =
|
|
themeNode.lookup_color('-barlevel-border-color', false);
|
|
if (!hasBorderColor)
|
|
barLevelBorderColor = barLevelColor;
|
|
let [hasActiveBorderColor, barLevelActiveBorderColor] =
|
|
themeNode.lookup_color('-barlevel-active-border-color', false);
|
|
if (!hasActiveBorderColor)
|
|
barLevelActiveBorderColor = barLevelActiveColor;
|
|
let [hasOverdriveBorderColor, barLevelOverdriveBorderColor] =
|
|
themeNode.lookup_color('-barlevel-overdrive-border-color', false);
|
|
if (!hasOverdriveBorderColor)
|
|
barLevelOverdriveBorderColor = barLevelOverdriveColor;
|
|
|
|
const TAU = Math.PI * 2;
|
|
|
|
let endX = 0;
|
|
if (this._maxValue > 0)
|
|
endX = barLevelBorderRadius + (width - 2 * barLevelBorderRadius) * this._value / this._maxValue;
|
|
|
|
let overdriveSeparatorX = barLevelBorderRadius + (width - 2 * barLevelBorderRadius) * this._overdriveStart / this._maxValue;
|
|
let overdriveActive = this._overdriveStart !== this._maxValue;
|
|
let overdriveSeparatorWidth = 0;
|
|
if (overdriveActive)
|
|
overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width');
|
|
|
|
/* background bar */
|
|
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
|
|
cr.lineTo(endX, (height + barLevelHeight) / 2);
|
|
cr.lineTo(endX, (height - barLevelHeight) / 2);
|
|
cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2);
|
|
Clutter.cairo_set_source_color(cr, barLevelColor);
|
|
cr.fillPreserve();
|
|
Clutter.cairo_set_source_color(cr, barLevelBorderColor);
|
|
cr.setLineWidth(barLevelBorderWidth);
|
|
cr.stroke();
|
|
|
|
/* normal progress bar */
|
|
let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2);
|
|
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 1 / 4, TAU * 3 / 4);
|
|
cr.lineTo(x, (height - barLevelHeight) / 2);
|
|
cr.lineTo(x, (height + barLevelHeight) / 2);
|
|
cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2);
|
|
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
|
|
cr.fillPreserve();
|
|
Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor);
|
|
cr.setLineWidth(barLevelBorderWidth);
|
|
cr.stroke();
|
|
|
|
/* overdrive progress barLevel */
|
|
x = Math.min(endX, overdriveSeparatorX) + overdriveSeparatorWidth / 2;
|
|
if (this._value > this._overdriveStart) {
|
|
cr.moveTo(x, (height - barLevelHeight) / 2);
|
|
cr.lineTo(endX, (height - barLevelHeight) / 2);
|
|
cr.lineTo(endX, (height + barLevelHeight) / 2);
|
|
cr.lineTo(x, (height + barLevelHeight) / 2);
|
|
cr.lineTo(x, (height - barLevelHeight) / 2);
|
|
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
|
|
cr.fillPreserve();
|
|
Clutter.cairo_set_source_color(cr, barLevelOverdriveBorderColor);
|
|
cr.setLineWidth(barLevelBorderWidth);
|
|
cr.stroke();
|
|
}
|
|
|
|
/* end progress bar arc */
|
|
if (this._value <= this._overdriveStart)
|
|
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
|
|
else
|
|
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
|
|
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
|
|
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
|
|
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
|
|
cr.lineTo(endX, (height - barLevelHeight) / 2);
|
|
cr.fillPreserve();
|
|
cr.setLineWidth(barLevelBorderWidth);
|
|
cr.stroke();
|
|
|
|
/* draw overdrive separator */
|
|
if (overdriveActive) {
|
|
cr.moveTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
|
|
cr.lineTo(overdriveSeparatorX + overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
|
|
cr.lineTo(overdriveSeparatorX + overdriveSeparatorWidth / 2, (height + barLevelHeight) / 2);
|
|
cr.lineTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height + barLevelHeight) / 2);
|
|
cr.lineTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
|
|
if (this._value <= this._overdriveStart)
|
|
Clutter.cairo_set_source_color(cr, fgColor);
|
|
else
|
|
Clutter.cairo_set_source_color(cr, barLevelColor);
|
|
cr.fill();
|
|
}
|
|
|
|
cr.$dispose();
|
|
}
|
|
|
|
_getCurrentValue(actor) {
|
|
return this._value;
|
|
}
|
|
|
|
_getOverdriveStart(actor) {
|
|
return this._overdriveStart;
|
|
}
|
|
|
|
_getMinimumValue(actor) {
|
|
return 0;
|
|
}
|
|
|
|
_getMaximumValue(actor) {
|
|
return this._maxValue;
|
|
}
|
|
|
|
_setCurrentValue(actor, value) {
|
|
this._value = value;
|
|
}
|
|
|
|
_valueChanged(barLevel, value, property) {
|
|
this._customAccessible.notify("accessible-value");
|
|
}
|
|
|
|
get value() {
|
|
return this._value;
|
|
}
|
|
};
|
|
Signals.addSignalMethods(BarLevel.prototype);
|