@bokeh/bokehjs
Version:
Interactive, novel data visualization
150 lines • 5.27 kB
JavaScript
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() {
yield* super.children();
yield 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