xulfr.org

11.6 Overlays

Écrit par Neil Deakin. Traduit par Alain B. (24/07/2004).
Page originale : http://www.xulplanet.com/tutorials/xultu/overlay.html xulplanet.com

Cette section décrit les overlays qui peuvent être utilisés pour partager du contenu commun.

Utilisation des Overlays

Dans une simple application ne comportant qu'une seule fenêtre, vous aurez généralement qu'un seul fichier XUL, associé avec un fichier de scripts, une feuille de style, un fichier d'entités DTD et peut être quelques images. Certaines applications contiennent également un certain nombre de boîtes de dialogue. Celles ci sont placées dans des fichiers XUL séparés. Des applications plus sophistiquées peuvent contenir de nombreuses fenêtres et boîtes de dialogues.

Une application contenant de nombreuses fenêtres aura certains éléments ou parties d'interface utilisateur communs entre chacune d'elles. Par exemple, chaque composant de Mozilla partage des éléments communs. Certains menus sont similaires, comme les menus Outils et Aide, la barre latérale est similaire, et chaque fenêtre partage des raccourcis claviers globaux communs.

Il est bien entendu possible de ré-implémenter des éléments ou des fonctions similaires dans chaque fichiers nécessaires. Toutefois, la maintenance devient difficile. Si vous décidez de modifier quelque chose, vous devrez le faire à différents endroits. En revanche, il est plus intéressant d'utiliser un mécanisme permettant de séparer les éléments communs et de les partager entre les fenêtres. Vous pouvez faire ceci avec des overlays.

Vous pouvez placer dans un overlay des éléments qui seront partagés par toutes les fenêtres utilisant cet overlay. Ces éléments sont ajoutés à l'intérieur des fenêtres aux emplacements déterminés par leurs identifiants id.

Par exemple, disons que vous voulez créer un menu Aide partagé par plusieurs fenêtres. Le menu Aide sera placé dans un overlay, en utilisant la syntaxe XUL habituelle. Un attribut id sera affecté au menu pour l'identifier. Chaque fenêtre importera l'overlay en utilisant une directive qui sera décrite dans un moment. Afin de pouvoir utiliser le menu Aide tel que définit dans l'overlay, il vous suffit d'ajouter un simple élément de menu ayant le même attribut id que celui utilisé dans l'overlay. Ce menu n'a pas besoin de contenir tous les éléments enfants comme ceux placés dans l'overlay.

Lorsqu'une fenêtre contenant un overlay est ouverte, les éléments de la fenêtre et ceux de l'overlay ayant le même identifiant id sont combinés entre eux. Les enfants des éléments correspondants sont ajoutés à la fin de l'ensemble des enfants des éléments de la fenêtre. Les attributs présents sur les éléments de l'overlay sont appliqués à ceux de la fenêtre. Ces détails seront expliqués ci après.

Pour importer un overlay dans une fenêtre, utilisez la syntaxe ci dessous. Ajoutons cette ligne vers le haut de notre exemple XUL de recherche de fichiers.

    <?xul-overlay href="chrome://findfile/content/helpoverlay.xul"?>

Cette ligne doit être ajoutée quelque part en haut du fichier, habituellement juste avant les déclarations d'entités DTD. Dans l'exemple précédent, la fenêtre importera un overlay contenu dans le fichier helpoverlay.xul.

L'overlay lui même est un fichier XUL contenant un élément overlay au lieu d'un élément window. À part cette différence, ils sont similaires. Il est possible d'importer des overlays à l'intérieur d'autres overlays. Les overlays peuvent aussi disposer de leurs propres feuilles de styles, fichiers d'entités DTD et scripts. L'exemple ci dessous montre un simple menu Aide placé dans un overlay.

Exemple 11.6.1 : Source

<?xml version="1.0"?>

<!DOCTYPE overlay SYSTEM "chrome://findfile/locale/findfile.dtd">

<overlay id="toverlay"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<menu id="help-menu">
  <menupopup id="help-popup">
    <menuitem id="help-contents" label="&contentsCmd.label;"
              accesskey="&contentsCmd.accesskey;"/>
    <menuitem id="help-index" label="&indexCmd.label;"
              accesskey="&indexCmd.accesskey;"/>
    <menuitem id="help-about" label="&aboutCmd.label;"
              accesskey="&aboutCmd.accesskey;"/>
  </menupopup>
