@bokeh/bokehjs
Version:
Interactive, novel data visualization
184 lines • 5.83 kB
JavaScript
import { View } from "../../core/view";
import { min, max } from "../../core/util/array";
import { entries } from "../../core/util/object";
import { isString } from "../../core/util/types";
import { Comparator } from "../../core/util/eq";
import { Model } from "../../model";
import { MenuItem, Menu } from "../ui/menus";
import { IconLike } from "../common/kinds";
export class ToolView extends View {
static __name__ = "ToolView";
connect_signals() {
super.connect_signals();
this.connect(this.model.properties.active.change, () => {
if (this.model.active) {
this.activate();
}
else {
this.deactivate();
}
});
}
get overlays() {
return [];
}
// activate is triggered by toolbar ui actions
activate() { }
// deactivate is triggered by toolbar ui actions
deactivate() { }
}
export class Tool extends Model {
static __name__ = "Tool";
constructor(attrs) {
super(attrs);
}
static {
this.prototype._known_aliases = new Map();
this.define(({ Bool, Or, Str, Nullable }) => ({
icon: [Nullable(IconLike), null],
description: [Nullable(Str), null],
visible: [Bool, true],
group: [Or(Str, Bool), true],
}));
this.internal(({ Bool }) => ({
active: [Bool, false],
disabled: [Bool, false],
}));
}
tool_name;
tool_icon; // CSS class (no dot)
// GestureTool {{{
event_type;
get event_role() {
const { event_type } = this;
return isString(event_type) ? event_type : "multi";
}
get event_types() {
const { event_type } = this;
return event_type == null ? [] : (isString(event_type) ? [event_type] : event_type);
}
// }}}
button_view;
menu_item() {
const item = new MenuItem({
icon: this.computed_icon,
label: this.tool_name,
tooltip: this.tooltip != this.tool_name ? this.tooltip : undefined,
checked: () => this.active,
disabled: () => this.disabled,
action: () => this.active = !this.active,
});
const submenu = this.menu;
if (submenu != null) {
item.menu = new Menu({ items: submenu });
}
return item;
}
get tooltip() {
return this.description ?? this.tool_name;
}
get computed_icon() {
const { icon, tool_icon } = this;
return icon ?? (tool_icon != null ? `.${tool_icon}` : undefined);
}
get menu() {
return null;
}
supports_auto() {
return false;
}
// utility function to get limits along both dimensions, given
// optional dimensional constraints
_get_dim_limits([sx0, sy0], [sx1, sy1], frame, dims) {
const hr = frame.bbox.h_range;
let sxlim;
if (dims == "width" || dims == "both") {
sxlim = [min([sx0, sx1]), max([sx0, sx1])];
sxlim = [max([sxlim[0], hr.start]), min([sxlim[1], hr.end])];
}
else {
sxlim = [hr.start, hr.end];
}
const vr = frame.bbox.v_range;
let sylim;
if (dims == "height" || dims == "both") {
sylim = [min([sy0, sy1]), max([sy0, sy1])];
sylim = [max([sylim[0], vr.start]), min([sylim[1], vr.end])];
}
else {
sylim = [vr.start, vr.end];
}
return [sxlim, sylim];
}
_compute_overlay_limits(sxlim, sylim, dims, line_width) {
if (dims == "width") {
sylim[0] -= line_width; // top
sylim[1] += line_width; // bottom
}
else if (dims == "height") {
sxlim[0] -= line_width; // left
sxlim[1] += line_width; // right
}
return [sxlim, sylim];
}
// utility function to return a tool name, modified
// by the active dimensions. Used by tools that have dimensions
_get_dim_tooltip(dims) {
const { description, tool_name } = this;
if (description != null) {
return description;
}
else if (dims == "both") {
return tool_name;
}
else if (dims == "auto") {
return `${tool_name} (either x, y or both dimensions)`;
}
else {
return `${tool_name} (${dims == "width" ? "x" : "y"}-axis)`;
}
}
/** @prototype */
_known_aliases;
static register_alias(name, fn) {
const tool = fn();
const attrs = tool.dirty_attributes;
const cmp = new Comparator();
const query = (obj) => {
if (!(obj instanceof tool.constructor)) {
return false;
}
for (const [attr, value] of entries(attrs)) {
if (!cmp.eq(value, obj.property(attr).get_value())) {
return false;
}
}
return true;
};
this.prototype._known_aliases.set(name, { fn, query });
}
/**
* Is the given tool member of the given tool family.
*/
static is_alias_of(tool, name) {
const spec = this.prototype._known_aliases.get(name);
return spec?.query(tool.underlying) ?? false;
}
static from_string(name) {
const spec = this.prototype._known_aliases.get(name);
if (spec != null) {
return spec.fn();
}
else {
const names = [...this.prototype._known_aliases.keys()];
throw new Error(`unexpected tool name '${name}', possible tools are ${names.join(", ")}`);
}
}
/**
* Unifying API with ProxyTool.
*/
get underlying() {
return this;
}
}
//# sourceMappingURL=tool.js.map