next up previous contents
suivant: 4.4 Construction et édition monter: 4. La boîte à précédent: 4.2 Les dispositifs d'ICON   Table des matières

Sous-sections

4.3 Programmation avec ICON

Pour programmer avec la boîte à outils ICON, il n'est pas nécessaire de connaître la structure et les mécanismes de base (typage et exécution) des configurations d'entrée, décrits indépendamment par le modèle ICOM.

Cependant, l'extension de la bibliothèque d'ICON, le développement d'applications interactives configurables et la distribution de configurations d'entrées réutilisables nécessitent la connaissance de quelques mécanismes essentiels propres à la boîte à outils ICON. Nous les décrivons dans cette partie.


4.3.1 Implémentation de nouveaux dispositifs

4.3.1.1 Dispositifs programmables

Figure: Fenêtre de propriétés du dispositif Script.
\begin{figure}
\begin{center}
\includegraphics[scale=0.45]{script_device}
\end{center}
\end{figure}

ICON fournit un dispositif utilitaire Script qui permet de décrire des comportements simples en JavaScript, directement dans l'éditeur de configurations et sans nécessité de recompilation. La liste des slots du dispositif ainsi que le code de traitement sont saisis dans la fenêtre de propriétés du dispositif, illustrée figure 4.6. Cet exemple décrit une fonction de transfert utilisée dans le contrôle d'un zoom par un dispositif isométrique.

4.3.1.2 L'interface Device

Figure: Les interfaces Device et Processor.
\begin{figure}
\begin{center}
\includegraphics[scale=0.8]{device_interfaces}
\end{center}
\end{figure}

Comme nous le verrons dans cette section, l'implémentation en Java d'un dispositif simple est relativement élémentaire. Les fonctionnalités d'un dispositif d'entrée sont décrites par l'interface Device dans l'API ICON. Cette interface est reproduite, avec les commentaires, sur la figure 4.7. La partie exécution des dispositifs d'entrée est décrite par l'interface Processor, reproduite sur la même figure.

En pratique, un dispositif dérive toujours de la classe AbstractDevice. Cette classe implémente un certain nombre de comportements par défaut communs à une grande majorité des dispositifs, à savoir, la gestion des slots d'entrée et de sortie à travers les méthodes addIn et addOut, l'auto-duplication (consistant en une ré-instanciation de la classe et la copie des valeurs des paramètres), et la gestion d'un processeur unique.

4.3.1.3 Exemple: le dispositif DColorConv

Figure: Code java du dispositif DColorConv.
\begin{figure}
\begin{center}
\includegraphics[scale=0.65]{device_code}
\end{center}
\end{figure}

La figure 4.8 montre un exemple de dispositif utilitaire qui a été ajouté à la bibliothèque d'ICON pour permettre un contrôle vocal des attributs de la brosse dans ICONDraw. Ce dispositif DColorConv convertit des noms de couleur en leurs composantes RGB.

