Skip to content

Commit

Permalink
Switch Param pane widget type when bounds (un)defined (#1953)
Browse files Browse the repository at this point in the history
* Switch Param pane widget type when bounds (un)defined

* Add test

* Fix test
  • Loading branch information
philippjfr authored Feb 1, 2021
1 parent adb8f01 commit 7501a96
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 19 deletions.
45 changes: 34 additions & 11 deletions panel/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,29 +427,31 @@ def action(change):

def link(change, watchers=[watcher]):
updates = {}
widget = self._widgets[p_name]
if change.what == 'constant':
updates['disabled'] = change.new
elif change.what == 'precedence':
if (change.new < self.display_threshold and
widget in self._widget_box.objects):
self._widget_box.pop(widget)
elif change.new >= self.display_threshold:
precedence = lambda k: self.object.param['name' if k == '_title' else k].precedence
params = self._ordered_params
if self.show_name:
params.insert(0, '_title')
widgets = []
for k in params:
if precedence(k) is None or precedence(k) >= self.display_threshold:
widgets.append(self._widgets[k])
self._widget_box.objects = widgets
self._rerender()
return
elif change.what == 'objects':
updates['options'] = p_obj.get_range()
elif change.what == 'bounds':
start, end = p_obj.get_soft_bounds()
updates['start'] = start
updates['end'] = end
supports_bounds = hasattr(widget, 'start')
if start is None or end is None:
rerender = supports_bounds
else:
rerender = not supports_bounds
if supports_bounds:
updates['start'] = start
updates['end'] = end
if rerender:
self._rerender_widget(p_name)
return
elif change.what == 'step':
updates['step'] = p_obj.step
elif change.what == 'label':
Expand Down Expand Up @@ -530,6 +532,27 @@ def _ordered_params(self):
# Model API
#----------------------------------------------------------------

def _rerender(self):
precedence = lambda k: self.object.param['name' if k == '_title' else k].precedence
params = self._ordered_params
if self.show_name:
params.insert(0, '_title')
widgets = []
for k in params:
if precedence(k) is None or precedence(k) >= self.display_threshold:
widgets.append(self._widgets[k])
self._widget_box.objects = widgets

def _rerender_widget(self, p_name):
watchers = []
for w in self._callbacks:
if w.inst is self._widgets[p_name]:
w.inst.param.unwatch(w)
else:
watchers.append(w)
self._widgets[p_name] = self.widget(p_name)
self._rerender()

def _get_widgets(self):
"""Return name,widget boxes for all parameters (i.e., a property sheet)"""
# Format name specially
Expand Down
38 changes: 30 additions & 8 deletions panel/tests/test_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import param

from bokeh.models import (
Div, Slider, Select, RangeSlider, MultiSelect, Row as BkRow,
CheckboxGroup, Toggle, Button, TextInput as BkTextInput,
Tabs as BkTabs, Column as BkColumn, TextInput)
Div, Slider, Select, RangeSlider as BkRangeSlider, MultiSelect,
Row as BkRow, CheckboxGroup, Toggle, Button, TextInput as
BkTextInput,Tabs as BkTabs, Column as BkColumn, TextInput)
from panel.pane import Pane, PaneBase, Matplotlib, Bokeh, HTML
from panel.layout import Tabs, Row
from panel.param import Param, ParamMethod, ParamFunction, JSONInit
from panel.widgets import LiteralInput
from panel.widgets import LiteralInput, RangeSlider
from panel.tests.util import mpl_available, mpl_figure


Expand Down Expand Up @@ -221,7 +221,7 @@ class Test(param.Parameterized):
model = test_pane.get_root(document, comm=comm)

widget = model.children[1]
assert isinstance(widget, RangeSlider)
assert isinstance(widget, BkRangeSlider)
assert widget.start == 0
assert widget.end == 1.1
assert widget.value == (0.1, 0.5)
Expand Down Expand Up @@ -660,9 +660,9 @@ class Test(param.Parameterized):
assert number.value != 3
assert test.a == 3

test.a = 4
assert number.value != 4
assert test.a == 4
pane._widgets['a']._process_events({'value': 4})
assert test.a == 3
assert number.value == 4


def test_set_show_name(document, comm):
Expand Down Expand Up @@ -1182,3 +1182,25 @@ def _update_text_pane(self, *_):
view.text = TextModel(text="New TextModel")
# Then
assert view.text_pane.parameters==["text"]


def test_rerender_bounded_widget_when_bounds_set_and_unset():
class Test(param.Parameterized):
num = param.Range()

test = Test()
p = Param(test)

assert isinstance(p._widgets['num'], LiteralInput)
assert p._widgets['num'] in p._widget_box

test.param.num.bounds = (0, 5)

assert isinstance(p._widgets['num'], RangeSlider)
assert p._widgets['num'] in p._widget_box

test.param.num.bounds = (None, 5)

assert isinstance(p._widgets['num'], LiteralInput)
assert p._widgets['num'] in p._widget_box

0 comments on commit 7501a96

Please sign in to comment.