4.2 - Scrutateurs d'arbres et de gabarits

Attention : Ce tutoriel est ancien, incomplet, et n'est pas mis à jour. Il ne contient pas toutes les nouveautés du système de template de Gecko 1.9 / Firefox 3.0 qui est largement simplifié et permet d'utiliser sqlite ou xml comme source de données. Aussi est-il préférable d'aller consulter la version anglaise sur developer.mozilla.org.

Pendant le processus de construction d'un gabarit, plusieurs scrutateurs (ou observateurs) sont utilisés, chacun pour des usages différents. Ils implémentent tous une interface XPCOM différente comme listée ci-après :

Scruter les reconstructions d'arbres

La première de ces interfaces est la plus simple et invoque deux méthodes, willRebuild et didRebuild. Vous implémenterez cet objet lorsque vous souhaitez être prévenu que le gabarit est reconstruit avec l'appel de la méthode rebuild. Le constructeur de gabarit peut également forcer une reconstruction lorsqu'une notification de modification des données sous-jacentes est signalée. La première utilisation de ce scrutateur est de stocker quelques états avant que le gabarit ne soit reconstruit, afin de les restaurer par la suite. Souvenez vous que lorsqu'un gabarit est reconstruit, tout son contenu existant est effacé et généré à neuf. La méthode willRebuild d'un scrutateur sera appelée avant que le contenu ne soit effacé, et la méthode didRebuild sera appelée après que le contenu ne soit re-généré. Ce scrutateur fonctionne également avec les constructeurs d'arbres, et appellera les méthodes appropriées avant et après que l'arbre ne soit généré.

Pour assigner un scrutateur de construction à un constructeur, utilisez la méthode addListener :

var someListener = {
  item: null,
  willRebuild : function(builder) {
    this.item = builder.getResourceAtIndex(builder.root.currentIndex);
  },
  didRebuild : function(builder) {
    if (this.item) {
      var idx = builder.getIndexOfResource(this.item)
      if (idx != -1) builder.root.view.selection.select(idx);
    }
  }
};
tree.builder.addListener(someListener);

Cet exemple est très simple. Il mémorise et restaure la sélection après un rebuild. Comme le contenu disparaît pendant la reconstruction, la sélection est perdue et elle sera restaurée au cours de la méthode didRebuild. Le gestionnaire des Marque-pages de Firefox utilise cette technique. Si vous essayez un exemple en utilisant le code ci-dessus, vous noterez que seul le premier arbre conserve sa sélection lorsque le bouton Reconstruire est pressé, le second arbre la perdant. La cause en est que le scrutateur n'est seulement attaché qu'au premier arbre.

L'exemple ci-dessus fait usage des méthodes getResourceAtIndex et getIndexOfResource. Ces deux méthodes sont disponibles pour les constructeurs d'arbres et convertiront un index dans l'arbre en sa ressource membre associée et vice-versa. Naturellement, nous ne pouvons mémoriser l'index d'un item car cet item peut changer de position, ou la ressource peut ne plus faire partie des résultats, ce qui nécessite de tester la valeur retournée par la méthode getIndexOfResource.

Comme cet exemple utilise les ressources RDF directement, il nécessite pour pouvoir le tester des niveaux de permissions élevés que vous n'obtiendrez qu'au travers d'une URL chrome.

Vous devez aussi songer que la propriété root du constructeur, telle qu'elle est utilisée ci-dessus, fait référence à l'arbre. Avec un constructeur de contenu, elle retournerait l'élément ayant l'attribut datasources qui est assimilé à un élément racine dans un constructeur de gabarit.

Finalement, vous pourrez supprimer un scrutateur en utilisant la méthode removeListener du constructeur.

Scruter les modifications dans l'arbre