Écrire un dispositif utilitaire consiste essentiellement à déclarer ses slots d'entrée et de sortie, et à remplir le corps de sa méthode de mise à jour update, pour assigner les valeurs des slots de sortie en fonction de celles des slots d'entrée (la gestion des tables de couleurs n'est pas montrée dans le code). À chaque fois qu'une des valeurs en entrée changera, cette méthode de mise à jour sera automatiquement appelée par la machine réactive d'ICON.

La classe AbstractDevice gère un processeur unique: elle implémente l'interface Processor, et sa méthode open() retourne this par défaut. La gestion de processeurs multiples, utile pour faire de la spécialisation de code, s'effectue par dérivation de la méthode open() et l'utilisation d'inner classes.

Le dispositif peut être rendu paramétrable (par exemple, une liste de couleurs personnalisable), simplement en ajoutant des méthodes de type accesseurs à la classe. ICON déduit automatiquement les noms de paramètres par introspection et génère la fenêtre de propriétés correspondante dans l'éditeur.

L'implémentation d'un dispositif d'application est similaire à celle d'un dispositif utilitaire comme DColorConv, à ceci près que les assignations de slots de sortie sont remplacées par des appels de méthodes dans l'application elle-même.


4.3.2 Initialisation d'une configuration

4.3.2.1 Principe général

Figure: Initialisation d'une configuration d'entrée dans une application interactive.
\begin{figure}
\begin{center}
\includegraphics[scale=0.58]{archi_contexte}
\end{center}
\end{figure}

Pour être configurable par ICON, une application doit créer une configuration d'entrée et faire le lien entre cette configuration et ses propres objets. L'ensemble des mécanismes de communication entre l'application et sa configuration d'entrée est résumé sur la figure fig:archi_contexte. La création d'une configuration d'entrée nécessite la déclaration d'un dossier de dispositifs et le passage d'un contexte d'exécution.

Le dossier de dispositifs contient l'ensemble des dispositifs qui pourront être utilisés dans la configuration, et qui seront visibles dans la partie gauche de l'éditeur de configurations (voir section 4.4.1). En général, il s'agit de la bibliothèque standard d'ICON comportant tous les dispositifs système et utilitaires organisés en sous-dossiers, à laquelle est ajouté un dossier spécifique à l'application. Comme tout dossier, ce dernier est un conteneur de dispositifs-prototypes, instances de dispositifs qui sont dupliquées pour être ajoutées à la configuration. Un ou plusieurs prototypes peuvent être déclarés par classe de dispositif, ce qui permet notamment de fournir des ensembles de dispositifs pré-paramétrés, ou de décrire des dispositifs d'instance statiques.

Le contexte d'exécution est une table de hachage qui contient toutes les informations nécessaires à l'exécution de l'ensemble des dispositifs du dossier. Les dispositifs de boîte à outils graphique, que nous avons évoqués précédemment, nécessitent une référence vers la ou les fenêtres qu'ils contrôlent. En outre, l'application possède ses propres dispositifs qui requièrent des références vers des objets de celle-ci, références qui sont ajoutées au contexte sur des clés spécifiques. Lors du lancement de la configuration d'entrée, chaque dispositif reçoit dans sa méthode open le contexte d'exécution d'où il va extraire les informations pertinentes, et le cas échéant produire un échec d'ouverture si celles-ci sont indisponibles.

4.3.2.2 Implémentation d'une application configurable

Figure: Code type d'une application configurable en entrée. Les dispositifs d'application ne sont pas représentés.
\begin{figure}
\begin{center}
\includegraphics[scale=0.8]{app_code}
\end{center}
\end{figure}

Le code type d'une application configurable par ICON est donné sur la figure 4.10. Ce code présente trois parties principales:

A. Initialisation de la configuration d'entrée. Ce code est ajouté à la fin de la méthode constructeur de l'application. Le dossier de dispositifs est créée en passant le dossier de l'application (MyDevices) au constructeur de la bibliothèque standard d'ICON (FRoot). La configuration d'entrée (ainsi que sa fenêtre d'édition) est ensuite créée, puis exécutée.

B. Gestion de la configuration. Une gestion minimale de la configuration consiste en l'ajout d'un élément interactif (élément de menu, par exemple) qui déclenche le passage en mode édition (méthode editInput()), et en la gestion propre de la désallocation des dispositifs lors de la fermeture de l'application (méthode quit()).

C. Dossier de dispositifs. Les dispositifs-prototypes de l'application sont déclarés par dérivation d'une classe abstraite (AbstractFolder).


4.3.3 Sérialisation et descripteurs

Pour pouvoir être sauvegardées et chargées, les configurations d'entrée doivent être sérialisables. La sérialisation consiste à convertir un objet en une série d'octets (que nous nommerons signature) pour pouvoir, lors d'une exécution ultérieure, recréer le même objet par le processus inverse. Dans cette section, nous évoquerons essentiellement la sérialisation de dispositifs.

4.3.3.1 Les difficultés de la sérialisation de dispositifs

Établir la signature d'un dispositif système n'est pas trivial. En voici quelques raisons:

  1. Un dispositif système n'est pas entièrement décrit par sa classe. Par exemple, deux dispositifs physiques de même type peuvent être présents, et produire dans ICON deux dispositifs qui dérivent de la même classe.
  2. Toutes les APIs d'entrée ne garantissent pas un mécanisme déterministe de détection et d'identification de dispositifs. L'ordre dans lequel les dispositifs sont listés peut également changer.
  3. Entre deux exécutions, un dispositif d'entrée physique peut avoir été débranché et rebranché sur un autre connecteur: il devra tout de même être retrouvé, puisqu'il s'agit du même dispositif.
  4. Deux dispositifs d'entrée physiques identiques (même marque, même modèle) peuvent être utilisés conjointement dans une configuration et y jouer un rôle différent. Il va de soi que ces dispositifs sont physiquement placés différemment sur l'espace de travail (main droite et main gauche, par exemple). D'une exécution à l'autre, leurs rôles respectifs ne devra donc pas être interverti.

