Objects#

Objects#

Object = TypeName <id:IDENT>? ObjectContent ObjectContent = ‘{’ (Signal | Property | Extension | 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 sub-templates have their own, isolated scope.

Example#

Label label1 {
  label: "Hello, world!";
}
Label label2 {
  label: bind-property file.name;
}

Type Names#

TypeName = TypeNameFull | TypeNameExternal | TypeNameShort TypeNameFull = <namespace:IDENT> ‘.’ <name:IDENT> TypeNameExternal = ‘$’ <name:IDENT> TypeNameShort = <name: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.

Properties#

Property = <name:IDENT> ‘:’ ( Binding | ObjectValue | 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#

Label {
  label: "text";
}

Button {
  /* Inline object value. Notice the semicolon after the object. */
  child: Image {
    /* ... */
  };
}

Signal Handlers#

Signal = <name:IDENT> (‘::’ <detail:IDENT>)? ‘=>’ ‘$’ <handler:IDENT> ‘(’ <object:IDENT>? ‘)’ (SignalFlag)* ‘;’ SignalFlag = ‘after’ | ‘swapped’

Signals are one way to respond to user input (another is actions, which use the action-name property).

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#

Button {
  clicked => $on_button_clicked();
}

Children#

Child = ChildAnnotation? Object ChildAnnotation = ‘[’ ( ChildInternal | ChildExtension | ChildType ) ‘]’ ChildInternal = ‘internal-child’ <internal-child:IDENT> ChildType = <child_type: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, have “child types” which allow different child objects to be treated in different ways. Some, such as Dialog and InfoBar, define child extensions, 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.

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, use a property to set their child instead. Widgets added in this way don’t have child annotations.

Examples#

Add children to a container#

Button {
  Image {}
}

Child types#

HeaderBar {
  [start]
  Label {
  }

  [end]
  Button {
  }
}

Child extensions#

Dialog {
  // Here, a child extension annotation defines the button's response.
  [action response=cancel]
  Button {}
}

Internal children#

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.
  }
}