menu: only render visible list items

Signed-off-by: Janar Sööt <janar.soot@gmail.com>
This commit is contained in:
Janar Sööt 2020-08-25 23:28:34 +03:00 committed by KevinOConnor
parent 9459549db3
commit 97da129793
1 changed files with 34 additions and 35 deletions

View File

@ -397,8 +397,8 @@ class MenuContainer(MenuElement):
return self.select_at(index) return self.select_at(index)
# override # override
def render_container(self, eventtime): def render_container(self, nrows, eventtime):
return ("", None) return []
def __iter__(self): def __iter__(self):
return iter(self._items) return iter(self._items)
@ -550,6 +550,7 @@ class MenuInput(MenuCommand):
class MenuList(MenuContainer): class MenuList(MenuContainer):
def __init__(self, manager, config): def __init__(self, manager, config):
super(MenuList, self).__init__(manager, config) super(MenuList, self).__init__(manager, config)
self._viewport_top = 0
# create back item # create back item
self._itemBack = self.manager.menuitem_from({ self._itemBack = self.manager.menuitem_from({
'type': 'command', 'type': 'command',
@ -562,29 +563,43 @@ class MenuList(MenuContainer):
def _populate(self): def _populate(self):
super(MenuList, self)._populate() super(MenuList, self)._populate()
self._viewport_top = 0
# add back as first item # add back as first item
self.insert_item(self._itemBack, 0) self.insert_item(self._itemBack, 0)
def render_container(self, eventtime): def render_container(self, nrows, eventtime):
rows = [] manager = self.manager
selected_row = None lines = []
selected_row = self.selected
# adjust viewport
if selected_row is not None:
if selected_row >= (self._viewport_top + nrows):
self._viewport_top = (selected_row - nrows) + 1
if selected_row < self._viewport_top:
self._viewport_top = selected_row
else:
self._viewport_top = 0
# clamps viewport
self._viewport_top = max(0, min(self._viewport_top, len(self) - nrows))
try: try:
for row, item in enumerate(self): for row in range(self._viewport_top, self._viewport_top + nrows):
s = "" s = ""
selected = (row == self.selected) if row < len(self):
if selected: current = self[row]
item.heartbeat(eventtime) selected = (row == selected_row)
selected_row = len(rows) if selected:
name = str(item.render_name(selected)) current.heartbeat(eventtime)
if isinstance(item, MenuList): name = manager.stripliterals(
s += name[:self.manager.cols-1].ljust(self.manager.cols-1) manager.aslatin(current.render_name(selected)))
s += '>' if isinstance(current, MenuList):
else: s += name[:manager.cols-1].ljust(manager.cols-1)
s += name[:self.manager.cols].ljust(self.manager.cols) s += '>'
rows.append(s) else:
s += name
lines.append(s[:manager.cols].ljust(manager.cols))
except Exception: except Exception:
logging.exception('List rendering error') logging.exception('List rendering error')
return ("\n".join(rows), selected_row) return lines
class MenuVSDList(MenuList): class MenuVSDList(MenuList):
@ -624,7 +639,6 @@ class MenuManager:
self.menuitems = {} self.menuitems = {}
self.menustack = [] self.menustack = []
self.children = {} self.children = {}
self.top_row = 0
self.display = display self.display = display
self.printer = config.get_printer() self.printer = config.get_printer()
self.pconfig = self.printer.lookup_object('configfile') self.pconfig = self.printer.lookup_object('configfile')
@ -682,7 +696,6 @@ class MenuManager:
def begin(self, eventtime): def begin(self, eventtime):
self.menustack = [] self.menustack = []
self.top_row = 0
self.timer = 0 self.timer = 0
if isinstance(self.root, MenuContainer): if isinstance(self.root, MenuContainer):
# send begin event # send begin event
@ -780,21 +793,7 @@ class MenuManager:
container = self.stack_peek() container = self.stack_peek()
if self.running and isinstance(container, MenuContainer): if self.running and isinstance(container, MenuContainer):
container.heartbeat(eventtime) container.heartbeat(eventtime)
content, viewport_row = container.render_container(eventtime) lines = container.render_container(self.rows, eventtime)
if viewport_row is not None:
while viewport_row >= (self.top_row + self.rows):
self.top_row += 1
while viewport_row < self.top_row and self.top_row > 0:
self.top_row -= 1
else:
self.top_row = 0
rows = self.aslatin(content).splitlines()
for row in range(0, self.rows):
try:
text = self.stripliterals(rows[self.top_row + row])
except IndexError:
text = ""
lines.append(text.ljust(self.cols))
return lines return lines
def screen_update_event(self, eventtime): def screen_update_event(self, eventtime):