From a2fb86bc3119fc31f0bb40b569c6439b6c91dcb0 Mon Sep 17 00:00:00 2001 From: Cameron Dehning Date: Sat, 8 Apr 2023 01:34:47 +0000 Subject: [PATCH] Builder list factory --- .gitignore | 4 ++- blueprintcompiler/language/__init__.py | 2 ++ .../language/gtk_list_item_factory.py | 32 +++++++++++++++++++ blueprintcompiler/outputs/xml/__init__.py | 10 ++++++ blueprintcompiler/outputs/xml/xml_emitter.py | 4 +++ docs/examples.rst | 15 +++++++++ tests/samples/list_factory.blp | 11 +++++++ tests/samples/list_factory.ui | 20 ++++++++++++ tests/test_samples.py | 1 + 9 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 blueprintcompiler/language/gtk_list_item_factory.py create mode 100644 tests/samples/list_factory.blp create mode 100644 tests/samples/list_factory.ui diff --git a/.gitignore b/.gitignore index 43e51bd..9aa4dd4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ coverage.xml /blueprint-regression-tests /corpus -/crashes \ No newline at end of file +/crashes + +.vscode \ No newline at end of file diff --git a/blueprintcompiler/language/__init__.py b/blueprintcompiler/language/__init__.py index a7334b1..d251fae 100644 --- a/blueprintcompiler/language/__init__.py +++ b/blueprintcompiler/language/__init__.py @@ -1,3 +1,4 @@ +from .gtk_list_item_factory import ListItemFactory from .adw_message_dialog import Responses from .attributes import BaseAttribute, BaseTypedAttribute from .binding import Binding @@ -57,6 +58,7 @@ OBJECT_CONTENT_HOOKS.children = [ Widgets, Items, Strings, + ListItemFactory, Responses, Child, ] diff --git a/blueprintcompiler/language/gtk_list_item_factory.py b/blueprintcompiler/language/gtk_list_item_factory.py new file mode 100644 index 0000000..d25b96d --- /dev/null +++ b/blueprintcompiler/language/gtk_list_item_factory.py @@ -0,0 +1,32 @@ +from .gobject_object import ObjectContent, validate_parent_type +from ..parse_tree import Keyword +from ..ast_utils import AstNode, validate + + +class ListItemFactory(AstNode): + grammar = [Keyword("template"), ObjectContent] + + @property + def gir_class(self): + return self.root.gir.get_type("ListItem", "Gtk") + + @validate("template") + def container_is_builder_list(self): + validate_parent_type( + self, + "Gtk", + "BuilderListItemFactory", + "sub-templates", + ) + + @property + def content(self) -> ObjectContent: + return self.children[ObjectContent][0] + + @property + def action_widgets(self): + """ + The sub-template shouldn't have it`s own actions this is + just hear to satisfy XmlOutput._emit_object_or_template + """ + return None diff --git a/blueprintcompiler/outputs/xml/__init__.py b/blueprintcompiler/outputs/xml/__init__.py index ad6e658..d6879fd 100644 --- a/blueprintcompiler/outputs/xml/__init__.py +++ b/blueprintcompiler/outputs/xml/__init__.py @@ -304,6 +304,16 @@ class XmlOutput(OutputFormat): self._emit_value(value, xml) xml.end_tag() xml.end_tag() + elif isinstance(extension, ListItemFactory): + child_xml = XmlEmitter() + child_xml.start_tag("interface") + child_xml.start_tag("template", **{"class": "GtkListItem"}) + self._emit_object_or_template(extension, child_xml) + child_xml.end_tag() + child_xml.end_tag() + xml.start_tag("property", name="bytes") + xml.put_cdata(child_xml.result) + xml.end_tag() elif isinstance(extension, Styles): xml.start_tag("style") diff --git a/blueprintcompiler/outputs/xml/xml_emitter.py b/blueprintcompiler/outputs/xml/xml_emitter.py index 374b406..3dd09a0 100644 --- a/blueprintcompiler/outputs/xml/xml_emitter.py +++ b/blueprintcompiler/outputs/xml/xml_emitter.py @@ -62,6 +62,10 @@ class XmlEmitter: self.result += saxutils.escape(str(text)) self._needs_newline = False + def put_cdata(self, text: str): + self.result += f"" + self._needs_newline = False + def _indent(self): if self.indent is not None: self.result += "\n" + " " * (self.indent * len(self._tag_stack)) diff --git a/docs/examples.rst b/docs/examples.rst index 13b97a8..d1a9762 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -414,6 +414,21 @@ Gtk.SizeGroup Gtk.Label label1 {} Gtk.Label label2 {} +Gtk.BuilderListItemFactory +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: + + Gtk.ListView { + factory: Gtk.BuilderListItemFactory { + template { + child: Label { + label: "Hello"; + }; + } + }; + } + Gtk.StringList ~~~~~~~~~~~~~~ diff --git a/tests/samples/list_factory.blp b/tests/samples/list_factory.blp new file mode 100644 index 0000000..ead74c3 --- /dev/null +++ b/tests/samples/list_factory.blp @@ -0,0 +1,11 @@ +using Gtk 4.0; + +Gtk.ListView { + factory: Gtk.BuilderListItemFactory list_item_factory { + template { + child: Label { + label: "Hello"; + }; + } + }; +} \ No newline at end of file diff --git a/tests/samples/list_factory.ui b/tests/samples/list_factory.ui new file mode 100644 index 0000000..664de85 --- /dev/null +++ b/tests/samples/list_factory.ui @@ -0,0 +1,20 @@ + + + + + + + + + +]]> + + + + diff --git a/tests/test_samples.py b/tests/test_samples.py index 9988bb6..823488b 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -169,6 +169,7 @@ class TestSamples(unittest.TestCase): self.assert_sample("flags") self.assert_sample("id_prop") self.assert_sample("layout") + self.assert_sample("list_factory") self.assert_sample("menu") self.assert_sample("numbers") self.assert_sample("object_prop")