Nous avons généralisé ce principe et ces mécanismes aux dispositifs génériques d'application, en particulier pour les manipulateurs d'objets graphiques de MAGGLITE (voir la section 7.4.2). Ces dispositifs, rappelons-le, sont des dispositifs d'instance (liés à un objet graphique particulier) qui permettent un contrôle direct d'un nœud du graphe de scène, externalisant alors les propriétés de cet objet dans le graphe d'interaction. Donc, lorsqu'un nouveau nœud est ajouté au graphe de scène, celui-ci peut, ou non, installer son manipulateur dans la librairie des dispositifs disponibles.
Le principe des manipulateurs, d'un point de vue technique, est d'associer un slot du manipulateur à un méthode de l'objet que l'on souhaite externaliser. Il aurait été fastidieux d'avoir à développer une classe de dispositifs ICON à chaque création d'une nouvelle classe d'objet graphique. Nous proposons donc un mécanisme utilisant les capacités d'introspection (réflection) du langage Java afin d'obtenir les méthodes de l'objet correspondantes aux slots à créer, de les invoquer sur l'objet lorsque le dispositif reçoit les signaux correspondants, et de les décrire à l'aide des annotations (metadata) spécifique à Java 5. Il suffit, lors du développement d'une nouvelle classe de nœuds du graphe de scène, de respecter les conventions de nommage que nous avons fixées afin que la boîte à outil crée le dispositif correspondant aux méthodes que nous avons nommées xmethods.
La figure C.9 présente sur un exemple les méthodes d'un objet associées à son dispositif. La méthode xcomVisible() est externalisée sous la forme d'un slot d'entrée booléen nommé visible, la méthode xsetMove(double dx, double dy) sous la forme de deux slots d'entrée de type double nommés move.dx et move.dy et enfin la méthode Object xgetId() sous la forme d'un slot de sortie de type Object.
|
Cet exemple introduit trois catégories de xmethods:
Les méthodes de commande et d'état sont invoquées lorsque le ou les slots associés reçoivent un signal, les méthodes d'émission sont invoquées à chaque pas de l'exécution. Toutefois, ces appels aux méthodes de l'objet pose un problème de stratégie à employer dans le cas des méthodes d'état et dans le cas des méthodes d'émission.
Pour les méthodes d'état, il est clair qu'elle ne peuvent être invoquées si tous les paramètres ne
sont pas définis, c'est à dire si tous les slots d'entrée correspondant du dispositif ne sont pas
connectés, et n'ont pas tous reçu au moins une fois un signal. Mais lorsque tous les slots (et
donc les paramètres de la méthode) ont une valeur, doit-on invoquer la méthode si tous les slots
n'ont pas reçu de signal (et donc une potentielle nouvelle valeur) ?
Pour les méthodes d'émission, le problème est inverse. La méthode de l'objet est invoquée à chaque
pas de l'exécution. Mais le dispositif doit-il émettre la valeur de retour de cette méthode à chaque
pas, même si celle-ci n'a pas changée ?
À ces problèmes de stratégie, s'ajoute aussi le problème du nommage des slots, en particulier dans le cas des méthodes d'état. En effet, les mécanismes d'introspection de Java nomment les paramètres des méthodes en utilisant des caractères alphanumériques, quel que soit le nom qui leur avait été donné dans le code source. Ainsi, les slots correspondant à une méthode prenant trois paramètres seraient nommé a, b et c. Il faut bien avouer qu'un tel nommage serait un sérieux obstacle au paradigme de programmation visuelle d'ICON. De plus, il pourrait être intéressant de regrouper les slots de certaines méthodes selon la sémantique de ces méthodes.
Nous proposons une solution unifiée à ces problèmes qui va permettre au programmeur d'annoter les xmethods de l'objet, et donc de spécifier les noms et groupes des slots qu'il veut voir apparaître pour la méthode, ainsi que la stratégie souhaitée pour leur invocation. Nous avons utilisé pour cela le mécanisme des annotations (ou metadata) de Java 5 afin de permettre la construction de descripteurs de méthodes. Voici un exemple de descripteur pour la méthode d'état xsetMove de la figure C.9:
Le descripteur de cet exemple, écrit juste avant la signature de la méthode, définit le nom qui sera donné à la méthode («move», ici), les noms de ses paramètres qui seront donc donné aux slots (préfixés par le nom de la méthode car nous somme dans le cas d'une méthode d'état) et la stratégie d'invocation de la méthode (lorsqu'au moins un des slots correspondant à la méthode a reçu un signal). Avec la valeur Vrai, ce descripteur allSignals signifierait qu'il faut que tous les slots aient reçus un signal au même pas d'exécution pour invoquer la méthode.L'exemple ci-après présente le champ de descripteur permettant de grouper des slots associés à différentes méthodes:
Le champ methodGroup permet dans ce cas de préfixer le nom des méthodes avec ce nom de groupe. Cela entraîne la création d'un groupe de slots, permettant de regrouper les slots correspondants à des méthodes de même sémantique. La figure C.10 présente le résultat du code précédent.
|
Globalement, l'architecture de la boîte à outil encourage la réutilisation des composants existants et l'implémentation des interfaces fournies afin de maintenir une cohérence au niveau des manipulateurs d'objets présentant des propriétés ou interfaces communes. Par exemple, tout objet graphique héritera des propriétés de l'objet de base «MaggLite». De ce fait, sont manipulateur présentera automatiquement les slots d'entrée (visible et label) et de sortie (id) communs à tous les objets de la classe MaggLite. Mais c'est aussi à ce niveau que peuvent être définies des xmethods de manière abstraite. Un composant conçu pour pouvoir être redimensionné implémentera une interface de la boîte à outil nommée « Sizeable». Cette interface impose l'implémentation de la méthode «xsetResize(double x, double y)» afin que tous les manipulateurs d'objets ayant cette capacité présente les slots d'entrée correspondants, de manière unifiée. Ainsi, un concepteur d'interfaces ou un utilisateur final retrouvera toujours les mêmes slots pour des capacités identiques (voir figure C.11).
|
Ce mécanisme de génération automatique de dispositifs permet de de ne pas se soucier de la programmation des dispositifs ICON lors de la création des objets de l'application que l'on veut externaliser. La notion de xmethods, associées à leurs descripteurs, permet un contrôle assez poussé sur les dispositifs générés, bien que n'offrant pas encore un accès à toutes les possibilités des dispositifs ICON (slots de type variant, contrôle plus spécifique des signaux reçus ou émis, paramètres de dispositifs). Il est envisageable de rendre les descripteurs plus précis et adaptés, mais nous pensons alors qu'il serait plus efficace de développer un dispositif de manière traditionnelle (ce que nous avons fait avec les autres dispositifs génériques d'application dans MAGGLITE: Dispositifs d'interaction, Outils internes et Comportements).
stuf