From b5436b65046db6b92ae322234a9bfe1a6e004470 Mon Sep 17 00:00:00 2001 From: Alexandra Ioan Date: Tue, 5 May 2026 12:30:47 +0200 Subject: [PATCH 1/3] use tabs instead of accordions --- .../gui/shape_editor/shape_editor.py | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/waveform_editor/gui/shape_editor/shape_editor.py b/waveform_editor/gui/shape_editor/shape_editor.py index 5aba3288..855dfa56 100644 --- a/waveform_editor/gui/shape_editor/shape_editor.py +++ b/waveform_editor/gui/shape_editor/shape_editor.py @@ -80,37 +80,38 @@ def __init__(self, main_gui): ) buttons = pn.Row(button_start, button_stop, nice_mode_radio) - # Accordion does not allow dynamic titles, so use separate card for each option - options = pn.Column( + settings_options = pn.Column( self._create_card( nice_settings_panel(self.nice_settings), "NICE Configuration", is_valid=self.nice_settings.param.are_required_filled.rx(), ), self._create_card(self.nice_plotter, "Plotting Parameters"), - self._create_card( - self.plasma_shape, - "Plasma Shape", - is_valid=self.plasma_shape.param.has_shape, - visible=self.nice_settings.param.is_inverse_mode.rx(), - ), - self._create_card( - pn.Column(self.plasma_properties, self.nice_plotter.profiles_pane), - "Plasma Properties", - is_valid=self.plasma_properties.param.has_properties, - ), - self._create_card(self.coil_currents, "Coil Currents"), ) + + options = pn.bind(self._create_options_tabs, + self.nice_settings.param.is_inverse_mode) menu = pn.Column(buttons, self.terminal, sizing_mode="stretch_width") self.panel = pn.Row( self.nice_plotter.flux_map_pane, pn.Column( menu, + settings_options, options, sizing_mode="stretch_both", ), ) + def _create_options_tabs(self, is_inverse_mode): + items = [] + if is_inverse_mode: + items.append(("Shape", self.plasma_shape)) + items.append(("Properties", pn.Column(self.plasma_properties, + self.nice_plotter.profiles_pane))) + items.append(("Coils", self.coil_currents)) + return pn.Tabs(*items, sizing_mode="stretch_width", + stylesheets=[".bk-tab { flex: 1; text-align: center; }"]) + def _create_card(self, panel_object, title, is_valid=None, visible=True): """Create a collapsed card containing a panel object and a title. From f373a048bcdc108f86e0b0408d354eb05719743e Mon Sep 17 00:00:00 2001 From: Alexandra Ioan Date: Tue, 5 May 2026 12:31:52 +0200 Subject: [PATCH 2/3] use tabs instead of accordions --- .../gui/shape_editor/shape_editor.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/waveform_editor/gui/shape_editor/shape_editor.py b/waveform_editor/gui/shape_editor/shape_editor.py index 855dfa56..7369dce5 100644 --- a/waveform_editor/gui/shape_editor/shape_editor.py +++ b/waveform_editor/gui/shape_editor/shape_editor.py @@ -89,8 +89,9 @@ def __init__(self, main_gui): self._create_card(self.nice_plotter, "Plotting Parameters"), ) - options = pn.bind(self._create_options_tabs, - self.nice_settings.param.is_inverse_mode) + options = pn.bind( + self._create_options_tabs, self.nice_settings.param.is_inverse_mode + ) menu = pn.Column(buttons, self.terminal, sizing_mode="stretch_width") self.panel = pn.Row( self.nice_plotter.flux_map_pane, @@ -106,11 +107,18 @@ def _create_options_tabs(self, is_inverse_mode): items = [] if is_inverse_mode: items.append(("Shape", self.plasma_shape)) - items.append(("Properties", pn.Column(self.plasma_properties, - self.nice_plotter.profiles_pane))) + items.append( + ( + "Properties", + pn.Column(self.plasma_properties, self.nice_plotter.profiles_pane), + ) + ) items.append(("Coils", self.coil_currents)) - return pn.Tabs(*items, sizing_mode="stretch_width", - stylesheets=[".bk-tab { flex: 1; text-align: center; }"]) + return pn.Tabs( + *items, + sizing_mode="stretch_width", + stylesheets=[".bk-tab { flex: 1; text-align: center; }"], + ) def _create_card(self, panel_object, title, is_valid=None, visible=True): """Create a collapsed card containing a panel object and a title. From 42f29c02b842bc6186574769b18a59f5af4c5618 Mon Sep 17 00:00:00 2001 From: Alexandra Ioan Date: Tue, 19 May 2026 14:08:27 +0200 Subject: [PATCH 3/3] restore --- .../gui/shape_editor/shape_editor.py | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/waveform_editor/gui/shape_editor/shape_editor.py b/waveform_editor/gui/shape_editor/shape_editor.py index fa9a20f9..af1000b1 100644 --- a/waveform_editor/gui/shape_editor/shape_editor.py +++ b/waveform_editor/gui/shape_editor/shape_editor.py @@ -66,14 +66,7 @@ def __init__(self, main_gui): ) # UI Configuration - button_start = pn.widgets.Button( - name="Run", - button_type="primary", - icon="player-play", - on_click=self.submit, - margin=(10, 0, 2, 0), - ) - button_start.disabled = ( + disabled_expr = ( ( self.plasma_shape.param.has_shape.rx.not_() & self.nice_settings.param.is_inverse_mode.rx() @@ -81,6 +74,22 @@ def __init__(self, main_gui): | self.plasma_properties.param.has_properties.rx.not_() | self.nice_settings.param.are_required_filled.rx.not_() ) + button_start = pn.widgets.Button( + name="Run", + button_type="primary", + icon="player-play", + on_click=self.submit, + description=pn.bind( + lambda disabled: ( + "Cannot run: missing required inputs" + if disabled + else "Run simulation" + ), + disabled_expr, + ), + disabled=disabled_expr, + margin=(10, 0, 2, 0), + ) button_stop = pn.widgets.Button( name="Stop", button_type="danger", @@ -168,26 +177,34 @@ def _load_slice(self, uri, ids_name, time=0): except Exception as e: pn.state.notifications.error(str(e)) - @param.depends("nice_settings.md_pf_active", watch=True) + @param.depends("nice_settings.md_pf_active.uri", watch=True) def _load_pf_active(self): - self.pf_active = self._load_slice(self.nice_settings.md_pf_active, "pf_active") + self.pf_active = self._load_slice( + self.nice_settings.md_pf_active.uri, "pf_active" + ) self.nice_plotter.pf_active = self.pf_active self.coil_currents.create_ui(self.pf_active) + self.nice_settings.md_pf_active.loaded = self.pf_active is not None - @param.depends("nice_settings.md_pf_passive", watch=True) + @param.depends("nice_settings.md_pf_passive.uri", watch=True) def _load_pf_passive(self): self.pf_passive = self._load_slice( - self.nice_settings.md_pf_passive, "pf_passive" + self.nice_settings.md_pf_passive.uri, "pf_passive" ) + self.nice_settings.md_pf_passive.loaded = self.pf_passive is not None - @param.depends("nice_settings.md_wall", watch=True) + @param.depends("nice_settings.md_wall.uri", watch=True) def _load_wall(self): - self.wall = self._load_slice(self.nice_settings.md_wall, "wall") + self.wall = self._load_slice(self.nice_settings.md_wall.uri, "wall") self.nice_plotter.wall = self.wall + self.nice_settings.md_wall.loaded = self.wall is not None - @param.depends("nice_settings.md_iron_core", watch=True) + @param.depends("nice_settings.md_iron_core.uri", watch=True) def _load_iron_core(self): - self.iron_core = self._load_slice(self.nice_settings.md_iron_core, "iron_core") + self.iron_core = self._load_slice( + self.nice_settings.md_iron_core.uri, "iron_core" + ) + self.nice_settings.md_iron_core.loaded = self.iron_core is not None def _create_equilibrium(self): """Create an empty equilibrium IDS and fill the plasma shape parameters and