UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

149 lines 5.28 kB
import { Annotation, AnnotationView } from "./annotation"; import { SideLayout } from "../../core/layout/side_panel"; import { BaseText } from "../text/base_text"; import { build_view } from "../../core/build_views"; import { isString } from "../../core/util/types"; import { parse_delimited_string } from "../text/utils"; import { Padding, BorderRadius } from "../common/kinds"; import * as resolve from "../common/resolve"; import { BBox } from "../../core/util/bbox"; import { round_rect } from "../common/painting"; import * as mixins from "../../core/property_mixins"; export class TextAnnotationView extends AnnotationView { static __name__ = "TextAnnotationView"; _text_view; children_views() { return [...super.children_views(), this._text_view]; } async lazy_initialize() { await super.lazy_initialize(); await this._init_text(); } async _init_text() { const { text } = this.model; const _text = isString(text) ? parse_delimited_string(text) : text; this._text_view = await build_view(_text, { parent: this }); } update_layout() { const { panel } = this; if (panel != null) { this.layout = new SideLayout(panel, () => this.get_size(), false); } else { this.layout = undefined; } } connect_signals() { super.connect_signals(); const { text } = this.model.properties; this.on_change(text, async () => { this._text_view.remove(); await this._init_text(); }); this.connect(this.model.change, () => this.request_paint()); } remove() { this._text_view.remove(); super.remove(); } has_finished() { if (!super.has_finished()) { return false; } if (!this._text_view.has_finished()) { return false; } return true; } get displayed() { return super.displayed && this._text_view.model.text != "" && this.visuals.text.doit; } get padding() { return resolve.padding(this.model.padding); } get border_radius() { return resolve.border_radius(this.model.border_radius); } _text_box; _rect; _get_size() { if (!this.displayed) { return { width: 0, height: 0 }; } const graphics = this._text_view.graphics(); graphics.angle = this.angle; graphics.align = "auto"; graphics.visuals = this.visuals.text.values(); const size = graphics.size(); const { padding } = this; const width = size.width + padding.left + padding.right; const height = size.height + padding.top + padding.bottom; return { width, height }; } compute_geometry() { super.compute_geometry(); const text_box = this._text_view.graphics(); text_box.position = { sx: 0, sy: 0, x_anchor: "left", y_anchor: "top" }; text_box.angle = 0; // needs reset because text_box is self-referential text_box.align = "auto"; text_box.visuals = this.visuals.text.values(); const size = text_box.size(); const { sx, sy } = this.origin; const { anchor, padding, border_radius, angle } = this; const width = size.width + padding.left + padding.right; const height = size.height + padding.top + padding.bottom; this._text_box = text_box; this._rect = { sx, sy, width, height, angle, anchor, padding, border_radius }; } _paint(ctx) { const { sx, sy, width, height, angle, anchor, padding, border_radius } = this._rect; const label = this._text_box; const dx = anchor.x * width; const dy = anchor.y * height; ctx.translate(sx, sy); ctx.rotate(angle); ctx.translate(-dx, -dy); const { background_fill, background_hatch, border_line, text } = this.visuals; if (background_fill.doit || background_hatch.doit || border_line.doit) { ctx.beginPath(); const bbox = new BBox({ x: 0, y: 0, width, height }); round_rect(ctx, bbox, border_radius); background_fill.apply(ctx); background_hatch.apply(ctx); border_line.apply(ctx); } if (text.doit) { const { left, top } = padding; ctx.translate(left, top); label.paint(ctx); ctx.translate(-left, -top); } ctx.translate(dx, dy); ctx.rotate(-angle); ctx.translate(-sx, -sy); } } export class TextAnnotation extends Annotation { static __name__ = "TextAnnotation"; constructor(attrs) { super(attrs); } static { this.mixins([ mixins.Text, ["border_", mixins.Line], ["background_", mixins.Fill], ["background_", mixins.Hatch], ]); this.define(({ Str, Or, Ref }) => ({ text: [Or(Str, Ref(BaseText)), ""], padding: [Padding, 0], border_radius: [BorderRadius, 0], })); this.override({ border_line_color: null, background_fill_color: null, }); } } //# sourceMappingURL=text_annotation.js.map