Skip to content

Commit

Permalink
Implement Player value_throttled
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Aug 13, 2022
1 parent 4a9b4d0 commit e4f0d47
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 22 deletions.
5 changes: 3 additions & 2 deletions examples/reference/widgets/DiscretePlayer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@
"\n",
"* **``direction``** (int): Current play direction of the Player (-1: playing in reverse,\n",
"0: paused, 1: playing).\n",
"* **``interval``** (int): Interval in milliseconds between updates\n",
"* **``loop_policy``** (str): Looping policy; must be one of 'once', 'loop', or 'reflect'\n",
"* **``options``** (list or dict): A list or dictionary of options to select from\n",
"* **``value``** (object): The current value; must be one of the option values\n",
"* **``value_throttled``** (object): The current value throttled until mouseup (when selected using slider)\n",
"\n",
"##### Display\n",
"\n",
"* **``disabled``** (boolean): Whether the widget is editable\n",
"* **``interval``** (int): Interval in milliseconds between updates\n",
"* **``name``** (str): The title of the widget\n",
"* **``loop_policy``** (str): Looping policy; must be one of 'once', 'loop', or 'reflect'\n",
"* **``show_loop_controls``** (boolean): Whether radio buttons allowing to switch between loop policies options are shown\n",
"\n",
"___"
Expand Down
7 changes: 4 additions & 3 deletions examples/reference/widgets/Player.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,18 @@
"\n",
"* **``direction``** (int): Current play direction of the Player (-1: playing in reverse,\n",
"0: paused, 1: playing).\n",
"* **``interval``** (int): Interval in milliseconds between updates\n",
"* **``loop_policy``** (str): Looping policy; must be one of 'once', 'loop', or 'reflect'\n",
"* **``start``** (int): The range's lower bound\n",
"* **``end``** (int): The range's upper bound\n",
"* **``step``** (int): The interval between values\n",
"* **``value``** (object): The current value; must be one of the option values\n",
"* **``value``** (int): The current integer value\n",
"* **``value_throttled``** (int): The current integer value throttled until mouseup (when selected using slider)\n",
"\n",
"##### Display\n",
"\n",
"* **``disabled``** (boolean): Whether the widget is editable\n",
"* **``interval``** (int): Interval in milliseconds between updates\n",
"* **``name``** (str): The title of the widget\n",
"* **``loop_policy``** (str): Looping policy; must be one of 'once', 'loop', or 'reflect'\n",
"* **``show_loop_controls``** (boolean): Whether radio buttons allowing to switch between loop policies options are shown\n",
"\n",
"___"
Expand Down
16 changes: 12 additions & 4 deletions panel/models/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ export class PlayerView extends WidgetView {
this.sliderEl.value = String(this.model.value)
this.sliderEl.min = String(this.model.start)
this.sliderEl.max = String(this.model.end)
this.sliderEl.onchange = (ev) => this.set_frame(parseInt((ev.target as HTMLInputElement).value))
this.sliderEl.addEventListener('input', (ev) => {
this.set_frame(parseInt((ev.target as HTMLInputElement).value), false)
})
this.sliderEl.addEventListener('change', (ev) => {
this.set_frame(parseInt((ev.target as HTMLInputElement).value))
})

// Buttons
const button_div = div() as any
Expand Down Expand Up @@ -211,9 +216,10 @@ export class PlayerView extends WidgetView {
this.el.appendChild(this.groupEl)
}

set_frame(frame: number): void {
if (this.model.value != frame)
this.model.value = frame;
set_frame(frame: number, throttled: boolean=true): void {
this.model.value = frame
if (throttled)
this.model.value_throttled = frame
if (this.sliderEl.value != String(frame))
this.sliderEl.value = String(frame);
}
Expand Down Expand Up @@ -358,6 +364,7 @@ export namespace Player {
step: p.Property<number>
loop_policy: p.Property<typeof LoopPolicy["__type__"]>
value: p.Property<any>
value_throttled: p.Property<any>
show_loop_controls: p.Property<boolean>
}
}
Expand Down Expand Up @@ -386,6 +393,7 @@ export class Player extends Widget {
step: [ Int, 1 ],
loop_policy: [ LoopPolicy, "once" ],
value: [ Int, 0 ],
value_throttled: [ Int, 0 ],
show_loop_controls: [ Boolean, true ],
}))

