# Setup logging
log = logging.getLogger("bricklayer.tui")
+def abort():
+ raise InstallAbortedError
+
+def cancel():
+ raise UserCanceledError
+
class Tui(object):
def __init__(self, bricklayer):
self.bricklayer = bricklayer
if buttons is None:
buttons = (_("OK"), _("Cancel"))
- return snack.ButtonChoiceWindow(self.screen, title=title, text=text,
+ window = ButtonsWindow(self, title=title, text=text,
buttons=buttons, width=width, help=help)
+ return window.run()
+
def error(self, title, text, buttons=None, width=40):
if not buttons:
- buttons = [_("Abort Installation")]
+ buttons = [
+ (_("Abort Installation"), abort),
+ ]
return self.message(title, text, buttons=buttons, width=width)
def progress(self, *args, **kwargs):
return ProgressWindow(self, *args, **kwargs)
- def select(self, title, text, items, buttons=None, default=None, help=None, width=40):
- # Translate default
- if default:
- default = items.get(default, None)
-
- # Convert items into a list which is sorted by its values
- items = sorted(items.items(), key=lambda item: item[1])
+ def select(self, title, text, items, default=None, buttons=None, height=None,
+ width=40, help=None):
+ window = ListboxChoiceWindow(self, title, text, items, default=default,
+ buttons=buttons, height=height, width=width, help=help)
- # Set some default buttons
- if buttons is None:
- buttons = (_("Select"), _("Cancel"))
-
- # Show the window
- button, item = snack.ListboxChoiceWindow(self.screen, title, text,
- [value for key, value in items], buttons=buttons, default=default, help=help,
- width=width)
-
- # Find the selected item
- key, value = items[item]
-
- # Return the key
- return key
+ return window.run()
def multi_select(self, title, text, items, selection=[], buttons=None,
width=40, height=None, help=None):
return checkboxes.getSelection()
+class Window(object):
+ def __init__(self, tui, title, text, height=None, width=None, help=None):
+ self.tui = tui
+ self.title = title
+ self.text = text
+ self.height = height
+ self.width = width
+ self.help = help
+
+ @property
+ def max_height(self):
+ """
+ The maximum height of any window
+ """
+ return self.tui.screen.height - 12
+
+ def run(self):
+ raise NotImplementedError
+
+
+class ButtonsWindow(Window):
+ def __init__(self, tui, title, text, buttons=None, height=None, width=None, help=None):
+ Window.__init__(self, tui, title, text, height=height, width=width, help=help)
+
+ # Configure some default buttons
+ if buttons is None:
+ buttons = [
+ (_("Ok"), None),
+ (_("Cancel"), cancel),
+ ]
+
+ self.buttons = snack.ButtonBar(self.tui.screen, buttons)
+
+ def _make_window(self):
+ # Create a grid
+ grid = snack.GridFormHelp(self.tui.screen, self.title, self.help, 1, 2)
+
+ # Create the box that shows the text
+ textbox = snack.TextboxReflowed(self.width, self.text, maxHeight=self.max_height)
+ grid.add(textbox, 0, 0, padding=(0, 0, 0, 1))
+
+ # Create the button bar
+ grid.add(self.buttons, 0, 1, growx=True)
+
+ return grid
+
+ def run(self):
+ window = self._make_window()
+
+ # Run the window
+ button = window.runOnce()
+
+ # Which button was pressed?
+ callback = self.buttons.buttonPressed(button)
+
+ # If the button had a callback, we will call the callback
+ if callable(callback):
+ return callback()
+
+ # Otherwise call the default action
+ return self.default_action()
+
+ def default_action(self):
+ """
+ Called when a button did not have a callback
+ """
+ pass
+
+
+class ListboxChoiceWindow(ButtonsWindow):
+ def __init__(self, tui, title, text, items, default=None, buttons=None, height=None,
+ width=None, help=None):
+ # Set height to number of items by default
+ if height is None:
+ height = len(items)
+
+ # Set some default buttons
+ if buttons is None:
+ buttons = [
+ (_("Select"), None),
+ (_("Cancel"), cancel),
+ ]
+
+ super().__init__(tui, title, text, buttons=buttons,
+ height=height, width=width, help=help)
+
+ self.items = items
+ self.default = default
+
+ # Should we enable scrolling?
+ scroll = height < len(items)
+
+ # Create the list box
+ self.listbox = snack.Listbox(self.height, scroll=scroll, returnExit=True)
+ for key in self.items:
+ self.listbox.append(self.items[key], key)
+
+ # Set the default value
+ if self.default:
+ self.listbox.setCurrent(self.default)
+
+ def _make_window(self):
+ # Create a grid
+ grid = snack.GridFormHelp(self.tui.screen, self.title, self.help, 1, 3)
+
+ # Create the text box
+ textbox = snack.TextboxReflowed(self.width, self.text)
+ grid.add(textbox, 0, 0)
+
+ # Add the listbox
+ grid.add(self.listbox, 0, 1, padding=(0, 1, 0, 1))
+
+ # Add the buttons
+ grid.add(self.buttons, 0, 2, growx=True)
+
+ return grid
+
+ def default_action(self):
+ # Return the selected item
+ return self.listbox.current()
+
+
class ProgressWindow(object):
def __init__(self, tui, title, text, max_value=0, width=60, help=None):
self.tui = tui