Blog tech

MacRuby - Introduction à HotCocoa

Rédigé par Nicolas Cavigneaux | 21 décembre 2010

HotCocoa, à quoi ça sert ?

HotCocoa est un librairie qui va vous permettre de générer et manipuler de manière simple une interface graphique (GUI) ainsi que ses interactions avec l’utilisateur directement depuis du code Ruby sans avoir besoin de passer par Interface Builder ou XCode.

Dans cette série d’articles sur HotCocoa, nous ne ferons rien d’extraordinaire mais nous couvrirons l’ensemble des bases nécessaires à l’écriture d’une application lourde en MacRuby sans utiliser Interface Builder. Ce tutoriel sera donc en plusieurs parties et aura pour but d’écrire une application capable de récupérer un flux RSS donné et d’afficher ses 5 dernières entrées.

Installation

Je vais ici considérer que vous avez déjà installé MacRuby grâce à notre introduction à MacRuby. Il ne nous reste donc qu’à installer HotCocoa. Auparavant, HotCocoa faisait partie intégrante de la distribution MacRuby mais c’est maintenant devenu un gem. Cette indépendance permet à l’équipe de HotCocoa d’accepter des contributions et d’évoluer plus rapidement.

Il nous faut donc lancer la commande suivante :

sudo macgem install hotcocoa

Nous avons maintenant accès à un nouveau binaire hotcocoa qui va nous permettre de créer la structure de base de notre projet.

Création d’un projet

Créons donc notre arborescence de base :

hotcocoa SynbiozFeeds

Une fois notre arborescence créée, nous pouvons nous déplacer dans le répertoire SynbiozFeeds et utiliser la commande macrake. Cette commande va lancer la tâche Rake par défaut qui a pour but de construire et démarrer l’application. Une fenêtre de type “Hello World” devrait apparaitre.

Quand vous utiliser MacRuby, pensez bien à utiliser tout ses outils dédiés : macrake, macirb, macgem et macruby.

Vous devez maintenant avoir, dans votre répertoire, un exécutable nommé SynbiozFeeds.app. Cet exécutable peut être lancé comme tout autre application Mac avec un double-clic. Il est nécessaire que le poste qui lance l’exécutable soit équipé de MacRuby. Il est également possible de compiler votre logiciel pour qu’il embarque MacRuby et puisse donc être exécuté sur une machine ne disposant pas de MacRuby mais nous verrons cela plus tard.

Structure

La structure de notre projet MacRuby / Cocoa est la suivante :

  • Rakefile
  • config/build.yml
  • resources/HotCocoa.icns
  • lib/application.rb
  • lib/menu.rb

Le fichier Rakefile nous permet de lancer des tâches telles que la compilation de l’application, le nettoyage des fichiers compilés, la génération d’une version embarquant MacRuby ou tout simplement le lancement de l’exécutable.

Le fichier build.yml contient quant à lui des informations utilisées par HotCocoa pour construire l’application. On y trouvera le nom de l’application, la version, l’icône, l’emplacement des sources.

Les fichiers primordiaux pour l’écriture de notre application sont application.rb and menu.rb.

Le menu

Le fichier menu.rb contient la définition du menu de notre application, par défaut voici à quoi il ressemble :

module HotCocoa
  def application_menu
    menu do |main|
      main.submenu :apple do |apple|
        apple.item :about, :title => "About #{NSApp.name}"
        apple.separator
        apple.item :preferences, :key => ","
        apple.separator
        apple.submenu :services
        apple.separator
        apple.item :hide, :title => "Hide #{NSApp.name}", :key => "h"
        apple.item :hide_others, :title => "Hide Others", :key => "h", :modifiers => [:command, :alt]
        apple.item :show_all, :title => "Show All"
        apple.separator
        apple.item :quit, :title => "Quit #{NSApp.name}", :key => "q"
      end
      main.submenu :file do |file|
        file.item :new, :key => "n"
        file.item :open, :key => "o"
      end
      main.submenu :window do |win|
        win.item :minimize, :key => "m"
        win.item :zoom
        win.separator
        win.item :bring_all_to_front, :title => "Bring All to Front", :key => "o"
      end
      main.submenu :help do |help|
        help.item :help, :title => "#{NSApp.name} Help"
      end
    end
  end
