# Documentation pour les développeurs

Auteur: Damien Guillaume

- Introduction
- Utilisation de Jaxe au sein d'une autre application
- Création de nouveaux éléments Jaxe
- Ajout d'une fonction

# Introduction

On supposera ici que le lecteur a déjà lu les documentations utilisateur, administrateur et sur les fichiers de configuration, et qu'il est familier de la programmation en Java.

Cette documentation explique comment utiliser Jaxe au sein d'une autre application, et comment lui ajouter des extensions pour l'affichage des éléments.

# Utilisation de Jaxe au sein d'une autre application

La classe de lancement de Jaxe est (sans surprise) `jaxe.Jaxe`. Cette classe rassemble la gestion des évènements externes à l'application (ouverture de fichier, fermeture, etc...), et on peut donc y jeter un œil pour voir comment un nouveau document Jaxe est créé ou comment un document est ouvert.

Une autre classe importante est `jaxe.JaxeFrame`. Cette classe correspond à une fenêtre de document XML. Elle utilise la classe `jaxe.JaxeMenuBar` pour la gestion de la barre de menus, celle-ci étant malheureusement (à cause d'une limitation de Java) liée à la fenêtre.

Le plus simple, pour utiliser Jaxe dans une autre application, est probablement de se servir de la classe `jaxe.JaxeTextPane`, qui correspond à la zone de texte dans la fenêtre XML. Comme cette classe est dérivée de `java.swing.JTextPane`, elle peut facilement être ajoutée où on le souhaite selon le layout de l'application hôte. Le constructeur requiert un `JaxeDocument` (lié au DOM) et une `JFrame` (la fenêtre parent).

L'objet de classe `jaxe.JaxeDocument` doit être initialisé avec un fichier de configuration de Jaxe (géré par la classe `jaxe.Config`) et éventuellement avec un fichier XML ou avec un objet DOM.

Pour récapituler, voilà une série d'instructions permettant d'incorporer une zone de texte Jaxe dans un `Container` `parent` se trouvant dans une fenêtre `frame`:

    JaxeDocument jaxeDoc = new JaxeDocument("monlangage_config.xml");
    JaxeTextPane jaxeTextPane = new JaxeTextPane(jaxeDoc, frame);
    jaxeDoc.lire(urlFichierXML);
    // ou jaxeDoc.setDOMDoc(documentDOM);
    parent.add(jaxeTextPane);

Les éléments peuvent être insérés avec le menu contextuel, ou avec des actions `jaxe.ActionInsertionBalise`. Le constructeur de `ActionInsertionBalise` demande le document Jaxe, et l'élément DOM correspondant à la définition de l'élément dans le fichier de configuration de Jaxe.

On peut plus tard enregistrer le document avec la méthode `JaxeDocument.ecrire(File f)`.

# Création de nouveaux éléments Jaxe

On appelle élément Jaxe une classe dérivée de la classe `jaxe.JaxeElement`, décrivant un affichage pour un élément XML donné. Les éléments Jaxe standard sont regroupés dans le package `jaxe.elements`. Ils correspondent à des types d'affichage des fichiers de configuration (par exemple, le type `string` correspond à l'élément Jaxe `jaxe.elements.JEString`).

La création d'un nouvel élément Jaxe se fait en créant une nouvelle classe dérivée de `jaxe.JaxeElement`. Il peut ensuite être utilisé dans un fichier de configuration avec le type `plugin`, en précisant la classe à utiliser. Par exemple:

    <AFFICHAGE_ELEMENT element="BOUBOULE" type="plugin">
      <PARAMETRE nom="classe" valeur="JEBooleen"/>
    </AFFICHAGE_ELEMENT>

Deux méthodes doivent impérativement être définies dans l'élément Jaxe: `init` et `nouvelElement`. Deux autres ne sont utiles que si on utilise des balises de début et de fin (comme expliqué plus loin): `insPosition` et (si l'élément a des attributs) `majAffichage`.

`init` est utilisé pour l'initialisation et l'insertion du composant Swing dans la zone de texte. On trouve en paramètres la position à laquelle l'élément doit être inséré, et le nœud DOM. A partir de ces paramètres, il faut insérer le composant avec la méthode `JaxeElement.insertComponent(Position pos, JComponent comp)`.

