Is there a way to show a user that a urwid listbox has additional items above / below the dispalyed section?
I'm thinking of something like a scrollbar that gives an idea of the number of entries.
Or a separate bar at the top / bottom of the list box.
If this behavior can not be implemented, what approaches are there to achieve this notification?
During my research, I found this question, which tried to achieve eventually the same. The given answer seems to check if all elements are visible. Unfortunately, this loses its functionality if some elements are hidden at any time because the terminal is not resized.
I've implemented a list box that applies the second visualization concept (bars at the top and bottom) by default.
It is called additional_urwid_widgets.IndicativeListBox
and can be installed via pip.
For a stand alone example, which illustrates the functionality of the widget, see here.
For more (and simpler) examples, see here.
For a more detailed explanation of the parameters and options, see the corresponding github wiki entry.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from additional_urwid_widgets import IndicativeListBox # installed via pip
import urwid # installed via pip
# Color schemes that specify the appearance off focus and on focus.
PALETTE = [("reveal_focus", "black", "light cyan", "standout")]
# The list box is filled with buttons.
body = [urwid.Button(letter) for letter in "abcdefghijklmnopqrstuvwxyz"]
# Wrap the list items into an 'urwid.AttrMap', so that they have an other appearance when focused.
# Instead of an simple list-like object you can/should create a 'urwid.ListWalker'.
attr_body = [urwid.AttrMap(entry, None, "reveal_focus") for entry in body]
ilb = IndicativeListBox(attr_body)
loop = urwid.MainLoop(ilb,
PALETTE)
loop.run()
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from additional_urwid_widgets import IndicativeListBox # installed via pip
import urwid # installed via pip
# Color schemes that specify the appearance off focus and on focus.
PALETTE = [("reveal_focus", "black", "light cyan", "standout")]
# The list box is filled with buttons.
body = [urwid.Button(letter) for letter in "abcdefghijklmnopqrstuvwxyz"]
# Wrap the list items into an 'urwid.AttrMap', so that they have an other appearance when focused.
# Instead of an simple list-like object you can/should create a 'urwid.ListWalker'.
attr_body = [urwid.AttrMap(entry, None, "reveal_focus") for entry in body]
ilb = IndicativeListBox(attr_body,
topBar_endCovered_prop=("{} above ...", None, None),
bottomBar_endCovered_prop=("{} below ...", None, None))
loop = urwid.MainLoop(ilb,
PALETTE)
loop.run()
In this example, ctrl must be additionally pressed so that the list box responds to the input.
This allows the widget to be used in vertical containers (such as urwid.Pile
).
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from additional_urwid_widgets import IndicativeListBox, MODIFIER_KEY # installed via pip
import urwid # installed via pip
# Color schemes that specify the appearance off focus and on focus.
PALETTE = [("reveal_focus", "black", "light cyan", "standout"),
("ilb_barActive_focus", "dark cyan", "light gray"),
("ilb_barActive_offFocus", "light gray", "dark gray"),
("ilb_barInactive_focus", "light cyan", "dark gray"),
("ilb_barInactive_offFocus", "black", "dark gray"),
("ilb_highlight_offFocus", "black", "dark cyan")]
# The list box is filled with buttons.
body = [urwid.Button(letter) for letter in "abcdefghijklmnopqrstuvwxyz"]
# Wrap the list items into an 'urwid.AttrMap', so that they have an other appearance when focused.
# Instead of an simple list-like object you can/should create a 'urwid.ListWalker'.
attr_body = [urwid.AttrMap(entry, None, "reveal_focus") for entry in body]
ilb = ilb = IndicativeListBox(attr_body,
modifier_key=MODIFIER_KEY.CTRL,
return_unused_navigation_input=False,
topBar_endCovered_prop=("ᐃ", "ilb_barActive_focus", "ilb_barActive_offFocus"),
topBar_endExposed_prop=("───", "ilb_barInactive_focus", "ilb_barInactive_offFocus"),
bottomBar_endCovered_prop=("ᐁ", "ilb_barActive_focus", "ilb_barActive_offFocus"),
bottomBar_endExposed_prop=("───", "ilb_barInactive_focus", "ilb_barInactive_offFocus"),
highlight_offFocus="ilb_highlight_offFocus")
pile = urwid.Pile([urwid.Text("The listbox responds only if 'ctrl' is pressed."),
urwid.Divider(" "),
urwid.Button("a button"),
urwid.BoxAdapter(ilb, 6), # Wrap flow widget in box adapter
urwid.Button("another button")])
loop = urwid.MainLoop(urwid.Filler(pile, "top"),
PALETTE)
loop.run()