# Copyright 2017 Canonical, Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from urwid import ( ACTIVATE, AttrWrap, connect_signal, LineBox, Padding as UrwidPadding, PopUpLauncher, SelectableIcon, Text, ) from subiquitycore.ui.container import ( Columns, ListBox, WidgetWrap, ) from subiquitycore.ui.utils import ClickableIcon class _PopUpSelectDialog(WidgetWrap): """A list of PopUpButtons with a box around them.""" def __init__(self, parent, cur_index): self.parent = parent group = [] for i, option in enumerate(self.parent._options): if option.enabled: btn = ClickableIcon(" " + option.label) connect_signal(btn, 'click', self.click, i) if i == cur_index: rhs = '\N{BLACK LEFT-POINTING SMALL TRIANGLE} ' else: rhs = ' ' btn = Columns([ btn, (2, Text(rhs)), ]) btn = AttrWrap(btn, 'menu_button', 'menu_button focus') else: btn = Text(" " + option.label) btn = AttrWrap(btn, 'info_minor') btn = UrwidPadding(btn, width=self.parent._padding.width) group.append(btn) list_box = ListBox(group) list_box.base_widget.focus_position = cur_index super().__init__(LineBox(list_box)) def click(self, btn, index): self.parent.index = index self.parent.close_pop_up() def keypress(self, size, key): if key == 'esc': self.parent.close_pop_up() else: return super().keypress(size, key) class SelectorError(Exception): pass class Option: def __init__(self, val): if not isinstance(val, tuple): if not isinstance(val, str): raise SelectorError("invalid option %r", val) self.label = val self.enabled = True self.value = val elif len(val) == 1: self.label = val[0] self.enabled = True self.value = val[0] elif len(val) == 2: self.label = val[0] self.enabled = val[1] self.value = val[0] elif len(val) == 3: self.label = val[0] self.enabled = val[1] self.value = val[2] else: raise SelectorError("invalid option %r", val) class _Launcher(PopUpLauncher): # PopUpLauncher is a WidgetDecoration, which means base_widget # steps past it. This means that if Selector just inherited from # PopUpLauncher, calling .base_widget on a (say) Padding # containing a Selector would return the SelectableIcon, not the # Selector. This is unhelpful, to put it mildly, so we do some # proxying about so that PopUpLauncher can inherit from WidgetWrap # instead. def __init__(self, parent, child): self.parent = parent super().__init__(child) def create_pop_up(self): return self.parent.create_pop_up() def get_pop_up_parameters(self): return self.parent.get_pop_up_parameters() class Selector(WidgetWrap): """A widget that allows the user to chose between options by popping up a list of options. (A bit like