Les choses se compliquent si on veut utiliser un composant pour une balise de départ et un composant pour une balise de fin, en laissant Jaxe traiter récursivement les sous-éléments. Il faut alors récupérer la position dans le texte après l'insertion de la balise de départ (elle est retournée par `insertComponent`), ajouter les enfants avec `creerEnfants(Position)`, puis insérer la balise de fin avec un nouvel appel à `insertComponent` (avec l'objet `Position` passé en paramètre à `creerEnfants`. Il faut ensuite mettre à jour le style des caractères pour les balises et le texte des enfants, ce qui nécessite d'avoir conservé la position de départ avant le premier `insertComponent`. Voilà un exemple:

    int offsetdebut = pos.getOffset();
    Position newpos = insertComponent(pos, composantBaliseDebut);
    creerEnfants(newpos);
    insertComponent(newpos, composantBaliseFin);
    if (newpos.getOffset() - offsetdebut - 1 > 0) {
      SimpleAttributeSet style = attStyle(null);
      if (style != null)
        doc.setCharacterAttributes(offsetdebut, newpos.getOffset() - offsetdebut - 1, style, false);
    }

La méthode `nouvelElement` est appelée quand l'utilisateur insère un nouvel élément. Elle doit éventuellement demander des informations à l'utilisateur (comme par exemples les attributs), et renvoyer l'élément DOM correspondant. On peut se servir de `jaxe.DialogueAttributs` pour demander les attributs à l'utilisateur.

`insPosition` peut être appelée pour obtenir la position à laquelle sera placé le curseur après l'insertion d'un nouvel élément. Par défaut le curseur sera placé après l'élément, mais il peut être utile de le placer entre les balises de début et de fin quand celles-ci sont utilisées.

Enfin, `majAffichage` est appelée pour mettre à jour l'affichage quand les attributs ont été modifiés dans le panneau d'attributs.

## Exemple

Le fichier suivant est un élément Jaxe utilisable pour un booléen, qui utilise une case à cocher pour l'affichage: JEBooleen.java. Il peut être compilé et placé dans un fichier jar pour être utilisable comme nouveau plugin de Jaxe, comme ceux disponibles sur la page des plugins.

# Ajout d'une fonction

On peut facilement ajouter un menu opérant une fonction particulière au lieu d'une insertion d'élément. Il suffit pour cela de créer une classe dérivant de `jaxe.Fonction` et implémentant la méthode `appliquer`, qui fournit le document Jaxe sur lequel on travaille, et les positions de début et de fin de la sélection dans le texte.

    public void appliquer(JaxeDocument doc, int start, int end)

On peut obtenir le document DOM à partir du document Jaxe en utilisant `doc.DOMdoc`. On peut aussi obtenir un élément Jaxe à partir d'une position du texte avec `doc.elementA(int pos)`, ou les éléments dans l'intervalle [start,end] avec `rootJE.elementsDans(start, end)`. Le noeud DOM correspondant est obtenu avec `JaxeElement.noeud`.

## Exemple

L'exemple suivant permet d'ajouter un menu donnant des statistiques sur le document.

- Télécharger le fichier FonctionStatistiques.java.
- Le mettre dans un dossier `pluginsjaxe` (c'est le nom du package).
- Le compiler. A partir de l'endroit où se trouve le dossier pluginsjaxe, il suffit de taper sous la ligne de commande : `javac -encoding ISO-8859-1 -classpath .:lib/Jaxe.jar pluginsjaxe/FonctionStatistiques.java` (en supposant que le fichier `Jaxe.jar` se trouve dans un dossier `lib` dans le répertoire courant). Cela doit créer un fichier `FonctionStatistiques.class` dans le dossier `pluginsjaxe`.
- Créer un fichier jar à partir du dossier `pluginsjaxe`, et le placer dans le dossier `plugins` de Jaxe.
- Modifier le fichier de configuration du langage utilisé pour ajouter un menu avec un appel à la fonction:

    <MENU nom="plugins">
      <MENU_FONCTION classe="pluginsjaxe.FonctionStatistiques" nom="Statistiques"/>
    </MENU>