From 6c8bd40a7a30acb4130a9a2ed69ea37ea461acbf Mon Sep 17 00:00:00 2001 From: Matt Craig Date: Mon, 29 Apr 2024 16:59:29 -0500 Subject: [PATCH 1/2] Better handle disabling widgets when displaying --- stellarphot/settings/custom_widgets.py | 11 +++++++- .../settings/tests/test_custom_widgets.py | 27 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/stellarphot/settings/custom_widgets.py b/stellarphot/settings/custom_widgets.py index ef180994..888d121b 100644 --- a/stellarphot/settings/custom_widgets.py +++ b/stellarphot/settings/custom_widgets.py @@ -4,6 +4,7 @@ import ipywidgets as ipw import traitlets as tr from ipyautoui.autoobject import AutoObject +from ipyautoui.custom.iterable import ItemBox from stellarphot.settings import ( Camera, @@ -239,8 +240,16 @@ def _set_disable_state_nested_models(self, top, value): State that ``disabled`` should be set to. """ - if hasattr(top, "disabled") or isinstance(top, AutoObject): + if isinstance(top, AutoObject): top.disabled = value + elif isinstance(top, ItemBox): + if value: + # Disabled, so do not show the add/remove buttons + top.add_remove_controls = "none" + else: + # Enabled, so show the add/remove buttons + top.add_remove_controls = "add_remove" + try: for child in top.children: self._set_disable_state_nested_models(child, value) diff --git a/stellarphot/settings/tests/test_custom_widgets.py b/stellarphot/settings/tests/test_custom_widgets.py index 1e4bcd32..9760db33 100644 --- a/stellarphot/settings/tests/test_custom_widgets.py +++ b/stellarphot/settings/tests/test_custom_widgets.py @@ -1,5 +1,6 @@ import ipywidgets as ipw import pytest +from ipyautoui.custom.iterable import ItemBox, ItemControl from stellarphot.settings import Camera, Observatory, PassbandMap, SavedSettings from stellarphot.settings.custom_widgets import ChooseOrMakeNew, Confirm @@ -198,6 +199,32 @@ def test_make_passband_map(self, tmp_path): assert len(choose_or_make_new._choose_existing.options) == 2 assert choose_or_make_new._choose_existing.options[0][0] == passband_map.name + def test_passband_map_buttons_are_disabled(self, tmp_path): + # When an existing PassbandMap is selected the add/remove buttons + # for individual rows should not be displayed. + saved = SavedSettings(_testing_path=tmp_path) + passband_map = PassbandMap(**DEFAULT_PASSBAND_MAP) + saved.add_item(passband_map) + + choose_or_make_new = ChooseOrMakeNew("passband_map", _testing_path=tmp_path) + + # There is no great way to get to the ItemBox widget that contains and controls + # the add/remove buttons, so we keep going down through widget children until we + # get to an ItemBox and then check that the buttons are disabled. + # Recursion is the easiest way to do that, so recurse we will.. + def find_item_box(top_widget): + for kid in top_widget.children: + if isinstance(kid, ItemBox): + return kid + if hasattr(kid, "children"): + result = find_item_box(kid) + if result: + return result + + item_box = find_item_box(choose_or_make_new) + print(f"{item_box.add_remove_controls=}") + assert item_box.add_remove_controls == ItemControl.none + class TestConfirm: def test_initial_value(self): From 66e376d77f6f8a077ee4e07cbd28d5e71020aa08 Mon Sep 17 00:00:00 2001 From: Matt Craig Date: Mon, 29 Apr 2024 18:48:53 -0500 Subject: [PATCH 2/2] Test enabling and disabling --- .../settings/tests/test_custom_widgets.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/stellarphot/settings/tests/test_custom_widgets.py b/stellarphot/settings/tests/test_custom_widgets.py index 9760db33..690ed9a3 100644 --- a/stellarphot/settings/tests/test_custom_widgets.py +++ b/stellarphot/settings/tests/test_custom_widgets.py @@ -188,18 +188,7 @@ def test_choosing_different_item_updates_display(self, tmp_path): # The item widget should now have the values of the second observatory assert Observatory(**choose_or_make_new._item_widget.value) == observatory2 - def test_make_passband_map(self, tmp_path): - # Make a passband map and save it, then check that it is in the dropdown - saved = SavedSettings(_testing_path=tmp_path) - passband_map = PassbandMap(**DEFAULT_PASSBAND_MAP) - saved.add_item(passband_map) - - # Should create a new passband map - choose_or_make_new = ChooseOrMakeNew("passband_map", _testing_path=tmp_path) - assert len(choose_or_make_new._choose_existing.options) == 2 - assert choose_or_make_new._choose_existing.options[0][0] == passband_map.name - - def test_passband_map_buttons_are_disabled(self, tmp_path): + def test_passband_map_buttons_are_disabled_or_enabled(self, tmp_path): # When an existing PassbandMap is selected the add/remove buttons # for individual rows should not be displayed. saved = SavedSettings(_testing_path=tmp_path) @@ -222,9 +211,24 @@ def find_item_box(top_widget): return result item_box = find_item_box(choose_or_make_new) - print(f"{item_box.add_remove_controls=}") assert item_box.add_remove_controls == ItemControl.none + # Next, we will click the "Edit" button and check that the buttons are enabled. + choose_or_make_new._edit_button.click() + item_box = find_item_box(choose_or_make_new) + assert item_box.add_remove_controls == ItemControl.add_remove + + def test_make_passband_map(self, tmp_path): + # Make a passband map and save it, then check that it is in the dropdown + saved = SavedSettings(_testing_path=tmp_path) + passband_map = PassbandMap(**DEFAULT_PASSBAND_MAP) + saved.add_item(passband_map) + + # Should create a new passband map + choose_or_make_new = ChooseOrMakeNew("passband_map", _testing_path=tmp_path) + assert len(choose_or_make_new._choose_existing.options) == 2 + assert choose_or_make_new._choose_existing.options[0][0] == passband_map.name + class TestConfirm: def test_initial_value(self):