8.6 Les objets boîtes des arbres

Écrit par Neil Deakin , mise à jour par les contributeurs à MDC .
Traduit par Alain B. (04/04/2007).
Page originale : http://developer.mozilla.org/en/docs/XUL_Tutorial/Tree_Box_Objects

Attention : Ce tutoriel est ancien et n'est pas mis à jour. Bien que beaucoup d'informations soient encore valables pour les dernières versions de gecko, beaucoup sont aussi obsolètes. Il est préférable d'aller consulter cette page sur la version française de ce tutoriel sur developer.mozilla.org.

Cette section va décrire l'objet de boîte d'arbre qui est utilisé pour gérer l'affichage d'un arbre.

À propos de l'objet de boîte

Les objets de boîte ont été décrits dans une section précédente. L'objet de boîte d'arbre est un objet de boîte spécial utilisé spécifiquement pour les arbres (tree). La boîte d'arbre implémente l'interface TreeBoxObject.

Rafraichissement de l'arbre

Nous avons déjà vu la fonction rowCountChanged() de l'objet de boîte d'arbre dans la section précédente. Elle est employée pour indiquer qu'une ou plusieurs lignes de l'arbre ont été ajoutées ou enlevées. L'arbre rafraîchira l'affichage de la zone affectée. Vous n'avez pas besoin d'appeler la fonction rowCountChanged() lorsqu'une ligne a simplement été modifiée, comme par exemple lors du changement du libellé d'une cellule. Dans ce cas, d'autres fonctions d'affichage peuvent être utilisées. La plus simple est la fonction invalidateRow() qui rafraîchit l'affichage d'une ligne spécifique d'un arbre. L'arbre appellera la vue pour obtenir les données mises à jour et actualise son contenu à l'écran.

Les autres fonctions de rafraichissement sont :

Notez que le rafraichissement de l'affichage n'aura lieu qu'une fois les tâches des scripts achevées, car Mozilla n'effectue pas cette opération en tâche de fond.

Défilement de l'arbre

Vous pouvez également faire défiler l'arbre en utilisant quatre méthodes différentes, similaires à celles disponibles pour les menus déroulants. La fonction scrollToRow() peut être utilisée pour faire le défilement jusqu'à une ligne particulière. Voici un exemple simple :

Exemple 8.6.1 : Source Voir

<script>
function doScroll()
{
  var value = document.getElementById("tbox").value;
  var tree = document.getElementById("thetree");

  var boxobject = tree.boxObject;
  boxobject.QueryInterface(Components.interfaces.nsITreeBoxObject);
  boxobject.scrollToRow(value);
}
</script>

<tree id="thetree" rows="4">
  <treecols>
    <treecol id="row" label="Ligne" primary="true" flex="1"/>
  </treecols>
  <treechildren>
    <treeitem label="Ligne 0"/>
    <treeitem label="Ligne 1"/>
    <treeitem label="Ligne 2"/>
    <treeitem label="Ligne 3"/>
    <treeitem label="Ligne 4"/>
    <treeitem label="Ligne 5"/>
    <treeitem label="Ligne 6"/>
    <treeitem label="Ligne 7"/>
    <treeitem label="Ligne 8"/>
    <treeitem label="Ligne 9"/>
  </treechildren>
</tree>

<hbox align="center">
  <label value="Défile jusqu'à la ligne :"/>
  <textbox id="tbox"/>
  <button label="Défile" oncommand="doScroll();"/>
</hbox>

Notez que nous utilisons l'attribut rows sur l'élément tree pour spécifier que quatre lignes seulement doivent être affichées à la fois. Ainsi, il est plus facile de se représenter l'exemple. Notez également que la première ligne commence à 0.

La fonction doScroll() récupère l'objet de boîte et appelle la fonction scrollToRow() avec comme argument la valeur saisie dans le champ texte. Vous noterez que l'objet de boîte d'arbre peut être obtenu de la même manière qu'avec d'autres objets de boîte, en utilisant la propriété boxObject. Nous devons cependant appeler QueryInterface() pour invoquer l'objet de boîte spécifique aux arbres. Les fonctions générales de l'objet de boîte sont également disponibles pour les arbres.

