#gtk #xml #serde #ui

gtk_comfy

Gtk Comfy offers a solution to use serde formats in GTK builder files

11 unstable releases (3 breaking)

0.4.4 Feb 6, 2022
0.4.3 Oct 23, 2021
0.3.0 Oct 16, 2021
0.2.0 Sep 17, 2021
0.1.3 Sep 4, 2021

#249 in GUI

Download history 10/week @ 2024-02-19 4/week @ 2024-02-26 161/week @ 2024-04-01

161 downloads per month

GPL-3.0-or-later

20KB
278 lines

Gtk Comfy

Gtk Comfy is an effort to improve GTK builder files. Whilst the separation between code and interface is a good one, but the implementation is poor. XML is tricky and obtuse:

Example

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <object class="GtkApplicationWindow" id="window">
    <property name="title">My GTK App</property>
    <child>
      <object class="GtkButton" id="button">
        <property name="label">Press me!</property>
        <property name="margin-top">12</property>
        <property name="margin-bottom">12</property>
        <property name="margin-start">12</property>
        <property name="margin-end">12</property>  
      </object>
    </child>
  </object>
</interface>

So with GTK Comfy you can instead use any serde compatable format, as shown in the example below:

# The root interface
interface:
  # The class of the object (reserverd keyword)
  class: GtkApplicationWindow

  # The id of the widget (reserved keyword)
  id: window

  # The title property. See that properties are automatically infered
  title: My Gtk App

  # The children
  children:
    - class: GtkButton
      id: Button
      label: Press me!
      margin-start: "12"
      margin-top: "12"
      margin-bottom: "12"
      margin-end: "12"

Features

Gtk Comfy provides many convinience features, such as:

  • Inferred properties, if it does not recognise a variable it will infer it as a property (see the title in the above example.)
  • Child types, if a widget is given the child_type property than you can set the child type (I can’t remember when you need this but you do.)
  • Pango Attributes. For labels (and suchlike) you can use attributes to provide a map of attributes (example below.)
  • Style classes, provided in a style array.
  • Grids, support for layout in children.
  • Translation domain for interface.
  • Translations

Examples

Use in rust

Put something along these lines in your build script:

use std::fs;

// Load the UI.
let interface: gtk_comfy::Interface =
    serde_yaml::from_str(include_str!("ui.yaml"))?;

// Write it as xml.
fs::write(
    "ui.xml",
    interface.to_string(),
)?;

Attributes

class: GtkLabel
label: "This is a red label"
attributes:
  foreground: '#FF0000'

Styles

class: GtkBox
orientation: "horizontal"
style:
  - linked
children:
# ...

Grids

class: GtkGrid
  id: grid
  children:
  - class: GtkButton
    id: button1
    label: Button 1
    layout:
      column: 0
      row: 0
  - class: GtkButton
    id: button2
    label: Button 2
    layout:
      column: 1
      row: 0
  - class: GtkButton
    id: button3
    label: Button 3
    layout:
      column: 2
      row: 0
      row-span: 2
  - class: GtkButton
    id: button4
    label: Button 4
    layout:
      column: 0
      row: 1
      column-span: 2

Translation domains

domain: "whatever_this_value_does_i_have_no_idea_what_it_is"
interface:
  class: GtkWindow
  #...

Translations

Translations can be done as follows:

label:
  translatable: Save
  comment: For saving the state

Extensibility

If you need to extend it to add custom XML (because this app is not perfect) you can use the xml property:

xml: <property name="label">

Dependencies

~0.7–1.3MB
~35K SLoC