Search code examples
gtk3gladevalagnome-3genie

Gtk HeaderBar ActionBar pack_start pack_end within UI xml file


We are trialing Gtk3/Vala/Genie for the development of application user interfaces using Gnome-Builder/Meson/Glade/Flatpak. While there are many examples of Gtk.HeaderBar.pack_start( ... ) and Gtk.ActionBar.pack_start( ... ) within the Vala and other Gtk documentation, we have not been able to find examples of use within an xml ui file.

So the question is: how does one use pack_start/pack_end with the ui xml file? Are there any examples of a generated xml ui file or how to generate within Glade? Would this be entered as a property/attribute/child of the HeaderBar/ActionBar? What would this look like - what would be the general structure? If it is not a GtkChild, then how does one access it within the Vala/Genie source file?

Supplying the following trivial xml file MainApplication.ui, for example, how would one pack_start and pack_end a GtkColorButton to the GtkHeaderBar?

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.2 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <template class="MainWindow" parent="GtkApplicationWindow">
    <property name="can_focus">False</property>
    <property name="default_width">1024</property>
    <property name="default_height">768</property>
    <child type="titlebar">
      <object class="GtkHeaderBar" id="header_bar">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="title">Test Application</property>
        <property name="subtitle">gnome.org</property>
        <property name="show_close_button">True</property>
      </object>
    </child>
    <child>
      <object class="GtkBox" id="content_box">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <placeholder/>
        </child>
        <child>
          <object class="GtkActionBar" id="action_bar">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </template>
</interface>

This is used within the source file MainApplication.gs as follows:

[GtkTemplate (ui = "/org/gnome/application/ui/MainApplication.ui")]
class MainWindow : Gtk.ApplicationWindow

    [GtkChild]
    header_bar:Gtk.HeaderBar

    [GtkChild]
    action_bar:Gtk.ActionBar

    construct ( application:Gtk.Application )

        GLib.Object( application: application )

class MainApplication:Gtk.Application

    construct( id:string, flags:GLib.ApplicationFlags )

        /* set locale: ALL, "" */
        Intl.setlocale()

        /* set properties */
        set_application_id( id )
        set_flags( flags )

Solution

  • how does one use pack_start/pack_end with the ui xml file?

    You don't. These methods are used to programmatically add child widgets to container widgets. Doing that using glade avoids the need to do it with code.

    Are there any examples of a generated xml ui file or how to generate within Glade?

    Not sure i understood the question here. Glade generates xml ui definition files. Using them with GtkBuilder would instantiate the widgets which you could then retrieve with Gtk.Builder get_object method. There is another option, which you are using, called Gtk Composite Templates. This allows you to create composite widgets inside glade and map the widgets to your code class/class properties/fields and this will accelerate the coding process. You can read more here

    Would this be entered as a property/attribute/child of the HeaderBar/ActionBar?

    It's flexible enough to have a Window class with an header bar as a property/field and widgets within the header bar would also be properties of the window OR separate concerns and have an header bar as a composite widget and then add the header bar to the window. For this last option you would then need to set the header bar to the window programmatically unless you are ready to work on glade widget catalogs allowing you to have your own header bar composite widget available on the left widget palette in glade.

    What would this look like - what would be the general structure? If it is not a GtkChild, then how does one access it within the Vala/Genie source file?

    If it's not a child we would assume it's not inside the glade definition or does not live anywhere and so it would have to be instantiated programmatically and added to a container with Gtk.Container add method or specific container add methods like pack_start/end, etc.

    Supplying the following trivial xml file MainApplication.ui, for example, how would one pack_start and pack_end a GtkColorButton to the GtkHeaderBar?

    You can add a GtkColorButton with glade, name it, set it as a GtkChild and retrieve it. It would be a field of your composite widget (assuming your code and the use of templates).

    If not, then you would create a new instance of Gtk.ColorButton and add it, programmatically, to the Gtk.HeaderBar. Since Gtk.HeaderBar is a container (inherits from Gtk.Container abstract class), you have some methods to add childs to it:

    1. Gtk.HeaderBar pack_start and pack_end
    2. Gtk.Container methods (add, add_with_properties...)

    Example, in Vala, to add a Gtk.ColorButton using 1 and 2:

    1. header_bar.pack_start (new Gtk.ColorButton ());
    2. header_bar.add (new Gtk.ColorButton ());