Mit GNOME 3.10 haben die neuen HeaderBars Einzug gehalten, die Titelleiste und Toolbar eines Fenster vereinen und so, vor allem auf kleinen Displays, Platz sparen.

Die HeaderBar in Nautilus spart Platz.
Die HeaderBar in Nautilus spart Platz.

Diese HeaderBars können auch einfach in die eigenen Programme integriert werden, wenn die aktuellen Bibliotheken, also libgtk-3-0 und libgtk-3-dev (>= 3.10), installiert sind. Das folgende Minimalbeispiel befolgt die aktuellen Empfehlungen zur Erstellung von GNOME-Apps, erweitert also die Gtk.Application Klasse. Eine HeaderBar besteht im Endeffekt aus drei Bereichen, dem linken und dem rechten, die jeweils mit Gtk.Widgets befüllt werden können, und dem mittleren, der entweder mit Titel und gegebenenfalls Untertitel oder mit einem Gtk.Widget belegt wird.

Minimalbeispiel

Minimalbeispiel für die GTK HeaderBar.
Minimalbeispiel für die GTK HeaderBar.

Dieses Minimalbeispiel kann schon mit wenigen Zeilen Code erstellt werden:

class Example : Gtk.Application {
	public Example () {
		Object (application_id: "com.example.app", flags: ApplicationFlags.FLAGS_NONE);
	}
	
	protected override void activate () {
		Gtk.ApplicationWindow window = new Gtk.ApplicationWindow (this);
		window.set_default_size (500, 500);
		
		Gtk.HeaderBar headerBar = new Gtk.HeaderBar ();
		headerBar.set_title ("Titel");
		headerBar.set_subtitle ("Untertitel");
		
		
		window.set_titlebar (headerBar);
		window.show_all ();
	}
}

int main (string[] args) {
	return new Example ().run (args);
}

Das ganze wird wie üblich als main.vala gespeichert und mit

valac --pkg gtk+-3.0 -o example main.vala

kompiliert. Interessant ist hier vor allem window.set_titlebar (headerBar);, das dem Fenster die erstellte HeaderBar als Titelzeile zuweist.

Die Erweiterung

Soll in der Titelleiste ein “Schließen”-Button angezeigt werden, reicht ein einfacher Befehl:

headerBar.set_show_close_button (true);

Der linke und der rechte Bereich der Titelleiste wird jetzt, wie bei einer Gtk.Box, mit pack_end () und pack_start () befüllt, soll also zum Beispiel ein “Öffnen”-Button hinzugefügt werden, reichen die beiden Zeilen:

Gtk.Button openButton = new Gtk.Button.from_icon_name ("document-open", Gtk.IconSize.LARGE_TOOLBAR);
headerBar.pack_start (openButton);

Hierbei wird schon der neue Gtk.Button.from_icon_name-Constructor genutzt, da Gtk.Stock ab GTK 3.10 als veraltet markiert ist. Die Iconnamen sind dabei standardisiert und nicht mehr GTK-intern, mehr dazu allerdings in einem anderen Blogpost.

Erweitertes Minimalbeispiel mit 'Öffnen'- und 'Schließen'-Buttons.
Erweitertes Minimalbeispiel mit 'Öffnen'- und 'Schließen'-Buttons.

Widgets in der Titelleiste

Soll der mittlere Bereich nun, statt mit Titel und Untertitel, mit einem Gtk.Widget befüllt werden, so geschieht dies mit headerBar.set_custom_title (). Sinnvoll ist das für zentrale Steuerungsobjekte, zum Beispiel ein Suchfeld wie bei der neuen GNOME Karten-App, oder für einen Ansichtswechsel. Mit den folgenden Befehlen lässt sich also ein Suchfeld erstellen:

Gtk.Entry entry = new Gtk.Entry ();
entry.set_icon_from_icon_name (Gtk.EntryIconPosition.PRIMARY, "system-search");
headerBar.set_custom_title (entry);
Erweitertes Minimalbeispiel mit Widget in der Titelleiste.
Erweitertes Minimalbeispiel mit Widget in der Titelleiste.

Auch hier kommen wieder die neuen Iconnamen zum Einsatz. Der Titel und der Untertitel werden durch das Gtk.Widget überschrieben, sollen sie wieder angezeigt werden muss der “custom_title” null gesetzt werden:

headerBar.set_custom_title (null);

Einfach, oder? Hier noch einmal der Quelltext des kompletten Minimalbeispiels:

class Example : Gtk.Application {
	public Example () {
		Object (application_id: "com.example.app", flags: ApplicationFlags.FLAGS_NONE);
	}

	protected override void activate () {
		Gtk.ApplicationWindow window = new Gtk.ApplicationWindow (this);
		window.set_default_size (500, 500);
	
		Gtk.HeaderBar headerBar = new Gtk.HeaderBar ();
		headerBar.set_show_close_button (true);
	
		Gtk.Entry entry = new Gtk.Entry ();
		entry.set_icon_from_icon_name (Gtk.EntryIconPosition.PRIMARY, "system-search");
		headerBar.set_custom_title (entry);
	
		Gtk.Button openButton = new Gtk.Button.from_icon_name ("document-open", Gtk.IconSize.LARGE_TOOLBAR);
		headerBar.pack_start (openButton);
	
		Gtk.Button closeButton = new Gtk.Button.from_icon_name ("document-save-as", Gtk.IconSize.LARGE_TOOLBAR);
		headerBar.pack_end (closeButton);
	
		window.set_titlebar (headerBar);
		window.show_all ();
	}
}

int main (string[] args) {
	return new Example ().run (args);
}

Update (24.04.2014): Natürlich kann und sollte man auch das extra für Suchfelder gedachte Gtk.SearchEntry anstelle eines einfachen Gtk.Entrys benutzen.