Merge pull request #265 from CanonicalLtd/mwhudson/scrollbars
add scrollbars to listboxes
This commit is contained in:
commit
75fdfb4c4e
|
@ -87,6 +87,8 @@ STYLES = [
|
|||
('string_input focus', 'bg', 'fg'),
|
||||
('progress_incomplete', 'fg', 'aubergine'),
|
||||
('progress_complete', 'fg', 'orange'),
|
||||
('scrollbar_fg', 'orange', 'bg'),
|
||||
('scrollbar_bg', 'fg', 'bg'),
|
||||
]
|
||||
|
||||
focus_styles = set([
|
||||
|
|
|
@ -38,10 +38,10 @@ class DiskPartitionView(BaseView):
|
|||
('pack', Text("")),
|
||||
Padding.center_79(ListBox(
|
||||
self._build_model_inputs() + [
|
||||
Text(""),
|
||||
self.show_disk_info_w(),
|
||||
])),
|
||||
('pack', Pile([
|
||||
Text(""),
|
||||
('pack', Padding.center_79(self.show_disk_info_w())),
|
||||
('pack', Text("")),
|
||||
self._build_buttons(),
|
||||
('pack', Text("")),
|
||||
|
|
|
@ -64,7 +64,7 @@ class FilesystemConfirmationView(WidgetWrap):
|
|||
Text(""),
|
||||
])
|
||||
lb = LineBox(pile, title=_("Confirm destructive action"))
|
||||
super().__init__(Padding.center_75(lb))
|
||||
super().__init__(lb)
|
||||
|
||||
def ok(self, sender):
|
||||
self.controller.finish()
|
||||
|
@ -261,4 +261,4 @@ class FilesystemView(BaseView):
|
|||
self.controller.reset()
|
||||
|
||||
def done(self, button):
|
||||
self.show_overlay(FilesystemConfirmationView(self, self.controller))
|
||||
self.show_overlay(FilesystemConfirmationView(self, self.controller), min_width=0)
|
||||
|
|
|
@ -40,7 +40,8 @@ class ProgressView(BaseView):
|
|||
self.model = model
|
||||
self.controller = controller
|
||||
self.listwalker = SimpleFocusListWalker([])
|
||||
self.linebox = MyLineBox(ListBox(self.listwalker))
|
||||
self.listbox = ListBox(self.listwalker)
|
||||
self.linebox = MyLineBox(self.listbox)
|
||||
body = [
|
||||
('pack', Text("")),
|
||||
('weight', 1, Padding.center_79(self.linebox)),
|
||||
|
@ -50,9 +51,11 @@ class ProgressView(BaseView):
|
|||
super().__init__(self.pile)
|
||||
|
||||
def add_log_tail(self, text):
|
||||
at_end = len(self.listwalker) == 0 or self.listbox.focus_position == len(self.listwalker) - 1
|
||||
for line in text.splitlines():
|
||||
self.listwalker.append(Text(line))
|
||||
self.listwalker.set_focus(len(self.listwalker) - 1)
|
||||
if at_end:
|
||||
self.listbox.set_focus(len(self.listwalker) - 1)
|
||||
|
||||
def clear_log_tail(self):
|
||||
self.listwalker[:] = []
|
||||
|
|
|
@ -405,7 +405,7 @@ class NetworkController(BaseController):
|
|||
self.cs.cancel()
|
||||
self.task_error('canceled')
|
||||
self.acw = ApplyingConfigWidget(len(tasks), cancel)
|
||||
self.ui.frame.body.show_overlay(self.acw)
|
||||
self.ui.frame.body.show_overlay(self.acw, min_width=60)
|
||||
|
||||
self.cs = TaskSequence(self.run_in_bg, tasks, self)
|
||||
self.cs.run()
|
||||
|
|
|
@ -230,6 +230,78 @@ class FocusTrackingListBox(TabCyclingListBox):
|
|||
def gained_focus(self):
|
||||
_maybe_call(self.focus, 'gained_focus')
|
||||
|
||||
|
||||
Columns = FocusTrackingColumns
|
||||
Pile = FocusTrackingPile
|
||||
ListBox = FocusTrackingListBox
|
||||
|
||||
|
||||
class ScrollBarListBox(FocusTrackingListBox):
|
||||
|
||||
def __init__(self, walker=None):
|
||||
def f(char, attr):
|
||||
return urwid.AttrMap(urwid.SolidFill(char), attr)
|
||||
self.bar = Pile([
|
||||
('weight', 1, f("\N{BOX DRAWINGS LIGHT VERTICAL}", 'scrollbar_bg')),
|
||||
('weight', 1, f("\N{FULL BLOCK}", 'scrollbar_fg')),
|
||||
('weight', 1, f("\N{BOX DRAWINGS LIGHT VERTICAL}", 'scrollbar_bg')),
|
||||
])
|
||||
super().__init__(walker)
|
||||
|
||||
def render(self, size, focus=False):
|
||||
visible = self.ends_visible(size, focus)
|
||||
if len(visible) == 2:
|
||||
return super().render(size, focus)
|
||||
else:
|
||||
# This implementation assumes that the number of rows is
|
||||
# not too large (and in particular is finite). That's the
|
||||
# case for all the listboxes we have in subiquity today.
|
||||
maxcol, maxrow = size
|
||||
|
||||
offset, inset = self.get_focus_offset_inset((maxcol - 1, maxrow))
|
||||
|
||||
seen_focus = False
|
||||
height = height_before_focus = 0
|
||||
focus_widget, focus_pos = self.body.get_focus()
|
||||
# Scan through the rows calculating total height and the
|
||||
# height of the rows before the focus widget.
|
||||
for widget in self.body:
|
||||
rows = widget.rows((maxcol - 1,))
|
||||
if widget is focus_widget:
|
||||
seen_focus = True
|
||||
elif not seen_focus:
|
||||
height_before_focus += rows
|
||||
height += rows
|
||||
|
||||
# Calculate the number of rows off the top and bottom of
|
||||
# the listbox.
|
||||
if 'top' in visible:
|
||||
top = 0
|
||||
else:
|
||||
top = height_before_focus + inset - offset
|
||||
if 'bottom' in visible:
|
||||
bottom = 0
|
||||
else:
|
||||
bottom = height - top - maxrow
|
||||
|
||||
# Prevent the box from being squished to 0 rows (if it
|
||||
# gets ('weight', maxrow) gets round(maxrow / (top +
|
||||
# maxrow + bottom)) and that being < 1 simplifies to the
|
||||
# below).
|
||||
if maxrow*maxrow < height:
|
||||
boxopt = self.bar.options('given', 1)
|
||||
else:
|
||||
boxopt = self.bar.options('weight', maxrow)
|
||||
|
||||
self.bar.contents[:] = [
|
||||
(self.bar.contents[0][0], self.bar.options('weight', top)),
|
||||
(self.bar.contents[1][0], boxopt),
|
||||
(self.bar.contents[2][0], self.bar.options('weight', bottom)),
|
||||
]
|
||||
canvases = [
|
||||
(super().render((maxcol - 1, maxrow), focus), self.focus_position, True, maxcol - 1),
|
||||
(self.bar.render((1, maxrow)), None, False, 1)
|
||||
]
|
||||
return urwid.CanvasJoin(canvases)
|
||||
|
||||
|
||||
ListBox = ScrollBarListBox
|
||||
|
|
|
@ -115,11 +115,11 @@ class NetworkView(BaseView):
|
|||
self.model_inputs = Pile(self._build_model_inputs())
|
||||
self.additional_options = Pile(self._build_additional_options())
|
||||
self.body = [
|
||||
Padding.center_90(self.model_inputs),
|
||||
self.model_inputs,
|
||||
Padding.center_79(self.additional_options),
|
||||
Padding.line_break(""),
|
||||
]
|
||||
self.lb = ListBox(self.body)
|
||||
self.lb = Padding.center_90(ListBox(self.body))
|
||||
self.footer = Pile([
|
||||
Text(""),
|
||||
self._build_buttons(),
|
||||
|
|
|
@ -34,7 +34,7 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
self._build_widgets()
|
||||
super().__init__(Pile([
|
||||
('pack', Text("")),
|
||||
ListBox(self._build_body()),
|
||||
Padding.center_79(ListBox(self._build_body())),
|
||||
('pack', Pile([
|
||||
('pack', Text("")),
|
||||
self._build_buttons(),
|
||||
|
@ -57,16 +57,16 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
body = []
|
||||
if self.dev.type == 'wlan':
|
||||
body.extend([
|
||||
Padding.center_79(self.wifi_info),
|
||||
Padding.center_79(self.wifi_method),
|
||||
self.wifi_info,
|
||||
self.wifi_method,
|
||||
Padding.line_break(""),
|
||||
])
|
||||
body.extend([
|
||||
Padding.center_79(self.ipv4_info),
|
||||
Padding.center_79(self.ipv4_method),
|
||||
self.ipv4_info,
|
||||
self.ipv4_method,
|
||||
Padding.line_break(""),
|
||||
Padding.center_79(self.ipv6_info),
|
||||
Padding.center_79(self.ipv6_method),
|
||||
self.ipv6_info,
|
||||
self.ipv6_method,
|
||||
Padding.line_break(""),
|
||||
])
|
||||
return body
|
||||
|
|
Loading…
Reference in New Issue