Skip to content

Commit

Permalink
Better estimation of value for editable sliders with fixed_start / fi…
Browse files Browse the repository at this point in the history
…xed_end (#4169)

* Better estimation of value for editable sliders with fixed_start / fixed_end

* Also add option to work with start and end
  • Loading branch information
hoxbro authored Dec 1, 2022
1 parent 8c838b0 commit 47fd67e
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 0 deletions.
113 changes: 113 additions & 0 deletions panel/tests/widgets/test_slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,3 +602,116 @@ def test_editable_rangeslider_bounds(
slider.value = val_update
except Exception:
assert fail_update


@pytest.mark.parametrize(
"editableslider,fixed_start,fixed_end",
[
(EditableFloatSlider, 5, 10),
(EditableIntSlider, 5, 10),
],
)
def test_editable_slider_fixed_novalue(editableslider, fixed_start, fixed_end):
slider = editableslider(
fixed_start=fixed_start, fixed_end=fixed_end,
)
assert slider.value == fixed_start

slider = editableslider(fixed_start=fixed_start)
assert slider.value == fixed_start

slider = editableslider(fixed_end=fixed_end)
assert slider.value == fixed_end - 1


def test_editable_rangeslider_fixed_novalue():
fixed_start, fixed_end, step = 5, 10, 0.01
slider = EditableRangeSlider(
fixed_start=fixed_start, fixed_end=fixed_end,
)
assert slider.value == (fixed_start, fixed_end)

slider = EditableRangeSlider(fixed_start=fixed_start)
assert slider.value == (fixed_start, fixed_start + 1)

slider = EditableRangeSlider(fixed_start=fixed_start, step=step)
assert slider.value == (fixed_start, fixed_start + step)

slider = EditableRangeSlider(fixed_end=fixed_end)
assert slider.value == (fixed_end - 1, fixed_end)

slider = EditableRangeSlider(fixed_end=fixed_end, step=step)
assert slider.value == (fixed_end - step, fixed_end)

@pytest.mark.parametrize(
"editableslider",
[EditableFloatSlider, EditableIntSlider, EditableRangeSlider],
)
def test_editable_fixed_nosoftbounds_fixed_start_end(editableslider):
start, end = 8, 9
fixed_start, fixed_end = 5, 10

slider = editableslider(
fixed_start=fixed_start, fixed_end=fixed_end,
)
assert slider.start == fixed_start
assert slider.end == fixed_end

slider = editableslider(
fixed_start=fixed_start, fixed_end=fixed_end,
start=start, end=end,
)
assert slider.start == start
assert slider.end == end


@pytest.mark.parametrize(
"editableslider",
[EditableFloatSlider, EditableIntSlider, EditableRangeSlider],
)
def test_editable_fixed_nosoftbounds_fixed_start(editableslider):
start, _ = 8, 9
fixed_start, _ = 5, 10
step = 2

slider = editableslider(fixed_start=fixed_start)
assert slider.start == fixed_start
assert slider.end == fixed_start + 1

slider = editableslider(fixed_start=fixed_start, step=step)
assert slider.start == fixed_start
assert slider.end == fixed_start + step

slider = editableslider(fixed_start=fixed_start, start=start)
assert slider.start == start
assert slider.end == start + 1

slider = editableslider(fixed_start=fixed_start, start=start, step=step)
assert slider.start == start
assert slider.end == start + step



@pytest.mark.parametrize(
"editableslider",
[EditableFloatSlider, EditableIntSlider, EditableRangeSlider],
)
def test_editable_fixed_nosoftbounds_fixed_end(editableslider):
_, end = 8, 9
_, fixed_end = 5, 10
step = 2
slider = editableslider(fixed_end=fixed_end)
assert slider.start == fixed_end - 1
assert slider.end == fixed_end

slider = editableslider(fixed_end=fixed_end, step=step)
assert slider.start == fixed_end - step
assert slider.end == fixed_end

slider = editableslider(fixed_end=fixed_end, end=end)
assert slider.start == end - 1
assert slider.end == end

slider = editableslider(fixed_end=fixed_end, end=end, step=step)
assert slider.start == end - step
assert slider.end == end
70 changes: 70 additions & 0 deletions panel/widgets/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,7 @@ class _EditableContinuousSlider(CompositeWidget):
def __init__(self, **params):
if not 'width' in params and not 'sizing_mode' in params:
params['width'] = 300
self._validate_init_bounds(params)
super().__init__(**params)
self._label = StaticText(margin=0, align='end')
self._slider = self._slider_widget(
Expand Down Expand Up @@ -816,6 +817,38 @@ def __init__(self, **params):
self._update_value()
self._update_bounds()

def _validate_init_bounds(self, params):
"""
This updates the default value, start and end
if outside the fixed_start and fixed_end
"""
start, end = None, None
if "start" not in params:
if "fixed_start" in params:
start = params["fixed_start"]
elif "end" in params:
start = params.get("end") - params.get("step", 1)
elif "fixed_end" in params:
start = params.get("fixed_end") - params.get("step", 1)

if "end" not in params:
if "fixed_end" in params:
end = params["fixed_end"]
elif "start" in params:
end = params["start"] + params.get("step", 1)
elif "fixed_start" in params:
end = params["fixed_start"] + params.get("step", 1)

if start is not None:
params["start"] = start
if end is not None:
params["end"] = end

if "value" not in params and "start" in params:
params["value"] = params["start"]
if "value" not in params and "end" in params:
params["value"] = params["end"]

@param.depends('width', 'height', 'sizing_mode', watch=True)
def _update_layout(self):
self._value_edit.sizing_mode = self.sizing_mode
Expand Down Expand Up @@ -977,6 +1010,7 @@ class EditableRangeSlider(CompositeWidget, _SliderBase):
def __init__(self, **params):
if not 'width' in params and not 'sizing_mode' in params:
params['width'] = 300
self._validate_init_bounds(params)
super().__init__(**params)
self._label = StaticText(margin=0, align='end')
self._slider = RangeSlider(margin=(0, 0, 5, 0), show_value=False)
Expand Down Expand Up @@ -1026,6 +1060,42 @@ def __init__(self, **params):
self._update_value()
self._update_bounds()

def _validate_init_bounds(self, params):
"""
This updates the default value, start and end
if outside the fixed_start and fixed_end
"""
start, end = None, None
if "start" not in params:
if "fixed_start" in params:
start = params["fixed_start"]
elif "end" in params:
start = params.get("end") - params.get("step", 1)
elif "fixed_end" in params:
start = params.get("fixed_end") - params.get("step", 1)

if "end" not in params:
if "fixed_end" in params:
end = params["fixed_end"]
elif "start" in params:
end = params["start"] + params.get("step", 1)
elif "fixed_start" in params:
end = params["fixed_start"] + params.get("step", 1)

if start is not None:
params["start"] = start
if end is not None:
params["end"] = end

if "value" not in params and "start" in params:
start = params["start"]
end = params.get("end", start + params.get("step", 1))
params["value"] = (start, end)
if "value" not in params and "end" in params:
end = params["end"]
start = params.get("start", end - params.get("step", 1))
params["value"] = (start, end)

@param.depends('editable', watch=True)
def _update_editable(self):
self._start_edit.disabled = not self.editable[0]
Expand Down

0 comments on commit 47fd67e

Please sign in to comment.