diff --git a/subiquity/ui/views/bcache.py b/subiquity/ui/views/bcache.py index 54ce630f..4af618da 100644 --- a/subiquity/ui/views/bcache.py +++ b/subiquity/ui/views/bcache.py @@ -70,7 +70,7 @@ class BcacheView(BaseView): selector = Selector(avail_devs) self.selected_disks[section] = selector - items.append(Color.string_input(Pile(selector.group), + items.append(Color.string_input(selector, focus_map="string_input focus")) return Pile(items) diff --git a/subiquity/ui/views/filesystem/add_format.py b/subiquity/ui/views/filesystem/add_format.py index 40792959..a64217ce 100644 --- a/subiquity/ui/views/filesystem/add_format.py +++ b/subiquity/ui/views/filesystem/add_format.py @@ -53,16 +53,13 @@ class AddFormatView(BaseView): ] return Pile(buttons) - def _format_edit(self): - return Pile(self.fstype.group) - def _container(self): total_items = [ Columns( [ ("weight", 0.2, Text("Format", align="right")), ("weight", 0.3, - Color.string_input(self._format_edit(), + Color.string_input(self.fstype, focus_map="string_input focus")) ], dividechars=4 ), diff --git a/subiquity/ui/views/filesystem/add_partition.py b/subiquity/ui/views/filesystem/add_partition.py index 666344fa..39687d45 100644 --- a/subiquity/ui/views/filesystem/add_partition.py +++ b/subiquity/ui/views/filesystem/add_partition.py @@ -88,9 +88,6 @@ class AddPartitionView(BaseView): ] return Pile(buttons) - def _format_edit(self): - return Pile(self.fstype.group) - def _container(self): total_items = [ Columns( @@ -115,7 +112,7 @@ class AddPartitionView(BaseView): [ ("weight", 0.2, Text("Format", align="right")), ("weight", 0.3, - Color.string_input(self._format_edit(), + Color.string_input(self.fstype, focus_map="string_input focus")) ], dividechars=4 ), diff --git a/subiquity/ui/views/raid.py b/subiquity/ui/views/raid.py index aff591f1..a25ae6ad 100644 --- a/subiquity/ui/views/raid.py +++ b/subiquity/ui/views/raid.py @@ -85,7 +85,7 @@ class RaidView(BaseView): [ ("weight", 0.2, Text("RAID Level", align="right")), ("weight", 0.3, - Color.string_input(Pile(self.raid_level.group), + Color.string_input(self.raid_level, focus_map="string_input focus")) ], dividechars=4 diff --git a/subiquitycore/core.py b/subiquitycore/core.py index 183de01b..c58c1d8d 100644 --- a/subiquitycore/core.py +++ b/subiquitycore/core.py @@ -130,7 +130,8 @@ class Application: additional_opts = { 'screen': urwid.raw_display.Screen(), 'unhandled_input': self.header_hotkeys, - 'handle_mouse': False + 'handle_mouse': False, + 'pop_ups': True, } if self.common['opts'].run_on_serial: palette = STYLES_MONO diff --git a/subiquitycore/ui/interactive.py b/subiquitycore/ui/interactive.py index 51c2015a..c9a1d864 100644 --- a/subiquitycore/ui/interactive.py +++ b/subiquitycore/ui/interactive.py @@ -16,7 +16,20 @@ """ Re-usable input widgets """ -from urwid import (Edit, IntEdit, RadioButton, WidgetWrap) +from urwid import ( + ACTIVATE, + AttrWrap, + connect_signal, + Edit, + Filler, + IntEdit, + LineBox, + Pile, + PopUpLauncher, + SelectableIcon, + TOP, + WidgetWrap, + ) import logging import re @@ -134,28 +147,81 @@ class IntegerEditor(WidgetWrap): return self._edit.get_edit_text() -class Selector(WidgetWrap): - """ Radio selection list of options - """ - def __init__(self, opts): - """ - :param list opts: list of options to display - """ - self.opts = opts - self.group = [] - self._add_options() +class _PopUpButton(SelectableIcon): + """It looks like a radio button, but it just emits 'click' on activation.""" - def _add_options(self): - for item in self.opts: - RadioButton(self.group, item) + signals = ['click'] + + states = { + True: "(X) ", + False: "( ) ", + } + + def __init__(self, option, state): + super().__init__(self.states[state] + option, 4) + + def keypress(self, size, key): + if self._command_map[key] != ACTIVATE: + return key + self._emit('click') + + +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): + btn = _PopUpButton(option, state=i==cur_index) + connect_signal(btn, 'click', self.click, i) + group.append(btn) + pile = Pile(group) + pile.set_focus(group[cur_index]) + fill = Filler(pile, valign=TOP) + super().__init__(LineBox(AttrWrap(fill, 'menu_button'))) + + def click(self, btn, index): + self.parent.index = index + self.parent.close_pop_up() + + +class Selector(PopUpLauncher): + """A widget that allows the user to chose between options by popping up this list of options. + + (A bit like