docs: Add syntax specification

Formally document the language syntax and provide examples and detailed
descriptions of how things work.
This commit is contained in:
James Westman 2023-03-11 18:43:32 -06:00
parent 3c1941a17e
commit ef39b5d7db
13 changed files with 1223 additions and 3 deletions

View file

@ -5,4 +5,20 @@
.experimental-admonition img {
width: 64px;
}
}
p.grammar-block {
font-family: var(--font-stack--monospace);
white-space: pre;
overflow: auto;
font-size: var(--code-font-size);
padding: .625rem .875rem;
line-height: 1.5;
background: #f8f8f8;
border-radius: .2rem;
}
body:not([data-theme="light"]) .grammar-block {
background: #202020;
color: #d0d0d0;
}

View file

@ -18,7 +18,7 @@
# -- Project information -----------------------------------------------------
project = 'Blueprint'
copyright = '2021, James Westman'
copyright = '2021-2023, James Westman'
author = 'James Westman'
@ -51,4 +51,4 @@ html_theme = 'furo'
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = ['styles.css']
html_css_files = ['styles.css']

View file

@ -18,6 +18,7 @@ Blueprint is a markup language and compiler for GTK 4 user interfaces.
setup
translations
flatpak
reference/index
examples
packaging

View file

@ -0,0 +1,188 @@
===========
Diagnostics
===========
.. _Diagnostic abstract_class:
abstract_class
--------------
Objects can't be created from abstract classes. Abstract classes are used as base classes for other classes, but they don't have functionality on their own. You may want to use a non-abstract subclass instead.
.. _Diagnostic bad_syntax:
bad_syntax
----------
The tokenizer encountered an unexpected sequence of characters that aren't part of any known blueprint syntax.
.. _Diagnostic child_not_accepted:
child_not_accepted
------------------
The parent class does not have child widgets (it does not implement `Gtk.Buildable <https://docs.gtk.org/gtk4/iface.Buildable.html>`_ and is not a subclass of `Gio.ListStore <https://docs.gtk.org/gio/class.ListStore.html>`_). Some classes use properties instead of children to add widgets. Check the parent class's documentation.
.. _Diagnostic conversion_error:
conversion_error
----------------
The value's type cannot be converted to the target type.
Subclasses may be converted to their superclasses, but not vice versa. A type that implements an interface can be converted to that interface's type. Many boxed types can be parsed from strings in a type-specific way.
.. _Diagnostic expected_bool:
expected_bool
-------------
A boolean value was expected, but the value is not ``true`` or ``false``.
.. _Diagnostic extension_not_repeatable:
extension_not_repeatable
------------------------
This extension can't be used more than once in an object.
.. _Diagnostic extension_wrong_parent_type:
extension_wrong_parent_type
---------------------------
No extension with the given name exists for this object's class (or, for a :ref:`child extension<Syntax ChildExtension>`, the parent class).
.. _Diagnostic invalid_number_literal:
invalid_number_literal
----------------------
The tokenizer encountered what it thought was a number, but it couldn't parse it as a number.
.. _Diagnostic member_dne:
member_dne
----------
The value is being interpreted as a member of an enum or flag type, but that type doesn't have a member with the given name.
.. _Diagnostic missing_gtk_declaration:
missing_gtk_declaration
-----------------------
All blueprint files must start with a GTK declaration, e.g. ``using Gtk 4.0;``.
.. _Diagnostic multiple_templates:
multiple_templates
------------------
Only one :ref:`template<Syntax Template>` is allowed per blueprint file, but there are multiple. The template keyword indicates which object is the one being instantiated.
.. _Diagnostic namespace_not_found:
namespace_not_found
--------------------
The ``.typelib`` files for the given namespace could not be found. There are several possibilities:
* There is a typo in the namespace name, e.g. ``Adwaita`` instead of ``Adw``
* The version number is incorrect, e.g. ``Adw 1.0`` instead of ``Adw 1``. The library's documentation will tell you the correct version number to use.
* The packages for the library are not installed. On some distributions, the ``.typelib`` file is in a separate package from the main library, such as a ``-devel`` package.
* There is an issue with the path to the typelib file. The ``GI_TYPELIB_PATH`` environment variable can be used to add additional paths to search.
.. _Diagnostic namespace_not_imported:
namespace_not_imported
----------------------
The given namespace was not imported at the top of the file. Importing the namespace is necessary because it tells blueprint-compiler which version of the library to use.
.. _Diagnostic object_dne:
object_dne
----------
No object with the given ID exists in the current scope.
.. _Diagnostic property_dne:
property_dne
------------
The class or interface doesn't have a property with the given name.
.. _Diagnostic property_convert_error:
property_convert_error
----------------------
The value given for the property can't be converted to the property's type.
.. _Diagnostic property_construct_only:
property_construct_only
-----------------------
The property can't be bound because it is a construct-only property, meaning it can only be set once when the object is first constructed. Binding it to an expression could cause its value to change later.
.. _Diagnostic property_read_only:
property_read_only
------------------
This property can't be set because it is marked as read-only.
.. _Diagnostic signal_dne:
signal_dne
----------
The class or interface doesn't have a signal with the given name.
.. _Diagnostic type_dne:
type_dne
--------
The given type doesn't exist in the namespace.
.. _Diagnostic type_not_a_class:
type_not_a_class
----------------
The given type exists in the namespace, but it isn't a class. An object's type must be a concrete (not abstract) class, not an interface or boxed type.
.. _Diagnostic version_conflict:
version_conflict
----------------
This error occurs when two versions of a namespace are imported (possibly transitively) in the same file. For example, this will cause a version conflict:
.. code-block:: blueprintui
using Gtk 4.0;
using Gtk 3.0;
But so will this:
.. code-block:: blueprintui
using Gtk 4.0;
using Handy 1;
because libhandy imports ``Gtk 3.0``.
.. _Diagnostic wrong_compiler_version:
wrong_compiler_version
----------------------
This version of blueprint-compiler is for GTK 4 blueprints only. Future GTK versions will use different versions of blueprint-compiler.

