WIP: Add AdwMessageDialog support

Support AdwMessageDialog's custom XML.
This commit is contained in:
James Westman 2022-07-09 15:43:50 -05:00
parent 08da6f79c7
commit c5aeb9a16f
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
8 changed files with 156 additions and 0 deletions

View file

@ -1,6 +1,7 @@
""" Contains all the syntax beyond basic objects, properties, signal, and """ Contains all the syntax beyond basic objects, properties, signal, and
templates. """ templates. """
from .adw_message_dialog import Responses
from .attributes import BaseAttribute, BaseTypedAttribute from .attributes import BaseAttribute, BaseTypedAttribute
from .expression import Expr from .expression import Expr
from .gobject_object import Object, ObjectContent from .gobject_object import Object, ObjectContent
@ -39,6 +40,7 @@ OBJECT_CONTENT_HOOKS.children = [
Widgets, Widgets,
Items, Items,
Strings, Strings,
Responses,
Child, Child,
] ]

View file

@ -0,0 +1,108 @@
# adw_message_dialog.py
#
# Copyright 2022 James Westman <james@jwestman.net>
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: LGPL-3.0-or-later
from .gobject_object import ObjectContent, validate_parent_type
from .attributes import BaseAttribute
from .common import *
class AppearanceClass(AstNode):
grammar = AnyOf(Keyword("destructive"), Keyword("suggested"))
@property
def name(self):
if self.tokens["destructive"]:
return "destructive"
else:
return "suggested"
@validate()
def unique_in_parent(self):
self.validate_unique_in_parent("Only one of 'destructive' or 'suggested' is allowed")
class Response(BaseAttribute):
tag_name = "response"
attr_name = "id"
value_type = gir.StringType()
grammar = [
UseIdent("name"),
":",
VALUE_HOOKS,
ZeroOrMore(AnyOf(
Keyword("disabled"),
AppearanceClass,
)),
]
@validate("name")
def unique_in_parent(self):
self.validate_unique_in_parent(
f"Duplicate response ID '{self.tokens['name']}'",
lambda other: other.tokens["name"] == self.tokens["name"],
)
def extra_attributes(self):
attrs = {}
if len(self.children[AppearanceClass]) == 1:
attrs["appearance"] = self.children[AppearanceClass][0].name
if self.tokens["disabled"]:
attrs["enabled"] = "false"
return attrs
def emit_xml(self, xml):
xml.put_self_closing("response", name=self.tokens["name"])
class Responses(AstNode):
grammar = [
Keyword("responses"),
"{",
Delimited(Response, ","),
"}",
]
@validate("responses")
def container_is_adw_message_dialog(self):
validate_parent_type(self, "Adw", "MessageDialog", "responses")
@validate("responses")
def unique_in_parent(self):
self.validate_unique_in_parent("Duplicate responses block")
def emit_xml(self, xml: XmlEmitter):
xml.start_tag("responses")
for child in self.children:
child.emit_xml(xml)
xml.end_tag()
@completer(
applies_in=[ObjectContent],
applies_in_subclass=("Gtk", "Widget"),
matches=new_statement_patterns,
)
def style_completer(ast_node, match_variables):
yield Completion("styles", CompletionItemKind.Keyword, snippet="styles [\"$0\"]")

View file

@ -32,6 +32,9 @@ class BaseAttribute(AstNode):
def name(self): def name(self):
return self.tokens["name"] return self.tokens["name"]
def extra_attributes(self):
return {}
def emit_xml(self, xml: XmlEmitter): def emit_xml(self, xml: XmlEmitter):
value = self.children[Value][0] value = self.children[Value][0]
attrs = { self.attr_name: self.name } attrs = { self.attr_name: self.name }
@ -39,6 +42,8 @@ class BaseAttribute(AstNode):
if isinstance(value, TranslatedStringValue): if isinstance(value, TranslatedStringValue):
attrs = { **attrs, **value.attrs } attrs = { **attrs, **value.attrs }
attrs = { **attrs, **self.extra_attributes() }
xml.start_tag(self.tag_name, **attrs) xml.start_tag(self.tag_name, **attrs)
value.emit_xml(xml) value.emit_xml(xml)
xml.end_tag() xml.end_tag()

View file

@ -0,0 +1,12 @@
using Gtk 4.0;
using Adw 1;
Adw.MessageDialog {
responses {
duplicate: _("Hello"),
duplicate_appearance: _("1") destructive suggested,
duplicate: _("Goodbye"),
}
responses {}
}

View file

@ -0,0 +1,3 @@
7,46,9,Only one of 'destructive' or 'suggested' is allowed
8,5,9,Duplicate response ID 'duplicate'
11,3,9,Duplicate responses block

View file

@ -0,0 +1,12 @@
using Gtk 4.0;
using Adw 1;
Adw.MessageDialog {
responses {
cancel: _("Cancel"),
discard: _("Discard") destructive,
save: "Save" suggested disabled,
}
response::save => on_response_save();
}

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<object class="AdwMessageDialog">
<responses>
<response id="cancel" translatable="yes">Cancel</response>
<response id="discard" translatable="yes" appearance="destructive">Discard</response>
<response id="save" enabled="false" appearance="suggested">Save</response>
</responses>
<signal name="response::save" handler="on_response_save"/>
</object>
</interface>

View file

@ -147,6 +147,7 @@ class TestSamples(unittest.TestCase):
self.assert_sample("object_prop") self.assert_sample("object_prop")
self.assert_sample("parseable") self.assert_sample("parseable")
self.assert_sample("property") self.assert_sample("property")
self.assert_sample("responses")
self.assert_sample("signal") self.assert_sample("signal")
self.assert_sample("size_group") self.assert_sample("size_group")
self.assert_sample("string_list") self.assert_sample("string_list")
@ -197,6 +198,7 @@ class TestSamples(unittest.TestCase):
self.assert_sample_error("obj_prop_type") self.assert_sample_error("obj_prop_type")
self.assert_sample_error("property_dne") self.assert_sample_error("property_dne")
self.assert_sample_error("read_only_properties") self.assert_sample_error("read_only_properties")
self.assert_sample_error("responses")
self.assert_sample_error("signal_dne") self.assert_sample_error("signal_dne")
self.assert_sample_error("signal_object_dne") self.assert_sample_error("signal_object_dne")
self.assert_sample_error("size_group_non_widget") self.assert_sample_error("size_group_non_widget")