</menu>

</overlay>

L'élément overlay entoure le contenu de l'overlay. Les mêmes espaces de noms sont utilisés qu'avec les fichier de fenêtres XUL. Un simple menu comprenant trois items a été défini dans l'overlay. L'attribut id de ce menu est help-menu. Cela signifie que son contenu sera ajouté à une fenêtre dans laquelle un élément similaire existe avec la même valeur d'attribut id. Si un tel élément n'existe pas, cette partie de l'overlay sera ignoré. L'overlay peut contenir autant d'éléments que nécessaire. Notez que le fichier d'entités DTD doit être inclus dans l'overlay. Nous avons utilisé ici le même que celui de la fenêtre principale, mais normalement vous devez créer des fichiers DTD séparés pour chaque overlay.

Ensuite, nous allons ajouter le menu Aide à notre boîte de dialogue de recherche de fichiers. Pour cela, ajoutez simplement un menu avec le même attribut id au bon endroit. Il se trouvera sa juste place après le menu Edition.

  <menu id="edit-menu" label="Edition" accesskey="e">
    <menupopup id="edit-popup">
      <menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;"
                key="cut_cmd"/>
      <menuitem label="&copyCmd.label;" accesskey="&copyCmd.accesskey;"
                key="copy_cmd"/>
      <menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;"
                key="paste_cmd" disabled="true"/>
    </menupopup>
  </menu>
  <menu id="help-menu" label="&helpCmd.label;"
        accesskey="&helpCmd.accesskey;"/>
</menubar>

Ici, l'élément du menu Aide n'a aucun contenu. Les items du menu proviennent de l'overlay car leurs attributs id correspondent. Nous pouvons importer l'overlay dans d'autres fenêtres et n'avoir défini le contenu du menu Aide qu'à un seul endroit. Nous devons aussi ajouter quelques lignes au fichier d'entités DTD :

<!ENTITY helpCmd.label "Aide">
<!ENTITY helpCmd.accesskey "a">
<!ENTITY contentsCmd.label "Contenus">
<!ENTITY indexCmd.label "Index">
<!ENTITY aboutCmd.label "A propos de...">
<!ENTITY contentsCmd.accesskey "c">
<!ENTITY indexCmd.accesskey "i">
<!ENTITY aboutCmd.accesskey "a">
<!ENTITY findfilehelpCmd.label "Aide sur la recherche de fichiers">
<!ENTITY findfilehelpCmd.accesskey "f">

Nous utiliserons les deux dernières entités dans un moment.

Menu Aide

Nous pouvons réduire encore la quantité de code dans la fenêtre en mettant les attributs du menu Aide directement dans l'overlay (label et accesskey dans cet exemple). Ces attributs seront hérités par l'élément. Si l'élément et celui de la fenêtre partage le même attribut, la valeur dans l'overlay aura priorité sur celle de l'élément.

Changeons notre menu Aide de cette manière :

findfile.xul:

<menu id="help-menu"/>

helpoverlay.xul:

<menu id="help-menu" label="&helpCmd.label;"
      accesskey="&helpCmd.accesskey;">

Si la fenêtre XUL et l'overlay ont du contenu, celui de la fenêtre sera utilisé comme tel et celui de l'overlay sera ajouté à la fin. L'exemple suivant en est une illustration :

Source : stopandgo toverloay Voir

stopandgo.xul:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>

<window title="Marche - Arrêt" id="test-window"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<?xul-overlay href="toverlay.xul"?>

<box id="singlebox">
  <button id="gobutton" label="Marche"/>
  <button id="stopbutton" label="Arrêt"/>
</box>

</window>

toverlay.xul:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<overlay id="toverlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<box id="singlebox">
  <button id="backbutton" label="Précédent"/>
  <button id="forwardbutton" label="Suivant"/>
</box>

</overlay>

Exemple Marche - Arrêt

Dans cet exemple, la boîte avec l'identifiant singlebox dispose de son propre contenu. Les éléments sont combinés et les deux boutons de l'overlay sont ajoutés à la fin de cette boîte.

