make scrollbar less intrusive

also pretty up its implementation a bit while I am here
This commit is contained in:
Michael Hudson-Doyle 2018-06-18 21:24:23 +12:00
parent 0d95adb89e
commit c0d66f5540
3 changed files with 34 additions and 38 deletions

View File

@ -50,8 +50,8 @@ STYLES = [
('progress_incomplete', 'fg', 'gray'), ('progress_incomplete', 'fg', 'gray'),
('progress_complete', 'fg', 'neutral'), ('progress_complete', 'fg', 'neutral'),
('scrollbar_fg', 'neutral', 'bg'), ('scrollbar', 'brand', 'bg'),
('scrollbar_bg', 'fg', 'bg'), ('scrollbar focus', 'gray', 'bg'),
] ]
STYLES_MONO = [ STYLES_MONO = [

View File

@ -59,8 +59,8 @@ STYLES = [
('progress_incomplete', 'fg', 'gray'), ('progress_incomplete', 'fg', 'gray'),
('progress_complete', 'fg', 'neutral'), ('progress_complete', 'fg', 'neutral'),
('scrollbar_fg', 'neutral', 'bg'), ('scrollbar', 'brand', 'bg'),
('scrollbar_bg', 'fg', 'bg'), ('scrollbar focus', 'gray', 'bg'),
] ]

View File

@ -419,47 +419,42 @@ Pile = FocusTrackingPile
class ScrollBarListBox(urwid.WidgetDecoration): class ScrollBarListBox(urwid.WidgetDecoration):
def __init__(self, lb): def __init__(self, lb):
def f(char, attr): self.bg = urwid.SolidFill(" ")
return urwid.AttrMap(urwid.SolidFill(char), attr) self.box = urwid.SolidFill("\N{FULL BLOCK}")
self.boxes = [ pile = Pile([
f("\N{FULL BLOCK}", 'scrollbar_bg'), ('weight', 1, self.bg),
f("\N{FULL BLOCK}", 'scrollbar_fg'), ('weight', 1, self.box),
] ('weight', 1, self.bg),
self.bar = Pile([
('weight', 1, f("\N{BOX DRAWINGS LIGHT VERTICAL}",
'scrollbar_bg')),
('weight', 1, self.boxes[0]),
('weight', 1, f("\N{BOX DRAWINGS LIGHT VERTICAL}",
'scrollbar_bg')),
]) ])
self.bar = urwid.AttrMap(pile, 'scrollbar', 'scrollbar focus')
super().__init__(lb) super().__init__(lb)
def keypress(self, size, key): def keypress(self, size, key):
visible = self.original_widget.ends_visible(size, True) lb = self.original_widget
visible = lb.ends_visible(size, True)
if len(visible) != 2: if len(visible) != 2:
size = (size[0]-1, size[1]) size = (size[0]-1, size[1])
return self.original_widget.keypress(size, key) return lb.keypress(size, key)
def render(self, size, focus=False): def render(self, size, focus=False):
visible = self.original_widget.ends_visible(size, focus) lb = self.original_widget
visible = lb.ends_visible(size, focus)
if len(visible) == 2: if len(visible) == 2:
return self.original_widget.render(size, focus) return lb.render(size, focus)
else: else:
# This implementation assumes that the number of rows is # This implementation assumes that the number of rows is
# not too large (and in particular is finite). That's the # not too large (and in particular is finite). That's the
# case for all the listboxes we have in subiquity today. # case for all the listboxes we have in subiquity today.
maxcol, maxrow = size maxcol, maxrow = size
offset, inset = ( offset, inset = lb.get_focus_offset_inset((maxcol - 1, maxrow))
self.original_widget.get_focus_offset_inset((maxcol - 1,
maxrow)))
seen_focus = False seen_focus = False
height = height_before_focus = 0 height = height_before_focus = 0
focus_widget, focus_pos = self.original_widget.body.get_focus() focus_widget, focus_pos = lb.body.get_focus()
# Scan through the rows calculating total height and the # Scan through the rows calculating total height and the
# height of the rows before the focus widget. # height of the rows before the focus widget.
for widget in self.original_widget.body: for widget in lb.body:
rows = widget.rows((maxcol - 1,)) rows = widget.rows((maxcol - 1,))
if widget is focus_widget: if widget is focus_widget:
seen_focus = True seen_focus = True
@ -486,23 +481,24 @@ class ScrollBarListBox(urwid.WidgetDecoration):
# #
# round(maxrow / (top + maxrow + bottom)) # round(maxrow / (top + maxrow + bottom))
# #
# rows and that being < 1 simplifies to the below). # rows and that being < 1 simplifies to the below.
o = self.bar.base_widget.options
if maxrow*maxrow < height: if maxrow*maxrow < height:
boxopt = self.bar.options('given', 1) boxopt = o('given', 1)
else: else:
boxopt = self.bar.options('weight', maxrow) boxopt = o('weight', maxrow)
self.bar.contents[:] = [ self.bar.base_widget.contents[:] = [
(self.bar.contents[0][0], self.bar.options('weight', top)), (self.bg, o('weight', top)),
(self.boxes[focus], boxopt), (self.box, boxopt),
(self.bar.contents[2][0], self.bar.options('weight', bottom)), (self.bg, o('weight', bottom)),
] ]
canvases = [ lb_canvas = lb.render((maxcol - 1, maxrow), focus)
(self.original_widget.render((maxcol - 1, maxrow), focus), bar_canvas = self.bar.render((1, maxrow), focus)
self.original_widget.focus_position, True, maxcol - 1), return urwid.CanvasJoin([
(self.bar.render((1, maxrow)), None, False, 1) (lb_canvas, lb.focus_position, True, maxcol - 1),
] (bar_canvas, None, False, 1),
return urwid.CanvasJoin(canvases) ])
def ListBox(body=None): def ListBox(body=None):