Les méthodes supplémentaires de défilement incluent les fonctions scrollByLines(), scrollByPages(), et ensureRowIsVisible().

la fonction scrollByLines() fait défiler vers le haut ou vers le bas d'un certain nombre de lignes ; un nombre positif fait défiler vers le bas, un nombre négatif fait défiler vers le haut. La fonction scrollByPages() fait défiler d'un certain nombre de pages. Elle est automatiquement appelée lorsque l'utilisateur appuie sur une des touches Page Up ou Page Down et que l'arbre a le focus. Une page est égale au nombre de lignes visibles. Par exemple, si un arbre affiche 10 lignes en même temps, une page sera équivalente à 10 lignes. C'est une méthode pratique dès lors que l'utilisateur redimensionne un arbre flexible : la taille de la page augmentera ou diminuera automatiquement sans avoir à la recalculer manuellement. Il n'est pas trop difficile de calculer cette taille manuellement car l'objet de boîte d'arbre fournit également une fonction getPageLength() qui retourne le nombre de lignes dans une page. Dans l'exemple de défilement ci-dessus, getPageLength() retournerait 4.

Notez que dans Firefox 1.0 et Mozilla 1.7, et les versions plus récentes, la fonction getPageLength() est plutôt appelée getPageCount(). Le nom a été changé en getPageLength() afin d'éviter les confusions avec une fonction qui ne retourne pas le nombre de pages d'un arbre, mais la taille de chaque page. Vous pouvez déterminer le nombre de pages en divisant le nombre total de lignes par la taille d'une page.

La fonction ensureRowIsVisible() fera défiler l'arbre jusqu'à une ligne, comme avec la fonction scrollToRow(), mais seulement si la ligne n'est pas visible au moment de l'appel.

Coordonnées d'une cellule

Certaines des fonctions les plus intéressantes d'un objet de boîte d'arbre sont utilisées pour obtenir les parties d'un arbre se trouvant à des coordonnées spécifiques et vice versa.

tree.boxObject.getRowAt( 50, 100 );

Cet exemple retournera l'index de la ligne ayant une position horizontale de 50 pixels et verticale de 100 pixel. Naturellement, la coordonnée x semble ne pas avoir beaucoup de sens dès lors que la ligne occupe tout l'espace horizontal de l'arbre.

Il est important de noter que les coordonnées sont mesurées à partir du coin supérieur gauche du document et non de l'arbre lui-même.

Il est donc facile de passer à ces fonctions les coordonnées événementielles de l'objet event, comme avec la fonction getCellAt() dans l'exemple suivant.

Exemple 8.6.2 : Source Voir

<script>
function updateFields(event)
{
  var row = {}, column = {}, part = {};
  var tree = document.getElementById("thetree");

  var boxobject = tree.boxObject;
  boxobject.QueryInterface(Components.interfaces.nsITreeBoxObject);
  boxobject.getCellAt(event.clientX, event.clientY, row, column, part);

  if (typeof column.value != "string") column.value = column.id;

  document.getElementById("row").value = row.value;
  document.getElementById("column").value = column.value;
  document.getElementById("part").value = part.value;
}
</script>

<tree id="thetree" flex="1" onmousemove="updateFields(event);">
  <treecols>
    <treecol id="ustensile" label="Ustensiles" primary="true" flex="1"/>
    <treecol id="nombre" label="Nombre" flex="1"/>
  </treecols>
  <treechildren>
    <treeitem>
      <treerow>
        <treecell label="Fourchette"/>
        <treecell label="5"/>
      </treerow>
    </treeitem>
    <treeitem>
      <treerow>
        <treecell label="Couteau"/>
        <treecell label="2"/>
      </treerow>
    </treeitem>
    <treeitem>
      <treerow>
        <treecell label="Cuillère"/>
        <treecell label="8"/>
      </treerow>
    </treeitem>
  </treechildren>
</tree>

