/******************************************************************************** * Copyright (c) 2024-2026 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the Eclipse * Public License v. 2.0 are satisfied: GNU General Public License, version 2 * with the GNU Classpath Exception which is available at * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ import { Bounds, EditLabelUI } from '@eclipse-glsp/sprotty'; import { inject, injectable } from 'inversify'; import { EditorContextService } from '../../base/editor-context-service'; import { CSS_HIDDEN_EXTENSION_CLASS, CSS_UI_EXTENSION_CLASS } from '../../base/ui-extension/ui-extension'; @injectable() export class GlspEditLabelUI extends EditLabelUI { @inject(EditorContextService) protected editorContextService: EditorContextService; protected override initializeContents(containerElement: HTMLElement): void { super.initializeContents(containerElement); containerElement.classList.add(CSS_UI_EXTENSION_CLASS); this.editorContextService.onViewportChanged(() => { window.requestAnimationFrame(() => { if (this.isActive && this.containerElement) { if (this.isLabelInVisibleViewport()) { this.setPosition(this.containerElement); this.applyFontStyling(); } else { // Cancel editing if the label moved out of the visible viewport this.hide(); } } }); }); } protected override setContainerVisible(visible: boolean): void { if (visible) { this.containerElement?.classList.remove(CSS_HIDDEN_EXTENSION_CLASS); this.editControl.focus(); } else { this.containerElement?.classList.add(CSS_HIDDEN_EXTENSION_CLASS); } } protected isLabelInVisibleViewport(): boolean { if (!this.labelElement) { return false; } const canvasBounds = this.editorContextService.canvasBounds; const scroll = { x: window.scrollX, y: window.scrollY }; const canvasScreenBounds: Bounds = { x: canvasBounds.x - scroll.x, y: canvasBounds.y - scroll.y, width: canvasBounds.width, height: canvasBounds.height }; const labelBounds = this.labelElement.getBoundingClientRect(); return Bounds.overlap(labelBounds, canvasScreenBounds); } }