From 2bed49ce2170ff646c87c0adee0466ac7f1e60fe Mon Sep 17 00:00:00 2001 From: Patrick O'Leary Date: Wed, 29 Apr 2026 08:12:34 -0500 Subject: [PATCH] Add reverse play button and forward/reverse looping --- src/e3sm_quickview/app.py | 1 + src/e3sm_quickview/components/toolbars.py | 33 ++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/e3sm_quickview/app.py b/src/e3sm_quickview/app.py index e4c104d..dacdb9b 100644 --- a/src/e3sm_quickview/app.py +++ b/src/e3sm_quickview/app.py @@ -56,6 +56,7 @@ def __init__(self, server=None): "trame__favicon": ASSETS.icon, "is_tauri": False, "animation_play": False, + "animation_direction": "forward", # All available variables "variables_listing": [], # Selected variables to load diff --git a/src/e3sm_quickview/components/toolbars.py b/src/e3sm_quickview/components/toolbars.py index 8fa0d10..7f9f8c9 100644 --- a/src/e3sm_quickview/components/toolbars.py +++ b/src/e3sm_quickview/components/toolbars.py @@ -482,10 +482,25 @@ def __init__(self): ) v3.VDivider(vertical=True, classes="mx-2") v3.VIconBtn( - icon=("animation_play ? 'mdi-stop' : 'mdi-play'",), + icon=( + "animation_play && animation_direction === 'reverse' ? 'mdi-stop' : 'mdi-play'", + ), flat=True, - click="animation_play = !animation_play", - disabled=("capture_recording",), + click="if (animation_play && animation_direction === 'reverse') { animation_play = false } else { animation_direction = 'reverse'; animation_play = true }", + disabled=( + "capture_recording || (animation_play && animation_direction === 'forward')", + ), + style="transform: scaleX(-1);", + ) + v3.VIconBtn( + icon=( + "animation_play && animation_direction === 'forward' ? 'mdi-stop' : 'mdi-play'", + ), + flat=True, + click="if (animation_play && animation_direction === 'forward') { animation_play = false } else { animation_direction = 'forward'; animation_play = true }", + disabled=( + "capture_recording || (animation_play && animation_direction === 'reverse')", + ), ) v3.VDivider(vertical=True, classes="mx-2") @@ -572,7 +587,13 @@ async def _run_animation(self): with self.state as s: while s.animation_play: await asyncio.sleep(0.1) - if s.animation_step < s.animation_step_max: - await self._step_to(s.animation_step + 1) + if s.animation_direction == "reverse": + if s.animation_step > 0: + await self._step_to(s.animation_step - 1) + else: + await self._step_to(s.animation_step_max) else: - s.animation_play = False + if s.animation_step < s.animation_step_max: + await self._step_to(s.animation_step + 1) + else: + await self._step_to(0)