UNPKG

lazy-widgets

Version:

Typescript retained mode GUI for the HTML canvas API

103 lines 3.68 kB
import { LeaveEvent } from '../events/LeaveEvent.js'; import { PointerMoveEvent } from '../events/PointerMoveEvent.js'; import { PassthroughWidget } from './PassthroughWidget.js'; import { PropagationModel } from '../events/WidgetEvent.js'; import { TooltipController } from '../helpers/TooltipController.js'; const SENSITIVITY_RADIUS = 8; const HOVER_TIME = 1000; /** * Wraps a widget and provides a tooltip. Automatically manages a given * {@link TooltipContainer}, which will be used as the actual visual tooltip. * * Whenever this widget is hovered for a small amount of time without moving * the pointer too much, a new layer will be created with the passed * {@link TooltipContainer}, in the top-most {@link LayeredContainer}. * Unhovering this wrapper will remove the layer. * * Has a tolerance for small movements, so that shaky pointers can still be used * to detect hovering. * * @category Widget */ export class Tooltip extends PassthroughWidget { constructor(child, tooltipWidget, properties) { super(child, properties); /** * The timestamp for when the hovering started. 0 if not hovering. For * internal use only. */ this._hoverStart = 0; /** * The pointer position for when the hovering started. For internal use * only. */ this._hoverStartPos = [0, 0]; this.tooltipWidget = tooltipWidget; this.controller = new TooltipController(this, tooltipWidget); } handleAttachment() { super.handleAttachment(); this.controller.findTopLayeredContainer(); } handleDetachment() { this.controller.clearTopLayeredContainer(); super.handleDetachment(); } handlePreLayoutUpdate() { super.handlePreLayoutUpdate(); // show tooltip if hovered for long enough if (this._hoverStart !== 0 && !this.controller.hasLayer && (Date.now() - this._hoverStart) >= HOVER_TIME) { this.controller.addLayer(this._hoverStartPos); } } handleEvent(event) { if (event.propagation !== PropagationModel.Trickling) { return super.handleEvent(event); } // check if this event should count as a hover/unhover if (event.isa(PointerMoveEvent)) { if (this._hoverStart === 0) { this._hoverStart = Date.now(); this._hoverStartPos[0] = event.x; this._hoverStartPos[1] = event.y; } else if (!this.controller.hasLayer) { const xDiff = Math.abs(this._hoverStartPos[0] - event.x); const yDiff = Math.abs(this._hoverStartPos[1] - event.y); if (xDiff > SENSITIVITY_RADIUS || yDiff > SENSITIVITY_RADIUS) { this._hoverStart = Date.now(); this._hoverStartPos[0] = event.x; this._hoverStartPos[1] = event.y; } } } else if (event.isa(LeaveEvent)) { this._hoverStart = 0; this.controller.removeLayer(); } // dispatch event to child return this.child.dispatchEvent(event); } resolvePosition(x, y) { super.resolvePosition(x, y); this.controller.updateTooltipRect(); } finalizeBounds() { super.finalizeBounds(); this.controller.updateTooltipRect(); } } Tooltip.autoXML = { name: 'tooltip', inputConfig: [ { mode: 'widget', name: 'child' }, { mode: 'widget', name: 'tooltip-widget' } ] }; //# sourceMappingURL=Tooltip.js.map