Aaron Fischer Ingenieur, Vater, Heimwerker, Problemlöser

20 Juni, 2008

XML als DSL für GUIs

Programmiersprachen

Ich bin schon seit vielen Jahren auf der Suche nach einer Möglichkeit, GUIs mit einem grafischen Editor zu erstellen und trotzdem nicht von einer IDE abhängig zu sein. Ich wünschte mir ein Tool, mit dem ich die GUI erstellen könnte und als Output eine (XML)-Beschreibung der erstellten Oberfläche erhalten würde.

AWT/Swing in Java war mir schon immer zuwider (mit und ohne GUI-Builder). Der (live) generierte Java-Code ist meist dermaßen hässlich und nachträglich unwartbar, so dass ich meist wieder selbst Hand angelegt habe und die GUI-Elemente selbst platziert habe. Dass es hier noch keine vernünftige Lösung gibt, wundert mich immer wieder.

Vor kurzem bin ich auf Ruby-Gnome2 gestoßen, was meine Erwartungen mehr als erfüllt hat: Mit dem general purpose GUI Builder GLADE erstellt man die GUI und speichert diese als Projekt ab. Das abgespeicherte Projekt besteht aus einer einzelnen XML-Datei, in der die komplette GUI inkl. signals (Event-/ActionListener für die Java-Programmierer) definiert sind. Diese XML-Datei lässt sich nun mit der GladeXML-Lib in Ruby mit wenigen Zeilen Code einlesen und ausführen. Auf Signale/Events kann man mühelos mit simplen Methoden zugreifen.

Wer mir nicht glaubt, hier eine kleine Demonstration: Zuerst wird mit GLADE die Oberfläche erstellt.

GLADE Interface Designer

Links (1) hat man die übliche Toolbox, die alle Komponenten enthält, die man für eine grafische Oberfläche braucht. Das Designfenster (5) in dem die GUI erstellt wrid, verhält sich genauso wie jedes andere Fenster. So kann man seine Oberfläche direkt live testen. Im Eigenschaften-Fenster lassen sich zu jeder platzierten Komponente Einstellungen wie Ausrichtung oder Beschriftung vornehmen (2). Unter dem Reiter Packing (3) lässt sich das Layout bestimmen. Unter Signale (4) lassen sich Events definieren und diesen Namen geben.

Hat man die Oberfläche soweit fertig, speichert man das Projekt ab. Als Resultat erhält man zwei Dateien. Eine projektname*.glade* und eine projektname*.gladep*. Die erste enthält die Beschreibung der GUI, und sieht ungefähr so aus (Ausschnitt!):

<glade-interface>
<widget class="GtkWindow" id="w1">
  <property name="visible">True</property>
  <property name="title" translatable="yes">Beispiel</property>
  <property name="type">>GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_NONE</property>
  <property name="modal">False</property>
...

Diese Datei lässt sich nun mit wenigen Zeilen Code in einer Ruby-Applikation einbinden. Wem das noch zu viel Arbeit ist, kann auch das Skript **ruby-glade-create-template** verwenden, um sich ein lauffähiges Grundgerüst zu generieren. Der so generierte Code sieht ungefähr so aus:

require "libglade2"

class SampleGlade
  include GetText
  attr :glade

  def initialize(path_or_data, root = nil, domain = nil, localedir = nil, flag = GladeXML::FILE)
    bindtextdomain(domain, localedir, nil, "UTF-8")
    @glade = GladeXML.new(path_or_data, root, domain, localedir, flag) {|handler| method(handler)}

  end

  def on_button1_clicked(widget)
    puts "on_button1_clicked() is not implemented yet."
  end
end

if __FILE__ == $0
  SampleGlade.new("sample.glade", nil, "Sample App")
  Gtk.main
end

Das so erstellte GUI-Programm ist direkt unter Windows und Linux lauffähig (GTK, Ruby und die Ruby-Gnome2-Lib vorausgesetzt). Genau so stelle ich mir Oberflächenprogrammierung vor! Sauber, einfach, Plattformunabhängig und komplett vom restlichen Code getrennt.

Toll wäre es nun, wenn sich jemand die Mühe machen würde und GladeXML in Java und Swing nachbilden würde. So könnte man ein und dieselbe GUI in einem Java-Programm und in einem Ruby-Programm nutzen!