The LabelRow is an implementation of the ListRow for the common case of displaying text to the user. It has some convenience properties for setting the xalign property and adding the "numeric" class to the Gtk.Label. The LabelFactory creates LabelRows. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
129 lines
4.7 KiB
Python
129 lines
4.7 KiB
Python
# Copyright 2022 (c) Anna Schumaker.
|
|
"""A customized Gtk.SignalListItemFactory for easier use."""
|
|
import typing
|
|
from gi.repository import GObject
|
|
from gi.repository import Gtk
|
|
|
|
|
|
class ListRow(GObject.GObject):
|
|
"""Extra state that we attach to the Gtk.ListItem."""
|
|
|
|
listitem = GObject.Property(type=Gtk.ListItem)
|
|
|
|
def __init__(self, listitem: Gtk.ListItem, **kwargs):
|
|
"""Initialize a ListRow object."""
|
|
GObject.GObject.__init__(self, listitem=listitem, **kwargs)
|
|
self.bindings = []
|
|
|
|
def do_bind(self) -> None:
|
|
"""Bind the list item to the child widget."""
|
|
|
|
def do_unbind(self) -> None:
|
|
"""Unbind the list item from the child widget."""
|
|
|
|
def bind_and_set(self, src: GObject.GObject, src_prop: str,
|
|
dst: GObject.GObject, dst_prop: str,
|
|
bidirectional: bool = False,
|
|
invert_boolean: bool = False) -> None:
|
|
"""Bind and set a property from the src object to the dst object."""
|
|
f_bidir = GObject.BindingFlags.BIDIRECTIONAL if bidirectional else 0
|
|
f_invrt = GObject.BindingFlags.INVERT_BOOLEAN if invert_boolean else 0
|
|
|
|
src_value = src.get_property(src_prop)
|
|
value = not src_value if invert_boolean else src_value
|
|
dst.set_property(dst_prop, value)
|
|
self.bindings.append(src.bind_property(src_prop, dst, dst_prop,
|
|
f_bidir | f_invrt))
|
|
|
|
def bind_and_set_property(self, item_prop: str, child_prop: str,
|
|
bidirectional: bool = False,
|
|
invert_boolean: bool = False) -> None:
|
|
"""Bind and set a list item property."""
|
|
self.bind_and_set(self.item, item_prop, self.child, child_prop,
|
|
bidirectional, invert_boolean)
|
|
|
|
def bind(self) -> None:
|
|
"""Bind the list item to the child widget."""
|
|
self.do_bind()
|
|
|
|
def unbind(self) -> None:
|
|
"""Unbind the list item from the child widget."""
|
|
for binding in self.bindings:
|
|
binding.unbind()
|
|
self.bindings.clear()
|
|
self.do_unbind()
|
|
|
|
@GObject.Property(type=Gtk.Widget)
|
|
def child(self) -> Gtk.Widget | None:
|
|
"""Get the child widget displayed by this Row."""
|
|
return self.listitem.get_child()
|
|
|
|
@child.setter
|
|
def child(self, newval: Gtk.Widget) -> None:
|
|
self.listitem.set_child(newval)
|
|
|
|
@GObject.Property(type=GObject.TYPE_PYOBJECT)
|
|
def item(self) -> GObject.TYPE_PYOBJECT:
|
|
"""Get the list item for this Row."""
|
|
return self.listitem.get_item()
|
|
|
|
|
|
class InscriptionRow(ListRow):
|
|
"""A ListRow for displaying Gtk.Inscription widgets."""
|
|
|
|
item_property = GObject.Property(type=str)
|
|
|
|
def __init__(self, listitem: Gtk.ListItem, item_property: str,
|
|
xalign: float = 0.0, numeric: bool = False) -> None:
|
|
"""Create a new Gtk.Label."""
|
|
super().__init__(listitem, item_property=item_property)
|
|
self.child = Gtk.Inscription(xalign=xalign)
|
|
if numeric:
|
|
self.child.add_css_class("numeric")
|
|
|
|
def do_bind(self) -> None:
|
|
"""Bind a ListItem to the Label."""
|
|
self.bind_and_set_property(self.item_property, "text")
|
|
|
|
|
|
class Factory(Gtk.SignalListItemFactory):
|
|
"""A customized Factory for making list row widgets."""
|
|
|
|
def __init__(self, row_type: typing.Type[ListRow], **kwargs):
|
|
"""Initialize a ListFactory."""
|
|
super().__init__()
|
|
self.row_type = row_type
|
|
|
|
self.connect("setup", self.__setup, kwargs)
|
|
self.connect("bind", self.__bind)
|
|
self.connect("unbind", self.__unbind)
|
|
self.connect("teardown", self.__teardown)
|
|
|
|
def __setup(self, factory: Gtk.SignalListItemFactory,
|
|
listitem: Gtk.ListItem, kwargs: dict) -> None:
|
|
listitem.listrow = self.row_type(listitem, **kwargs)
|
|
|
|
def __bind(self, factory: Gtk.SignalListItemFactory,
|
|
listitem: Gtk.ListItem) -> None:
|
|
listitem.listrow.bind()
|
|
|
|
def __unbind(self, factory: Gtk.SignalListItemFactory,
|
|
listitem: Gtk.ListItem) -> None:
|
|
listitem.listrow.unbind()
|
|
|
|
def __teardown(self, factory: Gtk.SignalListItemFactory,
|
|
listitem: Gtk.ListItem) -> None:
|
|
listitem.set_child(None)
|
|
listitem.listrow = None
|
|
|
|
|
|
class InscriptionFactory(Factory):
|
|
"""A Factory that creates InscriptionRows."""
|
|
|
|
def __init__(self, item_property: str,
|
|
script_type: typing.Type[InscriptionRow] = InscriptionRow,
|
|
xalign: float = 0.0, numeric: bool = False):
|
|
"""Initialize a LabelFactory."""
|
|
super().__init__(row_type=script_type, item_property=item_property,
|
|
xalign=xalign, numeric=numeric)
|