dot/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/shell/tooltip.js

307 lines
7.7 KiB
JavaScript

'use strict';
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
/**
* An StTooltip for ClutterActors
*
* Adapted from: https://github.com/RaphaelRochet/applications-overview-tooltip
* See also: https://github.com/GNOME/gtk/blob/master/gtk/gtktooltip.c
*/
var TOOLTIP_BROWSE_ID = 0;
var TOOLTIP_BROWSE_MODE = false;
var Tooltip = class Tooltip {
constructor(params) {
Object.assign(this, params);
this._hoverTimeoutId = 0;
this._showing = false;
this._destroyId = this.parent.connect(
'destroy',
this.destroy.bind(this)
);
this._hoverId = this.parent.connect(
'notify::hover',
this._onHover.bind(this)
);
this._buttonPressEventId = this.parent.connect(
'button-press-event',
this._hide.bind(this)
);
}
get custom() {
if (this._custom === undefined) {
this._custom = null;
}
return this._custom;
}
set custom(actor) {
this._custom = actor;
this._markup = null;
this._text = null;
this._update();
}
get gicon() {
if (this._gicon === undefined) {
this._gicon = null;
}
return this._gicon;
}
set gicon(gicon) {
this._gicon = gicon;
this._update();
}
get icon() {
return (this.gicon) ? this.gicon.name : null;
}
set icon(icon_name) {
if (!icon_name) {
this.gicon = null;
} else {
this.gicon = new Gio.ThemedIcon({
name: icon_name
});
}
}
get markup() {
if (this._markup === undefined) {
this._markup = null;
}
return this._markup;
}
set markup(text) {
this._markup = text;
this._text = null;
this._update();
}
get text() {
if (this._text === undefined) {
this._text = null;
}
return this._text;
}
set text(text) {
this._markup = null;
this._text = text;
this._update();
}
get x_offset() {
return (this._x_offset === undefined) ? 0 : this._x_offset;
}
set x_offset(offset) {
this._x_offset = (Number.isInteger(offset)) ? offset : 0;
}
get y_offset() {
return (this._y_offset === undefined) ? 0 : this._y_offset;
}
set y_offset(offset) {
this._y_offset = (Number.isInteger(offset)) ? offset : 0;
}
_update() {
if (this._showing) {
this._show();
}
}
_show() {
if (!this.text && !this.markup) {
this._hide();
return;
}
if (!this.bin) {
this.bin = new St.Bin({
style_class: 'osd-window gsconnect-tooltip',
opacity: 232
});
if (this.custom) {
this.bin.child = this.custom;
} else {
this.bin.child = new St.BoxLayout({vertical: false});
if (this.gicon) {
this.bin.child.icon = new St.Icon({
gicon: this.gicon,
y_align: St.Align.START
});
this.bin.child.icon.set_y_align(Clutter.ActorAlign.START);
this.bin.child.add_child(this.bin.child.icon);
}
this.label = new St.Label({text: this.markup || this.text});
this.label.clutter_text.line_wrap = true;
this.label.clutter_text.line_wrap_mode = Pango.WrapMode.WORD;
this.label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.label.clutter_text.use_markup = (this.markup);
this.bin.child.add_child(this.label);
}
Main.layoutManager.uiGroup.add_child(this.bin);
Main.layoutManager.uiGroup.set_child_above_sibling(this.bin, null);
} else if (this.custom) {
this.bin.child = this.custom;
} else {
if (this.bin.child.icon) {
this.bin.child.icon.destroy();
}
if (this.gicon) {
this.bin.child.icon = new St.Icon({gicon: this.gicon});
this.bin.child.insert_child_at_index(this.bin.child.icon, 0);
}
this.label.clutter_text.text = this.markup || this.text;
this.label.clutter_text.use_markup = (this.markup);
}
// Position tooltip
let [x, y] = this.parent.get_transformed_position();
x = (x + (this.parent.width / 2)) - Math.round(this.bin.width / 2);
x += this.x_offset;
y += this.y_offset;
// Show tooltip
if (this._showing) {
Tweener.addTween(this.bin, {
x: x,
y: y,
time: 0.15,
transition: 'easeOutQuad'
});
} else {
this.bin.set_position(x, y);
Tweener.addTween(this.bin, {
opacity: 232,
time: 0.15,
transition: 'easeOutQuad'
});
this._showing = true;
}
// Enable browse mode
TOOLTIP_BROWSE_MODE = true;
if (TOOLTIP_BROWSE_ID) {
GLib.source_remove(TOOLTIP_BROWSE_ID);
TOOLTIP_BROWSE_ID = 0;
}
if (this._hoverTimeoutId) {
GLib.source_remove(this._hoverTimeoutId);
this._hoverTimeoutId = 0;
}
}
_hide() {
if (this.bin) {
Tweener.addTween(this.bin, {
opacity: 0,
time: 0.10,
transition: 'easeOutQuad',
onComplete: () => {
Main.layoutManager.uiGroup.remove_actor(this.bin);
if (this.custom) {
this.bin.remove_child(this.custom);
}
this.bin.destroy();
delete this.bin;
}
});
}
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, () => {
TOOLTIP_BROWSE_MODE = false;
TOOLTIP_BROWSE_ID = 0;
return false;
});
if (this._hoverTimeoutId) {
GLib.source_remove(this._hoverTimeoutId);
this._hoverTimeoutId = 0;
}
this._showing = false;
this._hoverTimeoutId = 0;
}
_onHover() {
if (this.parent.hover) {
if (!this._hoverTimeoutId) {
if (this._showing) {
this._show();
} else {
this._hoverTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
(TOOLTIP_BROWSE_MODE) ? 60 : 500,
() => {
this._show();
this._hoverTimeoutId = 0;
return false;
}
);
}
}
} else {
this._hide();
}
}
destroy() {
this.parent.disconnect(this._destroyId);
this.parent.disconnect(this._hoverId);
this.parent.disconnect(this._buttonPressEventId);
if (this.custom) {
this.custom.destroy();
}
if (this.bin) {
Main.layoutManager.uiGroup.remove_actor(this.bin);
this.bin.destroy();
}
if (this._hoverTimeoutId) {
GLib.source_remove(this._hoverTimeoutId);
this._hoverTimeoutId = 0;
}
}
};