Skip to content

Commit

Permalink
Merge pull request #2283 from jtpio/play-widget
Browse files Browse the repository at this point in the history
Play widget: expose playing and repeat
  • Loading branch information
SylvainCorlay authored Jan 8, 2020
2 parents bd0f635 + 3661476 commit 0cd00a5
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 41 deletions.
13 changes: 7 additions & 6 deletions ipywidgets/widgets/widget_int.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,18 @@ def _validate_value(self, proposal):
class Play(_BoundedInt):
"""Play/repeat buttons to step through values automatically, and optionally loop.
"""
interval = CInt(100, help="The time between two animation steps (ms).").tag(sync=True)
step = CInt(1, help="Increment step").tag(sync=True)
disabled = Bool(False, help="Enable or disable user changes").tag(sync=True)

_view_name = Unicode('PlayView').tag(sync=True)
_model_name = Unicode('PlayModel').tag(sync=True)

_playing = Bool(help="Whether the control is currently playing.").tag(sync=True)
_repeat = Bool(help="Whether the control will repeat in a continous loop.").tag(sync=True)
playing = Bool(help="Whether the control is currently playing.").tag(sync=True)
repeat = Bool(help="Whether the control will repeat in a continous loop.").tag(sync=True)

interval = CInt(100, help="The time between two animation steps (ms).").tag(sync=True)
step = CInt(1, help="Increment step").tag(sync=True)
disabled = Bool(False, help="Enable or disable user changes").tag(sync=True)
show_repeat = Bool(True, help="Show the repeat toggle button in the widget.").tag(sync=True)


