Hi @_jm (and others…),
Following @_jm’s advice above, I took the RangeTool example (https://docs.bokeh.org/en/latest/docs/gallery/range_tool.html) and I tried extending the RangeTool class to a class that reacts to changes in the active
property. As you can see in the code below, I tried two things:
- Adding a variable
active
on the python side that will sync with the active
property of the parent Tool class (https://github.com/bokeh/bokeh/blob/branch-2.2/bokehjs/src/lib/models/tools/tool.ts) and then using the on_change
method to react to changes.
- Overriding the
activate
and deactivate
methods of the Tool class and using that to react to changes in the active
property.
Neither of the two worked. Any idea what I need to do to make one of these two methods work? (preferably both).
Here is the code. The main additions are made are marked with “ADDED”.
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, RangeTool
from bokeh.plotting import figure
from bokeh.sampledata.stocks import AAPL
from bokeh.util.compiler import TypeScript
from bokeh.core.properties import Bool
TS_CODE = """
import {RangeTool, RangeToolView} from "models/tools/gestures/range_tool"
export class RangeToolCustomView extends RangeToolView {
model: RangeToolCustom
# ADDED: override activate and deactivate methods from Tool
// activate is triggered by toolbar ui actions
activate(): void {
console.log("active")
}
// deactivate is triggered by toolbar ui actions
deactivate(): void {
console.log("non-active")
}
}
export class RangeToolCustom extends RangeTool {
__view_type__: RangeToolCustomView
}
"""
class RangeToolCustom(RangeTool):
__implementation__ = TypeScript(TS_CODE)
# ADDED: active variable on python side to sync with active variable of Tool on js side
active = Bool(default=False)
dates = np.array(AAPL['date'], dtype=np.datetime64)
source = ColumnDataSource(data=dict(date=dates, close=AAPL['adj_close']))
p = figure(plot_height=300, plot_width=800, tools="xpan", # toolbar_location=None,
x_axis_type="datetime", x_axis_location="above",
background_fill_color="#efefef", x_range=(dates[1500], dates[2500]))
p.line('date', 'close', source=source)
p.yaxis.axis_label = 'Price'
select = figure(title="Drag the middle and edges of the selection box to change the range above",
plot_height=130, plot_width=800, y_range=p.y_range,
x_axis_type="datetime", y_axis_type=None,
tools="xpan", # toolbar_location=None,
background_fill_color="#efefef")
range_tool = RangeToolCustom(x_range=p.x_range)
range_tool.overlay.fill_color = "navy"
range_tool.overlay.fill_alpha = 0.2
select.line('date', 'close', source=source)
select.ygrid.grid_line_color = None
select.add_tools(range_tool)
select.toolbar.active_multi = range_tool
# ADDED: react to changes in the active variable
def change_active(attr, old, new):
print("Active changed!")
range_tool.on_change("active", change_active)
curdoc().add_root(column(p, select))
One more issue that I’m having with this code is that in Chrome (but not in Firefox) I get the following error in the Console in Dev Tools:
DevTools failed to load SourceMap: Could not load content for http://localhost:5006/range_tool_custom.py:RangeToolCustom.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE
Any idea why this is happening? It also happens when I run the Custom Tool example (https://docs.bokeh.org/en/latest/docs/user_guide/extensions_gallery/tool.html#userguide-extensions-examples-tool) using Bokeh Server.
Thanks in advance! Ori