Nous pouvons aussi utiliser cette technique dans notre boîte de dialogue de recherche de fichiers.

findfile.xul : Source Voir

  <menu id="help-menu">
    <menupopup id="help-popup">
      <menuitem id="help-findfiles" label="&findfilehelpCmd.label;"
                accesskey="&findfilehelpCmd.accesskey;"/>
    </menupopup>
  </menu>
</menubar>

L'attribut id de l'élément menupopup correspond à celui de l'overlay. Il en résulte l'ajout des items dans le même menu déroulant. Les overlays vont réunir les items de même id même s'ils sont situés à l'intérieur d'autres éléments.

Menu Aide

Placement des éléments d'un overlay

Dans l'exemple précédent, nous aurions voulu que les items du menu de l'overlay soient placés au début du menu plutôt qu'à la fin. XUL offre un mécanisme permettant de ne pas seulement placer les éléments en tête, mais d'en placer certains en premier et le reste à la fin (ou n'importe où entre). Cela vous permet de positionner exactement où vous le souhaitez les overlays de menus, barres d'outils et autres éléments graphiques.

Pour cela, utilisez l'attribut insertbefore sur les éléments menuitem. Sa valeur doit être l'identifiant id de l'élément avant lequel on veut les insérer. De même, vous pouvez utilisez l'attribut insertafter pour indiquer quel élément insérer après. Seul l'élément contenant ces attributs est affecté. Si un élément est marqué par un attribut insertbefore, les autres continueront à être placés à la fin. Si vous voulez que tous les éléments soient placés avant, vous devez mettre l'attribut insertbefore sur tous les éléments.

De plus, vous pouvez utiliser l'attribut position pour spécifier une position d'index numérotée à partir de 1.

Disons que nous souhaitons que les items de menu "Contenus" et "Index" de l'exemple précédent apparaissent avant l'item "Aide sur la recherche de fichiers", et que l'item "À propos de" apparaisse ensuite. Il suffit d'ajouter l'attribut insertbefore sur les deux items du menu Contenus et Index. Pour être complet, vous devriez aussi ajouter un attribut insertafter sur le menu A propos de, mais il n'est pas nécessaire car le menu apparaîtra par défaut à la fin.

Dans cet exemple ci dessus, l'identifiant id de l'item du menu est help-findfiles. De ce fait, nous devons associer les attributs insertbefore à cet id. voici les changements :

<menupopup id="help-popup">
  <menuitem id="help-contents" label="Contenus" insertbefore="help-findfiles"/>
  <menuitem id="help-index" label="Index" insertbefore="help-findfiles"/>
  <menuitem id="help-about" label="A propos de..."/>
</menupopup>

Maintenant, lorsqu'une fenêtre utilisant l'overlay Aide (comme notre exemple de recherche de fichiers) est ouverte, les évènements suivants se produisent :

  1. Pour chaque élément de l'overlay, qui sont tous les enfants de l'élément overlay, un élément de la fenêtre principale est recherché avec le même identifiant id. S'il n'est pas trouvé, cet élément est ignoré. Dans cet exemple, les éléments avec les identifiants help-menu et help-popup sont recherchés.
  2. Si un élément est trouvé, les attributs de l'élément de l'overlay lui sont ajoutés.
  3. Les enfants de l'élément overlay, ici chaque élément menuitem, sont insérés comme enfants de l'élément de la fenêtre.
    • Si l'élément de l'overlay contient un attribut insertafter, il est ajouté juste après celui de la fenêtre principale ayant le même attribut id.
    • Si l'élément de l'overlay contient un attribut insertbefore, il est ajouté juste avant celui de la fenêtre principale ayant le même attribut id.
    • Si l'élément de l'overlay contient un attribut position, il est ajouté à son emplacement indexé par la valeur de l'attribut compté à partir de 1.
    • Dans les autres cas, l'élément est ajouté comme le dernier enfant.

En réalité, insertbefore et insertafter peuvent contenir des listes de valeurs séparées par des virgules, où le premier identifiant trouvé dans la liste est utilisé pour déterminer la position dans la fenêtre.


Nous allons voir comment appliquer des overlays à des fenêtres dans différents paquetages.