Le second type de scrutateur est utilisé pour traiter des actions particulières relatives aux arbres. Le constructeur d'arbres implémente l'interface nsITreeView, donc il gère l'assemblage et la transmission des données vers l'arbre. Les composants graphiques de l'arbre informe la vue d'arbre lorsque certaines opérations pouvant affecter les données sont réalisées. La vue d'arbre gère toutes ces opérations, mais elle permet que soit attaché un observateur qui est invoqué pendant ces opérations. Par exemple, l'observateur peut avoir une méthode onToggleOpenState qui sera appelée quand l'utilisateur ouvre ou ferme une ligne. Le constructeur d'arbres assurera la gestion des lignes ajoutées ou enlevées, mais il appellera aussi l'observateur qui pourra réaliser d'autres tâches.

L'observateur du constructeur d'arbres implémente l'interface nsIXULTreeBuilderObserver et il doit être attaché au constructeur d'arbres en utilisant la méthode addObserver de la propriété builder. Vous pouvez ajouter plus d'un observateur si nécessaire, et vous pouvez en supprimer grâce à la méthode removeObserver.

L'observateur est toujours invoqué avant que l'opération appropriée soit exécutée. Par exemple, la méthode onToggleOpenState de n'importe quel observateur sera appelée avant que l'item de l'arbre ne soit ouvert. Après que les observateurs aient fini, le constructeur d'arbres ouvre la ligne et ajoute toutes les lignes filles dedans.

Notez que vous ne pouvez pas annuler l'opération à partir d'un observateur.

Les quelques fonctions utiles des observateurs sont les fonctions de rappel du glisser-déposer qui traitent le cas d'un item déplacé vers un arbre. Elles rendent la gestion du glisser-déposer vers un arbre particulièrement simple. Tout ce que vous avez à faire est d'implémenter deux méthodes, canDrop et onDrop. Notez qu'avec Firefox 1.0 (Mozilla 1.7) et précédente, les fonctions glisser-déposer sont légèrement différentes. Pour ces versions, trois fonctions étaient utilisées, canDropOn, canDropBeforeAfter et onDrop. Les deux fonctions 'can' ont été combinées en une seule avec un argument supplémentaire. Si vous désirez supporter les anciennes et les nouvelles versions, vous pouvez implémenter toutes ces fonctions dans un observateur en partageant le code si nécessaire.

L'observateur d'arbre reçoit les évènements relatifs au glisser-déposer à trois endroits : au dessus d'un conteneur de ligne, avant une ligne, et après une ligne. Ces trois cas vous permettent une plus grande souplesse du glisser-déposer. Par exemple, dans certaines situations, vous aurez à glisser quelque chose vers un type dossier d'une ligne. Dans d'autres situations, vous souhaiterez permettre à des items d'être déplacés entre (avant ou après) des lignes. Il peut s'agir d'une situation où vous déplacez des items d'un point à un autre de l'arbre, comme par exemple le déplacement d'un marque-page d'un endroit vers un autre. Le composant graphique de l'arbre dessinera une petite ligne entre les lignes lors du déplacement. Tout ce que vous avez à faire est d'ajouter un observateur pour le constructeur d'arbre qui retourne true pour la méthode canDrop. Notez que le cas du déplacement n'est seulement permis qu'au dessus de conteneurs, mais pas sur des lignes ordinaires.

var treeBuilderObserver = {
  canDropBeforeAfter : function(idx, orient) { return false; },
  canDropOn : function(idx, orient) { return true; },
  canDrop : function(idx, orient) { return !orient; },
  onDrop : function(idx, orient) {
    // faire quelque chose ici
  },
};
tree.builder.addObserver(treeBuilderObserver);

Cet observateur implémente à la fois les anciennes et les nouvelles méthodes, et ne peut servir que pour des glisser sur des lignes. La méthode canDropBeforeAfter retourne false puisque nous ne voulons pas déposer des items avant et après des lignes. La méthode canDropOn retourne true. La méthode canDrop de Mozilla 1.8 teste l'orientation et retourne son opposé. Elle fonctionne comme si la valeur 'au dessus' est 0 et les valeurs 'entre' sont -1 et 1. Évidemment, ce code est bien plus simple qu'il ne serait en réalité -- nous devrions tester le contenu qui est en train d'être glissé pour être certain qu'il soit compatible avec l'arbre, ou ne permettre de déposer que sur des lignes spécifiques. Les méthodes pour déposer sont fournies avec un argument index pouvant servir aux tests.


Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.