make ScrollBarListBox decoration
This commit is contained in:
parent
3aac53cf1b
commit
517a733352
|
@ -66,21 +66,24 @@ class ProgressView(BaseView):
|
|||
|
||||
super().__init__(self.event_pile)
|
||||
|
||||
def add_event(self, text):
|
||||
at_end = len(self.event_listwalker) == 0 or self.event_listbox.focus_position == len(self.event_listwalker) - 1
|
||||
if len(self.event_listwalker) > 0:
|
||||
self.event_listwalker[-1] = self.event_listwalker[-1][0]
|
||||
self.event_listwalker.append(Columns([('pack', Text(text)), ('pack', self.spinner)], dividechars=1))
|
||||
def _add_line(self, lb, line):
|
||||
lb = lb.base_widget
|
||||
walker = lb.body
|
||||
at_end = len(walker) == 0 or lb.focus_position == len(walker) - 1
|
||||
walker.append(line)
|
||||
if at_end:
|
||||
self.event_listbox.set_focus(len(self.event_listwalker) - 1)
|
||||
self.event_listbox.set_focus_valign('bottom')
|
||||
lb.set_focus(len(walker) - 1)
|
||||
lb.set_focus_valign('bottom')
|
||||
|
||||
def add_event(self, text):
|
||||
walker = self.event_listwalker
|
||||
if len(walker) > 0:
|
||||
walker[-1] = walker[-1][0]
|
||||
new = Columns([('pack', Text(text)), ('pack', self.spinner)], dividechars=1)
|
||||
self._add_line(self.event_listbox, new)
|
||||
|
||||
def add_log_line(self, text):
|
||||
at_end = len(self.log_listwalker) == 0 or self.log_listbox.focus_position == len(self.log_listwalker) - 1
|
||||
self.log_listwalker.append(Text(text))
|
||||
if at_end:
|
||||
self.log_listbox.set_focus(len(self.log_listwalker) - 1)
|
||||
self.log_listbox.set_focus_valign('bottom')
|
||||
self._add_line(self.log_listbox, Text(text))
|
||||
|
||||
def set_status(self, text):
|
||||
self.event_linebox.set_title(text)
|
||||
|
|
|
@ -19,15 +19,17 @@ from urwid import (
|
|||
BOX,
|
||||
CheckBox,
|
||||
LineBox,
|
||||
ListBox as UrwidListBox,
|
||||
RadioButton,
|
||||
SelectableIcon,
|
||||
SimpleFocusListWalker,
|
||||
Text,
|
||||
Widget,
|
||||
WidgetWrap,
|
||||
)
|
||||
|
||||
from subiquitycore.ui.buttons import ok_btn, cancel_btn, other_btn
|
||||
from subiquitycore.ui.container import Columns, ListBox, Pile
|
||||
from subiquitycore.ui.container import Columns, ListBox, Pile, ScrollBarListBox
|
||||
from subiquitycore.ui.utils import button_pile, Color, Padding, screen
|
||||
from subiquitycore.view import BaseView
|
||||
|
||||
|
@ -54,20 +56,9 @@ class StarRadioButton(RadioButton):
|
|||
reserve_columns = 3
|
||||
|
||||
|
||||
class NoTabCyclingListBox(ListBox):
|
||||
# Carefully disable the TabCycling parts of our ListBox (but keep the scrollbar!)
|
||||
|
||||
def keypress(self, size, key):
|
||||
if not key.startswith("enter") and self._command_map[key] in ('next selectable', 'prev selectable'):
|
||||
return key
|
||||
else:
|
||||
return super().keypress(size, key)
|
||||
|
||||
def _select_first_selectable(self):
|
||||
return
|
||||
|
||||
def _select_last_selectable(self):
|
||||
return
|
||||
def NoTabCyclingListBox(body):
|
||||
body = SimpleFocusListWalker(body)
|
||||
return ScrollBarListBox(UrwidListBox(body))
|
||||
|
||||
|
||||
class SnapInfoView(Widget):
|
||||
|
|
|
@ -386,41 +386,46 @@ class FocusTrackingListBox(TabCyclingListBox):
|
|||
Columns = FocusTrackingColumns
|
||||
Pile = FocusTrackingPile
|
||||
|
||||
class ScrollBarListBox(urwid.WidgetDecoration):
|
||||
|
||||
class ScrollBarListBox(FocusTrackingListBox):
|
||||
|
||||
def __init__(self, walker=None):
|
||||
def __init__(self, lb):
|
||||
def f(char, attr):
|
||||
return urwid.AttrMap(urwid.SolidFill(char), attr)
|
||||
self.boxes = [
|
||||
urwid.AttrMap(urwid.SolidFill("\N{FULL BLOCK}"), 'scrollbar_bg'),
|
||||
urwid.AttrMap(urwid.SolidFill("\N{FULL BLOCK}"), 'scrollbar_fg'),
|
||||
f("\N{FULL BLOCK}", 'scrollbar_bg'),
|
||||
f("\N{FULL BLOCK}", 'scrollbar_fg'),
|
||||
]
|
||||
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')),
|
||||
])
|
||||
super().__init__(walker)
|
||||
super().__init__(lb)
|
||||
|
||||
def keypress(self, size, key):
|
||||
visible = self.original_widget.ends_visible(size, True)
|
||||
if len(visible) != 2:
|
||||
size = (size[0]-1, size[1])
|
||||
return self.original_widget.keypress(size, key)
|
||||
|
||||
def render(self, size, focus=False):
|
||||
visible = self.ends_visible(size, focus)
|
||||
visible = self.original_widget.ends_visible(size, focus)
|
||||
if len(visible) == 2:
|
||||
return super().render(size, focus)
|
||||
return self.original_widget.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))
|
||||
offset, inset = self.original_widget.get_focus_offset_inset((maxcol - 1, maxrow))
|
||||
|
||||
seen_focus = False
|
||||
height = height_before_focus = 0
|
||||
focus_widget, focus_pos = self.body.get_focus()
|
||||
focus_widget, focus_pos = self.original_widget.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:
|
||||
for widget in self.original_widget.body:
|
||||
rows = widget.rows((maxcol - 1,))
|
||||
if widget is focus_widget:
|
||||
seen_focus = True
|
||||
|
@ -459,10 +464,15 @@ class ScrollBarListBox(FocusTrackingListBox):
|
|||
(self.bar.contents[2][0], self.bar.options('weight', bottom)),
|
||||
]
|
||||
canvases = [
|
||||
(super().render((maxcol - 1, maxrow), focus), self.focus_position, True, maxcol - 1),
|
||||
(self.original_widget.render((maxcol - 1, maxrow), focus), self.original_widget.focus_position, True, maxcol - 1),
|
||||
(self.bar.render((1, maxrow)), None, False, 1)
|
||||
]
|
||||
return urwid.CanvasJoin(canvases)
|
||||
|
||||
|
||||
ListBox = ScrollBarListBox
|
||||
def ListBox(body=None):
|
||||
# urwid.ListBox converts an arbitrary sequence argument to a
|
||||
# PollingListWalker, which doesn't work with our code.
|
||||
if body is not None and getattr(body, 'get_focus', None) is None:
|
||||
body = urwid.SimpleFocusListWalker(body)
|
||||
return ScrollBarListBox(FocusTrackingListBox(body))
|
||||
|
|
Loading…
Reference in New Issue