1717class StageWidget (VBox ):
1818 """A specialized VBox widget for a stage in the case configurator."""
1919
20- def __init__ (self , main_body_type = VBox , title = "" , layout = {}, ** kwargs ):
20+ def __init__ (self , main_body_type = VBox , supplementary_widgets = [], add_ok_button = False , title = "" , layout = {}, ** kwargs ):
2121 """Initialize the StageWidget.
2222
2323 Parameters
2424 ----------
2525 main_body_type : VBox, HBox, or Tab
2626 The type of the main body of the StageWidget.
27+ supplementary_widgets : list
28+ A list of supplementary widgets to be added to the StageWidget.
29+ add_ok_button : bool
30+ Whether to add an OK button to the StageWidget. Defaults to False.
2731 title : str
2832 The title of the StageWidget.
2933 layout : dict
@@ -41,10 +45,13 @@ def __init__(self, main_body_type=VBox, title="", layout={}, **kwargs):
4145 HBox ,
4246 Tab ,
4347 ], "StageWidget main_body_type must be VBox, HBox, or Tab"
48+ assert isinstance (
49+ supplementary_widgets , (list , tuple )
50+ ), "StageWidget supplementary_widgets must be a list"
4451 self ._main_body_type = main_body_type
4552 self ._title = title
46- self ._main_body = None
47- self ._main_body = self . _gen_main_body ( children = ())
53+ self ._main_body = self . _main_body_type ()
54+ self ._supplementary_widgets = supplementary_widgets
4855 self ._top_bar = HBox ([])
4956 self ._stage = None # Reference to the stage object that this widget represents. To be set by the stage object.
5057 super ().__init__ (
@@ -55,6 +62,21 @@ def __init__(self, main_body_type=VBox, title="", layout={}, **kwargs):
5562 },
5663 ** kwargs ,
5764 )
65+ self .children = (
66+ self ._top_bar ,
67+ self ._main_body ,
68+ )
69+
70+ self ._ok_button = None # OK button, if added
71+ if add_ok_button :
72+ self ._ok_button = Button (
73+ description = "OK" ,
74+ icon = "check" ,
75+ tooltip = "Confirm the selections in this stage." ,
76+ layout = {"width" : "100px" , "align_self" : "center" },
77+ style = {"button_color" : bg_color_dark , "text_color" : font_color_dark },
78+ )
79+ self ._ok_button .on_click (self .attempt_to_proceed )
5880
5981 def _update_top_bar_title (
6082 self , title_prefix = "" , font_color = "gray" , background_color = bg_color_light
@@ -153,59 +175,52 @@ def _on_btn_info_click(b):
153175 self ._btn_proceed .on_click (self .attempt_to_proceed )
154176 top_bar_buttons .append (self ._btn_proceed )
155177
156- self ._top_bar = HBox ( [self ._top_bar_title ] + top_bar_buttons )
178+ self ._top_bar . children = [self ._top_bar_title ] + top_bar_buttons
157179
158- def _gen_main_body (self , children ):
159- """Generate the main body of the StageWidget. This method is called whenever the children attribute is set.
180+ def _set_main_body_children (self , first_child = None ):
181+ """Set the children of the main body of the StageWidget. If a first_child is provided,
182+ it will be added to the main body, followed by all its siblings to the right."""
160183
161- Parameters
162- ----------
163- children : list
164- The new list of children of the main body.
184+ main_body_children = [var .widget for var in self ._stage ._varlist ]
185+ if self ._supplementary_widgets :
186+ main_body_children .extend (self ._supplementary_widgets )
187+ if self ._ok_button :
188+ main_body_children .append (self ._ok_button )
189+ if first_child :
190+ main_body_children .append (first_child ._widget )
191+ main_body_children .extend (stage ._widget for stage in first_child .siblings_to_right ())
192+ self ._main_body .children = tuple (main_body_children )
193+
194+ def _refresh_main_body (self ):
195+ """Generate the main body of the StageWidget. This method is called whenever the children attribute is set.
165196 """
166197
167198 old_display = ""
168199 if self ._main_body :
169200 old_display = self ._main_body .layout .display
170201
171- return self ._main_body_type (
172- children = children ,
173- layout = {
174- "display" : old_display ,
175- "margin" : "0px" ,
176- },
177- )
202+ self ._set_main_body_children ()
203+
204+ self ._main_body .layout = {
205+ "display" : old_display ,
206+ "margin" : "0px" ,
207+ }
178208
179- def __setattr__ (self , name , value ):
180- """Override the __setattr__ method to handle the children attribute so that the widget
181- always has two children: the top bar and the main body. Any new children, unless they
182- are the top bar or the main body, are added to the main body. If the children attribute
183- is set, the top bar and the main body are updated accordingly.
209+ def add_child_stages (self , first_child ):
210+ """Append a child stage and all its siblings to the main body, which, by default,
211+ has the widgets of the varlist only, but may be extended to include the StageWidget
212+ instances of child stages.
184213
185214 Parameters
186215 ----------
187- name : str
188- The name of the attribute to set.
189- value : any
190- The value to set the attribute to.
216+ first_child : Stage
217+ The first child stage to append.
191218 """
192-
193- if name == "children" :
194- if len (value ) > 0 and value [0 ] is self ._top_bar :
195- value = value [1 :]
196- if len (value ) > 0 and value [0 ] is self ._main_body :
197- value = value [0 ].children + value [1 :]
198- self ._main_body = self ._gen_main_body (children = value )
199- super ().__setattr__ (
200- name ,
201- (
202- self ._top_bar ,
203- self ._main_body ,
204- ),
205- )
206- else :
207- # For all other attributes, use the default behavior
208- super ().__setattr__ (name , value )
219+ self ._set_main_body_children (first_child )
220+
221+ def remove_child_stages (self ):
222+ """Remove all child stages from the main body, leaving only the widgets of the varlist and supplementary widgets."""
223+ self ._set_main_body_children ()
209224
210225 @property
211226 def stage (self ):
@@ -220,7 +235,7 @@ def stage(self, value):
220235 # Set the children attribute. This will actually set the children of the StageWidget
221236 # to the top bar and the main body, and the main body's children to the widgets of the
222237 # variables in the stage.
223- self .children = [ var . widget for var in self . _stage . _varlist ]
238+ self ._refresh_main_body ()
224239 # Observe StageStat
225240 self ._stage .observe (self ._on_stage_status_change , names = "status" , type = "change" )
226241 self ._on_stage_status_change (
@@ -241,24 +256,6 @@ def _on_stage_status_change(self, change):
241256 self ._enable ()
242257 self ._update_btn_reset (old_state , new_state )
243258
244- def append_child_stages (self , first_child ):
245- """Append a child stage and all its siblings to the main body, which, by default,
246- has the widgets of the varlist only, but may be extended to include the StageWidget
247- instances of child stages.
248-
249- Parameters
250- ----------
251- first_child : Stage
252- The first child stage to append.
253- """
254-
255- self ._main_body .children = tuple (
256- itertools .chain (
257- [var .widget for var in self ._stage ._varlist ],
258- [first_child ._widget ],
259- [stage ._widget for stage in first_child .siblings_to_right ()],
260- )
261- )
262259
263260 def _disable (self ):
264261 """Disable the entire stage widget."""
@@ -345,4 +342,4 @@ def reset(self):
345342 """Reset the stage."""
346343 logger .debug (f"Resetting stage { self ._title } ..." )
347344 self ._stage .reset ()
348- self ._main_body . children = self . _stage ._gen_main_body ( children = () )
345+ self ._stage ._refresh_main_body ( )
0 commit comments