Simplify our UI declarative language, a strawman proposal

Modern GUI toolkits use declarative languages to construct user-interface elements/entities and manipulate their behavior from programming languages. This way, applications can have a clear separation of user-interface layouts and business logic, enabling popular design patterns for software engineering such as MVC, MVP, etc…

GTK is quite powerful in this aspect. With composite widget templates our developer story has become even more compelling. It has empowered our designers to contribute directly to the code base, eased our newcomers learning curve, and allowed for the composition of widgets to produce even more complex ones.

Our application developers tend to architect their application user interface with two different approaches: using Glade or writing UI files manually in a plaintext editor.

Glade

Being a WYSIWYG interface editor makes it a valuable entry point specifically for those not used to GTK application development. Composing interfaces by dragging-and-dropping widgets can be very handy, at least in theory.

Many experienced GTK application developers will advise you not to use Glade nowadays, for various reasons, including:

  • Lack of support for modern GTK widgets and custom widgets
  • Cumbersome changes in UI files, difficulting versioning operations such as git diff/blame
  • Lack of active maintainership

Manual editing

Widget packing is key to the way GTK UIs are built. By writing UI files manually I get full control of which widgets are used by my application and how their properties are set. I also get to make small changes in existing interfaces without generating unnecessary verbose results in the backing UI file.

Unfortunately, it can be considered a bit unpleasant having to write in such a verbose language.

<object class="GtkButton" id="my-button">
    <property name="visible">True</property>
    <child>
        <object class="GtkImage">
            <property name="visible">True</property>
            <property name="icon-name">audio-volume-high</property>
        </object>
    </child>
</object>

The example above shows that it takes about 10 lines to build a simple button with an image on it.

Also, the overuse of XML attributes instead of nodes makes you write “object class”, “property name” for every node.

The case for UI declarative languages

Writing interfaces by hand doesn’t need to be painful. Various thriving GUI frameworks don’t have WYSIWYG editors but have compelling declarative languages that make writing UI layouts a piece-of-cake.

After discussing this on Twitter, I decided to raise this discussion here, where we could evaluate the pros-and-cons of this proposal.

I understand markup parsers can be difficult to implement, and that the less verbose a markup is, the more undefined behavior one could expect as result. Therefore I suggest that we also discuss intermediary steps to gradually simplify our UI. I personally think that we should still stick to XML, but work towards simplifying our language spec.

In the Twitter thread linked above, I drafted how a simplified version could potentially look like (from an app developer’s convenience POV):

<button id="my-button">
  <image icon-name="audio-volume-high"/>
</button>

Please, notice that this is a strawman proposal to generate discussion of its disadvantages and to provoke the generation of new and better proposals.

4 Likes

The original libglade format used something like that:

<GtkHBox>
  <GtkLabel ...>
  <GtkButton ...>
</GtkHBox>

which was changed in libglade 2.0 to:

<widget class="GtkVBox">
 <child>
    <widget class="GtkLabel">
      <property name="text">...</property>
    </widget>
    <widget class="GtkButton">
    </widget>
  </child>
</widget>

to allow writing UI definitions for out-of-tree widgets and objects.

Once libglade was reworked to GtkBuilder, the XML changed to:

<object class="GtkBox">
  <property name="orientation">horizontal</property>
  <child>
    ...
</object>

to allow creating any type of GObject instance from a given type.

The problems with any compact XML schema you can come up with are:

  • you need to allow out-of-tree types
    The parser lives in GTK, and any custom parser for extending the format needs to instantiate the type itself, so it needs to know how to go from ThisIsATypeName to g_object_new (this_is_a_type_name_get_type (), NULL).
  • you need to avoid custom property names
    Every non-conforming property name needs custom parsing, which is slow.
  • XML attributes are terrible
    They are terrible to read, write, and validate.

The problem of any custom XML grammar is that it needs to adapt to the fact that GTK is not the only source of object types, properties, and signals. Out of tree libraries exist, and application developers might very well end up create their own types. This makes the grammar open ended, and open ended grammars cannot look nice at scale.

What are we trying to optimise, here? Writing XML by hand? Reading XML? Validating XML mechanically?

If we want to optimise hand-writing UI definitions, maybe XML is not a great option to begin width.

Or maybe we want something completely React-like, but at that point we don’t really use a base language that might work with it. See, for instance, vgtk for an implementation of a declarative UI with model-view-update patterns.

3 Likes

Lets try to answer this:

  • Is this proposal a language-independent Declarative UI syntax, In order to make it re-usable to any other one?
  • Is it expected to allow embedded scripts?

Language Independent UI declarative syntax

In order to make this happen, the syntax should be defined in a way it can be read from other programs a la .ui . It can support to translate it to current format at compilation time.

Making a handwritten friendly format, can be useful for a future Glade re-implementation or replacement app, in order to create a WYSIWYG app, where the UI designer can create reach and user friendly designs, keeping away from the Code required to make it works (business logic).

Friendly means to create a format where the properties are mapped elements’ attributes and the parser can understand how to set the required propoerty’s value. The parser can detect the type of the object it is and set it up, based on the parsed attributes, making more easy to write at hand with a few instructions to get visual results.

Lets say GXml is choosen as the parser, it will map the XML in a set of GObject classes for an easy to use API. The classes can be used to instantiate using g_object_new based on the type of UI element and its properties, in order to choose the one closest to the requested by the design.

Following code is just an snippet, the actual code in GXml, requires to add some annotations to enable proper property parsing

class Vui.Button : GXml.Element {
    // ID is a standard property in DOM4, so is inherited from GXml.Element