View file

@ -0,0 +1,74 @@
=======================
Document Root & Imports
=======================
.. _Syntax Root:
Document Root
-------------
.. rst-class:: grammar-block
Root = :ref:`GtkDecl<Syntax GtkDecl>` (:ref:`Using<Syntax Using>`)* ( :ref:`Template<Syntax Template>` | :ref:`Menu<Syntax Menu>` | :ref:`Object<Syntax Object>` )* EOF
A blueprint document consists of a :ref:`GTK declaration<Syntax GtkDecl>`, one sor more :ref:`imports<Syntax Using>`, and a list of :ref:`objects<Syntax Object>` and/or a :ref:`template<Syntax Template>`.
Example
~~~~~~~
.. code-block:: blueprintui
// Gtk Declaration
using Gtk 4.0;
// Import Statement
using Adw 1;
// Object
Window my_window {}
.. _Syntax GtkDecl:
GTK Declaration
---------------
.. rst-class:: grammar-block
GtkDecl = 'using' 'Gtk' '4.0' ';'
Every blueprint file begins with the line ``using Gtk 4.0;``, which declares the target GTK version for the file. Tools that read blueprint files should verify that they support the declared version.
Example
~~~~~~~
.. code-block:: blueprintui
using Gtk 4.0;
.. _Syntax Using:
GObject Introspection Imports
-----------------------------
.. rst-class:: grammar-block
Using = 'using' <namespace::ref:`IDENT<Syntax IDENT>`> <version::ref:`NUMBER<Syntax NUMBER>`> ';'
To use classes and types from namespaces other than GTK itself, those namespaces must be imported at the top of the file. This tells the compiler what version of the namespace to import.
You'll need the GIR name and version, not the package name and not the exact version number. These are listed at the top of each library's documentation homepage:
.. image:: gir-namespace.png
The compiler requires typelib files for these libraries to be installed. They are usually installed with the library, but on some distros, you may need to install the package that provides ``{namespace}-{version}.typelib`` (e.g. ``Adw-1.typelib``).
Example
~~~~~~~
.. code-block:: blueprintui
// Import libadwaita
using Adw 1;

View file

@ -0,0 +1,87 @@
===========
Expressions
===========
Expressions make your user interface code *reactive*. This means when your
application's data changes, the user interface reacts to the change
automatically.
.. code-block:: blueprintui
label: bind MyAppWindow.account.username;
/* ^ ^ ^
| creates lookup expressions that are re-evaluated when
| the account's username *or* the account itself changes
|
binds the `label` property to the expression's output
*/
When a value is bound to an expression using the ``bind`` keyword, the binding
monitors all the object properties that are inputs to the expression, and
reevaluates it if any of them change.
This is a powerful tool for ensuring consistency and simplifying your code.
Rather than pushing changes to the user interface wherever they may occur,
you can define your data model with GObject and let GTK take care of the rest.
.. _Syntax Expression:
Expressions
-----------
.. rst-class:: grammar-block
Expression = ( :ref:`ClosureExpression<Syntax ClosureExpression>` | :ref:`Literal<Syntax Literal>` | ( '(' Expression ')' ) ) ( :ref:`LookupExpression<Syntax LookupExpression>` | :ref:`CastExpression<Syntax CastExpression>` )*
.. note::
The grammar above is designed to eliminate `left recursion <https://en.wikipedia.org/wiki/Left_recursion>`_, which can make parsing more complex. In this format, an expression consists of a prefix (such as a literal value or closure invocation) followed by zero or more infix or suffix operators.
Expressions are composed of property lookups and/or closures. Property lookups are the inputs to the expression, and closures provided in application code can perform additional calculations on those inputs.
.. _Syntax LookupExpression:
Lookup Expressions
------------------
.. rst-class:: grammar-block
LookupExpression = '.' <property::ref:`IDENT<Syntax IDENT>`>
Lookup expressions perform a GObject property lookup on the preceding expression. They are recalculated whenever the property changes, using the `notify signal <https://docs.gtk.org/gobject/signal.Object.notify.html>`_
The type of a property expression is the type of the property it refers to.
.. _Syntax ClosureExpression:
Closure Expressions
-------------------
.. rst-class:: grammar-block
ClosureExpression = '$' <name::ref:`IDENT<Syntax IDENT>`> '(' ( :ref:`Expression<Syntax Expression>` ),* ')'
Closure expressions allow you to perform additional calculations that aren't supported in blueprint by writing those calculations as application code. These application-defined functions are created in the same way as :ref:`signal handlers<Syntax Signal>`.
Expressions are only reevaluated when their inputs change. Because blueprint doesn't manage a closure's application code, it can't tell what changes might affect the result. Therefore, closures must be *pure*, or deterministic. They may only calculate the result based on their immediate inputs, properties of their inputs or outside variables.
Blueprint doesn't know the closure's return type, so closure expressions must be cast to the correct return type using a :ref:`cast expression<Syntax CastExpression>`.
.. _Syntax CastExpression:
Cast Expressions
----------------
.. rst-class:: grammar-block
CastExpression = 'as' '<' :ref:`TypeName<Syntax TypeName>` '>'
Cast expressions allow Blueprint to know the type of an expression when it can't otherwise determine it.
.. code-block:: blueprintui
// Cast the result of the closure so blueprint knows it's a string
label: bind $my_closure() as <string>