<label value="Ligne:"/>
<label id="row"/>
<label value="Colonne:"/>
<label id="column"/>
<label value="Type enfant:"/>
<label id="part"/>

La fonction getCellAt() prend cinq arguments, les coordonnées où regarder et trois autres paramètres. Un argument par référence est utilisé parce que la fonction a besoin de retourner plusieurs valeurs. Vous verrez de nombreuses interfaces utilisant des arguments par référence avec les objets disponibles. Ces arguments sont marqués avec un préfixe 'out'. Pour ceux-ci, vous devez transmettre un objet vide et la fonction remplira sa propriété value avec la valeur adéquate.

Les trois paramètres par référence seront renseignés avec la ligne, la colonne et le type enfant. L'objet row contient l'index de la ligne survolée par la souris au moment où la fonction a été appelée par un événement mousemove, avec les coordonnées de cet événement. Si les coordonnées ne sont pas au-dessus d'une ligne de l'arbre, la valeur row.value sera égale à -1. La variable column est un objet column tel que défini dans Mozilla 1.8 et supérieur. Dans les versions plus anciennes, les colonnes étaient identifiées avec une chaîne de caractères (string) : l'identifiant id de la colonne. Avec les versions plus récentes, un objet de colonne spécifique existe et permet de réaliser des requêtes sur les données en colonne.

La ligne suivante est utilisée pour que l'exemple ci-dessus puisse fonctionner avec toutes les versions.

if (column.value && typeof column.value != "string")
  column.value = column.value.id;

Si la colonne est une chaîne de caractères, nous tournons sur Mozilla 1.7 ou inférieur, mais pour les versions récentes, nous obtenons l'identifiant de la colonne à partir de l'objet column. Si vous écrivez du code pour des versions multiples, vous devrez effectuer un test comme indiqué ci-avant.

Le dernier argument de la fonction getCellAt() est le type enfant renseigné avec une chaîne dépendante de la partie de la cellule pointée par les coordonnées. Si vous déplacez la souris dans l'exemple précédent, vous noterez que le libellé passe de text à cell. La valeur text indique la zone où le texte est dessiné et la valeur cell indique la zone autour du texte ; par exemple, la marge gauche où sont habituellement dessinées les poignées ouvrantes et fermantes. Toutefois, s'il y avait une poignée, la valeur aurait plutôt été twisty. Cette information pratique permet de déterminer si l'utilisateur a cliqué sur une poignée plutôt que sur une autre partie de la ligne. En fait, lorsque l'utilisateur double-clique sur la poignée, le code natif sous-jacent utilise cette méthode. La dernière valeur qui peut être retournée est image si une image se trouve dans la cellule et que les coordonnées correspondent à celles de cette image. Bien entendu, dans la plupart des cas, vous ne désirez pas connaître quelle partie de la cellule pointe les coordonnées, mais seulement la ligne et la colonne concernées.

Pour inverser la recherche et obtenir les coordonnées spécifiques d'une cellule, utilisez la fonction getCoordsForCellItem(). Elle prend sept arguments tels que décrits ci-dessous.

var x = {}, y = {}, width = {}, height = {};
if (typeof tree.columns != "undefined") column = tree.columns[column];
tree.boxObject.getCoordsForCellItem( row, column, part, x, y, width, height );

Les arguments 'row', 'column' et 'part' sont similaires à ceux retournés par la fonction getCellAt(). De nouveau, le type de l'argument 'column' dépend de la version que vous utilisez, soit une chaîne de caractères (string), soit un objet column. Le type de la zone de la cellule peut être utilisé pour obtenir les coordonnées, soit du texte, soit de toute la cellule, soit de la poignée, soit de l'image dans la cellule. Les mêmes valeurs que la fonction getCellAt() sont utilisées. La fonction getCoordsForCellItem() retourne par le biais des arguments passés en référence les coordonnées horizontales (x) et verticales (y), accompagnées de la largeur et la hauteur.


Par la suite, nous verrons comment RDF peut être utilisé automatiquement pour peupler des arbres et d'autres éléments.


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.