from asciimatics.exceptions import NextScene from asciimatics.widgets import Frame, Layout, Divider, Button, Label class CeoFrame(Frame): def __init__( self, screen, height, width, model, name, # key in model.viewdata on_load=None, title=None, save_data=False, # whether to save widget state for resizing ): super().__init__( screen, height, width, name=name, can_scroll=False, title=title, on_load=self._ceoframe_on_load, ) self._save_data = save_data self._extra_on_load = on_load self._model = model self._name = name self._loaded = False def _ceoframe_on_load(self): # We usually don't want _on_load() to be called multiple times # e.g. when switching back to a scene, or after calling reset() if self._loaded: return self._loaded = True if self._model.title is not None: self.title = self._model.title self._model.title = None if self._save_data: # restore the saved input fields' values self.data = self._model.viewdata[self._name] if self._extra_on_load is not None: self._extra_on_load() def _on_unload(self): if not self._save_data: return # save the input fields' values so that they don't disappear when # the window gets resized self.save() self._model.viewdata[self._name] = self.data def add_buttons( self, back_btn=False, back_btn_text='Back', next_scene=None, next_btn_text='Next', on_next=None, on_next_excl=None, ): """ Add a new layout at the bottom of the frame with buttons. If back_btn is True, a Back button is added. If next_scene is set to the name of the next scene, or on_next_excl is set, a Next button will be added. If on_next is set to a function, it will be called when the Next button is pressed, and the screen will switch to the next scene. If on_next_excl is set to a function, it will be called when the Next button is pressed, and the scene will not be switched. If both on_next and on_next_excl are set, on_next will be ignored. """ layout = Layout([100]) self.add_layout(layout) layout.add_widget(Divider()) def _back(): raise NextScene(self._model.scene_stack.pop()) def _next(): if on_next_excl is not None: on_next_excl() return if on_next is not None: on_next() self.go_to_next_scene(next_scene) layout = Layout([1, 1]) self.add_layout(layout) if back_btn: layout.add_widget(Button(back_btn_text, _back), 0) if next_scene is not None or on_next_excl is not None: layout.add_widget(Button(next_btn_text, _next), 1) def go_to_next_scene(self, next_scene: str): self._model.scene_stack.append(self._name) raise NextScene(next_scene) def add_flash_message_layout(self): layout = Layout([100]) self.add_layout(layout) self._status_label = Label('') layout.add_widget(self._status_label) def flash_message(self, msg: str, force_update: bool = False): self._status_label.text = msg if force_update: self._model.screen.force_update() self._model.screen.draw_next_frame() def clear_flash_message(self): self.flash_message('')