Skip to content

Commit

Permalink
Clean up app wrapper MVC
Browse files Browse the repository at this point in the history
  • Loading branch information
edan-bainglass committed Dec 20, 2024
1 parent 5f57e25 commit 2fe1211
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 51 deletions.
2 changes: 1 addition & 1 deletion qe.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"metadata": {},
"outputs": [],
"source": [
"controller.enable_toggles()"
"controller.enable_controls()"
]
}
],
Expand Down
101 changes: 57 additions & 44 deletions src/aiidalab_qe/app/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ipywidgets as ipw
import traitlets as tl
from IPython.display import display
from IPython.display import Javascript, display

from aiidalab_qe.common.guide_manager import guide_manager
from aiidalab_qe.common.widgets import LoadingWidget
Expand Down Expand Up @@ -48,10 +48,10 @@ def __init__(
self._view = view
self._set_event_handlers()

def enable_toggles(self) -> None:
"""Enable the toggle buttons."""
self._view.guide_toggle.disabled = False
self._view.about_toggle.disabled = False
def enable_controls(self) -> None:
"""Enable the control buttons at the top of the app."""
for control in self._view.controls.children:
control.disabled = False

@without_triggering("about_toggle")
def _on_guide_toggle(self, change: dict):
Expand Down Expand Up @@ -82,29 +82,35 @@ def _on_about_toggle(self, change: dict):
self._view.info_container.children = []
self._view.info_container.layout.display = "none"

def _on_guide_category_select(self, change: dict):
self._view.guide_selection.options = guide_manager.get_guides(change["new"])
self._update_active_guide()
def _on_calculation_history_click(self, _):
self._open_external_notebook("./calculation_history.ipynb")

def _on_guide_select(self, _):
self._update_active_guide()
def _on_guide_category_selection_change(self, change):
self._model.guide_options = guide_manager.get_guides(change["new"])

def _update_active_guide(self):
"""Sets the current active guide."""
def _on_guide_selection_change(self, _):
category = self._view.guide_category_selection.value
guide = self._view.guide_selection.value
active_guide = f"{category}/{guide}" if category != "none" else category
guide_manager.active_guide = active_guide
self._model.update_active_guide(category, guide)

def _set_guide_category_options(self, _):
"""Fetch the available guides."""
self._view.guide_category_selection.options = [
"none",
*guide_manager.get_guide_categories(),
]
def _open_external_notebook(self, url):
"""Open an external notebook in a new tab."""
display(Javascript(f"window.open('{url}', '_blank')"))

def _set_event_handlers(self) -> None:
"""Set up event handlers."""
self._model.observe(
self._on_guide_category_selection_change,
"selected_guide_category",
)
self._model.observe(
self._on_guide_selection_change,
[
"selected_guide_category",
"selected_guide",
],
)

self._view.guide_toggle.observe(
self._on_guide_toggle,
"value",
Expand All @@ -113,22 +119,38 @@ def _set_event_handlers(self) -> None:
self._on_about_toggle,
"value",
)
self._view.guide_category_selection.observe(
self._on_guide_category_select,
"value",
self._view.calculation_history_link.on_click(self._on_calculation_history_click)

ipw.dlink(
(self._model, "guide_category_options"),
(self._view.guide_category_selection, "options"),
)
self._view.guide_selection.observe(
self._on_guide_select,
"value",
ipw.link(
(self._model, "selected_guide_category"),
(self._view.guide_category_selection, "value"),
)
ipw.dlink(
(self._model, "guide_options"),
(self._view.guide_selection, "options"),
)
ipw.link(
(self._model, "selected_guide"),
(self._view.guide_selection, "value"),
)
self._view.on_displayed(self._set_guide_category_options)


class AppWrapperModel(tl.HasTraits):
"""An MVC model for `AppWrapper`."""

def __init__(self):
"""`AppWrapperModel` constructor."""
guide_category_options = tl.List(["none", *guide_manager.get_guide_categories()])
selected_guide_category = tl.Unicode("none")
guide_options = tl.List(tl.Unicode())
selected_guide = tl.Unicode(None, allow_none=True)

def update_active_guide(self, category, guide):
"""Sets the current active guide."""
active_guide = f"{category}/{guide}" if category != "none" else category
guide_manager.active_guide = active_guide


class AppWrapperView(ipw.VBox):
Expand Down Expand Up @@ -184,24 +206,23 @@ def __init__(self) -> None:
disabled=True,
)

self.calculation_history_button = ipw.Button(
self.calculation_history_link = ipw.Button(
layout=ipw.Layout(width="auto"),
button_style="",
icon="list",
description="Calculation history",
tooltip="View all calculations run with this app",
disabled=True,
)

self.calculation_history_button.on_click(self._open_calculation_history)

info_toggles = ipw.HBox(
self.controls = ipw.HBox(
children=[
self.guide_toggle,
self.about_toggle,
self.calculation_history_button,
self.calculation_history_link,
]
)
info_toggles.add_class("info-toggles")
self.controls.add_class("info-toggles")

env = Environment()
guide_template = files(templates).joinpath("guide.jinja").read_text()
Expand All @@ -211,9 +232,7 @@ def __init__(self) -> None:
self.about = ipw.HTML(env.from_string(about_template).render())

self.guide_category_selection = ipw.RadioButtons(
options=["none"],
description="Guides:",
value="none",
layout=ipw.Layout(width="max-content"),
)
self.guide_selection = ipw.RadioButtons(layout=ipw.Layout(margin="2px 20px"))
Expand All @@ -224,7 +243,7 @@ def __init__(self) -> None:
children=[
logo,
subtitle,
info_toggles,
self.controls,
self.info_container,
],
)
Expand All @@ -249,9 +268,3 @@ def __init__(self) -> None:
footer,
],
)

def _open_calculation_history(self, _):
from IPython.display import Javascript

url = "./calculation_history.ipynb"
display(Javascript(f"window.open('{url}', '_blank')"))
12 changes: 6 additions & 6 deletions tests/test_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@


class TestWrapper:
def test_enable_toggles(self):
"""Test enable_toggles method."""
def test_enable_controls(self):
"""Test enable_controls method."""
self._instansiate_mvc_components()
assert self.view.guide_toggle.disabled is True
assert self.view.about_toggle.disabled is True
self.controller.enable_toggles()
self.controller.enable_controls()
assert self.view.guide_toggle.disabled is False
assert self.view.about_toggle.disabled is False

def test_guide_toggle(self):
"""Test guide_toggle method."""
self._instansiate_mvc_components()
self.controller.enable_toggles()
self.controller.enable_controls()
self.controller._on_guide_toggle({"new": True})
self._assert_guide_is_on()
self.controller._on_guide_toggle({"new": False})
Expand All @@ -23,7 +23,7 @@ def test_guide_toggle(self):
def test_about_toggle(self):
"""Test about_toggle method."""
self._instansiate_mvc_components()
self.controller.enable_toggles()
self.controller.enable_controls()
self.controller._on_about_toggle({"new": True})
self._assert_about_is_on()
self.controller._on_about_toggle({"new": False})
Expand All @@ -32,7 +32,7 @@ def test_about_toggle(self):
def test_toggle_switch(self):
"""Test toggle_switch method."""
self._instansiate_mvc_components()
self.controller.enable_toggles()
self.controller.enable_controls()
self._assert_no_info()
self.controller._on_guide_toggle({"new": True})
self._assert_guide_is_on()
Expand Down

0 comments on commit 2fe1211

Please sign in to comment.