dotfiles/.local/share/gnome-shell/extensions/trayIconsReloaded@selfmade.pl/TrayIndicator.js

193 lines
4.8 KiB
JavaScript

const { GObject, Clutter, St, GLib } = imports.gi;
const { panelMenu, popupMenu } = imports.ui;
const { getCurrentExtension, getSettings } = imports.misc.extensionUtils;
const AppManager = getCurrentExtension().imports.AppManager;
var TrayIndicator = GObject.registerClass(
class TrayIndicator extends panelMenu.Button {
_init() {
this._icons = [];
super._init(0.0, null, false);
this._overflow = false;
this._indicators = new St.BoxLayout();
this.add_child(this._indicators);
this._icon = new St.Icon({
icon_name: "view-more-horizontal",
style_class: "system-status-icon",
reactive: true,
track_hover: true,
});
this._indicators.add_child(this._icon);
this._menuItem = new popupMenu.PopupBaseMenuItem({
reactive: false,
can_focus: true,
});
this.menu.addMenuItem(this._menuItem);
this.menu.actor.add_style_class_name("TrayIndicatorPopup");
this.hide();
}
get size() {
const context = St.ThemeContext.get_for_stage(global.stage);
return this._size * context.scale_factor;
}
setSize(size, margin, padding) {
this._size = size;
this._margin = margin;
this._padding = padding;
this._icons.forEach((icon) => {
icon.get_parent().style = this._getButtonStyle();
icon.set_size(this._size, this._size);
});
}
addIcon(icon) {
const isHidden = AppManager.getAppSetting(icon, "hidden");
if (isHidden) return;
const button = new St.Button({
child: icon,
button_mask:
St.ButtonMask.ONE | St.ButtonMask.TWO | St.ButtonMask.THREE,
style: this._getButtonStyle(),
style_class: "panel-button",
});
icon.opacity = 0;
icon.set_x_align(Clutter.ActorAlign.CENTER);
icon.set_y_align(Clutter.ActorAlign.CENTER);
icon.inOverflow = this._overflow;
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
icon.set_size(this.size, this.size);
icon.ease({
opacity: 255,
duration: 400,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
this._addEffectIcon(icon);
return GLib.SOURCE_REMOVE;
});
icon.connect("destroy", () => {
button.destroy();
});
button.connect("button-release-event", (actor, event) => {
switch (event.get_button()) {
case 1:
AppManager.leftClick(icon, event);
break;
case 2:
AppManager.middleClick(icon, event);
break;
case 3:
icon.click(event);
break;
}
if (AppManager.isWine(icon)) {
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1, () => {
this.menu.close();
return GLib.SOURCE_REMOVE;
});
} else {
this.menu.close();
}
});
this._icons.push(icon);
if (this._overflow) {
this._menuItem.actor.add(button);
} else {
this._indicators.insert_child_at_index(button, 0);
}
this.checkOverflow();
}
removeIcon(icon, ignoreCheckOverflow) {
const index = this._icons.indexOf(icon);
this._icons.splice(index, 1);
const actor = icon.get_parent();
actor.remove_actor(icon);
actor.destroy();
if (!ignoreCheckOverflow) {
this.checkOverflow();
}
}
checkOverflow() {
if (this._icons.length >= getSettings().get_int("icons-limit")) {
this._overflow = true;
this._icon.visible = true;
this.reactive = true;
this.style_class = "panel-button TrayIndicator";
} else {
this._overflow = false;
this._icon.visible = false;
this.reactive = false;
this.style_class = "TrayIndicator";
}
if (this._icons.length) {
this.show();
} else {
this.hide();
}
this._refreshIcons(this._overflow);
}
_refreshIcons(overflow) {
this._icons.forEach((icon) => {
if (icon.inOverflow != overflow) {
this.removeIcon(icon, true);
this.addIcon(icon);
}
});
}
_getButtonStyle() {
let style;
if (!this._overflow) {
style = `margin: ${this._margin.vertical}px ${this._margin.horizontal}px; padding: ${this._padding.vertical}px ${this._padding.horizontal}px`;
}
return `width: ${this.size}px; height: ${this.size}px;${style}`;
}
_addEffectIcon(icon) {
let brightnessContrast = new Clutter.BrightnessContrastEffect({});
brightnessContrast.set_contrast(
getSettings().get_int("icon-contrast") / 100
);
brightnessContrast.set_brightness(
getSettings().get_int("icon-brightness") / 100
);
icon.add_effect_with_name("brightnessContrast", brightnessContrast);
icon.add_effect_with_name(
"desaturate",
new Clutter.DesaturateEffect({
factor: getSettings().get_int("icon-saturation") / 100,
})
);
}
setEffect(contrast, saturation, brightness) {
this._icons.forEach((icon) => {
let brightnessContrast = icon.get_effect("brightnessContrast");
brightnessContrast.set_contrast(contrast / 100);
brightnessContrast.set_brightness(brightness / 100);
let desaturate = icon.get_effect("desaturate");
desaturate.set_factor(saturation / 100);
});
}
}
);