View file

@ -0,0 +1,303 @@
==========
Extensions
==========
.. _Syntax Extension:
Properties are the main way to set values on objects, but they are limited by the GObject type system in what values they can accept. Some classes, therefore, have specialized syntax for certain features.
.. note::
Extensions are a feature of ``Gtk.Buildable``--see `Gtk.Buildable.custom_tag_start() <https://docs.gtk.org/gtk4/vfunc.Buildable.custom_tag_start.html>`_ for internal details.
Because they aren't part of the type system, they aren't present in typelib files like properties and signals are. Therefore, if a library adds a new extension, syntax for it must be added to Blueprint manually. If there's a commonly used extension that isn't supported by Blueprint, please `file an issue <https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues>`_.
.. rst-class:: grammar-block
Extension = :ref:`ExtAccessibility<Syntax ExtAccessibility>`
| :ref:`ExtAdwMessageDialog<Syntax ExtAdwMessageDialog>`
| :ref:`ExtComboBoxItems<Syntax ExtComboBoxItems>`
| :ref:`ExtFileFilterMimeTypes<Syntax ExtFileFilter>`
| :ref:`ExtFileFilterPatterns<Syntax ExtFileFilter>`
| :ref:`ExtFileFilterSuffixes<Syntax ExtFileFilter>`
| :ref:`ExtLayout<Syntax ExtLayout>`
| :ref:`ExtListItemFactory<Syntax ExtListItemFactory>`
| :ref:`ExtSizeGroupWidgets<Syntax ExtSizeGroupWidgets>`
| :ref:`ExtStringListStrings<Syntax ExtStringListStrings>`
| :ref:`ExtStyles<Syntax ExtStyles>`
.. _Syntax ExtAccessibility:
Accessibility Properties
------------------------
.. rst-class:: grammar-block
ExtAccessibility = 'accessibility' '{' ExtAccessibilityProp* '}'
ExtAccessibilityProp = <name::ref:`IDENT<Syntax IDENT>`> ':' :ref:`Value <Syntax Value>` ';'
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.
.. _Syntax ExtAdwMessageDialog:
Adw.MessageDialog Responses
----------------------------
.. rst-class:: grammar-block
ExtAdwMessageDialog = 'responses' '[' (ExtAdwMessageDialogResponse),* ']'
ExtAdwMessageDialogResponse = <id::ref:`IDENT<Syntax IDENT>`> ':' :ref:`StringValue<Syntax StringValue>` ExtAdwMessageDialogFlag*
ExtAdwMessageDialogFlag = 'destructive' | 'suggested' | 'disabled'
Valid in `Adw.MessageDialog <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1-latest/class.MessageDialog.html>`_.
The ``responses`` block defines the buttons that will be added to the dialog. The ``destructive`` or ``suggested`` flag sets the appearance of the button, and the ``disabled`` flag can be used to disable the button.
.. code-block:: blueprintui
using Adw 1;
Adw.MessageDialog {
responses [
cancel: _("Cancel"),
delete: _("Delete") destructive,
save: "Save" suggested,
wipeHardDrive: "Wipe Hard Drive" destructive disabled,
]
}
.. _Syntax ExtComboBoxItems:
Gtk.ComboBoxText Items
----------------------
.. rst-class:: grammar-block
ExtComboBoxItems = 'items' '[' (ExtComboBoxItem),* ']'
ExtComboBoxItem = ( <id::ref:`IDENT<Syntax IDENT>`> ':' )? :ref:`StringValue<Syntax StringValue>`
Valid in `Gtk.ComboBoxText <https://docs.gtk.org/gtk4/class.ComboBoxText.html>`_, which is deprecated as of Gtk 4.10.
The ``items`` block defines the items that will be added to the combo box. The optional ID can be used to refer to the item rather than its label.
.. code-block:: blueprintui
ComboBoxText {
items [
item1: "Item 1",
item2: "Item 2",
item3: "Item 3",
]
}
.. _Syntax ExtFileFilter:
Gtk.FileFilter Filters
----------------------
.. rst-class:: grammar-block
ExtFileFilterMimeTypes = 'mime-types' '[' (ExtFileFilterItem),* ']'
ExtFileFilterPatterns = 'patterns' '[' (ExtFileFilterItem),* ']'
ExtFileFilterSuffixes = 'suffixes' '[' (ExtFileFilterItem),* ']'
ExtFileFilterItem = <item::ref:`QUOTED<Syntax QUOTED>`>
Valid in `Gtk.FileFilter <https://docs.gtk.org/gtk4/class.FileFilter.html>`_.
The ``mime-types``, ``patterns``, and ``suffixes`` blocks define the items that will be added to the file filter. The ``mime-types`` block accepts mime types (including wildcards for subtypes, such as ``image/*``). The ``patterns`` block accepts glob patterns, and the ``suffixes`` block accepts file extensions.
.. code-block:: blueprintui
FileFilter {
mime-types [ "text/plain", "image/*" ]
patterns [ "*.txt" ]
suffixes [ "png", "jpg" ]
}
.. _Syntax ExtLayout:
Widget Layouts
--------------
.. rst-class:: grammar-block
ExtLayout = 'layout' '{' ExtLayoutProp* '}'
ExtLayoutProp = <name::ref:`IDENT<Syntax IDENT>`> ':' :ref:`Value<Syntax Value>` ';'
Valid in `Gtk.Widget <https://docs.gtk.org/gtk4/class.Widget.html>`_.
The ``layout`` block describes how the widget should be positioned within its parent. The available properties depend on the parent widget's layout manager.
.. code-block:: blueprintui
Grid {
Button {
layout {
column: 0;
row: 0;
}
}
Button {
layout {
column: 1;
row: 0;
}
}
Button {
layout {
column: 0;
row: 1;
row-span: 2;
}
}
}
.. _Syntax ExtListItemFactory:
Gtk.BuilderListItemFactory Templates
------------------------------------
.. rst-class:: grammar-block
ExtListItemFactory = 'template' :ref:`ObjectContent<Syntax Object>`
Valid in `Gtk.BuilderListItemFactory <https://docs.gtk.org/gtk4/class.BuilderListItemFactory.html>`_.
The ``template`` block defines the template that will be used to create list items. This block is unique within Blueprint because it defines a completely separate sub-blueprint which is used to create the list items. The sub-blueprint may not reference objects in the main blueprint or vice versa.
The template type is `Gtk.ListItem <https://docs.gtk.org/gtk4/class.ListItem.html>`_, and the template should have a ``child`` property.
.. code-block:: blueprintui
ListBox {
factory: ListItemFactory {
template {
child: Label {
label: bind item.string;
}
}
}
model: StringList {
strings [ "Item 1", "Item 2", "Item 3" ]
}
}
.. _Syntax ExtSizeGroupWidgets:
Gtk.SizeGroup Widgets
---------------------
.. rst-class:: grammar-block
ExtSizeGroupWidgets = 'widgets' '[' (ExtSizeGroupWidget),* ']'
ExtSizeGroupWidget = <id::ref:`IDENT<Syntax IDENT>`>
Valid in `Gtk.SizeGroup <https://docs.gtk.org/gtk4/class.SizeGroup.html>`_.
The ``widgets`` block defines the widgets that will be added to the size group.
.. code-block:: blueprintui
Box {
Button button1 {}
Button button2 {}
}
SizeGroup {
widgets [button1, button2]
}
.. _Syntax ExtStringListStrings:
Gtk.StringList Strings
----------------------
.. rst-class:: grammar-block
ExtStringListStrings = 'strings' '[' (ExtStringListItem),* ']'
ExtStringListItem = :ref:`StringValue<Syntax StringValue>`
Valid in `Gtk.StringList <https://docs.gtk.org/gtk4/class.StringList.html>`_.
The ``strings`` block defines the strings in the string list.
.. code-block:: blueprintui
StringList {
strings ["violin", "guitar", _("harp")]
}
.. _Syntax ExtStyles:
CSS Styles
----------
.. rst-class:: grammar-block
ExtStyles = 'styles' '[' ExtStylesProp* ']'
ExtStylesClass = <name::ref:`QUOTED<Syntax QUOTED>`>
Valid in any `Gtk.Widget <https://docs.gtk.org/gtk4/class.Widget.html>`_.
The ``styles`` block defines CSS classes that will be added to the widget.
.. code-block:: blueprintui
Button {
styles ["suggested-action"]
}
.. _Syntax ChildExtension:
Child Extensions
----------------
.. rst-class:: grammar-block
ChildExtension = :ref:`ExtResponse<Syntax ExtResponse>`
Child extensions are similar to regular extensions, but they apply to a child of the object rather than the object itself. They are used to add properties to child widgets of a container, such as the buttons in a `Gtk.Dialog <https://docs.gtk.org/gtk4/class.Dialog.html>`_. The child extension takes the place of a child type inside the square brackets.
Currently, the only child extension is :ref:`ExtResponse<Syntax ExtResponse>`.
.. _Syntax ExtResponse:
Dialog & InfoBar Responses
--------------------------
.. rst-class:: grammar-block
ExtResponse = 'action' 'response' '=' ( <name::ref:`IDENT<Syntax IDENT>`> | <id::ref:`NUMBER<Syntax NUMBER>`> ) 'default'?
Valid as a child extension for children of `Gtk.Dialog <https://docs.gtk.org/gtk4/class.Dialog.html>`_ or `Gtk.InfoBar <https://docs.gtk.org/gtk4/class.InfoBar.html>`_, which are both deprecated as of Gtk 4.10.
The ``action response`` extension sets the ``action`` child type for the child and sets the child's integer response type. The response type may be either a member of the `Gtk.ResponseType <https://docs.gtk.org/gtk4/enum.ResponseType.html>`_ enum or a positive, application-defined integer.
No more than one child of a dialog or infobar may have the ``default`` flag.
.. code-block:: blueprintui
Dialog {
[action response=ok default]
Button {}
[action response=cancel]
Button {}
[action response=1]
Button {}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

50
docs/reference/index.rst Normal file
View file

@ -0,0 +1,50 @@
================
Syntax Reference
================
This is the official specification of the blueprint format.
The grammar is expressed as a `parsing expression grammar <https://en.wikipedia.org/wiki/Parsing_expression_grammar>`_. This has two important implications: the parser will never backtrack, and alternation (e.g. a ``|`` in the specification) will always take the *first* branch that matches, even if that causes an error later. These properties make PEGs both unambiguous and simple to implement in code.
Blueprint uses C-style line comments (``// comment for the rest of the line``) and block comments (``/* multiline comment... */``).
Wherever commas are used as delimiters in repetition (expressed in this reference as ``( <rule> ),*``), the trailing comma is permitted and optional.
.. toctree::
:maxdepth: 1
document_root
objects
templates
values
expressions
menus
extensions
diagnostics
Tokens
------
.. _Syntax IDENT:
IDENT
~~~~~
An identifier starts with an ASCII underscore ``_`` or letter ``[A-Za-z]`` and consists of ASCII underscores, letters, digits ``[0-9]``, and dashes ``-``. Dashes are included for historical reasons, since GObject properties are traditionally kebab-case.
.. _Syntax NUMBER:
NUMBER
~~~~~~
Numbers begin with an ASCII digit and consist of ASCII digits, underscores, dots ``.``, and letters (for radix pre-/suffixes). More than one dot in a number is not allowed. Underscores are permitted for increased readability, and are ignored.
Hexadecimal numbers may be specified using the ``0x`` prefix and may use uppercase or lowercase letters, or a mix. Hexadecimal values may not have a fractional part. They are generally converted to decimal in the output.
.. _Syntax QUOTED:
QUOTED
~~~~~~
Quotes begin with an ASCII single quote ``'`` or double quote ``"`` and end with the same character they started with. An ASCII backslash ``\`` begins an escape sequence; this allows newlines ``\n``, tabs ``\t``, and quotes ``\'``, ``\"`` to be inserted. It also allows multiline strings by escaping a newline character, which will be ignored.

