Les paramètres path et pos
Toutes les annotations définies dans le réacteur permettent de préciser des paramètres path et pos en plus des paramètres décrits ci-dessus. Ces paramètres permettent d’appliquer des commandes non seulement aux instances de la classe sur laquelle les annotations sont placées, mais aussi sur n’importe lequel de leurs descendants. Cela permet de préciser le comportement de descendants du composant que l’on écrit et d’éviter de créer une nouvelle classe à chaque fois que l’on veut modifier le comportement d’un tag.
Le paramètre path a comme valeur un tableau de classes indiquant les classes des instances du chemin à emprunter lors de la descente dans l’arbre pour aboutir au(x) tag(s) concerné(s) par l’annotation.
Il n’est pas obligatoire de préciser la classe exacte de ces tags, mais seulement une superclasse.
Exemple :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@ReverseFlexDirection(path = Composite.class) @Style(path = Composite.class, name = "flex", value = "0 1 auto") @Children({ HeaderRow.class, InstanceBuilder.class, ContentRow.class }) /* ... */ public class InstancesTable extends FlexDiv implements SelectionDefaults { } public class HeaderRow extends Composite { } public class ContentRow extends Composite { } public class InstanceBuilder extends Composite implements GSBuilderDefaults, PasswordDefaults { } |
Une instance d’InstancesTable a trois enfants, de types HeaderRow, InstanceBuilder et ContentRow. Comme ces trois classes étendent Composite, les annotations @ReverseFlexDirection et @Style avec un path Composite.class placées sur la classe InstancesTable s’appliqueront à ces trois enfants.
Le paramètre pos, s’il est précisé, doit être un tableau d’entiers de la même longueur que le tableau path. Son rôle est de permettre de désigner un tag précis dans le cas où la classe ne suffit pas, c’est-à-dire lorsque plusieurs enfants sont des instances de la même classe. Quand une annotation comporte un path mais pas de pos, elle s’applique à tous les descendants auxquels on aboutit en empruntant un chemin constitué d’instances des classes indiquées dans path.
Si pos[i] est supérieur ou égal à 0, lors du i-e niveau de descente, on ne considèrera que le i-e enfant (en comptant à partir de 0) qui est une instance de path[i] ou d’une classe étendant celle-ci. S’il n’existe pas de tel enfant, l’annotation ne concerne aucun tag.
Si pos[i] est égal à -1, on considèrera tous les enfants qui sont des instances de pos[i] ou d’une classe étendant celle-ci.
Exemple :
1 2 3 4 5 6 7 8 9 |
@Children({ HtmlHyperLink.class, HtmlHyperLink.class }) @Children(path = HtmlHyperLink.class, value = HtmlImg.class) @StyleClass(path = { HtmlHyperLink.class, HtmlImg.class }, pos = { -1, 0 }, value = "img") @Attribute(path = { HtmlHyperLink.class, HtmlImg.class }, pos = { 1, 0 }, name = "src", value = "delete.png") @Attribute(path = { HtmlHyperLink.class, HtmlImg.class }, pos = { 0, 0 }, name = "src", value = "edit.png") @BindAction(path = HtmlHyperLink.class, pos = 1, value = REMOVE.class) @BindAction(path = HtmlHyperLink.class, pos = 0, value = SET_SELECTION.class) public static class LinksDiv extends ButtonDiv { } |
On définit une div qui contient deux liens. Chacun de ces lien contient une image, car il n’y a pas de paramètre pos sur la seconde annotation @Children, mais les actions liées au clic sont différentes pour chacun des liens. Ces deux images ont la classe « img », mais l’attribut src est différent pour chaque image.
Priorité des annotations
La définition de l’arbre des tags à l’aide de classes annotées implique la présence de deux hiérarchies :
- la hiérarchie des classes Java : une classe peut avoir une classe-mère ;
- l’arborescence des tags : chaque tag sauf la racine a un tag parent.
La priorité des annotations est définie ainsi :
- Les annotations placées sur les classes-filles l’emportent sur celles placées sur la classe-mère.
- Les annotations placées sur la classe d’un ascendant concernant un descendant l’emportent sur les annotations placées sur la classe de ce descendant, et sur les annotations placées sur les classes des ascendants situés plus bas dans l’arbre des tags. Pour un tag donné, c’est l’annotation applicable ayant le path le plus long qui est appliquée.
Exemple :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Children({ RedDiv.class, BlueDiv.class, BlueDiv.class }) @Style(path = BlueDiv.class, pos = 1, name = "background-color", value = "green") @SetText(path = BlueDiv.class, pos = 1, value = "White on green") public static class ExempleDiv extends HtmlDiv { } @Style(name = "background-color", value = "red") @Style(name = "color", value = "white") @SetText("White on red") public static class RedDiv extends HtmlDiv { } @Style(name = "background-color", value = "blue") @SetText("White on blue") public static class BlueDiv extends RedDiv { } |
On crée un tag qui contient une instance de RedDiv et deux de BlueDiv. Ces trois divs ont le style « color: white; » défini sur la classe RedDiv. Seule la première instance de BlueDiv a une couleur de fond bleue comme indiqué sur BlueDiv, car la couleur et le texte de la deuxième instance sont redéfinis sur la classe du tag parent.