@bokeh/bokehjs
Version:
Interactive, novel data visualization
121 lines • 4.39 kB
JavaScript
import { SelectTool, SelectToolView } from "./select_tool";
import { Modifiers, satisfies_modifiers } from "./common";
import { MenuItem } from "../../ui/menus";
import { execute } from "../../../core/util/callbacks";
import { SelectionMode } from "../../../core/enums";
import { TapBehavior, TapGesture } from "../../../core/enums";
import { tool_icon_tap_select, tool_icon_toggle_mode } from "../../../styles/icons.css";
export class TapToolView extends SelectToolView {
static __name__ = "TapToolView";
_tap(ev) {
const is_tap = this.model.gesture == "tap";
if (is_tap) {
this._handle_tap(ev);
}
return is_tap;
}
_doubletap(ev) {
const is_doubletap = this.model.gesture == "doubletap";
if (is_doubletap) {
this._handle_tap(ev);
}
return is_doubletap;
}
_handle_tap(ev) {
if (!satisfies_modifiers(this.model.modifiers, ev.modifiers)) {
return;
}
const { sx, sy } = ev;
const { frame } = this.plot_view;
if (!frame.bbox.contains(sx, sy)) {
return;
}
this._clear_other_overlays();
const geometry = { type: "point", sx, sy };
if (this.model.behavior == "select") {
this._select(geometry, true, this._select_mode(ev.modifiers));
}
else {
this._inspect(geometry, ev.modifiers);
}
}
_select(geometry, final, mode) {
const renderers_by_source = this._computed_renderers_by_data_source();
for (const [, renderers] of renderers_by_source) {
const sm = renderers[0].get_selection_manager();
const r_views = renderers.map((r) => this.plot_view.views.find_one(r)).filter((r) => r != null);
const did_hit = sm.select(r_views, geometry, final, mode);
if (did_hit) {
const [rv] = r_views;
this._emit_callback(rv, geometry, sm.source);
}
}
this._emit_selection_event(geometry);
this.plot_view.state.push("tap", { selection: this.plot_view.get_selection() });
}
_inspect(geometry, modifiers) {
for (const r of this.computed_renderers) {
const rv = this.plot_view.views.find_one(r);
if (rv == null) {
continue;
}
const sm = r.get_selection_manager();
const did_hit = sm.inspect(rv, geometry);
if (did_hit) {
this._emit_callback(rv, geometry, sm.source, modifiers);
}
}
}
_emit_callback(rv, geometry, source, modifiers) {
const { callback } = this.model;
if (callback != null) {
const x = rv.coordinates.x_scale.invert(geometry.sx);
const y = rv.coordinates.y_scale.invert(geometry.sy);
const data = {
geometries: { ...geometry, x, y },
source,
event: { modifiers },
};
void execute(callback, this.model, data);
}
}
}
export class TapTool extends SelectTool {
static __name__ = "TapTool";
constructor(attrs) {
super(attrs);
}
static {
this.prototype.default_view = TapToolView;
this.define(({ Any, Nullable }) => ({
mode: [SelectionMode, "toggle"],
behavior: [TapBehavior, "select"],
gesture: [TapGesture, "tap"],
modifiers: [Modifiers, {}],
callback: [Nullable(Any /*TODO*/), null],
}));
this.register_alias("click", () => new TapTool({ behavior: "inspect" }));
this.register_alias("tap", () => new TapTool());
this.register_alias("doubletap", () => new TapTool({ gesture: "doubletap" }));
}
tool_name = "Tap";
tool_icon = tool_icon_tap_select;
event_type = "tap";
default_order = 10;
get menu() {
return [
new MenuItem({
icon: `.${tool_icon_toggle_mode}`,
label: "Toggle mode",
tooltip: "Toggle the current selection",
checked: () => this.mode == "toggle",
action: () => {
this.mode = "toggle";
this.active = true;
},
}),
...super.menu,
];
}
}
//# sourceMappingURL=tap_tool.js.map