end

On voit que c’est ici que sont définis les noms de menus, les raccourcis clavier, la disposition des menus, etc.

Le sous-menu :apple est un menu spécial qui apparaitra sous la forme du nom de votre application comme on y est habitué dans les applications OS X.

Pour les autres menus, par défaut, les titres des menus seront la version capitalisée du symbole qui est passé en paramètre. Vous pouvez, si vous le souhaitez, définir un attribut :title => 'Mon menu' pour utiliser un autre nom.

Le symbole que vous définissez dans les éléments de sous-menus seront utilisés pour générer le nom de la méthode qui sera invoquée lors d’un clic. Par exemple, pour le menu file.item :new, la méthode on_new sera utilisée pour la délégation. Si la méthode on_ n’existe pas dans votre code, l’élément du menu sera désactivé.

L’application

Le fichier application.rb généré par défaut est le suivant. Il est très court et facilement compréhensible.

require ‘rubygems’ require ‘hotcocoa’

# Replace the following code with your own hotcocoa code

class Application

include HotCocoa

def start
  application :name => "SynbiozFeeds" do |app|
    app.delegate = self
    window :frame => [100, 100, 500, 500], :title => "SynbiozFeeds" do |win|
      win << label(:text => "Hello from HotCocoa", :layout => {:start => false})
      win.will_close { exit }
    end
  end
end

# file/open
def on_open(menu)
end

# file/new
def on_new(menu)
end

# help menu item
def on_help(menu)
end

# This is commented out, so the minimize menu item is disabled
#def on_minimize(menu)
#end

# window/zoom
def on_zoom(menu)
end

# window/bring_all_to_front
def on_bring_all_to_front(menu)
end   end

Application.new.start

La librairie hotcocoa est chargée et on inclus la classe pour raccourcir notre code. L’application démarre grâce à la dernière ligne de code Application.new.start.

La méthode Application#start crée un instance de notre application en définissant son titre.

On définit ensuite la délégation des événements vers notre propre classe. Notre classe va donc recevoir tous les appels aux méthodes de rappel (callbacks) effectués depuis notre application. Les appels aux méthodes on_* du menu sont elles aussi concernées. Notre classe gère donc l’ensemble des interactions possibles depuis notre interface graphique.

À la ligne suivante, on crée une fenêtre qui sera positionnée à 100 pour l’axe des X et des Y. Ces valeurs sont relatives au coin inférieur gauche. Notre fenêtre aura une taille de 500 par 500. On spécifie le titre de la fenêtre grâce à l’option :title. Nous aurions pu choisir uniquement la taille de la fenêtre sans définir son positionnement grâce à l’option :size => [500, 500] et décider de la positionner au beau milieu du bureau grâce à l’option :center => true.

L’ensemble des options disponibles peuvent être consultées directement depuis la documentation de Cocoa en regardant du côté de la classe NSWindow. Toutes les options disponible en Cocoa le sont également depuis HotCocoa.

Une fois la fenêtre créée, on y ajoute une étiquette (label) avec un texte, puis on demande à ce que l’application quitte lorsqu’on ferme la fenêtre.

Le callback will_close est le nom utilisé dans HotCocoa, son équivalent Cocoa étant windowWillClose:. La plupart des callbacks ont étés renommés pour adhérer au style de Ruby. Si vous voulez une liste complète, un simple coup d’oeil au code source des mappings HotCocoa vous apprendra tout. On voit par exemple, que pour la classe Window, on a une liste exhaustive à la fin du fichier window.rb

Conclusion

Cet article nous a permit d’effleurer la surface de HotCocoa et de l’écriture d’une application riche grâce à MacRuby. Maintenant que la structure de base de notre application est prête, dans un prochain article, nous verrons comment préparer notre interface pour quelle soit en mesure de recueillir des informations tirés de flux RSS dont l’adresse est saisie par l’utilisateur.

L’ensemble du code source utilisé pour cet article est disponible sur notre compte GitHub

L’équipe Synbioz.

Libres d’être ensemble.