@bokeh/bokehjs
Version:
Interactive, novel data visualization
123 lines • 4.45 kB
JavaScript
import { DataRenderer, DataRendererView } from "./data_renderer";
import { GlyphRenderer } from "./glyph_renderer";
import { LayoutProvider } from "../graphs/layout_provider";
import { GraphHitTestPolicy, NodesOnly } from "../graphs/graph_hit_test_policy";
import { build_view } from "../../core/build_views";
import { logger } from "../../core/logging";
import { XYGlyph } from "../glyphs/xy_glyph";
import { MultiLine } from "../glyphs/multi_line";
import { Patches } from "../glyphs/patches";
export class GraphRendererView extends DataRendererView {
static __name__ = "GraphRendererView";
edge_view;
node_view;
get glyph_view() {
return this.node_view.glyph;
}
*children() {
yield* super.children();
yield this.edge_view;
yield this.node_view;
}
async lazy_initialize() {
await super.lazy_initialize();
this.apply_coordinates();
const { parent } = this;
const { edge_renderer, node_renderer } = this.model;
this.edge_view = await build_view(edge_renderer, { parent });
this.node_view = await build_view(node_renderer, { parent });
}
connect_signals() {
super.connect_signals();
this.connect(this.model.layout_provider.change, async () => {
this.apply_coordinates();
await this.edge_view.set_data();
await this.node_view.set_data();
this.request_paint();
});
}
apply_coordinates() {
const { edge_renderer, node_renderer } = this.model;
const edge_coords = this.model.layout_provider.edge_coordinates;
const node_coords = this.model.layout_provider.node_coordinates;
const xs = { expr: edge_coords.x };
const ys = { expr: edge_coords.y };
const x = { expr: node_coords.x };
const y = { expr: node_coords.y };
const edge_glyphs = [
edge_renderer.glyph,
edge_renderer.hover_glyph,
edge_renderer.muted_glyph,
edge_renderer.selection_glyph,
edge_renderer.nonselection_glyph,
];
const node_glyphs = [
node_renderer.glyph,
node_renderer.hover_glyph,
node_renderer.muted_glyph,
node_renderer.selection_glyph,
node_renderer.nonselection_glyph,
];
for (const glyph of edge_glyphs) {
if (glyph == null || glyph == "auto") {
continue;
}
if (!(glyph instanceof MultiLine || glyph instanceof Patches)) {
logger.warn(`${this}.edge_renderer only supports MultiLine and Patches glyphs`);
continue;
}
glyph.properties.xs.internal = true;
glyph.properties.ys.internal = true;
glyph.xs = xs;
glyph.ys = ys;
}
for (const glyph of node_glyphs) {
if (glyph == null || glyph == "auto") {
continue;
}
if (!(glyph instanceof XYGlyph)) {
logger.warn(`${this}.node_renderer only supports XY glyphs`);
continue;
}
glyph.properties.x.internal = true;
glyph.properties.y.internal = true;
glyph.x = x;
glyph.y = y;
}
}
remove() {
this.edge_view.remove();
this.node_view.remove();
super.remove();
}
_paint(ctx) {
this.edge_view.paint(ctx);
this.node_view.paint(ctx);
}
get has_webgl() {
return this.edge_view.has_webgl || this.node_view.has_webgl;
}
hit_test(geometry) {
return this.model.inspection_policy.hit_test(geometry, this);
}
}
export class GraphRenderer extends DataRenderer {
static __name__ = "GraphRenderer";
constructor(attrs) {
super(attrs);
}
static {
this.prototype.default_view = GraphRendererView;
this.define(({ Ref }) => ({
layout_provider: [Ref(LayoutProvider)],
node_renderer: [Ref((GlyphRenderer))],
edge_renderer: [Ref((GlyphRenderer))],
selection_policy: [Ref(GraphHitTestPolicy), () => new NodesOnly()],
inspection_policy: [Ref(GraphHitTestPolicy), () => new NodesOnly()],
}));
}
get_selection_manager() {
return this.node_renderer.data_source.selection_manager;
}
}
//# sourceMappingURL=graph_renderer.js.map