emmental/emmental/factory.py
Anna Schumaker 236a1e60c2 factory: Create a LabelRow and LabelFactory
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>
2023-04-12 10:41:42 -04:00

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)