mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
Created Tutorial page; TODOs pending.
This commit is contained in:
parent
6ad1433587
commit
52e651a168
1 changed files with 452 additions and 0 deletions
452
docs/tutorial.rst
Normal file
452
docs/tutorial.rst
Normal file
|
@ -0,0 +1,452 @@
|
|||
========
|
||||
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. Here is
|
||||
for `Link Gtk <https://docs.gtk.org/gtk4/index.html>`.
|
||||
|
||||
Naming Widgets
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Widgets can be given **name**s so that they can be referenced by other
|
||||
widgets in the blueprint.
|
||||
|
||||
.. code-block::
|
||||
Namespace.WidgetClass widget-name {
|
||||
|
||||
}
|
||||
|
||||
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 **name** (e.g.
|
||||
`main-window`).
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
Every widget has properties defined by their GObject class. For example,
|
||||
Libadwaita Toast properties can be found
|
||||
`Link here <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 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
|
||||
`Link 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 **name**.
|
||||
|
||||
.. 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.
|
||||
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
|
||||
**name**. 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.
|
||||
|
||||
.. code-block::
|
||||
Box my-box {
|
||||
hexpand: true; // Source
|
||||
}
|
||||
|
||||
Button {
|
||||
vexpand: bind my-box.hexpand inverted bidirectional; // Target
|
||||
}
|
||||
|
||||
no-sync-create
|
||||
.. TODO: I'm not exactly sure what this does
|
||||
Only update the target value when the *Source* value changes, not when
|
||||
the binding is first created.
|
||||
|
||||
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 below.
|
||||
|
||||
|
||||
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 name 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, and 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 `.` to prevent the
|
||||
compiler from trying to validate the widget. This is essentially leaving
|
||||
out the *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
|
||||
-----------------
|
||||
.. Unsure if to group styles with widget-specific items
|
||||
Widgets can be given style classes that can be used with your CSS or
|
||||
`Link 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.
|
||||
|
||||
The syntax may change to `styles! [...]` in the future so that it is not
|
||||
confused with the properties syntax.
|
||||
|
||||
Consult your language's bindings of Gtk to use a CSS file.
|
||||
|
||||
Non-property Elements
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
.. TODO: ^^^ should it be called that?
|
||||
|
||||
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. Similarly 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 the `Link examples page <examples.html>`_ 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.
|
||||
|
||||
Similarly to how it is explained in
|
||||
`Link Gtk.PopoverMenu <https://docs.gtk.org/gtk4/class.PopoverMenu.html#menu-models>`_,
|
||||
in Blueprint `menu`s have *items*, *sections*, and *submenus*. `Menu`s can
|
||||
also be given a **name** like a widget. Please read the **Menu Model**
|
||||
section of `Gtk.PopoverMenu` for more 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. You can write the menu inline with the
|
||||
property, or write the menu separately and reference it by **name**.
|
||||
|
||||
.. code-block::
|
||||
MenuButton {
|
||||
menu-model: my-menu;
|
||||
}
|
||||
|
||||
|
||||
Child Types
|
||||
-----------
|
||||
|
||||
Child types describe how a child widget is placed on a parent widget. For
|
||||
example, HeaderBars 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:
|
||||
|
||||
---------------------------
|
||||
| Button |
|
||||
---------------------------
|
||||
|
||||
And the following blueprint code...
|
||||
|
||||
.. code-block::
|
||||
HeaderBar {
|
||||
[end]
|
||||
Button {
|
||||
label: "Button";
|
||||
}
|
||||
}
|
||||
|
||||
\... would look like this:
|
||||
|
||||
---------------------------
|
||||
| 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_("have", "1st have");
|
||||
}
|
||||
|
||||
Label {
|
||||
label: C_("have", "2nd have");
|
||||
}
|
||||
|
||||
See `Link translations page <translations.html>`_ for more details.
|
Loading…
Add table
Add a link
Reference in a new issue