Listbox dynamic list: OK with simple lists.

pull/50/head
Peter Hinch 2024-09-11 14:21:51 +01:00
rodzic c2a4e541f0
commit f756f00f33
2 zmienionych plików z 47 dodań i 22 usunięć

Wyświetl plik

@ -1,8 +1,9 @@
# listbox.py Extension to ugui providing the Listbox class # listbox.py Extension to ugui providing the Listbox class
# Released under the MIT License (MIT). See LICENSE. # Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2021-2022 Peter Hinch # Copyright (c) 2021-2024 Peter Hinch
# 11 Sep 24 Support variable list contents.
# 12 Sep 21 Support for scrolling. # 12 Sep 21 Support for scrolling.
from gui.core.ugui import Widget, display from gui.core.ugui import Widget, display
@ -14,6 +15,7 @@ dolittle = lambda *_ : None
# entries is sequential. This can affect the choice in when the callback runs. # entries is sequential. This can affect the choice in when the callback runs.
# It always runs when select is pressed. See 'also' ctor arg. # It always runs when select is pressed. See 'also' ctor arg.
class Listbox(Widget): class Listbox(Widget):
ON_MOVE = 1 # Also run whenever the currency moves. ON_MOVE = 1 # Also run whenever the currency moves.
ON_LEAVE = 2 # Also run on exit from the control. ON_LEAVE = 2 # Also run on exit from the control.
@ -30,12 +32,25 @@ class Listbox(Widget):
textwidth = max(writer.stringlen(s) for s in elements) + 4 textwidth = max(writer.stringlen(s) for s in elements) + 4
return entry_height, height, dlines, textwidth return entry_height, height, dlines, textwidth
def __init__(self, writer, row, col, *, def __init__(
self,
writer,
row,
col,
*,
elements, elements,
dlines=None, width=None, value=0, dlines=None,
fgcolor=None, bgcolor=None, bdcolor=False, width=None,
fontcolor=None, select_color=DARKBLUE, value=0,
callback=dolittle, args=[], also=0): fgcolor=None,
bgcolor=None,
bdcolor=False,
fontcolor=None,
select_color=DARKBLUE,
callback=dolittle,
args=[],
also=0
):
e0 = elements[0] e0 = elements[0]
# Check whether elements specified as (str, str,...) or ([str, callback, args], [...) # Check whether elements specified as (str, str,...) or ([str, callback, args], [...)
@ -43,16 +58,15 @@ class Listbox(Widget):
self.els = elements # Retain original for .despatch self.els = elements # Retain original for .despatch
self.elements = [x[0] for x in elements] # Copy text component self.elements = [x[0] for x in elements] # Copy text component
if callback is not dolittle: if callback is not dolittle:
raise ValueError('Cannot specify callback.') raise ValueError("Cannot specify callback.")
self.cb = self.despatch self.cb = self.despatch
else: else:
self.cb = callback self.cb = callback
self.elements = elements self.elements = elements
if any(not isinstance(s, str) for s in self.elements): if any(not isinstance(s, str) for s in self.elements):
raise ValueError('Invalid elements arg.') raise ValueError("Invalid elements arg.")
# Calculate dimensions # Calculate dimensions
self.entry_height, height, self.dlines, tw = self.dimensions( self.entry_height, height, self.dlines, tw = self.dimensions(writer, self.elements, dlines)
writer, self.elements, dlines)
if width is None: if width is None:
width = tw # Text width width = tw # Text width
@ -71,6 +85,13 @@ class Listbox(Widget):
self._value = value # No callback until user selects self._value = value # No callback until user selects
self.ev = value # Value change detection self.ev = value # Value change detection
def update(self): # Elements list has changed.
l = len(self.elements)
nl = self.dlines # No. of lines that can fit in window
self.ntop = max(0, min(self.ntop, l - nl))
self._value = min(self._value, l - 1)
self.show()
def show(self): def show(self):
if not super().show(False): # Clear to self.bgcolor if not super().show(False): # Clear to self.bgcolor
return return
@ -95,7 +116,9 @@ class Listbox(Widget):
text = text[:nch] text = text[:nch]
if n == self._value: if n == self._value:
display.fill_rect(x, y + 1, self.width, eh - 1, self.select_color) display.fill_rect(x, y + 1, self.width, eh - 1, self.select_color)
display.print_left(self.writer, x + 2, y + 1, text, self.fontcolor, self.select_color) display.print_left(
self.writer, x + 2, y + 1, text, self.fontcolor, self.select_color
)
else: else:
display.print_left(self.writer, x + 2, y + 1, text, self.fontcolor, self.bgcolor) display.print_left(self.writer, x + 2, y + 1, text, self.fontcolor, self.bgcolor)
y += eh y += eh
@ -112,6 +135,8 @@ class Listbox(Widget):
return self.elements[self._value] return self.elements[self._value]
else: # set value by text else: # set value by text
try: try:
# print(text)
# print(self.elements.index(text))
v = self.elements.index(text) v = self.elements.index(text)
except ValueError: except ValueError:
v = None v = None
@ -127,7 +152,7 @@ class Listbox(Widget):
elif vnew < self.ntop: elif vnew < self.ntop:
self.ntop = vnew self.ntop = vnew
self.value(vnew) self.value(vnew)
if (self.also & Listbox.ON_MOVE): # Treat as if select pressed if self.also & Listbox.ON_MOVE: # Treat as if select pressed
self.do_sel() self.do_sel()
def do_adj(self, _, val): def do_adj(self, _, val):