62
docs/reference/menus.rst Normal file
View file

@ -0,0 +1,62 @@
=====
Menus
=====
.. _Syntax Menu:
Menus
-----
.. rst-class:: grammar-block
Menu = 'menu' <id::ref:`IDENT<Syntax IDENT>`>? '{' MenuChild* '}'
MenuChild = ( MenuSection | MenuSubmenu | :ref:`MenuItemShorthand<Syntax MenuItemShorthand>` | MenuItem )
MenuSection = 'section' <id::ref:`IDENT<Syntax IDENT>`>? '{' ( MenuChild | MenuAttribute )* '}'
MenuSubmenu = 'submenu' <id::ref:`IDENT<Syntax IDENT>`>? '{' ( MenuChild | MenuAttribute )* '}'
MenuItem = 'item' '{' MenuAttribute* '}'
MenuAttribute = <name::ref:`IDENT<Syntax IDENT>`> ':' :ref:`StringValue<Syntax StringValue>` ';'
Menus, such as the application menu, are defined using the ``menu`` keyword. Menus have the type `Gio.MenuModel <https://docs.gtk.org/gio/class.MenuModel.html>`_ and can be referenced by ID. They cannot be defined inline.
Example
~~~~~~~
.. code-block:: blueprintui
menu my_menu {
submenu {
label: _("File");
item {
label: _("New");
action: "app.new";
icon: "document-new-symbolic";
}
}
}
MenuButton {
menu-model: my_menu;
}
.. _Syntax MenuItemShorthand:
Item Shorthand
--------------
.. rst-class:: grammar-block
MenuItemShorthand = 'item' '(' :ref:`StringValue<Syntax StringValue>` ( ',' ( :ref:`StringValue<Syntax StringValue>` ( ',' :ref:`StringValue<Syntax StringValue>`? )? )? )? ')'
The most common menu attributes are ``label``, ``action``, and ``icon``. Because they're so common, Blueprint provides a shorter syntax for menu items with just these properties.
Example
~~~~~~~
.. code-block:: blueprintui
menu {
item ("label")
item ("label", "action")
item ("label", "action", "icon")
}

