@bokeh/bokehjs
Version:
Interactive, novel data visualization
245 lines • 7.24 kB
JavaScript
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