novembre
2009
Hier, afin d’illustrer l’usage de LablGtk2, le binding GTK+ pour le langage Objective-Caml j’ai posté le code de ce Hello Developpez tout ce qu’il y a de plus basique :
Toutefois, une comparaison ligne à ligne avec la version Gtk2Hs pour Haskell, grâcieusement postée par Alp, n’était pas possible puisque mon code n’utilisait pas libglade.
On pourrait se demander pour quelle raison utiliser libglade car OCaml est un langage statiquement typé particulièrement sûr comparé à un fichier XML chargé dynamiquement et qui pourrait être modifié sans contrôle à tout moment. On pourrait argumenter qu’il est bon de séparer le visuel de l’interface et sa logique interne mais là encore le système de modules de OCaml est particulièrement bien adapté pour le separation of concerns.
L’intérêt indiscutable c’est la flexibilité, en particulier l’internationalisation est bien plus facile à réaliser que si elle était codée en dur. Et puis après tout la question n’est pas là, c’est à la mode, on peut le faire en Haskell, on peut le faire en OCaml, c’est facile à faire et ça justifie bien un nouveau billet blog.
Mon fichier XML est en tous points identique à celui de Alp :
<glade-interface>
<!-- interface-requires gtk+ 2.16 -->
<!-- interface-naming-policy project-wide -->
<widget class="GtkWindow" id="window1">
<property name="title" translatable="yes">Hello, Developpez !</property>
<property name="default_width">400</property>
<property name="default_height">400</property>
<child>
<widget class="GtkButton" id="yo">
<property name="label" translatable="yes">Bonjour Developpez, comment vas-tu ?
Je suis un programme OCaml qui utilise
LablGtk2, le binding GTK+ pour OCaml.
Clique pour fermer.</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</widget>
</child>
</widget>
</glade-interface>
Faites attention à ce que la balise ?xml soit bien sur la toute 1ière ligne du fichier sinon OCaml génèrera un avertissement et/ou une exception.
Le code source OCaml pour charger le XML et quitter quand l’utilisateur clique sur le bouton :
let xml = Glade.create ~file:"hello.glade" () in let window = new GWindow.window (GtkWindow.Window.cast(Glade.get_widget xml "window1")) in let button = new GButton.button (GtkButton.Button.cast(Glade.get_widget xml "yo") in button#connect#clicked ~callback: (fun () -> print_endline "Bye"; window#destroy (); GMain.Main.quit ()); window#show (); GMain.Main.main ()
La différence principale avec Gtk2Hs, hormis l’absence de la do-notation, se situe au niveau du chargement et de la conversion.
C’est légèrement plus tortueux qu’en Gtk2Hs, ça se fait en 3 étapes. C’est dû à la couche orienté-objet de LablGtk.
- on charge le gadget à l’aide de Glade.get_widget, on obtient un Gtk.widget Gtk.obj
- on converti ce Gtk.widget Gtk.obj en Gtk.window Gtk.obj à l’aide de GtkWindow.Window.cast
- ça ne s’arrête pas là, il n’est toujours pas possible d’utiliser cette fenêtre avec les méthodes de LablGtk parce qu’un Gtk.window Gtk.obj est une valeur mais pas un objet. il faut une deuxième conversion en un objet GWindow.window, en fait une instanciation réalisée par new GWindow.window
Voilà, ça n’était pas sorcier mais comme il faut naviguer dans une doc hyper-texte touffue et avare en explication, la première fois c’est toujours un peu déroutant.
C’est intéressant de comparer d’une part nos deux codes, et d’autre par nos codes avec ceux des autres langages.
Il faudrait faire plus de billets de ce genre pour montrer aux gens « comment on fait des choses conrètes et répandues avec des langages « différents » comme nos chers langages fonctionnels.