189
docs/reference/objects.rst Normal file
View file

@ -0,0 +1,189 @@
=======
Objects
=======
.. _Syntax Object:
Objects
-------
.. rst-class:: grammar-block
Object = :ref:`TypeName<Syntax TypeName>` <id::ref:`IDENT<Syntax IDENT>`>? ObjectContent
ObjectContent = '{' (:ref:`Signal<Syntax Signal>` | :ref:`Property<Syntax Property>` | :ref:`Extension<Syntax Extension>` | :ref:`Child<Syntax Child>`)* '}'
Objects are the basic building blocks of a GTK user interface. Your widgets are all objects, as are some other features such as list models.
Optionally, objects may have an ID to provide a handle for other parts of the blueprint and your code to access objects.
.. note::
Object IDs must be unique within their scope. The document root is a scope, but :ref:`sub-templates<Syntax ExtListItemFactory>` have their own, isolated scope.
Example
~~~~~~~
.. code-block:: blueprintui
Label label1 {
label: "Hello, world!";
}
Label label2 {
label: bind-property file.name;
}
.. _Syntax TypeName:
Type Names
----------
.. rst-class:: grammar-block
TypeName = TypeNameFull | TypeNameExternal | TypeNameShort
TypeNameFull = <namespace::ref:`IDENT<Syntax IDENT>`> '.' <name::ref:`IDENT<Syntax IDENT>`>
TypeNameExternal = '$' <name::ref:`IDENT<Syntax IDENT>`>
TypeNameShort = <name::ref:`IDENT<Syntax IDENT>`>
There are three forms of type names: full, short, and external. Full type names take the form ``{namespace}.{name}``, e.g. ``Gtk.ApplicationWindow`` or ``Adw.Leaflet``. Because GTK types are so common, the Gtk namespace may be omitted, shortening ``Gtk.ApplicationWindow`` to just ``ApplicationWindow``.
External type names refer to types defined in your application. They are prefixed with ``$`` and do not have a dot between the namespace and class name. In fact, anywhere a ``$`` is used in a blueprint, it refers to something that must be defined in your application code.
.. _Syntax Property:
Properties
----------
.. rst-class:: grammar-block
Property = <name::ref:`IDENT<Syntax IDENT>`> ':' ( :ref:`PropertyBinding<Syntax PropertyBinding>` | :ref:`Binding<Syntax Binding>` | :ref:`ObjectValue<Syntax ObjectValue>` | :ref:`Value<Syntax Value>` ) ';'
Properties specify the details of each object, like a label's text, an image's icon name, or the margins on a container.
Most properties are static and directly specified in the blueprint, but properties can also be bound to a data model using the ``bind`` or ``bind-property`` keywords.
A property's value can be another object, either inline or referenced by ID.
Example
~~~~~~~
.. code-block:: blueprintui
Label {
label: "text";
}
Button {
/* Inline object value. Notice the semicolon after the object. */
child: Image {
/* ... */
};
}
.. _Syntax Signal:
Signal Handlers
---------------
.. rst-class:: grammar-block
Signal = <name::ref:`IDENT<Syntax IDENT>`> ('::' <detail::ref:`IDENT<Syntax IDENT>`>)? '=>' '$' <handler::ref:`IDENT<Syntax IDENT>`> '(' <object::ref:`IDENT<Syntax IDENT>`>? ')' (SignalFlag)* ';'
SignalFlag = 'after' | 'swapped'
Signals are one way to respond to user input (another is `actions <https://docs.gtk.org/gtk4/actions.html>`_, which use the `action-name property <https://docs.gtk.org/gtk4/property.Actionable.action-name.html>`_).
Signals provide a handle for your code to listen to events in the UI. The handler name is prefixed with ``$`` to indicate that it's an external symbol which needs to be provided by your code; if it isn't, things might not work correctly, or at all.
Optionally, you can provide an object ID to use when connecting the signal.
Example
~~~~~~~
.. code-block:: blueprintui
Button {
clicked => $on_button_clicked();
}
.. _Syntax Child:
Children
--------
.. rst-class:: grammar-block
Child = ChildAnnotation? :ref:`Object<Syntax Object>`
ChildAnnotation = '[' ( ChildInternal | :ref:`ChildExtension<Syntax ChildExtension>` | ChildType ) ']'
ChildInternal = 'internal-child' <internal-child::ref:`IDENT<Syntax IDENT>`>
ChildType = <child_type::ref:`IDENT<Syntax IDENT>`>
Some objects can have children. This defines the hierarchical structure of a user interface: containers contain widgets, which can be other containers, and so on.
Child annotations are defined by the parent widget. Some widgets, such as `HeaderBar <https://docs.gtk.org/gtk4/class.HeaderBar.html>`_, have "child types" which allow different child objects to be treated in different ways. Some, such as `Dialog <https://docs.gtk.org/gtk4/class.Dialog.html>`_ and `InfoBar <https://docs.gtk.org/gtk4/class.InfoBar.html>`_, define child :ref:`extensions<Syntax ChildExtension>`, which provide more detailed information about the child.
Internal children are a special case. Rather than creating a new object, children marked with ``[internal-child <name>]`` modify an existing object provided by the parent. This is used, for example, for the ``content_area`` of a `Dialog <https://docs.gtk.org/gtk4/class.Dialog.html>`_.
.. note::
The objects at the root of a blueprint cannot have child annotations, since there is no root widget for them to be a child of.
.. note::
Some widgets, like `Button <https://docs.gtk.org/gtk4/class.Button.html>`_, use a property to set their child instead. Widgets added in this way don't have child annotations.
Examples
~~~~~~~~
Add children to a container
+++++++++++++++++++++++++++
.. code-block:: blueprintui
Button {
Image {}
}
Child types
+++++++++++
.. code-block:: blueprintui
HeaderBar {
[start]
Label {
}
[end]
Button {
}
}
Child extensions
++++++++++++++++
.. code-block:: blueprintui
Dialog {
// Here, a child extension annotation defines the button's response.
[action response=cancel]
Button {}
}
Internal children
++++++++++++++++
.. code-block:: blueprintui
Dialog {
[internal-child content_area]
Box {
// Unlike most objects in a blueprint, this internal-child widget
// represents the properties, signal handlers, children, and extensions
// of an existing Box created by the Dialog, not a new Box created by
// the blueprint.
}
}

