Files
blockly/core/bubbles/text_bubble.ts
Christopher Allen ce22f42868 chore: Organise imports (#8527)
* chore(deps): Add pretter-plugin-organize-imports

* chore: Remove insignificant blank lines in import sections

  Since prettier-plugin-organize-imports sorts imports within
  sections separated by blank lines, but preserves the section
  divisions, remove any blank lines that are not dividing imports
  into meaningful sections.

  Do not remove blank lines separating side-effect-only imports
  from main imports.

* chore: Remove unneded eslint-disable directives

* chore: Organise imports
2024-08-15 03:16:14 +01:00

103 lines
2.9 KiB
TypeScript

/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {Coordinate} from '../utils/coordinate.js';
import * as dom from '../utils/dom.js';
import {Rect} from '../utils/rect.js';
import {Size} from '../utils/size.js';
import {Svg} from '../utils/svg.js';
import {WorkspaceSvg} from '../workspace_svg.js';
import {Bubble} from './bubble.js';
/**
* A bubble that displays non-editable text. Used by the warning icon.
*/
export class TextBubble extends Bubble {
private paragraph: SVGTextElement;
constructor(
private text: string,
public readonly workspace: WorkspaceSvg,
protected anchor: Coordinate,
protected ownerRect?: Rect,
) {
super(workspace, anchor, ownerRect);
this.paragraph = this.stringToSvg(text, this.contentContainer);
this.updateBubbleSize();
}
/** @returns the current text of this text bubble. */
getText(): string {
return this.text;
}
/** Sets the current text of this text bubble, and updates the display. */
setText(text: string) {
this.text = text;
dom.removeNode(this.paragraph);
this.paragraph = this.stringToSvg(text, this.contentContainer);
this.updateBubbleSize();
}
/**
* Converts the given string into an svg containing that string,
* broken up by newlines.
*/
private stringToSvg(text: string, container: SVGGElement) {
const paragraph = this.createParagraph(container);
const spans = this.createSpans(paragraph, text);
if (this.workspace.RTL)
this.rightAlignSpans(paragraph.getBBox().width, spans);
return paragraph;
}
/** Creates the paragraph container for this bubble's view's spans. */
private createParagraph(container: SVGGElement): SVGTextElement {
return dom.createSvgElement(
Svg.TEXT,
{
'class': 'blocklyText blocklyBubbleText blocklyNoPointerEvents',
'y': Bubble.BORDER_WIDTH,
},
container,
);
}
/** Creates the spans visualizing the text of this bubble. */
private createSpans(parent: SVGTextElement, text: string): SVGTSpanElement[] {
return text.split('\n').map((line) => {
const tspan = dom.createSvgElement(
Svg.TSPAN,
{'dy': '1em', 'x': Bubble.BORDER_WIDTH},
parent,
);
const textNode = document.createTextNode(line);
tspan.appendChild(textNode);
return tspan;
});
}
/** Right aligns the given spans. */
private rightAlignSpans(maxWidth: number, spans: SVGTSpanElement[]) {
for (const span of spans) {
span.setAttribute('text-anchor', 'end');
span.setAttribute('x', `${maxWidth + Bubble.BORDER_WIDTH}`);
}
}
/** Updates the size of this bubble to account for the size of the text. */
private updateBubbleSize() {
const bbox = this.paragraph.getBBox();
this.setSize(
new Size(
bbox.width + Bubble.BORDER_WIDTH * 2,
bbox.height + Bubble.BORDER_WIDTH * 2,
),
true,
);
}
}