UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

245 lines 7.24 kB
import { StyledElement, StyledElementView } from "../ui/styled_element"; import { build_view } from "../../core/build_views"; import * as visuals from "../../core/visuals"; import { RenderLevel } from "../../core/enums"; import { isNumber } from "../../core/util/types"; import { assert } from "../../core/util/assert"; import { CoordinateTransform, CoordinateMapping } from "../coordinates/coordinate_mapping"; import { Menu } from "../ui/menus/menu"; import { RendererGroup } from "./renderer_group"; import { InlineStyleSheet } from "../../core/dom"; export class RendererView extends StyledElementView { static __name__ = "RendererView"; visuals; layout; _panel = null; get panel() { return this._panel; } set panel(panel) { this._panel = panel; } position = new InlineStyleSheet("", "position"); computed_stylesheets() { return [...super.computed_stylesheets(), this.position]; } rendering_target() { return this.plot_view.canvas_view.underlays_el; } _context_menu = null; get context_menu() { return this._context_menu; } _coordinates; get coordinates() { const { _coordinates } = this; if (_coordinates != null) { return _coordinates; } else { return this._coordinates = this._initialize_coordinates(); } } _custom_coordinates = null; set coordinates(custom_coordinates) { this._custom_coordinates = custom_coordinates; } initialize() { super.initialize(); this.visuals = new visuals.Visuals(this); } async lazy_initialize() { await super.lazy_initialize(); const { context_menu } = this.model; if (context_menu != null) { this._context_menu = await build_view(context_menu, { parent: this.plot_view }); } } remove() { this._context_menu?.remove(); super.remove(); } connect_signals() { super.connect_signals(); const { group } = this.model; if (group != null) { this.on_change(group.properties.visible, () => { this.model.visible = group.visible; }); } const { x_range_name, y_range_name } = this.model.properties; this.on_change([x_range_name, y_range_name], () => delete this._coordinates); this.connect(this.plot_view.frame.model.change, () => delete this._coordinates); } _initialize_coordinates() { if (this._custom_coordinates != null) { return this._custom_coordinates; } const { coordinates } = this.model; const { frame } = this.plot_view; if (coordinates != null) { return coordinates.get_transform(frame); } else { const { x_range_name, y_range_name } = this.model; const x_scale = frame.x_scales.get(x_range_name); const y_scale = frame.y_scales.get(y_range_name); assert(x_scale != null, `missing '${x_range_name}' range`); assert(y_scale != null, `missing '${y_range_name}' range`); return new CoordinateTransform(x_scale, y_scale); } } get plot_view() { return this.parent; } get plot_model() { return this.parent.model; } get layer() { const { overlays, primary } = this.canvas; return this.model.level == "overlay" ? overlays : primary; } get canvas() { return this.plot_view.canvas_view; } request_paint() { this.plot_view.request_paint(this); } request_layout() { this.plot_view.request_layout(); } notify_finished() { this.plot_view.notify_finished(); } notify_finished_after_paint() { this.plot_view.notify_finished_after_paint(); } get needs_clip() { return false; } get has_webgl() { return false; } /* get visible(): boolean { const {visible, group} = this.model return !visible ? false : (group?.visible ?? true) } */ get displayed() { return this.model.visible; } get is_renderable() { return true; } get is_dual_renderer() { return false; } paint(ctx) { // It would be better to update geometry (the internal layout) only when // necessary, but conditions for that are not clear, so for now update // at every paint. this.update_geometry(); this.compute_geometry(); this.update_position(); if (this.displayed && this.is_renderable) { this._paint(ctx); } this.mark_finished(); } renderer_view(_renderer) { return undefined; } /** * Geometry setup that doesn't change between paints. */ update_geometry() { } /** * Geometry setup that changes between paints. */ compute_geometry() { } /** * Updates the position of the associated DOM element. */ update_position() { const { bbox, position } = this; if (bbox != null && bbox.is_valid) { if (this.panel != null) { position.replace(` :host { position: relative; width: ${bbox.width}px; height: ${bbox.height}px; } `); } else { position.replace(` :host { position: absolute; left: ${bbox.left}px; top: ${bbox.top}px; width: ${bbox.width}px; height: ${bbox.height}px; } `); } } else { position.replace(` :host { display: none; } `); } } resolve_frame() { return this.plot_view.frame; // TODO CartesianFrameView (PR #13286) } resolve_canvas() { return this.plot_view.canvas; } resolve_plot() { return this.plot_view; } resolve_symbol(node) { const target = this; const { bbox } = target; if (bbox == null) { return { x: NaN, y: NaN }; } else { const value = bbox.resolve(node.symbol); const { offset } = node; if (isNumber(value)) { return value + offset; } else { const { x, y } = value; return { x: x + offset, y: y + offset }; } } } get attribution() { return null; } } export class Renderer extends StyledElement { static __name__ = "Renderer"; constructor(attrs) { super(attrs); } static { this.define(({ Bool, Str, Ref, Nullable }) => ({ group: [Nullable(Ref(RendererGroup)), null], level: [RenderLevel, "image"], visible: [Bool, true], x_range_name: [Str, "default"], y_range_name: [Str, "default"], coordinates: [Nullable(Ref(CoordinateMapping)), null], propagate_hover: [Bool, false], context_menu: [Nullable(Ref(Menu)), null], })); } } //# sourceMappingURL=renderer.js.map