From e0be0538161953f98130d89975281cf7d3974b13 Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Wed, 4 Nov 2020 00:22:05 +0100 Subject: [PATCH] Toggle button for Periodic table Change container height when toggling to simulate an accordion kind effect. Add `embedded` option to OptimadeQueryFilterWidget. --- optimade_client/query_filter.py | 3 +- optimade_client/subwidgets/filter_inputs.py | 15 +++++-- optimade_client/subwidgets/periodic_table.py | 42 ++++++++++++++++++-- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/optimade_client/query_filter.py b/optimade_client/query_filter.py index 4ce88567..99d7b1a1 100644 --- a/optimade_client/query_filter.py +++ b/optimade_client/query_filter.py @@ -48,6 +48,7 @@ def __init__( self, result_limit: int = None, button_style: Union[ButtonStyle, str] = None, + embedded: bool = False, **kwargs, ): self.page_limit = result_limit if result_limit else 10 @@ -75,7 +76,7 @@ def __init__( self.filter_header = ipw.HTML( '

Apply filters

' ) - self.filters = FilterTabs() + self.filters = FilterTabs(show_large_filters=not embedded) self.filters.freeze() self.filters.on_submit(self.retrieve_data) diff --git a/optimade_client/subwidgets/filter_inputs.py b/optimade_client/subwidgets/filter_inputs.py index 026e4d56..1256ae21 100644 --- a/optimade_client/subwidgets/filter_inputs.py +++ b/optimade_client/subwidgets/filter_inputs.py @@ -19,11 +19,11 @@ class FilterTabs(ipw.Tab): """Separate filter inputs into tabs""" - def __init__(self, **kwargs): + def __init__(self, show_large_filters: bool = True): sections: Tuple[Tuple[str, FilterTabSection]] = ( - ("Basic", FilterInputs()), + ("Basic", FilterInputs(show_large_filters=show_large_filters)), # ("Advanced", ipw.HTML("This input tab has not yet been implemented.")), - ("Raw", FilterRaw()), + ("Raw", FilterRaw(show_large_filters=show_large_filters)), ) super().__init__( @@ -74,6 +74,10 @@ class FilterTabSection(ipw.VBox): range_nx = traitlets.Dict(allow_none=True) + def __init__(self, show_large_filters: bool = True, **kwargs): + super().__init__(**kwargs) + self._show_large_filters = show_large_filters + @traitlets.observe("range_nx") def update_ranged_inputs(self, change: dict): """Update ranged inputs' min/max values""" @@ -334,6 +338,7 @@ class FilterInputs(FilterTabSection): "unselected_color": "#5096f1", # Blue "selected_colors": ["#66BB6A", "#EF5350"], # Green, red "border_color": "#000000", # Black + "extended": "self._show_large_filters", }, ), ( @@ -394,6 +399,7 @@ class FilterInputs(FilterTabSection): } def __init__(self, **kwargs): + self._show_large_filters = kwargs.get("show_large_filters", True) self.query_fields: Dict[str, FilterInput] = {} self._layout = ipw.Layout(width="auto") @@ -492,6 +498,9 @@ def new_section( for user_input in inputs: input_config = user_input[1] if isinstance(input_config, dict): + for key, value in input_config.items(): + if isinstance(value, str) and value.startswith("self."): + input_config[key] = getattr(self, value[len("self.") :]) new_input = FilterInput(**input_config) else: new_input = FilterInput(field=input_config) diff --git a/optimade_client/subwidgets/periodic_table.py b/optimade_client/subwidgets/periodic_table.py index ee778780..ce6cd19f 100644 --- a/optimade_client/subwidgets/periodic_table.py +++ b/optimade_client/subwidgets/periodic_table.py @@ -3,6 +3,7 @@ from widget_periodictable import PTableWidget from optimade_client.logger import LOGGER +from optimade_client.utils import ButtonStyle __all__ = ("PeriodicTable",) @@ -11,20 +12,38 @@ class PeriodicTable(ipw.VBox): """Wrapper-widget for PTableWidget""" - def __init__(self, **kwargs): + def __init__(self, extended: bool = True, **kwargs): self._disabled = kwargs.get("disabled", False) + self.toggle_button = ipw.ToggleButton( + value=extended, + description="Hide Periodic Table" if extended else "Show Periodic Table", + button_style=ButtonStyle.INFO.value, + icon="flask", + tooltip="Hide Periodic Table" if extended else "Show Periodic Table", + layout={"width": "auto"}, + ) self.select_any_all = ipw.Checkbox( value=False, description="Structure must ex-/include ALL chosen elements", indent=False, layout={"width": "auto"}, - disabled=kwargs.get("disabled", False), + disabled=self.disabled, ) self.ptable = PTableWidget(**kwargs) + self.ptable_container = ipw.VBox( + children=(self.select_any_all, self.ptable), + layout={ + "width": "auto", + "height": "auto" if extended else "0px", + "visibility": "visible" if extended else "hidden", + }, + ) + + self.toggle_button.observe(self._toggle_widget, names="value") super().__init__( - children=(self.select_any_all, self.ptable), + children=(self.toggle_button, self.ptable_container), layout=kwargs.get("layout", {}), ) @@ -67,3 +86,20 @@ def freeze(self): def unfreeze(self): """Activate widget (in its current state)""" self.disabled = False + + def _toggle_widget(self, change: dict): + """Hide or show the widget according to the toggle button""" + if change["new"]: + # Show widget + LOGGER.debug("Show widget since toggle is %s", change["new"]) + self.ptable_container.layout.visibility = "visible" + self.ptable_container.layout.height = "auto" + self.toggle_button.tooltip = "Hide Periodic Table" + self.toggle_button.description = "Hide Periodic Table" + else: + # Hide widget + LOGGER.debug("Hide widget since toggle is %s", change["new"]) + self.ptable_container.layout.visibility = "hidden" + self.ptable_container.layout.height = "0px" + self.toggle_button.tooltip = "Show Periodic Table" + self.toggle_button.description = "Show Periodic Table"