Catégorie : Programmation     Tags :      

    Retrouvez cet article dans : Linux Magazine 99

    Ruby est principalement connu par son framework Web : Ruby on Rails. Certains l’emploient pour développer des scripts système, mais QUID des applications de bureau ?
    Nous allons voir par cet article qu’elles ne sont pas en reste. En effet, le binding Ruby-GNOME possède toutes les bases permettant de développer une application de bureau complète.

    Cet article nécessite quelques bases en Ruby, mais aucune en GTK+.
    À savoir, pour les personnes qui utilisent Ubuntu, la version de Ruby-GNOME2 0.15 incluse dans Ubuntu 7.4 est fortement boguée. Cependant, à l’heure où paraîtra ce numéro, la nouvelle version 7.10 d’Ubuntu sera sortie. Aussi, je vous encourage fortement à mettre à jour votre système si ce n’est déjà fait. L’autre solution est de télécharger la version 0.16 et de la compiler : http://sourceforge.net/project/showfiles.php?group_id=53614

    1. Ruby-GNOME2 : le binding

    Derrière ce terme quelque peu barbare que l’on peut traduire par " passerelle ", se cache en fait un concept simple. Son but est de permettre de développer une application, ici avec GTK+, en Ruby. GTK+ étant en langage C, comment peut-on développer en GTK+ depuis Ruby ?
    Le binding crée un pont vers les bibliothèques GTK+. C’est un ensemble de bibliothèques développées en langage C qui vont contenir un ensemble de méthodes vers des fonctions de GTK+. Pour chaque fonction de celui-ci, une méthode équivalente sera créée pour Ruby. Outre le fait de pouvoir utiliser GTK+ depuis Ruby, l’intérêt est que ces méthodes Ruby vont respecter le formalisme de Ruby et sa conception objet.
    Exemple :
    En C, pour créer un bouton avec un label, on appelle la fonction suivante :

      gtk_button_new_with_label("Toto")

    En Ruby, on fera :

        Gtk::Button.new("Toto")

    ou bien :

    monbouton = Gtk::Button.new
    monbouton.label = “Toto”

    Plus objet non ? :)
    Le binding Ruby GTK+ s’installe de la manière suivante sur un système basé sur Debian :

        apt-get install libgtk2-ruby

    Ce paquet, outre les exemples fournis, installe le paquet libgtk2-ruby1.8 qui contient, lui, le binaire /usr/lib/ruby/1.8/i486-linux/gtk2.so faisant office de pont entre GTK+ et Ruby.
    On peut vérifier cela via la commande ldd qui affiche les bibliothèques liées à ce binaire :

        $ ldd /usr/lib/ruby/1.8/i486-linux/gtk2.so
            libruby1.8.so.1.8 => /usr/lib/libruby1.8.so.1.8 (0xb7dc3000)
            libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0xb7cf7000)
            libgtk-x11-2.0.so.0 => /usr/lib/libgtk-x11-2.0.so.0 (0xb7972000)
            [...]

    On y voit entre autres la bibliothèque GTK+ (libgtk-x11-2.0.so.0), la glib, mais aussi la bibliothèque Ruby (libruby1.8.so.1.8).
    Le link vers Ruby permet d’accéder au binding depuis Ruby, par exemple :

    irb
    irb(main):001:0> require ‘gtk2’
    => true

    Le link vers la lib GTK+ permet au binding d’appeler les fonctions GTK+ et de renvoyer les résultats au programme Ruby appelant :

    irb(main):002:0> monbouton = Gtk::Button.new("Toto")
    => #<Gtk::Button:0xb648f920 ptr=0x84daeb8>
    irb(main):003:0> monbouton.class
    => Gtk::Button

    monbouton.methods affichera l’ensemble des méthodes proposées par la classe Gtk::Button.
    GTK+ possède un grand nombre de bindings, ce qui permet de l’utiliser depuis à peu près tous les langages connus.

    2. Historique

    Ruby-GTK (son nom de l’époque) a été démarré en 1998 par le créateur de Ruby, Yukihiro Matsumoto, puis reprit en 2002 par Masao Mutoh l’actuel mainteneur (http://ruby-gnome2.sourceforge.jp/fr/hiki.cgi?Historique).
    Entre 1998 et maintenant, le développement du binding est monté en flèche et, de nos jours, nous avons accès à toutes les bibliothèques GTK+ et GNOME.
    Attention à ne pas se fier au nom. En effet, celui-ci contient, comme on va le voir, autant les binding GTK+ que GNOME. Vous pouvez donc développer une application uniquement GTK+ avec Ruby-GNOME2, si vous le souhaitez.

    3. API

    Elle est scindée en 2 parties, celle dédiée à GTK+ et donc multiplaforme et celle dédiée à GNOME, essentiellement pour Linux.

    /img-articles/lm/99/cc-art-ruby/t1.jpg

    Il ne s’agit pas ici d’être exhaustif, vous avez accès à la liste complète sur le site web, mais de montrer l’étendue du binding : http://ruby-gnome2.sourceforge.jp/hiki.cgi?Ruby-GNOME2+API+Reference.
    Si vous souhaitez utiliser l’ensemble des fonctions proposées par GTK+ et GNOME, il ne sera pas nécessaire d’installer chaque portion séparément. En effet, chaque bibliothèque est séparée dans son binding. Par exemple, pour la lib gconf, il faut installer le paquet libgconf2-ruby, idem pour libpango1-ruby.
    L’installation du méta paquet ruby-gnome2 permet d’installer l’ensemble de ces bibliothèques.

    apt-cache show ruby-gnome2|grep Depends
    Depends: libgnome2-ruby, libgconf2-ruby, libglade2-ruby, libgtkhtml2-ruby, libgtkglext1-ruby, libgnomevfs2-ruby, libgtksourceview1-ruby, libpanel-applet2-ruby, libgnomeprint2-ruby, libgnomeprintui2-ruby, librsvg2-ruby, libgtk-mozembed-ruby, libvte-ruby, libart2-ruby, libatk1-ruby, libgdk-pixbuf2-ruby, libgnomecanvas2-ruby, libpango1-ruby

    Attention, si vous n’utilisez pas GNOME, cela installera bien évidemment ses bibliothèques !
    Rien de gênant de toute manière, une application GNOME fonctionne très bien dans un environnement KDE, l’inverse est aussi vrai.

    4. " Developers, developers, developers ! ", criait le singe

    Maintenant que ces bases sont posées, nous allons enfin démarrer une application de test. Ce léger apprentissage vous permettra d’assimiler les bases de GTK+. Cela risque d’être un peu rebutant, mais rapide et vous apprécierez par la suite la solution Glade.

    Prenons le code suivant :

    1 require ‘gtk2’
    2
    3 Gtk.init
    4 window = Gtk::Window.new
    5 window.set_title(‘test’)
    6 window.signal_connect(‘destroy’) { Gtk.main_quit }
    7
    8 vb = Gtk::VBox.new
    9
    10 hb = Gtk::HBox.new
    11 hb.pack_start(Gtk::Label.new(‘tu fais quoi ?’))
    12 entry = Gtk::Entry.new
    13 hb.pack_start(entry)
    14 b = Gtk::Button.new(‘Valider’)
    15 b.signal_connect(‘clicked’) { puts "je fais : #{entry.text}" }
    16 hb.pack_start(b)
    17 vb.pack_start(hb)
    18
    19 ok = Gtk::Button.new(Gtk::Stock::CLOSE)
    20 ok.signal_connect(‘clicked’) { Gtk.main_quit }
    21 vb.pack_start(ok)
    22
    23 window.add(vb)
    24 window.show_all
    25
    26 Gtk.main

    Enregistrez-le via votre éditeur emacs préféré et sauvegardez-le sous test.rb. Ensuite, exécutez la commande suivante : ruby test.rb.
    Si l’installation de Ruby-GTK s’est bien passée, vous devriez voir la fenêtre suivante.

    /img-articles/lm/99/cc-art-ruby/fig-1.jpg

    Il suffit d’écrire " rien " dans le champ de saisie, puis de cliquer sur le bouton " valider " pour voir apparaître sur la console : " Je fais : rien ".
    Pas très impressionnant, je l’avoue :) De plus, vous devez être dubitatif quant au code nécessaire pour afficher cela. Je vous assure cependant que ce code est beaucoup plus lisible que son équivalent en C.
    Je vous décris sans entrer dans les détails le code, ensuite, on passe à la méthode simple qu’il faut utiliser.

    4.1 Les widgets

    GTK+ fonctionne sur la méthode des poupées russes, chaque widget (objet GTK+ comme une fenêtre, un bouton, un label...) est encapsulé à l’intérieur d’un autre. Il peut s’agrandir proportionnellement à la taille de la fenêtre et ainsi permettre à l’utilisateur de profiter de tout l’espace offert au lieu d’avoir des widgets riquiqui, comme avec certaines bibliothèques graphiques. Évidemment, chaque widget peut ne pas avoir cette propriété, si vous le décidez, par exemple pour un bouton, mais pour un treeview, cela devient plus intéressant.

    4.2 Les signaux

    La deuxième et dernière chose à comprendre en GTK+ sont les signaux. Outre ses propriétés, chaque widget possède un ensemble de signaux. Par exemple, le bouton possède un signal appelé " clicked " qui sera émis lorsque l’utilisateur va cliquer dessus. Émis pour qui ? C’est justement à vous d’accrocher votre programme à ce signal pour lui permettre d’effectuer le traitement associé.

    4.3 Étude du code

    En ligne 3, on initialise GTK+.
    En ligne 4 et 5, on crée une fenêtre et on définit son titre via les propriétés du widget Window.
    En ligne 6, on met en pratique ce que je viens d’expliquer sur les signaux, c’est-à-dire que l’on associe le signal " destroy " du widget Window à un bloc de code Ruby. Ici, le bloc de code termine le programme. On appréciera l’élégance du binding qui permet d’utiliser un des avantages de Ruby que sont les blocs.
    En ligne 8, on crée un conteneur vertical Vbox. Comme indiqué plus haut, chaque widget est encapsulé. Si l’on veut disposer les widgets d’une certaine manière, il est donc nécessaire d’utiliser des conteneurs de widgets qui vont permettre via leurs propriétés de placer les widgets qu’ils contiennent de la manière que l’on souhaite. Ici, ce widget affiche les objets verticalement.
    Ligne 10, on crée un conteneur horizontal Hbox.
    Ligne 11, via la propriété pack_start de ce widget, on lui fait contenir un widget Label.
    Ligne 12, on crée un champ de saisie Entry.
    Ligne 13, on ajoute au conteneur Hbox le widget Entry. Il se met à la suite du Label.
    Ligne 14, on crée un bouton.
    Ligne 15, on associe au signal " clicked " du bouton un bloc de code. Ce bloc affiche simplement le contenu du champ de saisie.
    Ligne 16, on ajoute au conteneur Hbox le widget Button.
    Ligne 17, on ajoute au conteneur Vbox le conteneur Hbox. On aura donc sur une même ligne le label, le champ de saisie et le bouton
    Ligne 19, on crée un bouton contenant une icône.
    Ligne 20, on associe au signal " clicked " du bouton, un bloc de code. Ce bloc termine le programme.
    Ligne 21, on ajoute au Vbox le bouton. On voit ici l’intérêt d’utiliser le Vbox, car le but est de disposer le bouton " quitter " en dessous des autres objets alignés.
    Ligne 23, on ajoute la Vbox, qui contient tous les éléments, à la fenêtre.
    Ligne 24, par défaut, rien ne s’affiche. Il faut donc demander l’affichage de la fenêtre et de tous ses éléments.
    Ligne 26, il faut ici donner la main à la boucle d’événement de GTK+, sinon le programme quitterait immédiatement.
    Et voilà un programme basique en quelques lignes de code !
    Cependant si vous avez bien suivi, vous commencez à vous poser des questions :
    Comment connaître tous les widgets à ma disposition ?
    Comment connaître les propriétés de chaque widget ?
    Comment connaître les signaux de chaque widget ?

    En effet, à moins de lire la documentation détaillée sur le site de Ruby-GNOME2, ce que je ne vous conseille pas immédiatement, vous ne pouvez pas deviner tout ça.
    Mais je dois écrire l’appel de chaque objet que je veux utiliser ? Mais, si je veux écrire une interface graphique chargée, cela va être laborieux !
    En effet, si l’on s’arrête à cet exemple, oui. Mais, je vous rassure, on est en 2007 et, même sous Linux, il existe des solutions modernes pour répondre à toutes ces questions d’un coup, ce que nous allons voir avec Glade.

    5. Tutoriels

    Vous trouverez sur notre site web un tutoriel avancé : http://www.rubyfrance.org/documentations/ruby-gnome/creer-une-interface-graphique-avec-rubygtk/.
    Enfin, des exemples très complets sont livrés avec le paquet libgtk2-ruby dans le répertoire /user/share/doc/libgtk2-ruby/examples.
    Lancez le programme graphique des exemples :

     

    cd /usr/share/doc/libgtk2-ruby/examples/gtk-demo
    ./main

    /img-articles/lm/99/cc-art-ruby/fig-2.jpg
    L’onglet " Info " décrit l’exemple sélectionné, l’onglet " Source " montre son code source. Ensuite, il suffit de double cliquer sur une des applications de la liste pour tester l’exemple. Très pratique !

    Je vous conseille les exemples sur les treeviews. Ils vont permettront de comprendre plus rapidement leur fonctionnement.

    /img-articles/lm/99/cc-art-ruby/fig-3.jpg
    Une animation utilisant la bibliothèque Pixbufs

    6. Glade

    Nous disposons depuis un certain temps d’une interface graphique qui permet de créer votre interface graphiquement, à la manière de Windev ou Visual Basic. Il suffit d’installer le paquet glade-3.
    Une fois lancé, vous obtenez une interface graphique complète.

    /img-articles/lm/99/cc-art-ruby/fig-4.jpg
    Une animation utilisant la bibliothèque Pixbufs

    Sur le côté gauche, vous disposez de la palette complète de widgets proposés par GTK+.
    Au plus haut, les widgets de plus haut niveau comme les fenêtres, ensuite les conteneurs et pour finir les contrôleurs.
    Cliquez sur le widget tout en haut à gauche pour créer une fenêtre. Un fond gris apparaît et en cliquant dessus toutes les propriétés apparaissent sur le côté droit. Il suffit de les définir telles que vous le souhaitez. Plus besoin de le faire dans le code.
    Ensuite, cliquez sur le Vbox dans les conteneurs, puis cliquez dans la fenêtre créée pour l’y poser. Un popup apparaît, sélectionnez 2 items.
    Faites de même pour la Hbox, cliquez sur la partie du haut de la fenêtre et laissez 3 items.
    Sélectionnez le label, le Text Entry et le Button et disposez-les dans chacune des 3 sections du haut. Finissez avec un bouton en bas.
    Je vous laisse fouiller dans les propriétés de chaque widget, afin de les personnaliser, mais ce qui compte pour la suite est de les nommer correctement, puis de définir leurs signaux.
    Nommez le bouton du bas : " quitter " ; le bouton du haut : " valider " ; le champ de saisie : " saisie " ; puis, la fenêtre principale : " main ".
    Cliquez sur le bouton du bas, puis allez dans l’onglet Signal à droite. Sélectionnez le signal " clicked ", puis, dans la colonne Handler, choisissez " on_quitter_clicked ". Ce nom correspond à la fonction Ruby qui sera appelée lorsque le signal " clicked " sera déclenché par l’utilisateur. Vous pourrez le modifier par la suite si vous le désirez.
    Faites de même pour le bouton du haut, choisissez le traitement " on_valider_clicked "
    Et voilà, on a terminé. Enregistrez votre projet sous le nom test2, ce qui créera un fichier XML test2.glade.
    Écrivez le code suivant dans le fichier test2.rb.

    #!/usr/bin/env ruby
    #
    require ‚libglade2‘
    require ‚gtk2‘
    class MonAppli
      def initialize(file, root)
        @main_glade = GladeXML.new(file, root) {|handler| method(handler)}
        @main_glade[„main“].show_all
      end 
    
      def on_valider_clicked
        puts @main_glade[„saisie“].text
      end 
    
      def on_quitter_clicked
        Gtk.main_quit
      end 
    
    end 
    
    Gtk.init
    MonAppli.new(„test2.glade“,nil)
    Gtk.main

    Si tout va bien, vous devez obtenir une interface identique, et, en écrivant dans le champ de saisie, puis en cliquant sur le bouton en haut à droite, le contenu du texte doit s’afficher dans la console.

    La différence est que, maintenant, le code est beaucoup plus court, simple et clair ! De plus, vous pouvez modifier à tout moment le design de votre interface rapidement sans retoucher au code.
    Ce qui nous a permis de faire tout ça est le binding vers glade, la libglade.
    Cette bibliothèque lit le fichier XML .glade, ce qui permet d’accéder à tous les widgets de votre interface via l’objet @main_glade.
    Il suffit de préciser le nom du widget, @main_glade["lenomduwidget"], pour utiliser son instance. Il n’y a donc pas d’utilité à nommer, dans Glade, les widgets auxquels vous n’accédez pas, comme les décorateurs ou les conteneurs. À moins que vous ne désiriez modifier leurs propriétés dans votre code, sur un événement quelconque.
    Tout cela devient plus intéressant, mais c’est encore loin de ce que peut vous proposer le binding Ruby-GNOME2. Sa richesse dépend de l’ensemble des bindings mis à votre disposition, à vous d’en tirer profit.
    Pour finir, nous allons voir comment, en quelques lignes de codes, nous allons intégrer le moteur web Gecko, puis, enfin, lire une vidéo grâce au binding de Gstreamer, la bibliothèque multimédia de GNOME.

    7. Gecko

    Gecko est le moteur web du navigateur Firefox. Il peut être facilement intégré dans une application comme on peut l’observer ici :

    1 require ‘gtkmozembed’
    2
    3 w = Gtk::Window.new
    4 w.title = “Bienvenue sur RubyFrance”
    5 w.resize(780, 570)
    6 w << Gtk::MozEmbed.new
    7 w.child.location = "http://www.rubyfrance.org"
    8 w.show_all
    9 Gtk.main

    Les lignes 3 à 5 définissent une fenêtre et ses propriétés.
    Ligne 6, nous ajoutons le widget Gecko à la fenêtre. La dernière version de Glade ne permet pas de l’ajouter graphiquement, mais, comme on le voit ici, c’est extrêmement trivial.
    Ligne 7, on définit le site web ciblé.
    Enfin, nous affichons le tout et donnons la main à la boucle d’évènement de GTK+.

    /img-articles/lm/99/cc-art-ruby/fig-5.jpg
    Une animation utilisant la bibliothèque Pixbufs

    Et voilà, en quelques lignes, un navigateur web !
    Il manque bien sûr les contrôles pour obtenir un vrai navigateur (marque-pages, champ de saisie pour les URL, etc.), mais libre à vous de les ajouter.
    Cependant l’intérêt d’intégrer ce widget n’est pas de concurrencer Firefox. Il existe déjà des alternatives utilisant Gecko. Mais, il est ainsi possible de proposer des fonctionnalités complémentaires dans votre programme, comme le fait iTunes ou Winamp.

    8. Gstreamer

    Gstreamer est la bibliothèque multimédia de GNOME. Elle permet de lire tout type de fichier audio, mais aussi de la vidéo. C’est une bibliothèque très complète utilisée par de plus en plus d’applications.
    Le binding Ruby faisait partie jusqu’à récemment de Ruby-GNOME2. Faute de mainteneur, il en est sorti, puis a été repris en main récemment.
    Aussi, il vous faut l’installer via un paquet complémentaire.

        apt-get install libgstreamer0.10-ruby1.8

    Malheureusement, à cette date, Ubuntu Gutsy n’est pas encore terminé et ce paquet semble bogué. Faute de ne pouvoir tester cette version, je vous renvoie donc vers les exemples du site. Vous y trouverez un exemple de lecteur vidéo et audio : https://trac.luon.net/ruby-gstreamer0.10/browser/trunk/ruby-gstreamer0.10/sample.

    9. Applications ?

    Il y a actuellement très peu d’applications en Ruby-GNOME2, malheureusement. Mais, cela va changer grâce à vous ! ;) On peut malgré tout citer :

    • Alexandria : http://alexandria.rubyforge.org/ (un gestionnaire de livre et code excellent à étudier) ;
    • Fantasdic : http://www.gnome.org/projects/fantasdic/ (un dictionnaire) ;
    • Geekast (de votre serviteur, mais plus à jour pour l’instant) : http://home.gna.org/geekast/ (un client à Peercast.org) ;
    • GNOME Splash Screen Manager : http://www.miketech.net/gnome-art/ (un gestionnaire de thèmes et de fonds d’écran en provenance de Art.gnome.org) ;
    • Mr. Guid : http://mr-guid.rubyforge.org/ (un débogueur Ruby) ;
    • et d’autres, dans la catégorie GNOME, sur RubyForge : http://rubyforge.org/softwaremap/trove_list.php?form_cat=58.

    10. Oui, mais j’aime pas GTK+

    Ruby possède plusieurs bindings vers d’autres bibliothèques graphiques.

    • QtRuby : http://developer.kde.org/language-bindings/ruby/index.html (paquet libqt0-ruby1.8) ;
    • FXRuby : http://www.fxruby.org/ ;
    • Anvil (WxWidgets) : http://anvil.rubyforge.org/.

    Faites votre choix !

     

    Conclusion

    Vous avez pu constater qu’il est très simple de développer une application de bureau en Ruby-GNOME2. Cet article n’aborde pas le développement sur d’autres systèmes d’exploitation comme Windows ou Mac OS, mais, en pratique, l’environnement Windows est supporté si vous vous limitez aux fonctionnalités de GTK+. GTK+ n’étant pas encore natif sur l’environnement Mac, il vous faudra utiliser une autre bibliothèque graphique.
    GNU/Linux manque encore énormément d’applications de bureau. N’hésitez pas à vous lancer, en sachant qu’un projet n’aboutit le plus souvent que lorsqu’il manque un outil à vous-même ou à vos proches. Par contre, nous possédons un grand nombre d’applications en mode console. Il est donc judicieux de regarder de ce côté avant de vous lancer, puis d’utiliser ces applications à travers votre interface pour vous simplifier le travail et ne pas réinventer la roue.
    N’hésitez pas à poser vos questions par IRC : irc://rubyfr@freenode.net ou sur notre liste de diffusion publique : http://groups.google.com/group/rubyfr-public.
    Bon code avec Ruby et GTK+ !

     

    Références

    Les outils

    • http://ruby-gnome2.sourceforge.jp/fr/hiki.cgi?rbbr (un navigateur de classes : apt-get install rbbr)
    • Environnements de développement : http://anjuta.sourceforge.net/, le puissant Gedit livré dans GNOME et bien sûr Emacs (pensez à installer ruby1.8-elisp).

    Les documentations

    • http://ruby-gnome2.sourceforge.jp/
    • http://www.rubyfrance.org/documentations/ruby-gnome/creer-une-interface-graphique-avec-rubygtk/
    • http://www.rubyfrance.org/documentations/ruby-gnome/creer-une-interface-graphique-avec-ruby-gnome2-et-glade/
    • http://library.gnome.org/devel/
    • Un forum francophone dédié à Ruby-GNOME2 : http://fr.gnomesupport.org/forums/viewforum.php?id=29
    Posté par (La rédaction) | Signature : Frédéric Logier | Article paru dans Creative Commons License

    Laissez une réponse

    Vous devez avoir ouvert une session pour écrire un commentaire.