diff --git a/src/scwidgets/answer/_widget_answer_registry.py b/src/scwidgets/answer/_widget_answer_registry.py
index 3d05760..0ad5131 100644
--- a/src/scwidgets/answer/_widget_answer_registry.py
+++ b/src/scwidgets/answer/_widget_answer_registry.py
@@ -260,9 +260,6 @@ def filename_prefix(self, filename_prefix: str):
dropdown_options = self._get_dropdown_options()
self._answers_files_dropdown.options = dropdown_options
- dropdown_options = self._get_dropdown_options()
- self._answers_files_dropdown.options = dropdown_options
-
@property
def registered_widgets(self):
return self._widgets.copy()
diff --git a/src/scwidgets/code/_widget_code_demo.py b/src/scwidgets/code/_widget_code_demo.py
index a55f926..fe28198 100644
--- a/src/scwidgets/code/_widget_code_demo.py
+++ b/src/scwidgets/code/_widget_code_demo.py
@@ -6,7 +6,7 @@
from platform import python_version
from typing import Any, Callable, Dict, List, Optional, Union
-from ipywidgets import Box, HBox, Layout, VBox, Widget
+from ipywidgets import HTML, Box, HBox, HTMLMath, Layout, VBox, Widget
from widget_code_input.utils import CodeValidationError
from .._utils import Printer
@@ -68,6 +68,8 @@ def __init__(
update_func: Optional[
Callable[[CodeDemo], Union[Any, Check.FunOutParamsT]]
] = None,
+ exercise_description: Optional[str] = None,
+ exercise_title: Optional[str] = None,
*args,
**kwargs,
):
@@ -81,6 +83,27 @@ def __init__(
self._update_func = update_func
+ self._exercise_description = exercise_description
+ if exercise_description is None:
+ self._exercise_description_html = None
+ else:
+ self._exercise_description_html = HTMLMath(self._exercise_description)
+ if exercise_title is None:
+ if answer_key is None:
+ self._exercise_title = None
+ self._exercise_title_html = None
+ else:
+ self._exercise_title = answer_key
+ self._exercise_title_html = HTML(f"{answer_key}")
+ else:
+ self._exercise_title = exercise_title
+ self._exercise_title_html = HTML(f"{exercise_title}")
+
+ if self._exercise_description_html is not None:
+ self._exercise_description_html.add_class("exercise-description")
+ if self._exercise_title_html is not None:
+ self._exercise_title_html.add_class("exercise-title")
+
# verify if input argument `parameter` is valid
if parameters is not None:
allowed_parameter_types = [dict, ParameterPanel]
@@ -372,6 +395,11 @@ def __init__(
)
demo_children = []
+ if self._exercise_title_html is not None:
+ demo_children.append(self._exercise_title_html)
+ if self._exercise_description_html is not None:
+ demo_children.append(self._exercise_description_html)
+
if self._cue_code is not None:
demo_children.append(self._cue_code)
if self._cue_parameter_panel is not None:
@@ -453,6 +481,14 @@ def panel_parameters(self) -> Dict[str, Check.FunInParamT]:
return parameter_panel.parameters
return {}
+ @property
+ def exercise_title(self) -> Union[str, None]:
+ return self._exercise_title
+
+ @property
+ def exercise_description(self) -> Union[str, None]:
+ return self._exercise_description
+
def _on_trait_parameters_changed(self, change: dict):
if self._update_button is None:
self._output.clear_output(wait=True)
diff --git a/src/scwidgets/css/widgets.css b/src/scwidgets/css/widgets.css
index a0644d7..ee94f32 100644
--- a/src/scwidgets/css/widgets.css
+++ b/src/scwidgets/css/widgets.css
@@ -111,3 +111,22 @@
.scwidget-cue-output--cue {
opacity: 0.4;
}
+
+.exercise-title {
+ font-family: helvetica;
+ font-size: 150%;
+}
+.exercise-description {
+ font-family: helvetica;
+ font-size: 110%;
+ color: black;
+ word-spacing: 2px;
+}
+
+a {
+ color: blue;
+}
+
+a:hover {
+ color: lightblue;
+}
diff --git a/src/scwidgets/exercise/_widget_textarea.py b/src/scwidgets/exercise/_widget_textarea.py
index f8fc981..d8615c7 100644
--- a/src/scwidgets/exercise/_widget_textarea.py
+++ b/src/scwidgets/exercise/_widget_textarea.py
@@ -1,7 +1,7 @@
from typing import Optional, Union
import ipywidgets
-from ipywidgets import HBox, Layout, Output, VBox
+from ipywidgets import HTML, HBox, HTMLMath, Layout, Output, VBox
from .._utils import Printer
from ..answer import AnswerRegistry, AnswerWidget
@@ -19,16 +19,37 @@ class Textarea(VBox, AnswerWidget):
def __init__(
self,
- textarea: Optional[ipywidgets.Textarea] = None,
- answer_registry: Optional[AnswerRegistry] = None,
+ value: Optional[str] = None,
answer_key: Optional[str] = None,
+ answer_registry: Optional[AnswerRegistry] = None,
+ exercise_description: Optional[str] = None,
+ exercise_title: Optional[str] = None,
*args,
**kwargs,
):
- if textarea is None:
- textarea = ipywidgets.Textarea(layout=Layout(width="auto"))
+ self._exercise_description = exercise_description
+ if exercise_description is None:
+ self._exercise_description_html = None
+ else:
+ self._exercise_description_html = HTMLMath(self._exercise_description)
+ if exercise_title is None:
+ if answer_key is None:
+ self._exercise_title = None
+ self._exercise_title_html = None
+ else:
+ self._exercise_title = answer_key
+ self._exercise_title_html = HTML(f"{answer_key}")
+ else:
+ self._exercise_title = exercise_title
+ self._exercise_title_html = HTML(f"{exercise_title}")
- self._textarea = textarea
+ if self._exercise_description_html is not None:
+ self._exercise_description_html.add_class("exercise-description")
+ if self._exercise_title_html is not None:
+ self._exercise_title_html.add_class("exercise-title")
+
+ layout = kwargs.pop("layout", Layout(width="auto", height="150px"))
+ self._textarea = ipywidgets.Textarea(value, *args, layout=layout, **kwargs)
self._cue_textarea = self._textarea
self._output = Output()
@@ -80,6 +101,10 @@ def __init__(
AnswerWidget.__init__(self, answer_registry, answer_key)
widget_children = []
+ if self._exercise_title_html is not None:
+ widget_children.append(self._exercise_title_html)
+ if self._exercise_description_html is not None:
+ widget_children.append(self._exercise_description_html)
widget_children.append(self._cue_textarea)
if self._button_panel:
widget_children.append(self._button_panel)
@@ -89,10 +114,16 @@ def __init__(
VBox.__init__(
self,
widget_children,
- *args,
- **kwargs,
)
+ @property
+ def exercise_title(self) -> Union[str, None]:
+ return self._exercise_title
+
+ @property
+ def exercise_description(self) -> Union[str, None]:
+ return self._exercise_description
+
@property
def answer(self) -> dict:
return {"textarea": self._textarea.value}