    // This is a custom GXml.Collection to hold any derived type on declaration
    public Vui.Children  children { get; set; 

}

Above code can read <button/> element and setup the attribute id as a GObject property, while is possible to access any children through the GXml.Collection, in charge to recognize all possible object types and map them to GObject classes, for easy API usage.

class Vui.Image : GXml.Element {
    public string icon_name { get; set; }
}

Above code declare the Image class, it can read the element <image/> and map the icon-name attribute to icon_nameproperty. GXml has a reach set of ways to map different types of attributes to basic property’s types and GObject classes to/from attributes.

Gtk will not change its internal format, not for the near feature, so the proposal should consider to convert this declarative, simpliest, format to .ui files, able to be used by Gtk widgets.

isn’t that what the proposal is about? If course, it would be about GTK4, 3.24 of course won’t change anything here.

Gtk maintainers are hard to convince and if the proposed format requires heavy translations, they will be reluctant, because can produce performance lost.

The first part is to design a format easy to struct by hand, easy to map to Gtk widgets and then try to propose it to Gtk as a new, maybe alternative format.

While GXml is designed to implement the easy to use DOM4 based Object Oriented API, Gtk wants to use C codding for XML parsing; above code in Vala is easy to implement on, but heaviest on C.

GXml has a on-the-fly XML parsing to GObject implementation, avoiding to create libxml2 tree, improving memory and performance.

A heavy Object Oriented declarative format, requires a OO oriented development, so Vala is one of the best candidates here, because it produce C binding friendly code, while keep it simple.

Is possible to create the GObject classes representation of the declarative format, make it converted to .ui in the middle, then propose as a new format to Gtk, if it takes care about restrictions imposed by maintainers, which should be consulted constantly to take his opinion and design the new format for the user and for the developer in mind

There’s already a branch to use CSS syntax instead, for example.

GtkStatusBar {
  children: {
    GtkFrame {
      id: "frame";
      shadow-type: none;
      hexpand: true;

      children: {
        GtkBox {
          id: "message_area";
          spacing: 4;

          children: {
            GtkLabel {
              id: "label";
              halign: start;
              valign: center;
              ellipsize: end;
              single-line-mode: true;
            }
          }
        }
      }
    }
  }
}

(from #gtk on irc, by baedert)

Edit: ahem, it’s not a tag

1 Like

Using CSS-like syntax, we have:

button {
    image {
        icon-name: 'audio-volume-high'
    }
}

Gtk already has support for CSS and that makes most of the magic on UI visualization; used because is easiest for Ui designers to use CSS instead of C code.

1 Like

Well, I think it’s more because that parser was generalized recently to be also used for the GSK render node editor?

1 Like

I think the point in discussion is:

What is the Easiest Format for handwriting UI definitions?

Sure, but I mean it doens’t seem the goal is to make what would be an ui file preprocessor basically, but to replace them with something better. And it doesn’t have to be XML.

I agree.

The ui file preprocessor, is just in the middle waiting on to get a reach and easy to use format; and should be implemented in parallel but independent.

I’ve used GLib.Scanner to implement custom parsers, if that can help check out at libvda, converting tokens to GObjec classes.

And to comment on a message from IRC:

The only reason why people want a human readable UI definition is because there aren’t any good UI tools

I disagree. For me it’s usually easier to write markup than to work with WYSIWYG. It’s not only GTK, e.g. it’s same with Markdown or even LaTeX vs things like LibreOffice/various wysiwyg html editors.

Edit: err, not question, just message.

I think is possible to help some UI designers wanting to use visual editors and the ones wanting to write by them self the code. Personally, I would like to see a WYSIWYG editor, showing the interface while I write it down.

Sure, I’m not saying they are not useful. Just saying that for me personally, and maybe for somebody else too, markup is easier in any case, so I see lots of value in having readable markup whether there’s a good tool or not.

Having a simpler/human readable format is entirely possible as an add on on top of a low level UI definition format. You can take a JSON-like/Elm-like approach and transform it into GtkBuilder XML already, today; it doesn’t need to live in GTK at all.

As for serializing GObjects: we are definitely not going to add a libxml2/GXml dependency to GObject; we could have a serialization/deserialization interface in GObject and use GIO extension points to have modules providing out of tree formats. The downside of that approach is that the more generic you make your serialization format, the less readable that becomes, as it needs to cover more and more use cases than UI descriptions.

The topic is constantly slipping away, and now we’re getting bogged down into a discussion on serialization formats and technologies, while I still haven’t seen a proper discussion of the goals of a UI description format.

  1. what is the intended audience
  2. how is this format going to be used
  3. what kind of tooling can be built around it
  4. what kind of use cases is this format going to facilitate?
  5. what kind of use cases are out of scope for this format?
  6. what kind of conversion mechanisms are going to be available to port existing UI descriptions from GtkBuilder to FancyNewBuilder?
  7. how do we deal with out-of-tree widgets and object types?
  8. how do we deal with out-of-tree widgets and object types for which we don’t have source access?
  9. how do we deal with versioning?
  10. how do we deal with property bindings?
  11. how do we deal with settings bindings?
  12. how do we deal with custom elements/attributes?
  13. who is going to do the work?

Open this sub-thread for: what is the intended audience:

For me:

  1. UI designers (primary)
  2. Programmers

These two are generally antithetical groups, and trying to cater to both will generally produce antithetical results. In other words: just because UI designers can write HTML and CSS it doesn’t mean they have the same tolerance for pain as programmers.