Le premier objet de cet exemple instancie la classe MaggLiteFoldableComponent. Comme tout
composant de base de la boîte à outils, il est nécessaire de passer en argument du constructeur la
forme géométrique de l'objet à créer. Il est ajouté au bureau par la méthode
desk.add(mc). Cette approche de création d'objets à partir d'une forme géométrique est tout a
fait adaptée à la création d'interfaces innovantes, mais aussi à l'utilisation de constructeurs
d'interfaces basés sur le dessin tels que celui que nous avons proposé dans la section
8.4.2.
Le second objet créé est de la classe MaggLiteWindow, classe abstraite qui propose trois
implémentations par défaut dans la boîte à outils, selon la géométrie désiré: Rectangle,
Oval ou Star. Cet exemple montre l'utilisation de méthodes de manipulation de l'objet
(setSize et moveTo). Les objets par défaut proposent aussi des méthodes d'accès à leur
propriétés particulières (contexte graphique, état, etc.) permettant de contrôler leur apparence et
leurs paramètres selon leurs capacités: setVisible, setColor, setOpacity,
etc. Cet exemple utilise aussi la méthode setExternalizeManipulator qui permet de rendre
disponible ou non le dispositif manipulateur de l'objet dans le configurateur graphique
d'interactions. Visibles par défaut, les manipulateurs d'objets graphiques peuvent être masqués à
l'initialisation de l'application. Par contre, malgré le fait que ce soit techniquement possible, la
modification de cette propriété est rendue impossible dès lors que l'environnement d'ICON a été
lancé, afin d'éviter la suppression de dispositifs présents dans une configuration en cours
d'exécution.
Enfin, le dernier objet créé, de la classe MaggLiteSlider, est ajouté dans le composant
précédent plutôt que sur le bureau.
La figure D.1 présente le résultat visuel de ce code.
Cette classe permet de construire des objets de forme ovale et de couleur bleue. Ces propriétés sont
définies dans le constructeur (ligne 5). La classe créée étend donc la classe abstraite
MaggLiteContainer, et implémente pour cela ses méthodes abstraites (lignes 13 à 20). Ce sont en particulier des méthodes d'affichage. Sur ce point, les lignes 9 et 10 montrent comment des propriétés graphiques sont définies dans le contexte de l'objet,
contexte qui sera mis en place lors des opérations d'affichage de l'objet. Si certains attributs ne
sont pas définis, ceux du nœud parent seront alors utilisés.
Afin de définir une forme aux objets, il faut implémenter l'interface MaggLiteShaped (lignes
22 à 31). Cela permettra aux objets d'être «reconnus» par les mécanismes et
interactions génériques de la boîte à outils. Il seront alors de fait compatibles avec les
opérations associées. De la même manière, cette classe implémente l'interface
MaggLiteDraggable afin de pouvoir utiliser le dispositif d'interaction Drag
(Glisser-Déposer) avec ces objets. D'une manière générale, les interfaces proposées dans la boîte à
outils permettent la compatibilité des objets avec les IAPs qui peuvent en tirer parti (nous
reviendrons sur ce principe avec l'exemple de la conception du Glisser-Déposer dans la section
D.2.1).
Cet exemple minimal permet déjà d'apprécier la base de la programmation d'objets graphiques avec MAGGLITE. Par contre, partir comme nous l'avons fait des classes abstraites pour créer des objets aux propriétés plus avancées nécessite de reimplémenter des méthodes déjà présentes dans des classes de plus haut niveau (gestion des formes, du glisser-déposer, des innertools, etc...): MaggLiteComponent et ses dérivées (voir section 8.3.1). C'est pourquoi il est plus judicieux d'étendre ces classes de plus haut niveau implémentant déjà les interfaces et mécanismes souhaités, et de surcharger les méthodes correspondant aux modifications voulues (l'exemple précédent se résumerait alors à surcharger le constructeur pour définir une forme et une couleur).
Toutefois, l'extension des capacités des objets graphiques par héritage s'avère peu flexible et modulaire dans le cas fréquent où il est nécessaire d'associer de nouvelles possibilités graphiques à des interactions particulières. Prenons pour cela l'exemple du dessin. Il peut être utile, pour beaucoup d'interfaces avancées, de dessiner sur des objets de l'interface (reconnaissance de gestes, annotations, etc.). Dès lors, il faut spécifier l'interaction de dessin et les propriétés de l'objet graphique associé. Mais si l'on veut pouvoir dessiner sur plusieurs types d'objets, il faut:
Cette nouvelle classe de calques hérite des propriétés de la classe MaggLiteLayer (redimensionnement automatique, adaptation à la forme du composant conteneur, transparence, pliage, etc.) et surcharge ses méthodes graphiques pour afficher le dessin sur l'objet. Pour le dessin, elle implémente les méthodes de l'interface MaggLiteDraw afin d'être compatible avec les interactions de dessin qui seront définies par un nouveau dispositif d'interaction ou un nouvel outil interne (voir la section D.3.1 de cette annexe).
Il suffit alors d'associer un outil interne à une instance de ce calque et de l'ajouter dans un objet graphique pour pouvoir dessiner sur l'objet, sans avoir eu à modifier son code ou ses propriétés (voir code D.1.2).
Cette approche permet d'étendre et de réutiliser les capacités internes des objets. Elle s'avère par contre inadaptée à l'extension des capacités des objets pour une interaction directe (qui doivent agir sur l'objet). Pour cela, la méthode précédente, par héritage, est appropriée bien que favorisant la redondance du code. Il serait alors intéressant d'étudier l'utilisation de la programmation par aspects pour l'extension des objets graphiques. Toutefois, cette technologie nous semble trop limitée à l'heure actuelle, en particulier au niveau des performances dans le cadre d'applications graphiques et hautement interactives comme celle que nous proposons. Cela en fait tout de même une piste pour compléter les mécanismes de notre boîte à outils afin de proposer trois approches d'extension complémentaires:
stuf