View file

@ -0,0 +1,82 @@
===================
Composite Templates
===================
.. _Syntax Template:
Composite Templates
-------------------
.. rst-class:: grammar-block
Template = 'template' <id::ref:`IDENT<Syntax IDENT>`> ( ':' :ref:`TypeName<Syntax TypeName>` )? :ref:`ObjectContent<Syntax Object>`
Widget subclassing is one of the primary techniques for structuring an application. For example, a maps app might have a `Gtk.ApplicationWindow <https://docs.gtk.org/gtk4/class.ApplicationWindow.html>`_ subclass, ``MapsApplicationWindow``, that implements the functionality of its main window. But a maps app has a lot of functionality, so the headerbar might be split into its own `Gtk.HeaderBar <https://docs.gtk.org/gtk4/class.HeaderBar.html>`_ subclass, ``MapsHeaderBar``, for the sake of organization.
You could implement this with the following blueprint:
.. code-block:: blueprintui
using Gtk 4.0;
$MapsApplicationWindow window {
$MapsHeaderBar {
/* probably a lot of buttons ... */
}
$MapsMainView {
/* a lot more UI definitions ... */
}
}
There are two problems with this approach:
1. The widget code may be organized neatly into different files, but the UI is not. This blueprint contains the entire UI definition for the app.
2. Widgets aren't in control of their own contents. It shouldn't be up to the caller to construct a widget using the correct blueprint--that's an implementation detail of the widget.
We can solve these problems by giving each widget its own blueprint file, which we reference in the widget's constructor. Then, whenever the widget is instantiated (by another blueprint, or by the application), it will get all the children and properties defined in its blueprint.
For this to work, we need to specify in the blueprint which object is the one being instantiated. We do this with a template block:
.. code-block:: blueprintui
using Gtk 4.0;
template MapsHeaderBar : Gtk.HeaderBar {
/* probably a lot of buttons ... */
}
Gio.ListStore bookmarked_places_store {
/* This isn't the object being instantiated, just an auxillary object. GTK knows this because it isn't the
one marked with 'template'. */
}
This blueprint can only be used by the ``MapsHeaderBar`` constructor. Instantiating it with ``Gtk.Builder`` won't work since it needs an existing, under-construction ``MapsHeaderBar`` to use for the template object. The ``template`` block must be at the top level of the file (not nested within another object) and only one is allowed per file.
This ``MapsHeaderBar`` class, along with its blueprint template, can then be referenced in another blueprint:
.. code-block:: blueprintui
using Gtk 4.0;
ApplicationWindow {
$MapsHeaderBar {
/* Nothing needed here, the widgets are in the MapsHeaderBar template. */
}
}
ID & Parent Parameters
~~~~~~~~~~~~~~~~~~~~~~
The ID of a template must match the full class name in your application code. The ID can be used elsewhere in the blueprint to reference the template object, just like any other object ID.
The parent type is optional and enables type checking for the template object.
Language Implementations
------------------------
- ``gtk_widget_class_set_template ()`` in C: https://docs.gtk.org/gtk4/class.Widget.html#building-composite-widgets-from-template-xml
- ``#[template]`` in gtk-rs: https://gtk-rs.org/gtk4-rs/stable/latest/book/composite_templates.html
- ``GObject.registerClass()`` in GJS: https://gjs.guide/guides/gtk/3/14-templates.html