Expand Down
2 changes: 2 additions & 0 deletions panel/models/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class Player(Widget):

value = Int(0, help="Current value of the player app")

value_throttled = Int(0, help="Current throttled value of the player app")

step = Int(1, help="Number of steps to advance the player by.")

interval = Int(500, help="Interval between updates")
Expand Down
46 changes: 33 additions & 13 deletions panel/widgets/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import param

from ..config import config
from ..models.widgets import Player as _BkPlayer
from ..util import indexOf, isIn
from .base import Widget
Expand All @@ -20,23 +21,23 @@

class PlayerBase(Widget):

direction = param.Integer(0, doc="""
Current play direction of the Player (-1: playing in reverse,
0: paused, 1: playing)""")

interval = param.Integer(default=500, doc="""
Interval between updates, in milliseconds. Default is 500, i.e.
two updates per second.""")

loop_policy = param.ObjectSelector(default='once',
objects=['once', 'loop', 'reflect'], doc="""
loop_policy = param.ObjectSelector(
default='once', objects=['once', 'loop', 'reflect'], doc="""
Policy used when player hits last frame""")

step = param.Integer(default=1, doc="""
Number of frames to step forward and back by on each event.""")

show_loop_controls = param.Boolean(default=True, doc="""
Whether the loop controls radio buttons are shown""")

direction = param.Integer(0, doc="""
Current play direction of the Player (-1: playing in reverse,
0: paused, 1: playing)""")
step = param.Integer(default=1, doc="""
Number of frames to step forward and back by on each event.""")

height = param.Integer(default=80)

Expand All @@ -48,6 +49,11 @@ class PlayerBase(Widget):

__abstract = True

def __init__(self, **params):
if 'value' in params and 'value_throttled' in self.param:
params['value_throttled'] = params['value']
super().__init__(**params)

def play(self):
self.direction = 1

Expand Down Expand Up @@ -79,6 +85,9 @@ class Player(PlayerBase):

value = param.Integer(default=0, doc="Current player value")

value_throttled = param.Integer(default=0, constant=True, doc="""
Current throttled player value.""")

_supports_embed: ClassVar[bool] = True

def __init__(self, **params):
Expand All @@ -91,6 +100,14 @@ def __init__(self, **params):
params['value'] = params['start']
super().__init__(**params)

def _process_property_change(self, msg):
if config.throttled:
if "value" in msg:
del msg["value"]
if "value_throttled" in msg:
msg["value"] = msg["value_throttled"]
return super()._process_property_change(msg)

def _get_embed_state(self, root, values=None, max_opts=3):
if values is None:
values = list(range(self.start, self.end, self.step))
Expand Down Expand Up @@ -121,9 +138,11 @@ class DiscretePlayer(PlayerBase, SelectBase):

value = param.Parameter(doc="Current player value")

value_throttled = param.Parameter(constant=True, doc="Current player value")

_rename: ClassVar[Mapping[str, str | None]] = {'name': None, 'options': None}

_source_transforms: ClassVar[Mapping[str, str | None]] = {'value': None}
_source_transforms: ClassVar[Mapping[str, str | None]] = {'value': None, 'value_throttled': None}

def _process_param_change(self, msg):
values = self.values
Expand All @@ -141,8 +160,9 @@ def _process_param_change(self, msg):
return super()._process_param_change(msg)

def _process_property_change(self, msg):
if 'value' in msg:
value = msg.pop('value')
if value < len(self.options):
msg['value'] = self.values[value]
for prop in ('value', 'value_throttled'):
if prop in msg:
value = msg.pop(prop)
if value < len(self.options):
msg[prop] = self.values[value]
return msg

0 comments on commit e4f0d47

Please sign in to comment.