17 novembre 2014
Comm. : 0

Programmation événementielle en ExtendScript

Plusieurs années d’utilisation d’Adobe Flex et d’ActionScript nous ont rôdés à la programmation événementielle. En d’autres termes, comment faire communiquer les différentes briques logicielles entre elles sans devoir systématiquement les relier systématiquement les unes aux autres. Qui dit « événement » pense bien souvent à la programmation d’interface. Un clic de bouton est un événement qu’il faut capturer. D’autres auront à l’esprit ces événements d’interface propres à InDesign comme un appel de menu ou une action de l’utilisateur type « ouverture de document ».

Pourtant c’est bien d’autre chose que dont nous allons converser ici. Il s’agit tout simplement de créer notre propre classe événementielle en ExtendScript. Objectif : programmer à la Flex dans nos scripts javascript.

Dès lors que nous créons des scripts plutôt conséquents, il devient plus commode d’éclater notre code en plusieurs briques logicielles. Il suffira alors de rassembler ce petit monde à l’aise d’une instruction « #include » ad hoc. Mais une fois ce fractionnement atteint, il faut pouvoir conserver des échanges entre les différentes dépendances. Par exemple, si on souhaite appeler une fonction de la dépendance A dans l’inclusion B. S’il est possible de faire appel à une librairie en la nommant expressément, cela peut vite devenir complexe à entretenir et peu propice à une réutilisation du code pour d’autres scripts.

Pour contourner cet écueil, nous vous proposons d’envisager ici un classe sur mesure qui va nous permettre de communiquer entre nos dépendances avec un maximum d’abstraction. Nous nous sommes inspirés d’EventBroker, un travail mené par developmentarc-core et qui vise aux mêmes buts de découplage de la communication événementielle entre classes. Notre objectif n’était pas de le porter en l’état en ExtendScript mais d’en reprendre l’esprit.

A) Inclure « EventManager »

Avant d’utiliser EventManager, prenez soin d’ajouter la classe à votre script avec l’instruction suivante :

#include 'EventManager.jsinc'

La classe est désormais utilisable. Vous allez pouvoir faire interagir vos classes via EventManager et une syntaxe éprouvée.

B) Utiliser EventManager

Avant de pouvoir réagir à un événement, il faut déjà pouvoir l’écouter. Nous allons donc ajouter un écouteur pour notre « événement » générique :

var eventHandler = function(){alert("Event was triggered")};
EventManager.addEventListener ( "EVENT_FIRED", eventHandler );

Pour déclencher l’événement, on utilisera la syntaxe suivante :

EventManager.dispatchEvent ("EVENT_FIRED");

EventManager triggered

Pour transmettre des données, on pourra utiliser la syntaxe suivante :

var eventHandler = function(data){alert(data)};
EventManager.addEventListener ( "EVENT_FIRED", eventHandler );
EventManager.dispatchEvent ("EVENT_FIRED", "Hello there !");

Pour suppimer un écouteur, il suffit d’écrire :

EventManager.removeEventListener ( "EVENT_FIRED", eventHandler );

C) EventManager et ScriptUI

Un exemple possible d’utilisation est dans un projet d’interface en ScriptUI. Bien que ScriptUI dispose déjà de mécanismes internes relatifs à la gestion des événements, nous avons trouvé utile d’implémenter EventManager en complément de ce dernier. Lors d’un projet spécifique, nous ne parvenions pas à obtenir une disposition adéquate de nos éléments (champs texte, labels, boutons…) dans notre fenêtre ScriptUI sur la seule base du LayoutManager interne. En clair, ça faisait n’importe quoi…

Nous en sommes arrivés à la conclusion que le mieux était encore de nous occuper de la disposition des éléments en cas de redimensionnement ou de mise à jour de l’interface. Comme nos vues étaient éclatées en plusieurs dépendances, il aurait fallu ajouter le même écouteur d’événements à savoir l’affichage final du dialogue.

var w = new Window('dialog');
w.onShow = function() {
//dialog is now open. Do something then.
}

Problème : comment accéder facilement à cet objet « w » dans les dépendances ? Variable globale…bof. Paramètre d’une fonction…peut-être. C’est quand même se donner beaucoup de mal. Et si on écoutait cet événement une fois dans la dépendance contenant l’objet « w » et utiliser EventManager pour informer toutes les dépendances ?

//MAIN WINDOW => window.jsx
var w = new Window('dialog');
w.onShow = function() {
EventManager.dispatchEvent ( "WINDOW_SHOWN", w);
}

//UI COMPONENT => uiComponent.jsinc
var p = parentUI.add('panel');
var resizeFunction = function(w) {
p.size.width = w.size.width/2;
}
EventManager.addEventLister ( "WINDOW_SHOWN", resizeFunction );

EventManager Schema

Nous évitons ainsi toutes les problèmatiques liées aux cascades d’initialisation : qui est affiché en premier ? L’objet sera t-il accessible lors de son appel ? Etc.

D) Conclusion

EventManager fait partie intégrante de nos scripts désormais. Nous n’affirmons aucune supériorité sur toute autre approche. Nous avons simplement souhaité exposer une approche avec ses qualités intrinsèques. EventManager nous apporte toute la souplesse et la réactivité dont nous avions besoin et nous espérons que vous y trouverez autant d’intérêt à l’utiliser que nous avons eu à la produire. Si tel est le cas, n’hésitez pas à nous en faire part dans les commentaires.

A bientôt,

Télécharger EventManager

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *