mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
Allow for multiple a11y properties
This commit is contained in:
parent
b308adc3af
commit
3dfce3bbe0
10 changed files with 103 additions and 7 deletions
|
@ -17,6 +17,8 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
import typing as T
|
||||||
|
|
||||||
from ..decompiler import escape_quote
|
from ..decompiler import escape_quote
|
||||||
from .attributes import BaseAttribute
|
from .attributes import BaseAttribute
|
||||||
from .common import *
|
from .common import *
|
||||||
|
@ -97,6 +99,16 @@ def get_types(gir):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
allow_duplicates = [
|
||||||
|
"controls",
|
||||||
|
"described-by",
|
||||||
|
"details",
|
||||||
|
"flow-to",
|
||||||
|
"labelled-by",
|
||||||
|
"owns",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def _get_docs(gir, name):
|
def _get_docs(gir, name):
|
||||||
name = name.replace("-", "_")
|
name = name.replace("-", "_")
|
||||||
if gir_type := (
|
if gir_type := (
|
||||||
|
@ -111,7 +123,7 @@ class A11yProperty(BaseAttribute):
|
||||||
grammar = Statement(
|
grammar = Statement(
|
||||||
UseIdent("name"),
|
UseIdent("name"),
|
||||||
":",
|
":",
|
||||||
Value,
|
AnyOf(Value, ["[", UseLiteral("list_form", True), Delimited(Value, ","), "]"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -132,8 +144,8 @@ class A11yProperty(BaseAttribute):
|
||||||
return self.tokens["name"].replace("_", "-")
|
return self.tokens["name"].replace("_", "-")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> Value:
|
def values(self) -> T.List[Value]:
|
||||||
return self.children[0]
|
return list(self.children)
|
||||||
|
|
||||||
@context(ValueTypeCtx)
|
@context(ValueTypeCtx)
|
||||||
def value_type(self) -> ValueTypeCtx:
|
def value_type(self) -> ValueTypeCtx:
|
||||||
|
@ -146,7 +158,7 @@ class A11yProperty(BaseAttribute):
|
||||||
SymbolKind.Field,
|
SymbolKind.Field,
|
||||||
self.range,
|
self.range,
|
||||||
self.group.tokens["name"].range,
|
self.group.tokens["name"].range,
|
||||||
self.value.range.text,
|
", ".join(v.range.text for v in self.values),
|
||||||
)
|
)
|
||||||
|
|
||||||
@validate("name")
|
@validate("name")
|
||||||
|
@ -165,6 +177,20 @@ class A11yProperty(BaseAttribute):
|
||||||
check=lambda child: child.tokens["name"] == self.tokens["name"],
|
check=lambda child: child.tokens["name"] == self.tokens["name"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def list_only_allowed_for_subset(self):
|
||||||
|
if self.tokens["list_form"] and self.tokens["name"] not in allow_duplicates:
|
||||||
|
raise CompileError(
|
||||||
|
f"'{self.tokens['name']}' does not allow a list of values",
|
||||||
|
)
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def list_non_empty(self):
|
||||||
|
if len(self.values) == 0:
|
||||||
|
raise CompileError(
|
||||||
|
f"'{self.tokens['name']}' may not be empty",
|
||||||
|
)
|
||||||
|
|
||||||
@docs("name")
|
@docs("name")
|
||||||
def prop_docs(self):
|
def prop_docs(self):
|
||||||
if self.tokens["name"] in get_types(self.root.gir):
|
if self.tokens["name"] in get_types(self.root.gir):
|
||||||
|
|
|
@ -292,8 +292,11 @@ class XmlOutput(OutputFormat):
|
||||||
def _emit_extensions(self, extension, xml: XmlEmitter):
|
def _emit_extensions(self, extension, xml: XmlEmitter):
|
||||||
if isinstance(extension, ExtAccessibility):
|
if isinstance(extension, ExtAccessibility):
|
||||||
xml.start_tag("accessibility")
|
xml.start_tag("accessibility")
|
||||||
for prop in extension.properties:
|
for property in extension.properties:
|
||||||
self._emit_attribute(prop.tag_name, "name", prop.name, prop.value, xml)
|
for val in property.values:
|
||||||
|
self._emit_attribute(
|
||||||
|
property.tag_name, "name", property.name, val, xml
|
||||||
|
)
|
||||||
xml.end_tag()
|
xml.end_tag()
|
||||||
|
|
||||||
elif isinstance(extension, AdwBreakpointCondition):
|
elif isinstance(extension, AdwBreakpointCondition):
|
||||||
|
|
|
@ -37,12 +37,15 @@ Accessibility Properties
|
||||||
.. rst-class:: grammar-block
|
.. rst-class:: grammar-block
|
||||||
|
|
||||||
ExtAccessibility = 'accessibility' '{' ExtAccessibilityProp* '}'
|
ExtAccessibility = 'accessibility' '{' ExtAccessibilityProp* '}'
|
||||||
ExtAccessibilityProp = <name::ref:`IDENT<Syntax IDENT>`> ':' :ref:`Value <Syntax Value>` ';'
|
ExtAccessibilityProp = <name::ref:`IDENT<Syntax IDENT>`> ':' (:ref:`Value <Syntax Value>` | ('[' (:ref: Value <Syntax Value>),* ']') ) ';'
|
||||||
|
|
||||||
Valid in any `Gtk.Widget <https://docs.gtk.org/gtk4/class.Widget.html>`_.
|
Valid in any `Gtk.Widget <https://docs.gtk.org/gtk4/class.Widget.html>`_.
|
||||||
|
|
||||||
The ``accessibility`` block defines values relevant to accessibility software. The property names and acceptable values are described in the `Gtk.AccessibleRelation <https://docs.gtk.org/gtk4/enum.AccessibleRelation.html>`_, `Gtk.AccessibleState <https://docs.gtk.org/gtk4/enum.AccessibleState.html>`_, and `Gtk.AccessibleProperty <https://docs.gtk.org/gtk4/enum.AccessibleProperty.html>`_ enums.
|
The ``accessibility`` block defines values relevant to accessibility software. The property names and acceptable values are described in the `Gtk.AccessibleRelation <https://docs.gtk.org/gtk4/enum.AccessibleRelation.html>`_, `Gtk.AccessibleState <https://docs.gtk.org/gtk4/enum.AccessibleState.html>`_, and `Gtk.AccessibleProperty <https://docs.gtk.org/gtk4/enum.AccessibleProperty.html>`_ enums.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Relations which allow for a list of values, for example `labelled-by`, must be given as a single relation with a list of values instead of duplicating the relation like done in Gtk.Builder.
|
||||||
|
|
||||||
.. _Syntax ExtAdwBreakpoint:
|
.. _Syntax ExtAdwBreakpoint:
|
||||||
|
|
||||||
|
|
9
tests/sample_errors/a11y_list_empty.blp
Normal file
9
tests/sample_errors/a11y_list_empty.blp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
Box {
|
||||||
|
accessibility {
|
||||||
|
label: _("Hello, world!");
|
||||||
|
labelled-by: [];
|
||||||
|
checked: true;
|
||||||
|
}
|
||||||
|
}
|
1
tests/sample_errors/a11y_list_empty.err
Normal file
1
tests/sample_errors/a11y_list_empty.err
Normal file
|
@ -0,0 +1 @@
|
||||||
|
6,5,11,'labelled-by' may not be empty
|
15
tests/sample_errors/a11y_non_list_property.blp
Normal file
15
tests/sample_errors/a11y_non_list_property.blp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
Box {
|
||||||
|
accessibility {
|
||||||
|
label: _("Hello, world!");
|
||||||
|
active-descendant: [my_label1, my_label2, my_label3];
|
||||||
|
checked: true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label my_label1 {}
|
||||||
|
|
||||||
|
Label my_label2 {}
|
||||||
|
|
||||||
|
Label my_label3 {}
|
1
tests/sample_errors/a11y_non_list_property.err
Normal file
1
tests/sample_errors/a11y_non_list_property.err
Normal file
|
@ -0,0 +1 @@
|
||||||
|
6,5,17,'active-descendant' does not allow a list of values
|
15
tests/samples/accessibility_multiple_labelled_by.blp
Normal file
15
tests/samples/accessibility_multiple_labelled_by.blp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
Box {
|
||||||
|
accessibility {
|
||||||
|
label: _("Hello, world!");
|
||||||
|
labelled-by: [my_label1, my_label2, my_label3];
|
||||||
|
checked: true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label my_label1 {}
|
||||||
|
|
||||||
|
Label my_label2 {}
|
||||||
|
|
||||||
|
Label my_label3 {}
|
21
tests/samples/accessibility_multiple_labelled_by.ui
Normal file
21
tests/samples/accessibility_multiple_labelled_by.ui
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
DO NOT EDIT!
|
||||||
|
This file was @generated by blueprint-compiler. Instead, edit the
|
||||||
|
corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||||
|
-->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<accessibility>
|
||||||
|
<property name="label" translatable="yes">Hello, world!</property>
|
||||||
|
<relation name="labelled-by">my_label1</relation>
|
||||||
|
<relation name="labelled-by">my_label2</relation>
|
||||||
|
<relation name="labelled-by">my_label3</relation>
|
||||||
|
<state name="checked">1</state>
|
||||||
|
</accessibility>
|
||||||
|
</object>
|
||||||
|
<object class="GtkLabel" id="my_label1"></object>
|
||||||
|
<object class="GtkLabel" id="my_label2"></object>
|
||||||
|
<object class="GtkLabel" id="my_label3"></object>
|
||||||
|
</interface>
|
|
@ -221,6 +221,8 @@ class TestSamples(unittest.TestCase):
|
||||||
"list_factory",
|
"list_factory",
|
||||||
# Not implemented yet
|
# Not implemented yet
|
||||||
"subscope",
|
"subscope",
|
||||||
|
# Not implemented yet
|
||||||
|
"accessibility_multiple_labelled_by",
|
||||||
]
|
]
|
||||||
|
|
||||||
if sample in REQUIRE_ADW_1_4 and not self.have_adw_1_4:
|
if sample in REQUIRE_ADW_1_4 and not self.have_adw_1_4:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue