mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-03 15:49:07 -04:00
481 lines
12 KiB
ReStructuredText
481 lines
12 KiB
ReStructuredText
========
|
|
Tutorial
|
|
========
|
|
|
|
.. margin at column 75
|
|
|
|
Read this if you want to learn how to use Blueprint and never used
|
|
the XML syntax that can be read by GtkBuilder.
|
|
|
|
For compatibility with Blueprint IDE extensions, blueprint files
|
|
should end with ``.blp``.
|
|
|
|
|
|
Namespaces
|
|
----------
|
|
|
|
Blueprint needs the widget library to be imported. These include Gtk,
|
|
Libadwaita, Shumate, etc. To import a namespace, write ``using`` followed
|
|
by the library and version number.
|
|
|
|
.. code-block::
|
|
|
|
using Gtk 4.0;
|
|
using Adw 1;
|
|
|
|
The Gtk import is required in all blueprints and the minor version
|
|
number must be 0.
|
|
|
|
|
|
Comments
|
|
--------
|
|
|
|
Blueprint has inline or multi-line comments
|
|
|
|
.. code-block::
|
|
|
|
// This is an inline comment
|
|
/* This is
|
|
a multiline
|
|
comment */
|
|
|
|
Multi-line comments can't have inner multi-line comments. The compiler
|
|
will interpret the inner comment's closing token as the outer comment's
|
|
closing token. For example, the following will not compile:
|
|
|
|
.. code-block::
|
|
|
|
// Bad comment below:
|
|
/* Outer comment
|
|
/* Inner comment */
|
|
*/
|
|
|
|
|
|
Widgets
|
|
-------
|
|
|
|
Create widgets in the following format:
|
|
|
|
.. code-block::
|
|
|
|
Namespace.WidgetClass {
|
|
|
|
}
|
|
|
|
The Gtk namespace is implied for widgets, so you can just write the
|
|
widget class
|
|
|
|
.. code-block::
|
|
|
|
Box {
|
|
|
|
}
|
|
|
|
Other namespaces must be written explicitly.
|
|
|
|
.. code-block::
|
|
|
|
Adw.Leaflet {
|
|
|
|
}
|
|
|
|
Consult the widget library's documentation for a list of widgets.
|
|
A good place to start is
|
|
`the Gtk4 widget list <https://docs.gtk.org/gtk4/index.html>`_.
|
|
|
|
Naming Widgets
|
|
~~~~~~~~~~~~~~
|
|
|
|
Widgets can be given a **name/ID** so that they can be referenced by your
|
|
program or other widgets in the blueprint.
|
|
|
|
.. code-block::
|
|
|
|
Namespace.WidgetClass widget_id {
|
|
|
|
}
|
|
|
|
Any time you want to use this widget as a property (more about that in the
|
|
next section) or something else, write the widget's **ID** (e.g.
|
|
``main_window``).
|
|
|
|
|
|
Properties
|
|
----------
|
|
|
|
Every widget has properties defined by their GObject class.
|
|
For example, the Libadwaita documentation lists the
|
|
`properties of the Toast class <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1.2/class.Toast.html#properties>`_.
|
|
Write properties inside the curly brackets of a widget:
|
|
|
|
.. code-block::
|
|
|
|
Namespace.WidgetClass {
|
|
property-name: value;
|
|
}
|
|
|
|
Properties values are *all lowercase* (except strings) and must end with a
|
|
semicolon (``;``).
|
|
|
|
Property Types
|
|
~~~~~~~~~~~~~~
|
|
|
|
These are the **types** of values that can be used in properties:
|
|
- Booleans: ``true``, ``false``
|
|
- Numbers: e.g. ``1``, ``1.5``, ``-2``, ``-2.5``
|
|
- Strings (single- or double-quoted): e.g. ``"a string"``, ``'another string'``
|
|
- Enums
|
|
- Widgets
|
|
|
|
Properties are **strongly typed**, so you can't use, for example, a string
|
|
for the orientation property, which requires an ``Orientation`` enum
|
|
vartiant as its value.
|
|
|
|
Enum Properties
|
|
~~~~~~~~~~~~~~~
|
|
|
|
In the Gtk documentation, enum variants have long names and are
|
|
capitalized. For example, these are the
|
|
`Orientation <https://docs.gtk.org/gtk4/enum.Orientation.html>`_
|
|
enum variants:
|
|
|
|
- GTK_ORIENTATION_HORIZONTAL
|
|
- GTK_ORIENTATION_VERTICAL
|
|
|
|
In the blueprint, you would only write the *variant* part of the enum in
|
|
*lowercase*, just like you would in the XML.
|
|
|
|
.. code-block::
|
|
|
|
Box {
|
|
orientation: horizontal;
|
|
}
|
|
|
|
Widget Properties
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
Some widgets take other widgets as properties. For example, the
|
|
``Gtk.StackSidebar`` has a stack property which takes a ``Gtk.Stack`` widget.
|
|
You can create a new widget for the value, or you can reference another
|
|
widget by its **ID**.
|
|
|
|
.. code-block::
|
|
|
|
StackSidebar {
|
|
stack: Stack { };
|
|
}
|
|
|
|
OR
|
|
|
|
.. code-block::
|
|
|
|
StackSidebar {
|
|
stack: my_stack;
|
|
}
|
|
|
|
Stack my_stack {
|
|
|
|
}
|
|
|
|
Note the use of a semicolon at the end of the property in both cases.
|
|
Inline widget properties are not exempt of this rule.
|
|
|
|
|
|
Property Bindings
|
|
-----------------
|
|
|
|
If you want a widget's property to have the same value as another widget's
|
|
property (without hard-coding the value), you could ``bind`` two widgets'
|
|
properties of the same type. Bindings must reference a *source* widget by
|
|
**ID**. As long as the two properties have the same type, you can bind
|
|
properties of different names and of widgets with different widget classes.
|
|
|
|
.. code-block::
|
|
|
|
Box my_box {
|
|
halign: fill; // Source
|
|
}
|
|
|
|
Button {
|
|
valign: bind my_box.halign; // Target
|
|
}
|
|
|
|
Binding Flags
|
|
~~~~~~~~~~~~~
|
|
|
|
Modify the behavior of bindings with flags. Flags are written after the
|
|
binding. The default behavior is that the *Target*'s value will be
|
|
changed to the *Source*'s value when the binding is created and when the
|
|
*Source* value changes.
|
|
|
|
.. code-block::
|
|
|
|
Box my_box {
|
|
hexpand: true; // Source
|
|
}
|
|
|
|
Button {
|
|
vexpand: bind my_box.hexpand inverted bidirectional; // Target
|
|
}
|
|
|
|
no-sync-create
|
|
Prevent setting the *Tartget* with the *Source*'s value,
|
|
updating the target value when the *Source* value changes, not when
|
|
the binding is first created. Useful when the *Target* property has
|
|
another initial value that is not the *Source* value.
|
|
|
|
bidirectional
|
|
When either the *Source* or *Target* value is modified, the other's
|
|
value will be updated. For example, if the logic of the program
|
|
changes the Button's vexpand value to ``false``, then the Box's halign
|
|
value will also be updated to ``false``.
|
|
|
|
inverted
|
|
If the property is a boolean, the value of the bind can be negated
|
|
with this flag. For example, if the Box's hexpand property is ``true``,
|
|
the Button's vexpand property will be ``false`` in the code above.
|
|
|
|
|
|
Signals
|
|
-------
|
|
|
|
Gtk allows you to register signals in your program. This can be done by
|
|
getting the object from the GtkBuilder and connecting a handler to the
|
|
signal. Or register the handler with the application and reference it in
|
|
the blueprint.
|
|
|
|
Signals have an *event name*, a *handler* (aka callback), and optionally
|
|
some *flags*. Each widget will have a set of defined signals. Consult the
|
|
widget's documentation for a list of its signals.
|
|
|
|
To register a handler with the application, consult the documentation for
|
|
your language's bindings of Gtk.
|
|
|
|
.. code-block::
|
|
|
|
WidgetClass {
|
|
event_name => handler_name() flags;
|
|
}
|
|
|
|
.. TODO: add a list of flags and their descriptions
|
|
|
|
By default, signals in the blueprint will pass the widget that the signal
|
|
is for as an argument to the *handler*. However, you can specify the
|
|
widget that is passed to the handler by referencing its **ID** inside the
|
|
parenthesis.
|
|
|
|
.. code-block::
|
|
|
|
Label my_label {
|
|
label: "Hide me";
|
|
}
|
|
|
|
Button {
|
|
clicked => hide_widget(my_label);
|
|
}
|
|
|
|
|
|
Custom Widget Classes
|
|
---------------------
|
|
|
|
Some programs have custom widgets defined in their logic, so blueprint
|
|
won't know that they exist. Writing widgets not defined in the GIR will
|
|
result in an error. Prepend a custom widget with a period (``.``) to prevent the
|
|
compiler from trying to validate the widget. This is essentially saying
|
|
the widget has no *namespace*.
|
|
|
|
To register a custom widget with the application consult the documentation
|
|
for your language's bindings of Gtk.
|
|
|
|
.. code-block::
|
|
|
|
.MyCustomWidget {
|
|
|
|
}
|
|
|
|
|
|
Templates
|
|
---------
|
|
.. TODO
|
|
|
|
|
|
CSS Style Classes
|
|
-----------------
|
|
|
|
.. TODO: Unsure if to group styles with widget-specific items
|
|
|
|
Widgets can be given style classes that can be used with your CSS or
|
|
`predefined styles <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1.2/style-classes.html>`_
|
|
in libraries like Libadwaita.
|
|
|
|
.. code-block::
|
|
|
|
Button {
|
|
label: "Click me";
|
|
styles ["my-style", "pill"]
|
|
}
|
|
|
|
Note the lack of a *colon* after "styles" and a *semicolon* at the end of
|
|
the line. This syntax looks like the properties syntax, but it compiles to
|
|
XML completely different from properties.
|
|
|
|
Consult your language's bindings of Gtk to use a CSS file.
|
|
|
|
Non-property Elements
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Some widgets will have elements which are not properties, but they sort
|
|
of act like properties. Most of the time they will be specific only to a
|
|
certain widget. *Styles* is one of these elements, except that styles can
|
|
be used for any widget. Similar to how every widget has styles,
|
|
``Gtk.ComboBoxText`` has *items*:
|
|
|
|
.. code-block::
|
|
|
|
Gtk.ComboBoxText {
|
|
items [
|
|
item1: "Item 1",
|
|
item2: _("Items can be translated"),
|
|
"The item ID is not required",
|
|
]
|
|
}
|
|
|
|
See :doc:`examples <examples#widget-specific-items>` for a list of more of these
|
|
widget-specific items.
|
|
|
|
|
|
Menus
|
|
-----
|
|
|
|
Menus are usually the widgets that are placed along the top-bar of a
|
|
window, or pop up when you right-click some other widget. In Blueprint, a
|
|
``menu`` is a ``Gio.MenuModel`` that can be shown by MenuButtons or other
|
|
widgets.
|
|
|
|
In Blueprint, a ``menu`` can have *items*, *sections*, and *submenus*.
|
|
Like widgets, a ``menu`` can also be given an **ID**.
|
|
The `Menu Model section of the Gtk.PopoverMenu documentation <https://docs.gtk.org/gtk4/class.PopoverMenu.html#menu-models>`_
|
|
has complete details on the menu model.
|
|
|
|
Here is an example of a menu:
|
|
|
|
.. code-block::
|
|
|
|
menu my_menu {
|
|
section {
|
|
label: "File";
|
|
item {
|
|
label: "Open";
|
|
action: "win.open";
|
|
icon-name: "document-open-symbolic";
|
|
}
|
|
item {
|
|
label: "Save";
|
|
action: "win.save";
|
|
icon-name: "document-save-symbolic";
|
|
}
|
|
submenu {
|
|
label: "Save As";
|
|
icon-name: "document-save-as-symbolic";
|
|
item {
|
|
label: "PDF";
|
|
action: "win.save_as_pdf";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
There is a shorthand for *items*. Items require at least a label. The
|
|
action and icon-name are optional.
|
|
|
|
.. code-block::
|
|
|
|
menu {
|
|
item ( "Item 2" )
|
|
item ( "Item 2", "app.action", "icon-name" )
|
|
}
|
|
|
|
A widget that uses a ``menu`` is ``Gtk.MenuButton``. It has the *menu-model*
|
|
property, which takes a menu. Write the menu at the root of the blueprint
|
|
(meaning not inside any widgets) and reference it by **ID**.
|
|
|
|
.. code-block::
|
|
|
|
MenuButton {
|
|
menu-model: my_menu;
|
|
}
|
|
|
|
|
|
Child Types
|
|
-----------
|
|
|
|
Child types describe how a child widget is placed on a parent widget. For
|
|
example, HeaderBar widgets can have children placed either at the *start*
|
|
or the *end* of the HeaderBar. Child widgets of HeaderBars can have the
|
|
*start* or *end* types. Values for child types a widget can have are
|
|
defined in the widget's documentation.
|
|
|
|
Child types in blueprint are written between square brackets (``[`` ``]``) and before
|
|
the child the type is for.
|
|
|
|
The following blueprint code...
|
|
|
|
.. code-block::
|
|
|
|
HeaderBar {
|
|
[start]
|
|
Button {
|
|
label: "Button";
|
|
}
|
|
}
|
|
|
|
\... would look like this:
|
|
|
|
.. code-block::
|
|
|
|
---------------------------
|
|
| Button |
|
|
---------------------------
|
|
|
|
And the following blueprint code...
|
|
|
|
.. code-block::
|
|
|
|
HeaderBar {
|
|
[end]
|
|
Button {
|
|
label: "Button";
|
|
}
|
|
}
|
|
|
|
\... would look like this:
|
|
|
|
.. code-block::
|
|
|
|
---------------------------
|
|
| Button |
|
|
---------------------------
|
|
|
|
|
|
Translatable Strings
|
|
--------------------
|
|
|
|
Mark any string as translatable using this syntax: ``_("...")``.
|
|
|
|
Two strings that are the same in English could be translated in different
|
|
ways in other languages because of different *contexts*. Translatable
|
|
strings with context look like this: ``C_("context", "...")``. An example
|
|
where a context is needed is the word "have", which in Spanish could
|
|
translate to "tener" or "haber".
|
|
|
|
.. code-block::
|
|
|
|
Label {
|
|
label: C_("1st have", "have");
|
|
}
|
|
|
|
Label {
|
|
label: C_("2nd have", "have");
|
|
}
|
|
|
|
See `translations <translations.html>`_ for more details.
|