168
docs/reference/values.rst Normal file
View file

@ -0,0 +1,168 @@
======
Values
======
.. _Syntax Value:
Values
------
.. rst-class:: grammar-block
Value = :ref:`Translated<Syntax Translated>` | :ref:`Flags<Syntax Flags>` | :ref:`Literal<Syntax Literal>`
.. _Syntax Literal:
Literals
--------
.. rst-class:: grammar-block
Literal = :ref:`TypeLiteral<Syntax TypeLiteral>` | QuotedLiteral | NumberLiteral | IdentLiteral
QuotedLiteral = <value::ref:`QUOTED<Syntax QUOTED>`>
NumberLiteral = ( '-' | '+' )? <value::ref:`NUMBER<Syntax NUMBER>`>
IdentLiteral = <ident::ref:`IDENT<Syntax IDENT>`>
Literals are used to specify values for properties. They can be strings, numbers, references to objects, types, boolean values, or enum members.
.. _Syntax TypeLiteral:
Type Literals
-------------
.. rst-class:: grammar-block
TypeLiteral = 'typeof' '<' :ref:`TypeName<Syntax TypeName>` '>'
Sometimes, you need to specify a type as a value. For example, when creating a list store, you may need to specify the type of the items in the list store. This is done using a ``typeof<>`` literal.
The type of a ``typeof<>`` literal is `GType <https://docs.gtk.org/gobject/alias.Type.html>`_, GObject's "meta-type" for type information.
Example
~~~~~~~
.. code-block:: blueprintui
Gio.ListStore {
item-type: typeof<GObject.Object>;
}
.. _Syntax Flags:
Flags
-----
.. rst-class:: grammar-block
Flags = <first::ref:`IDENT<Syntax IDENT>`> '|' ( <rest::ref:`IDENT<Syntax IDENT>`> )|+
Flags are used to specify a set of options. One or more of the available flag values may be specified, and they are combined using ``|``.
Example
~~~~~~~
.. code-block:: blueprintui
Adw.TabView {
shortcuts: control_tab | control_shift_tab;
}
.. _Syntax Translated:
Translated Strings
------------------
.. rst-class:: grammar-block
Translated = ( '_' '(' <string::ref:`QUOTED<Syntax QUOTED>`> ','? ')' ) | ( '\C_' '(' <context::ref:`QUOTED<Syntax QUOTED>`> ',' <string::ref:`QUOTED<Syntax QUOTED>`> ','? ')' )
Use ``_("...")`` to mark strings as translatable. You can put a comment for translators on the line above if needed.
.. code-block::
Gtk.Label label {
/* Translators: This is the main text of the welcome screen */
label: _("Hello, world!");
}
Use ``C_("context", "...")`` to add a *message context* to a string to disambiguate it, in case the same string appears in different places. Remember, two strings might be the same in one language but different in another depending on context.
.. code-block::
Gtk.Label label {
/* Translators: This is a section in the preferences window */
label: C_("preferences window", "Hello, world!");
}
.. _Syntax PropertyBinding:
Property Bindings
-----------------
.. rst-class:: grammar-block
PropertyBinding = 'bind-property' <source::ref:`IDENT<Syntax IDENT>`> '.' <property::ref:`IDENT<Syntax IDENT>`> (PropertyBindingFlag)*
PropertyBindingFlag = 'inverted' | 'bidirectional' | 'no-sync-create'
Bindings keep a property updated as another property changes. They can be used to keep the UI in sync with application data, or to connect two parts of the UI.
Example
~~~~~~~
.. code-block:: blueprintui
/* Use property bindings to show a label when a switch
* is active, without any application code */
Switch advanced_feature {}
Label warning {
visible: bind-property advanced_feature.active;
label: _("This is an advanced feature. Use with caution!");
}
.. _Syntax Binding:
Expression Bindings
-------------------
.. rst-class:: grammar-block
Binding = 'bind' :ref:`Expression<Syntax Expression>`
Expression bindings serve the same purpose as property bindings, but are more powerful. They can call application code to compute the value of a property, and they can do multi-step property lookups. See :ref:`the expressions page<Syntax Expression>`.
.. _Syntax ObjectValue:
Object Values
-------------
.. rst-class:: grammar-block
ObjectValue = :ref:`Object<Syntax Object>`
The value of a property can be an object, specified inline. This is particularly useful for widgets that use a ``child`` property rather than a list of child widgets. Objects constructed in this way can even have IDs and be referenced in other places in the blueprint.
Such objects cannot have child annotations because they aren't, as far as blueprint is concerned, children of another object.
.. _Syntax StringValue:
String Values
-------------
.. rst-class:: grammar-block
StringValue = :ref:`Translated<Syntax Translated>` | :ref:`QuotedLiteral<Syntax Literal>`
Menus, as well as some :ref:`extensions<Syntax Extensions>`, have properties that can only be string literals or translated strings.