class _BoundedIntRange(_IntRange):
max = CInt(100, help="Max value").tag(sync=True)
min = CInt(0, help="Min value").tag(sync=True)
Expand Down
86 changes: 55 additions & 31 deletions packages/controls/src/widget_int.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,8 @@ class PlayModel extends BoundedIntModel {
return _.extend(super.defaults(), {
_model_name: 'PlayModel',
_view_name: 'PlayView',
_playing: false,
_repeat: false,
repeat: false,
playing: false,
show_repeat: true,
interval: 100,
step: 1,
Expand All @@ -789,42 +789,47 @@ class PlayModel extends BoundedIntModel {
}

loop(): void {
if (this.get('_playing')) {
const next_value = this.get('value') + this.get('step');
if (next_value <= this.get('max')) {
this.set('value', next_value);
if (!this.get('playing')) {
return;
}
const next_value = this.get('value') + this.get('step');
if (next_value <= this.get('max')) {
this.set('value', next_value);
this.schedule_next();
} else {
if (this.get('repeat')) {
this.set('value', this.get('min'));
this.schedule_next();
} else {
if(this.get('_repeat')) {
this.set('value', this.get('min'));
this.schedule_next();
} else {
this.set('_playing', false);
}
this.pause();
}
this.save_changes();
}
this.save_changes();
}

schedule_next(): void {
window.setTimeout(this.loop.bind(this), this.get('interval'));
this._timerId = window.setTimeout(this.loop.bind(this), this.get('interval'));
}

stop(): void {
this.set('_playing', false);
this.pause();
this.set('value', this.get('min'));
this.save_changes();
}

pause(): void {
this.set('_playing', false);
window.clearTimeout(this._timerId);
this._timerId = null;
this.set('playing', false);
this.save_changes();
}

play(): void {
this.set('_playing', true);
if (this.get('value') == this.get('max')) {
// if the value is at the end, reset if first, and then schedule the next
animate(): void {
if (this._timerId !== null) {
return;
}
if (this.get('value') === this.get('max')) {
// if the value is at the end, reset it first, and then schedule the next
this.set('value', this.get('min'));
this.schedule_next();
this.save_changes();
Expand All @@ -833,12 +838,20 @@ class PlayModel extends BoundedIntModel {
// loop will call save_changes in this case
this.loop();
}
this.save_changes();
}

play(): void {
this.set('playing', !this.get('playing'));
this.save_changes();
}

repeat(): void {
this.set('_repeat', !this.get('_repeat'));
this.set('repeat', !this.get('repeat'));
this.save_changes();
}

private _timerId: number | null = null;
}

export
Expand Down Expand Up @@ -882,11 +895,11 @@ class PlayView extends DOMWidgetView {
this.stopButton.onclick = this.model.stop.bind(this.model);
this.repeatButton.onclick = this.model.repeat.bind(this.model);

this.listenTo(this.model, 'change:_playing', this.update_playing);
this.listenTo(this.model, 'change:_repeat', this.update_repeat);
this.listenTo(this.model, 'change:show_repeat', this.update_repeat);
this.update_playing();
this.update_repeat();
this.listenTo(this.model, 'change:playing', this.onPlayingChanged);
this.listenTo(this.model, 'change:repeat', this.updateRepeat);
this.listenTo(this.model, 'change:show_repeat', this.updateRepeat);
this.updatePlaying();
this.updateRepeat();
this.update();
}

Expand All @@ -896,11 +909,22 @@ class PlayView extends DOMWidgetView {
this.pauseButton.disabled = disabled;
this.stopButton.disabled = disabled;
this.repeatButton.disabled = disabled;
this.update_playing();
this.updatePlaying();
}

onPlayingChanged() {
this.updatePlaying();
const previous = this.model.previous('playing');
const current = this.model.get('playing');
if (!previous && current) {
this.model.animate();
} else {
this.model.pause();
}
}

update_playing(): void {
const playing = this.model.get('_playing');
updatePlaying(): void {
const playing = this.model.get('playing');
const disabled = this.model.get('disabled');
if (playing) {
if (!disabled) {
Expand All @@ -915,8 +939,8 @@ class PlayView extends DOMWidgetView {
}
}

update_repeat(): void {
const repeat = this.model.get('_repeat');
updateRepeat(): void {
const repeat = this.model.get('repeat');
this.repeatButton.style.display = this.model.get('show_repeat') ? this.playButton.style.display : 'none';
if (repeat) {
this.repeatButton.classList.add('mod-active');
Expand Down
4 changes: 2 additions & 2 deletions packages/schema/jupyterwidgetmodels.latest.md
Original file line number Diff line number Diff line change
Expand Up @@ -784,8 +784,6 @@ Attribute | Type | Default | Help
`_model_module` | string | `'@jupyter-widgets/controls'` |
`_model_module_version` | string | `'1.5.0'` |
`_model_name` | string | `'PlayModel'` |
`_playing` | boolean | `false` | Whether the control is currently playing.
`_repeat` | boolean | `false` | Whether the control will repeat in a continous loop.
`_view_module` | string | `'@jupyter-widgets/controls'` |
`_view_module_version` | string | `'1.5.0'` |
`_view_name` | string | `'PlayView'` |
Expand All @@ -795,6 +793,8 @@ Attribute | Type | Default | Help
`layout` | reference to Layout widget | reference to new instance |
`max` | number (integer) | `100` | Max value
`min` | number (integer) | `0` | Min value
`playing` | boolean | `false` | Whether the control is currently playing.
`repeat` | boolean | `false` | Whether the control will repeat in a continous loop.
`show_repeat` | boolean | `true` | Show the repeat toggle button in the widget.
`step` | number (integer) | `1` | Increment step
`style` | reference to DescriptionStyle widget | reference to new instance | Styling customizations
Expand Down
4 changes: 2 additions & 2 deletions packages/schema/jupyterwidgetmodels.v8.md
Original file line number Diff line number Diff line change
Expand Up @@ -717,8 +717,8 @@ Attribute | Type | Default | Help
`_model_module` | string | `'@jupyter-widgets/controls'` |
`_model_module_version` | string | `'1.4.0'` |
`_model_name` | string | `'PlayModel'` |
`_playing` | boolean | `false` | Whether the control is currently playing.
`_repeat` | boolean | `false` | Whether the control will repeat in a continous loop.
`playing` | boolean | `false` | Whether the control is currently playing.
`repeat` | boolean | `false` | Whether the control will repeat in a continous loop.
`_view_module` | string | `'@jupyter-widgets/controls'` |
`_view_module_version` | string | `'1.4.0'` |
`_view_name` | string | `'PlayView'` |
Expand Down

0 comments on commit 0cd00a5

Please sign in to comment.