| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- // SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
- //
- // SPDX-License-Identifier: GPL-2.0-or-later
- import Clutter from 'gi://Clutter';
- import Gio from 'gi://Gio';
- import GLib from 'gi://GLib';
- import Pango from 'gi://Pango';
- import St from 'gi://St';
- import * as Main from 'resource:///org/gnome/shell/ui/main.js';
- /**
- * 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
- */
- export let TOOLTIP_BROWSE_ID = 0;
- export let TOOLTIP_BROWSE_MODE = false;
- export default class Tooltip {
- constructor(params) {
- Object.assign(this, params);
- this._bin = null;
- 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;
- if (this._showing)
- this._show();
- }
- get gicon() {
- if (this._gicon === undefined)
- this._gicon = null;
- return this._gicon;
- }
- set gicon(gicon) {
- this._gicon = gicon;
- if (this._showing)
- this._show();
- }
- 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;
- if (this._showing)
- this._show();
- }
- get text() {
- if (this._text === undefined)
- this._text = null;
- return this._text;
- }
- set text(text) {
- this._markup = null;
- this._text = text;
- if (this._showing)
- this._show();
- }
- get x_offset() {
- if (this._x_offset === undefined)
- this._x_offset = 0;
- return this._x_offset;
- }
- set x_offset(offset) {
- this._x_offset = (Number.isInteger(offset)) ? offset : 0;
- }
- get y_offset() {
- if (this._y_offset === undefined)
- this._y_offset = 0;
- return this._y_offset;
- }
- set y_offset(offset) {
- this._y_offset = (Number.isInteger(offset)) ? offset : 0;
- }
- _show() {
- if (this.text === null && this.markup === null)
- return this._hide();
- if (this._bin === null) {
- 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) {
- this._bin.ease({
- x: x,
- y: y,
- time: 0.15,
- transition: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- } else {
- this._bin.set_position(x, y);
- this._bin.ease({
- opacity: 232,
- time: 0.15,
- transition: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- 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) {
- this._bin.ease({
- opacity: 0,
- time: 0.10,
- transition: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- Main.layoutManager.uiGroup.remove_actor(this._bin);
- if (this.custom)
- this._bin.remove_child(this.custom);
- this._bin.destroy();
- this._bin = null;
- },
- });
- }
- TOOLTIP_BROWSE_ID = 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 (TOOLTIP_BROWSE_ID) {
- GLib.source_remove(TOOLTIP_BROWSE_ID);
- TOOLTIP_BROWSE_ID = 0;
- }
- if (this._hoverTimeoutId) {
- GLib.source_remove(this._hoverTimeoutId);
- this._hoverTimeoutId = 0;
- }
- }
- }
|