From 684242078d2044ad0f293065ea5a59a094b3df66 Mon Sep 17 00:00:00 2001 From: Alexander Goscinski Date: Fri, 22 Dec 2023 16:53:51 +0100 Subject: [PATCH] add exercise title and description to CodeDemo and exercise.Textarea --- .../answer/_widget_answer_registry.py | 3 -- src/scwidgets/code/_widget_code_demo.py | 38 ++++++++++++++- src/scwidgets/css/widgets.css | 19 ++++++++ src/scwidgets/exercise/_widget_textarea.py | 47 +++++++++++++++---- 4 files changed, 95 insertions(+), 12 deletions(-) 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}