Établir des signatures les plus précises possibles, notamment en s'appuyant sur des identifiants uniques (à condition qu'ils soient fournis par l'API d'entrée), peut résoudre en partie ces problèmes. Des interrogations subsistent cependant: faut-il prendre en compte l'identifiant matériel du dispositif ou celui du connecteur sur lequel il est branché ? Si seul l'identifiant matériel est utilisé, la situation 4. évoquée précédemment ne sera pas résolue. Dans le cas contraire, c'est la situation 3. qui posera problème.

D'autres arguments vont à l'encontre de l'emploi d'identifiants uniques. Le remplacement d'une souris par une autre, par exemple, ne devrait pas rendre une configuration standard inutilisable. De même, certaines configurations d'entrée devraient pouvoir être réutilisables d'un poste à l'autre et d'un utilisateur à l'autre. Il est clair que la réutilisabilité des configurations d'entrée et l'identification précise des dispositifs physiques pour la persistance sont deux exigences incompatibles, et c'est pourquoi il est essentiel d'employer des stratégies de signature adaptées à chaque contexte.

Notons enfin que ces problèmes sont généralisables à tous les dispositifs comportant des entrées ou sorties implicites (les dispositifs d'application en particulier), car, d'une exécution à l'autre, il faut être capable de reconstruire ou de retrouver les objets extérieurs avec lesquels ils communiquaient.

La gestion de la sérialisation dans ICON est d'une grande souplesse, grâce au principe de descripteurs sur lequel il repose. La signature d'un dispositif est obtenue par la signature d'un de ses descripteurs. Des descripteurs plus ou moins sélectifs peuvent être construits, chaque dossier de dispositifs ayant la charge de fournir des descripteurs stricts (uniques) pour ses dispositifs fils.

4.3.3.2 Les descripteurs: définition

Un descripteur est un ensemble non nécessairement dénombrable de dispositifs. En outre, chaque descripteur est lié à une représentation textuelle, tel qu'il existe une bijection entre l'ensemble des descripteurs et l'ensemble de leurs représentations textuelles.

Dans ICON, l'interface DeviceDescriptor est définie par les méthodes suivantes:
public boolean contains(Device d)

public String getString()

Une classe de descripteurs est une classe:

  1. Qui implémente l'interface DeviceDescriptor
  2. Dont le nom est préfixé par DD
  3. Qui comporte un constructeur du type public DDFoo(String s)
  4. Qui vérifie pour toute instance desc:
    desc $ \equiv$ new DDFoo(desc.getString())
    (équivalence de leurs fonctions contains et getString).

Un descripteur est une instance d'une classe de descripteurs. La signature d'un descripteur est obtenue par concaténation de son nom de classe sans le préfixe DD, du signe =, et de sa représentation textuelle.

Exemple: pour une instance de DDFoo dont getString()=4, la signature est foo=4.

4.3.3.3 Les classes de descripteurs d'ICON

Il existe plusieurs classes de descripteurs prédéfinies dans ICON. Il est ainsi possible de décrire des ensembles de dispositifs possédant un nom donné, dérivant d'une classe donnée, possédant un ensemble minimal de slots (noms et/ou types), ou provenant d'un dossier donné. Ces descripteurs sont extrêmement puissants et la plupart permettent d'utiliser des caractères génériques (* et ?). De nouvelles classes de descripteurs peuvent créées et employées.

Les descripteurs sont composables: les meta-descripteurs sont des descripteurs qui comportent un ou plusieurs descripteurs-fils. La plupart permettent d'effectuer des opérations ensemblistes. Le descripteur DDAnd, par exemple, effectue des intersections de descripteurs. À titre d'exemple, la phrase « tous les dispositifs dont le nom commence par "mouse" et qui dérivent d'une classe "DMouse" » sera construite ainsi:

DeviceDescriptor mydesc =
new DDAnd(new DDName("mouse*"), new DDClass("*.DMouse"));

ou pourra être spécifiée par la signature suivante:

DeviceDescriptor desc = DescriptorUtilities.createDD("
and {
 name=mouse*;
class=*.DMouse;
}
");

4.3.3.4 L'algorithme de chargement

Lors du chargement d'un fichier de configuration, et pour chaque descripteur de ce fichier, le dossier de dispositifs est parcouru jusqu'à ce qu'un dispositif-prototype convienne (contains(d)==true). Celui-ci est alors copié, ajouté à la configuration et n'est plus pris en compte dans les recherches ultérieures.

Le descripteur DDProperties, qui décrit des paramétrages pour les dispositifs, joue un rôle particulier dans l'algorithme de désérialisation. Lorsqu'un dispositif-prototype correct a été trouvé, puis copié, l'algorithme lui applique le paramétrage spécifié par le descripteur lorsqu'il existe. Si ce paramétrage provoque une erreur (paramètre inexistant ou valeur incorrecte), l'algorithme reprend la recherche.

Lors d'une désérialisation, plusieurs dispositifs-prototypes peuvent répondre à un descripteur. C'est le premier rencontré qui est choisi, puis éliminé des choix ultérieurs. L'algorithme effectue cependant des retours arrière lorsqu'il aboutit à une impasse (dispositif introuvable).

4.3.3.5 Les descripteurs stricts

Lors d'une sauvegarde, ICON utilise par défaut des descripteurs stricts, garantissant l'unicité. Chaque dossier de dispositifs est chargé de fournir des descripteurs stricts pour ses dispositifs, par la méthode getDescriptor(Device d). Dans la classe AbstractFolder, cette méthode retourne simplement un descripteur sur la classe du dispositif passé en paramètre. Ce comportement par défaut convient aux dispositifs utilitaires et à la plupart des dispositifs d'application. Le plus souvent, l'implémentation d'une application configurable par ICON ne nécessite donc aucune connaissance sur les descripteurs.

Pour un dossier comportant plusieurs prototypes de même classe, il devient cependant nécessaire de retourner un descripteur plus précis, portant par exemple sur le nom du dispositif. Les dossiers de dispositifs système, quant à eux, devront retourner une liste complète des caractéristiques physiques du dispositif pour s'assurer que deux dispositifs ne possèdent jamais le même descripteur. Des classes spécifiques de descripteurs pourront également être créées et employées.

4.3.3.6 Le langage ICSCRIPT

Les fichiers de configurations sont générés dans un langage de script dédié nommé ICSCRIPT. Un exemple de fichier de configuration est donné figure 4.11. Celui-ci est partagé en trois sections (en gras italique): la déclaration des dispositifs composée de descripteurs, les connections, et la partie présentation, optionnelle et propre à l'éditeur de configurations. Chaque descripteur est nommé (en gras) dans la première section afin de pouvoir être référencé dans les sections suivantes. Une syntaxe similaire permet également le nommage des descripteurs de slots, lorsque des connexions doivent être spécifiées entre des slots dont le nom concret n'est pas connu (attribut name absent du descripteur ou comportant des caractères génériques, par exemple).

L'auteur d'une configuration peut éditer ce fichier et modifier les descripteurs qui s'y trouvent avant de le distribuer à d'autres utilisateurs. Par exemple, les slots non utilisés d'un dispositif peuvent être supprimés de sa déclaration, ou plusieurs dispositifs interchangeables peuvent être spécifiés en reliant simplement leurs descripteurs par un or. Les opérations ensemblistes and, or et not peuvent être imbriquées et appliquées sur n'importe quel sous-ensemble de descripteurs.

Le langage ICSCRIPT est un premier pas vers la réutilisabilité des configurations d'entrée. À terme, des stratégies de réutilisabilité intégrées pourront être mises en \oeuvre sur la base des descripteurs, telles que la visualisation et l'édition graphique des descripteurs, ou l'utilisation d'un moteur de résolution de contraintes dans l'algorithme de chargement des configurations.

Figure: Fichier ICSCRIPT généré à partir de la configuration de la figure fig:config_freehand.
\begin{figure}
\begin{center}
\includegraphics[scale=1.2]{ic_format}
\end{center}
\end{figure}


next up previous contents
suivant: 4.4 Construction et édition monter: 4. La boîte à précédent: 4.2 Les dispositifs d'ICON   Table des matières
Pierre Dragicevic 2005-07-22