Retrouvez cet article dans : Linux Pratique Hors série 9
OpenOffice.org propose tous les outils attendus d'une suite bureautique : publipostage, application des styles, gestion des modèles, feuille de calculs, dessin et présentation, etc. Néanmoins, les utilisateurs sont en droit d'en demander plus : utiliser les fonctionnalités internes d'OpenOffice.org pour l'étendre, l'enrichir et surtout l'adapter à leurs besoins. Les extensions sont là pour çà et offrent de nombreuses possibilités de tout niveau de technicité.
Cet article se veut une introduction succincte et pragmatique à la création d'extensions pour OpenOffice.org. Sur la base d'exemples simples, nous allons illustrer les outils et principes de base de la création d'extensions. L'objectif de cet exposé est de rester didactique et abordable à toute personne désirant agir sur OpenOffice.org sans pour autant être versée dans les arcanes d'UNO (Universal Network Object) et de l'API (Application Programming Interface) interne.
Nous commencerons donc par définir ce qu'est une extension au sens d'OpenOffice.org et par indiquer la manipulation des outils indispensables pour débuter.
Nous verrons ensuite que les extensions ne sont pas réservées au code, mais peuvent être également utilisées pour déployer des fichiers complémentaires à OpenOffice.org comme des modèles ou des galeries. Nous illustrerons notre discours par la création d'une extension déployant les modèles lauréats du concours du projet documentation qui a eu lieu en fin d'année 2006.
Suivront alors deux exemples illustrant ce qu'il est possible de faire de manière simple dans deux cas d'études que nous poserons. Le premier sera une macro OOoBasic permettant l'export d'un document dans un format PDF. Cette macro pourra être déployée sous forme d'extension et même appelée en ligne de commande.
Le deuxième exemple présentera un exemple plus évolué en Python permettant une utilisation plus poussée de l'API et du framework en proposant une alternative au démarrage automatique des présentations Impress.
Extensions au sens d'OpenOffice.org
Une extension est un package amenant une fonctionnalité supplémentaire à OpenOffice.org
Contrairement à une idée reçue, OpenOffice.org propose depuis longtemps la possibilité de créer des extensions logicielles. Macros ou code contenus dans un fichier zip, seule la possibilité de déploiement en ligne de commande par pkgchk en faisait une fonctionnalité confidentielle. Avec l'avènement de la version 2 d'OpenOffice.org, le gestionnaire de packages (ou d'extensions) est inclus dans l'interface utilisateur (Outils -> Gestionnaire de packages) tout en conservant une possibilité de ligne de commande par unopkg.
Au fil des versions, le framework s'est enrichi pour permettre le déploiement de modèles et autres éléments non issus de code. Les fonctions de présentation des licences, gestion des dépendances et mises à jour sont également en cours de développement.
Le Projet Extensions [1-1] d'OpenOffice.org a pour objectif de faciliter l'entrée des nouveaux venus dans ce monde ainsi que la mise en valeur des productions. Trois Axes de travail sont ainsi proposés à tous les volontaires :
- introduction au framework : une introduction et les outils pour créer son extension dans son langage de prédilection, ainsi que les éléments de packaging communs ;
- création d'une infrastructure regroupant les extensions mises à disposition pour OOo ainsi que leur gestion ;
- l'installation et la mise à jour automatique aux utilisateurs depuis différentes infrastructures proposant des extensions.
Le projet Extensions évolue tous les jours et beaucoup de choses sont en cours de réalisation. Tout volontaire est le bienvenu.
Principaux langages utilisables
Une extension peut permettre de déployer tout type de fichiers : des ressources comme les modèles, des éléments de configuration, mais le plus souvent des extensions issues de code. Ce code peut être autant une macro qu'un code complet non issu de l'EDI (Environnement de Développement Intégré).
OpenOffice.org permet l'utilisation d'un très grand nombre de langages :
- OOoBasic : langage de prédilection pour la création de macros et de composants simples utilisant l'API. Il ressemble grammaticalement à tout Basic, dont VBA (Visual Basic for Application), mais la ressemblance s'arrête là . L'API et les objets manipulés sont totalement différents.
- Il est à noter une initiative de Novell visant à créer une couche intermédiaire de compatibilité, mais qui est restreinte à Excel pour le moment et qui n'est pas sans poser des questions d'utilisabilité sur le mélange des API et la couverture fonctionnelle (sans parler d'autres considérations plus éloignées de l'implémentation elle-même). [1-2]
- OOoBasic propose un très grand nombre de simplifications par rapport à l'API réelle permettant un développement accéléré. Un EDI est également fourni permettant le débogage pas à pas, la coloration syntaxique, l'organisation des sources en bibliothèques et modules...
- Python : ce langage est livré avec OOo, actuellement en version 2.3.5, ce qui en fait une plate-forme naturelle pour le développement d'extensions évoluées. Avoir une machine virtuelle livrée avec OOo vous assure de pouvoir toujours compter sur la disponibilité des fonctions dont vous avez besoin. De plus, la nature orientée objet de Python permet, outre les simplifications d’OOoBasic de créer soi-même de nouveaux services UNO, tirant ainsi parti de toute la puissance de l'API. On déplorera cependant l'absence pour le moment d'un EDI facilitant la tâche au développeur.
- Java : langage de prédilection pour l'écriture des extensions, il bénéficie d'une documentation adaptée abondante (même si celle-ci peut être utilisée et interprétée pour d'autres langages). Des outils récents intégrés à NetBeans [1-3] et Eclipse [1-4] facilitent désormais la création de tels composants et automatisent certaines tâches. L'emploi de ce langage reste cependant dédié aux personnes désirant s'investir un peu plus dans la structure d’UNO.
- C++ : langage utilisé par OpenOffice.org en interne, il est également possible de créer des extensions dans ce langage. Néanmoins, malgré un bénéfice attendu en termes de performance, il faudra être vigilant à la portabilité de votre extension. Le framework prévoit ce cas en permettant de livrer plusieurs binaires différents [1-5], mais cela reste un travail conséquent.
D'autres langages sont disponibles et bien que leur utilisation reste plus confidentielle, ils illustrent la richesse des possibilités offerte par la plate-forme. Parmi ces langages, nous citerons Javascript et Beanshell pour les macros qui disposent d'un EDI rudimentaire et les langages issus de .NET, traduisant la volonté de couverture muliplateforme d’OOo.
Enfin, l'approche objet permet par exemple de définir un service dans un langage pour qu'il soit utilisé par la suite par d'autres langages (par exemple [1-6]). La réutilisabilité des composants est alors assurée.
Contenu d'une extension
Une extension est un fichier compressé renommé en .oxt. Elle est déployable par l'utilisateur en utilisant le menu Outils -> Gestionnaire des extensions ou en ligne de commande avec unopkg.
Cette archive peut contenir un grand nombre de fichiers différents, mais, de manière générale, on y retrouvera :
- les éléments à déployer comme des modèles ou du code comme nous le verrons plus loin ;
- des paramétrages complémentaires des fichiers du registre d'OpenOffice.org (les fichiers
.xcu) que ce soit en rapport avec la fonctionnalité que vous déployez ou bien des paramétrages spécifiques à un utilisateur par exemple [1-7] ; - le fichier
manifest.xmlcontenant la description de tous les fichiers contenus dans l'archive [1-8] ; - tout autre fichier dont vous pourriez avoir besoin comme les icônes des menus ou des images pour vos assistants.
Nous aurons un aperçu de quelques-uns des éléments dans les exemples que nous traiterons par la suite.
Les outils
De nombreux outils sont développés par la communauté afin de faciliter la prise en main et la génération des extensions. Nous allons en évoquer quelques-uns parmi ceux jugés comme indispensables. Nous ne pouvons être exhaustifs et renvoyons le lecteur vers le site du projet Extensions.
Le Software Development Kit
Le SDK (Software Development Kit) est un ensemble d'outils nécessaires à la création d'extensions. Il est indispensable pour certains langages comme Java et C++, car il en contient certains compilateurs, mais reste une ressource incontournable pour les autres langages comme OOoBasic ou Python, puisqu’il
contient une documentation abondante.
En effet, toute l'API est présente sous forme de fichiers HTML navigables dont la référence IDL (Interface Definition Language), exposant tous les services, interfaces, propriétés, méthodes accessibles (Fig. 1, page suivante), et le guide du développeur, documentation exhaustive de plus de 1200 pages, en plus de 18 chapitres, bien qu'essentiellement décrite pour Java, permet à quiconque l'aborde, d'avoir un exemple d'application d'une API donnée, ainsi qu'un description textuelle et des cas d'utilisation type (Fig. 2).

Fig. 1 : La référence IDL

Fig. 2 : Le guide du développeur
 De plus, l'indexation alphabétique de la référence IDL, sa navigation hypertexte, les liens croisés entre référence IDL et Guide du Développeur en font une documentation complète et efficace permettant au néophyte de trouver une information très rapidement. S’il y a un point à déplorer, c'est que cette riche
documentation reste en anglais.
Enfin, il est à noter que ces deux ressources sont également disponibles en ligne sur le site du projet API [1-9] [1-10] [1-11].
Introspection et Xray
L'introspection est la capacité d'un objet à exposer dynamiquement ses propriétés et méthodes. Le framework UNO l'utilise abondamment et elle permet la création d'outils d'aide à la découverte de l'API et au débogage.
L'un des plus connus et des plus efficaces est incontestablement Xray, de Bernard Marcelly, qui est une ressource indispensable à l'exploration de l'API [1-12].
Son utilisation est très simple, puisqu'il s'agit d'inclure un appel contenant l'objet à examiner, passé aux rayons X, lors de l'exécution. Les méthodes, les propriétés ainsi que leurs valeurs à cet instant sont affichées. Un point primordial est qu'XRay permet de visualiser la fiche IDL de toute méthode ou propriété dynamiquement et donc pointer sur le guide du développeur contextuellement. Les appels récursifs permettent alors de se promener dans toute la hiérarchie des objets à partir d'un point donné. Cet outil est incomparable pour qui veut apprendre et appréhender toute la richesse de l'API (Fig. 3).
 sub ExempleXray() 'thisComponent represente le document 'en cours ouvert sous OOo xray thisComponent end sub

 Fig. 3 : Xray en action
Xray est utilisable avec le langage OOoBasic et peut être appelé depuis d'autres langages. Il est à noter l'existence de pyXray [1-13], une implémentation spécifique en Python ainsi qu'un outil pour Java en cours de développement [1-14].
Outils de construction d'extensions
Une extension OpenOffice.org doit contenir plusieurs fichiers indispensables pour être reconnue comme telle et déployable. Souvent, l'ossature générale reste la même et seuls certains paramètres changent. Ces fichiers, comme les paramétrages .xcu, le fichier de manifest.xml, etc., seront évoqués plus en détail par la suite.
Toujours dans l'optique de faciliter la tâche aux développeurs, le projet Extensions, par l'intermédiaire de Paolo Mantovani, fournit un outil de construction pour l'instant dédié à OOoBasic. Un minimum de travail devrait être nécessaire pour le rendre exploitable pour d'autres langages.
Nous ne rentrerons pas dans le détail du Basic Addon Builder et renvoyons le lecteur à sa description en ligne [1-15]. Sous forme d'assistant, toutes les étapes sont traitées (Fig. 4) et vous pourrez packager vos réalisations pour qu'elles apparaissent dans une barre d'outils, dans un menu, associé à une icône (avec les contraintes inhérentes).

Fig. 4Â : Basic Addon BuilderÂ
Il est à noter qu’AddonTool de Bernard Marcelly [1-16], bien qu'un peu plus ancien, reste tout à fait utilisable au moins pour la création du fichier addons.xcu de paramétrage.
Références partie 1Â
[1-1] http://wiki.services.openoffice.org/wiki/Extensions
[1-2] http://wiki.services.openoffice.org/wiki/VBA
[1-3] http://wiki.services.openoffice.org/wiki/General_UNO_Component_Project_Type
[1-4] http://wiki.services.openoffice.org/wiki/JavaEclipseTuto
[1-5] http://api.openoffice.org/docs/DevelopersGuide/Components/Components.xhtml
[1-6] http://wiki.services.openoffice.org/wiki/General_UNO_Component_Project_Type
[1-7] http://blogs.nuxeo.com/sections/blogs/laurent_godard/2006_02_24_enhancing-ooo-calc-csv-file-recognition
[1-8] http://api.openoffice.org/docs/DevelopersGuide/Components/Components.xhtml#1_9_1_1_Package_Bundle_Structure
[1-9] http://api.openoffice.org/
[1-10] http://api.openoffice.org/docs/common/ref/com/sun/star/module-ix.html
[1-11] http://api.openoffice.org/DevelopersGuide/DevelopersGuide.html
[1-12] http://wiki.services.openoffice.org/wiki/Extensions_development_basic#X-Ray_tool
[1-13] http://www.indesko.com/telechargements/
[1-14] http://wiki.services.openoffice.org/wiki/Object_Inspector
[1-15] http://wiki.services.openoffice.org/wiki/Extensions_Packager
[1-16] http://fr.openoffice.org/Documentation/Outils/Addons1_1fr.sxw
Déployer un modèle de document
Depuis la version 2.0.4, il est possible de déployer un modèle de document (ou un ensemble) en tant qu'extensions. Nous ne reviendrons pas sur l'utilité de définir des modèles de documents pour vos documents bureautiques courants (et non pas utiliser le document précédent pour en rédiger un nouveau). Les modèles d'OpenOffice.org sont accessibles par le menu Fichier -> Modèles de document et Ficher -> Nouveau -> Modèles et Documents.
Si vous créez un modèle que vous souhaitez diffuser soit à la communauté, soit au sein de votre entreprise, il vous suffit de le packager en termes d'extension. Son déploiement sera alors automatisé et adapté aux postes destinataires vis à vis des chemins à utiliser. Le principe va donc être de créer une archive contenant ce modèle et un fichier XML indiquant le chemin où le déployer.
A titre d'exemple, nous allons déployer les modèles lauréats du concours organisé à l'automne 2006 par le projet documentation d'OpenOffice.org [2-1].
Une extension contenant des modèles doit comporter les fichiers suivants :
- les modèles à déployer : Ici les 5 fichiers lauréats (2 modèles Writer, 2 modèles Calc et un modèle Impress) ;
Paths.xcu: où trouver les modèles dans l'archive ;META-INF/manifest.xmlcontenant la description des fichiers contenus dans l'extension.
Commençons par créer un nouveau répertoire de travail représentant la structure de notre fichier d'extension. Le fichier final .oxt sera créé par simple compression zip du contenu de ce répertoire. Nous allons stocker les modèles à déployer dans le dossier fichiers/. Nous les y copions donc.
Le fichier Paths.xcu va servir à indiquer, dans la hiérarchie XML des paramétrages, qu'il y a un nouveau répertoire source pour les modèles de documents.
<?xml version='1.0' encoding='UTF-8'?>
<oor:component-data oor:package="org.openoffice.Office" oor:name="Paths"
xmlns:install="http://openoffice.org/2004/installation" xmlns:oor="http://openoffice.org/2001/registry"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<node oor:name="Paths">
<node oor:name="Template" oor:op="fuse">
<node oor:name="InternalPaths">
<node oor:name="%origin%/fichiers" oor:op="fuse"/>
</node>
</node>
</node>
</oor:component-data>
Tout d'abord notons que tous les fichiers de configuration d'OpenOffice.org sont au format UTF-8. Cet encodage est obligatoire et doit être respecté.
Le fichier .xcu déclare donc que le nœud org.openoffice.Office.Paths doit être modifié. Les informations du chemin (Paths) des modèles (Template) doivent être modifiées en fusionnant (fuse) dans le nœud InternalPaths le chemin %origin%/fichiers à la liste actuelle.
%origin% représente donc le répertoire dans lequel sera déployée notre extension et qui sera résolu lors de l'installation.
Enfin, comme pour toute extension, il nous faut définir le fichier manifest.xml indiquant les fichiers contenus ainsi que leurs types :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
<manifest:file-entry
 manifest:media-type="application/vnd.sun.star.configuration-data"
 manifest:full-path ="Paths.xcu"/>
<manifest:file-entry
 manifest:media-type="vnd.oasis.opendocument.spreadsheet-template"
 manifest:full-path ="fichiers/Calendar_pg.ots"/>
<manifest:file-entry
 manifest:media-type="vnd.oasis.opendocument.spreadsheet-template"
 manifest:full-path ="fichiers/MapCharts.ots"/>
<manifest:file-entry
 manifest:media-type="vnd.oasis.opendocument.text-template"
 manifest:full-path ="fichiers/origamiletter.ott"/>
<manifest:file-entry
 manifest:media-type="vnd.oasis.opendocument.text-template"
 manifest:full-path ="fichiers/Thesis.ott"/>
<manifest:file-entry
 manifest:media-type="vnd.oasis.opendocument.presentation-template"
 manifest:full-path ="fichiers/Beach.otp"/>
</manifest:manifest>
Chaque entrée de ce fichier représente un fichier à déployer de l'extension, que ce soit un paramétrage ou un des fichiers de modèle. Chaque entrée doit fournir deux informations :
- Le type de fichier dont il est question, le
media-type. Il s'agit du type mime du fichier en question comme nous pouvons le voir sur les fichiers listés ici. - Le chemin relatif à l'intérieur du répertoire de travail, notre extension. Ici tous les modèles sont bien déclarés comme étant à l'intérieur du dossier fichiers.
Notre extension est désormais prête et il nous suffit de zipper le contenu de notre répertoire (attention de ne pas zipper le répertoire lui-même, le fichier paths.xcu devant être à la racine du fichier zip). Enfin, il nous suffit de renommer ce fichier en modeles.oxt pour être prêts à le déployer.
Pour déployer cette extension, nous pouvons soit utiliser le menu Outils -> Gestionnaire de packages et ajouter notre fichier (Fig. 5), soit passer en ligne de commande :
$ /opt/openoffice.org2.0/program/unopkg add --verbose modeles.oxt Copie du package : modeles.oxt Activation du package : modeles.oxt Activation du package : Paths.xcu unopkg done.

 Fig. 5 : Le gestionnaire de packages d'OpenOffice.org
Nos modèles sont désormais déployés et vous pouvez les utiliser à votre gré en allant dans le menu Fichier -> Nouveau -> Modèles et Documents -> Mes modèles.
Votre extension est utilisable par toute personne à qui vous la transmettrez et qui souhaitera la déployer
[2-2]. Par souci de concision, nous ne sommes pas entré dans tous les détails possibles de configuration comme le déploiement généralisé à tout un poste (mode share) ou la définition plus fine des modèles (catégories, multilinguisme) ; vous pourrez trouver de plus amples informations sur le site du projet Extensions [2-3] et dans la description des fichiers de configuration d'OpenOffice.org [2-4][2-5].
 Références partie 2
[2-1] http://documentation.openoffice.org/contests/template_clipart_2006/winners.html
[2-2] http://fr.openoffice.org/Documentation/Outils/TemplatePackage.oxt
[2-3] http://wiki.services.openoffice.org/wiki/Non-code_extensions
[2-4] http://util.openoffice.org/common/configuration/oor-document-format.html
[2-5] http://util.openoffice.org/common/configuration/oor-registry.html
Un basic pour OpenOffice.org
OpenOffice.org est fourni avec son propre langage de scripts et macros, OOoBasic, ainsi que tout l'environnement interne pour manipuler et gérer ces réalisations.
Nous allons dans cette partie survoler les principales caractéristiques de ce langage ainsi que les outils mis à disposition pour la manipulation de ces macros. Puis, nous illustrerons leur utilisation dans le cadre du déploiement d'une extension.
Principes de base
Nous excluons tout d'abord de notre champ l'enregistreur de macros. S'il peut, dans certains cas très particuliers, s'avérer un allié précieux dans la conception de macros, il ne peut faire que ce pour quoi il a été conçu : reproduire une séquence de commandes de l'utilisateur. Ce n'est en aucun cas un outil d'apprentissage de l'API.
Les macros sont organisées en termes de bibliothèques et modules. Elles sont accessibles par le menu Outils -> Macros -> Gérer les macros -> OpenOffice.org Basic.
Les deux catégories visualisées dépendent de l'endroit où les macros sont stockées :
Mes Macros : les bibliothèques sont stockées dans le répertoire ~/.openoffice.org2/user/basic de l'utilisateur et en sont accessibles que de celui-ci. Les extensions déployées sont également visibles à ce niveau et sont stockées dans ~/.openoffice.org2/user/uno_packages.
- Macros OpenOffice.org : ce sont les macros accessibles par tous les utilisateurs du poste. Elles sont stockées dans
/opt/openoffice.org2/share/basicou, si déployées par une extension, dans/opt/openoffice.org2/share/uno_packages. OpenOffice.org est fourni avec un bon nombre de macros utiles et nous vous conseillons de les étudier, autant pour leur intérêt pédagogique que fonctionnel.
Chaque bibliothèque peut contenir plusieurs modules (et chaque module, plusieurs routines), et il est conseillé de cloisonner ainsi la création de vos extensions (ou macros).
Nous ne pourrons pas entrer dans le détail des macros sous OpenOffice.org dans cet article, tellement le sujet est vaste (et fait l'objet de publications de livres). Nous nous contenterons de présenter quelques-unes des adaptations apportées par rapport à l'API et les simplifications.
- Des fonctions toutes faites permettent d'accéder aux objets les plus courants. Là où plusieurs lignes de l'API seraient nécessaires,
ThisComponentdonne accès au document courant etStarDesktopau conteneur de celui-ci. Ce sont les deux objets principaux desquels beaucoup d'autres découlent (Il en existe d'autres, mais leur utilisation est moindre). Par exemple, le code suivant va remplacer tout le texte du document courant par un message de bienvenue :
 ThisComponent.string = "Bonjour tout le monde"
- Toutes les méthodes de l'API en
get...etset...(commegetString()ousetString()par exemple) sont transformées en propriétés en lecture/écriture. Les vraies méthodes de l'API restent disponibles. On retrouve cette particularité en pyUNO également. - Tous les objets exposant la méthode
getByIndex()sont accessibles par tableau. Ainsi,ThisComponent.Sheets(0)donne accès à la première feuille d'un classeur au même titre queThisComponent.getSheets().getByIndex(0)
Les spécificités les plus courantes d’UNO sont également simplifiées :CreateUNOService,CreateUNOStruct,CreateUNODialog, ... permettent l'instanciation d'objets qu'il serait lourd de créer pour une macro. De même, la reconnaissance des types et constantes nommées facilite la création des arguments à passer à l'API comme nous le verrons ci-après :
dim argument(0 to 2) as new com.sun.star.beans.PropertyValue
De nombreuses simplifications sont donc disponibles. Néanmoins, comme nous pouvons le constater, les éléments d'API utilisés par OOoBasic sont différents de ceux de VBA. Seuls les éléments structurels de langage, (les boucles, conditions...), la grammaire du basic restent les mêmes.
Environnement de développement intégré
L'environnement de développement intégré offre quelques fonctionnalités destinées à faciliter la vie de l'utilisateur. Le gestionnaire de bibliothèques et modules permet de créer, déplacer, exporter les macros (Fig. 6).

Fig. 6Â : Le gestionnaire de macros
L'EDI offre également la coloration syntaxique du code (Fig. 7). Celle-ci permet de détecter les fautes de frappes sur les mots clés ou les oublis de guillemets par exemple. Pour les personnes que les couleurs gêneraient (dominantes vertes et rouges, ce n'est pas des plus pertinents), il est possible de les modifier par l'intermédiaire du menu Outils -> options -> OpenOffice.org -> Apparence -> Mise en évidence de la syntaxe du basic.
Un outil indispensable que fournit l'EDI est le debugger pas à pas. Il permet d'explorer chaque ligne de la macro en interrompant l'exécution à un point d'arrêt mis en marge et symbolisé par un point rouge.

Fig. 7 : Environnement de Développement Intégré
En cours d'exécution pas à pas (touche [F8]), la ligne courante est pointée par une flèche jaune. La touche [F5] permet quant à elle de sauter jusqu'au point d'arrêt suivant. Exécuter une macro pas à pas est un moyen très efficace pour résoudre certains comportements erratiques de macros un peu complexes.
Nous pouvons également constater la présence d'une pile des appels et d'une zone de visualisation des valeurs des variables observées.
Enfin, les différents modules, ici DicOOo et FontOOo sont accessibles par les onglets en bas de la fenêtre.
Un point souvent reproché à l'EDI, avec raison, est de ne pas fournir d'auto-complétion. Rappelons que XRay amène une réponse partielle à ce problème. L'implémentation de cette fonctionnalité n'est pas à l'ordre du jour.

Fig. 8 : La boîte à outils des contrôles
Création d'interface graphique
OpenOffice.org fournit également un environnement de développement d'interfaces graphiques. Tous les composants classiques (enfin, presque tous) sont disponibles : boutons, cases à cocher, bouton radio, listes déroulantes ou non, à choix simple ou multiple... (Fig. 8).
Tous ces éléments permettent de créer des interfaces riches à vos macros (Fig. 9).
A chaque contrôle est associé une liste d'événements auxquels il suffit d'associer une macro pour que celle-ci soit déclenchée. Bien entendu, une liste des propriétés des contrôles est également disponible (Fig. 10).
A titre d'exemple, nous fournissons l'appel de la fenêtre de DicOOo et nous rappelons au passage que DicOOo est une macro que tout un chacun peut ouvrir et étudier :

Fig. 9Â : Conception d'un dialogue

Fig. 10 : Propriétés et événements d'un contrôle
DialogLibraries.LoadLibrary("InstallDicOO")
Feuille=DialogLibraries.InstallDicOO.WizInstall
oDlg=CreateUnoDialog(Feuille)
'ici certains parametrages si necessaire
resultat = oDlg.execute()
Nous commençons par charger la bibliothèque graphique contenant notre dialogue. L'objet DialogLibraries est une facilité d’OOoBasic exposant l'ensemble des bibliothèques accessibles. Nous chargeons donc (LoadLibrary) notre bibliothèque InstallDicOO. Nous récupérons alors dans la variable Feuille le dialogue lui-même (WizInstall) se situant dans notre bibliothèque.
L'objet dialogue est alors créé (CreateUnoDialog) et accessible par l'objet oDlg. Certains paramétrages initiaux comme la taille ou le remplissage de listes peuvent alors intervenir (un contrôle est accessible par monControle = oDlg.getControl(nomDuControle).
Enfin, la boîte de dialogue est réellement affichée avec l'appel de la méthode execute(). Cet appel est bloquant et le retour resultat donne l'état de sortie (bouton OK ou Annuler).
Les dialogues d'OpenOffice.org sont très faciles à utiliser et même appelables depuis d'autres langages qu’OOoBasic. Ils fournissent tous beaucoup d'objets et de fonctionnalités dont la propriété step de la boîte de dialogue elle-même qui est une bénédiction pour quiconque veut créer un assistant multi-page.
Exemple : exporter un document
A titre d'exemple, nous allons créer un composant minimaliste permettant d'exporter un document que nous donnerons en argument en PDF.
L'idée est de nous créer notre propre ligne de commande d'export en appelant cette macro. Il nous faut donc une macro qui accepte en argument le chemin du fichier. Celle ci va alors charger le document et l'exporter en PDF par un simple appel d'API.
Nous commençons par créer une nouvelle bibliothèque (par le bouton Gérer du gestionnaire de macros) que nous appelons " exporter ", puis ajoutons un module dont nous laisserons le nom par défaut Module1. Ces éléments nous serviront pour l'appel en ligne de commande.
Le code principal de notre outil peut s'écrire comme suit :
sub Export2PDF(filename as string)
if not fileExists(filename) then
exit sub
endif
dim argsLoad(0) as new com.sun.star.beans.PropertyValue
argsLoad(0).Name = "Hidden"
argsLoad(0).Value = True
url = convertToURL(filename)
theDoc = StarDesktop.loadComponentFromURL(url,"_blank",0,argsLoad())
filtername = ""
if theDoc.supportsService("com.sun.star.text.TextDocument") then
filtername = "writer_pdf_Export"
endif
if theDoc.supportsService("com.sun.star.sheet.SpreadsheetDocument") then
filtername = "calc_pdf_Export"
endif
if theDoc.supportsService("com.sun.star.presentation.PresentationDocument") then
filtername = "impress_pdf_Export"
endif
if filtername <> "" then
dim argsSave(0) as new com.sun.star.beans.
PropertyValue
argsSave(0).Name = "FilterName"
argsSave(0).Value = filtername
urlDestination = convertToURL(filename & .pdf")
theDoc.storeToURL(urlDestination,argsSave())
theDoc.close(True)
endif
end sub
Nous commençons donc par contrôler que le fichier fourni en argument existe bien, en utilisant la fonction OOoBasic FileExists. Si ce n'est pas le cas (not), nous sortons directement de la routine avec un exit sub.
Si le fichier existe, nous préparons le terrain au chargement. Afin de travailler en arrière-plan, nous allons définir les paramètres de chargement.
Ces arguments sont regroupés dans un tableau de PropertyValues. Chaque type est défini par un couple Name, Value. Dans notre cas, nous définissons que la propriété Hidden est vraie (True).
L'API d'OpenOffice.org travaille le plus souvent avec des URL. Nous utilisons donc la fonction très utile convertToURL d’OOoBasic (notez l'existence de sa complémentaire, converFromURL) pour transformer notre chemin local en notation URL. Nous chargeons enfin le fichier en appelant la méthode loadComponentFromURL du desktop.
Une fois le fichier chargé, nous cherchons de quel type il est afin de pouvoir déterminer le bon filtre d'export à appliquer. En effet, les filtres dépendant du type de document et leurs noms peuvent être trouvés dans les fichiers de paramétrage xcu d’OpenOffice.org (dans /opt/openoffice.org2.0/share/registry/modules/org/openoffice/TypeDetection/Filter/*.xcu).
Pour ce faire, nous testons que l'objet manipulé est bien par exemple un document Calc, puisqu'il implémente bien le service com.sun.star.sheet.SpreadsheetDocument en utilisant la méthode supportsService() du document ouvert. Si c'est le cas, nous définissons le nom de notre filtre, ici calc_pdf_Export.
Nous exportons ensuite notre document en utilisant le filtre déterminé. Nous utilisons la méthode storeToURL (ne pas confondre avec storeAsURL qui ne marche que pour les filtres dont le résultat peut être ouvert par OpenOffice.org comme les filtres MsOffice, mais ce qui n'est pas le cas de PDF) et passons la propriété FilterName par une PropertyValue. Nous choisissons de simplement ajouter une extension .pdf au nom de fichier fourni en entrée comme nom et emplacement de sauvegarde.
Enfin, une fois exporté, nous fermons notre document par la méthode close().
Nous pouvons tester succinctement notre outil en écrivant une petit macro d'appel comme suit (les chemins étant, bien entendu, à adapter) :
sub TestExport
call Export2PDF("/home/lgodard/test.odt")
end sub
Après exécution, nous pouvons constater que le fichier test.odt.pdf a bien été créé.
Utilisation en ligne de commande
Notre macro étant prête, nous pouvons la tester en ligne de commande :
$ /opt/openoffice.org2.0/program/soffice "macro:///exporter.Module1.Export2PDF("/home/lgodard/test.odt")"
Nous vous conseillons, afin d'éviter des lignes trop fastidieuses, de créer un petit script ooo2pdf comme :
 #!/bin/bash /opt/openoffice.org2.0/program/soffice -headless "macro:///exporter.Module1.Export2PDF($1)"
Le commutateur -headless est une sécurité supplémentaire permettant d'ouvrir OpenOffice.org en mode automatique, c'est-à -dire répondant aux éventuelles boîtes de dialogues avec la réponse par défaut. Afin de gérer les chemins relatifs correctement et permettre un export multiple de fichiers, nous utiliserons quant à nous un petit script Python livré dans
le package, que vous pourrez également utiliser.
Ainsi, notre outil de ligne de commande est prêt :
$ ooo2pdf /home/lgodard/test.odt
 Déploiement en extensions
Notre macro étant utile (est-ce vraiment certain, ça ?), nous voulons la diffuser à notre entourage. Nous allons la packager sous la forme d'une extension (bien entendu, notre script final ooo2pdf, lui, sera à transmettre à part). Nous utilisons pour cela le BasicAddonBuilder mentionné auparavant et obtenons une archive .oxt. Celle ci est alors installable par l'intermédiaire du menu Outils -> Gestionnaire des Extensions.
Nous vous invitons à décompresser cette archive pour l'analyser en détail. Remarquez la présence d'un fichier Addons.xcu, ainsi que manifest.xml. De même, nous retrouvons les fichiers de déclaration des macros, le nom du répertoire étant le nom de la bibliothèque, chaque module étant un fichier.
Cette macro n'est qu'une première étape et nous vous invitons à la consulter. Le code que nous avons exposé ici est disponible sur le site de la communauté [3-1].
Elle pourrait être adaptée en ajoutant d'autres filtres d'export, le chemin de destination comme argument ou en fermant complètement OpenOffice.org (si après fermeture de notre fichier, il n'y a plus d'autres composants ouverts, c'est-à -dire que la collection StarDesktop.Components est vide). Ce ne sont, bien entendu, que quelques propositions...
Référence partie 3
 [3-1] http://fr.openoffice.org/Documentation/Outils/ooo2pdf.zip
Démarrer automatiquement une présentation
Lancer une présentation en ligne de commande à l'aide de l'option -show de l'exécutable soffice permet de démarrer automatiquement dès le chargement du fichier :
soffice -show maPresentation.odp
Néanmoins, peu d'utilisateurs la connaissent et ce mode de démarrage automatique est souvent demandé. Nous allons donc simuler cette fonctionnalité dans un code Python et la déployer sous forme d'extension. Ceci nous permettra d'illustrer la simplicité et la puissance de l'approche Python pour OOo.
Le contexte
L'idée est d'insérer une nouvelle métadonnée dans le document Impress par l'intermédiaire d'un champ utilisateur, et au chargement de tout document Impress, de détecter que cette métadonnée est présente et démarrer automatiquement la présentation le cas échéant.
Ainsi, le rédacteur n'aura qu'à indiquer cette métadonnée lors de la conception de sa présentation dans le champ Info 1 du menu Fichier -> Propriétés -> Utilisateur et l'utilisateur, sous réserve d'avoir déployé l'extension, verra le fichier démarrer automatiquement au lancement.
Structure de notre composant
Nous allons créer un Job [4-1] qui visiblement est fait spécialement pour être déclenché suivant certaines actions. Nous cherchons en effet à déclencher l'exécution de notre code à l'apparition de l'événement OnLoad. Nous allons donc créer notre classe (dans le monde OpenOffice.org, c'est un service) en dérivant du service com.sun.star.task.Job et en fournissant la méthode execute(). Nous associerons ensuite notre Job à l'événement par le simple paramétrage d'un fichier job.xcu qui sera joint à l'extension et déployé. Il est à noter que pyUNO permet de créer des services à part entière, sans être obligé de dériver d'un service existant. Cette fonctionnalité nécessite une étape de création d'un fichier IDL et sa compilation ce qui nous aurait amené un peu loin pour cet article.
Développement des fonctionnalités
Notre service UNO est un classe Python dérivant du service unohelper.Base (commun à tout service) et, dans notre cas, de l'interface XJob du service com.sun.star.task.Job. Pour qu'il soit enregistrable par le gestionnaire de package, il faut qu'il fournisse certaines informations.
implementation_name = "org.openoffice.extensions.indesko.ImpressRunner"
implementation_services = ("com.sun.star.task.Job",)
class ImpressRunner(unohelper.Base, Xjob):
....
g_TypeTable = {}
# pythonloader looks for a static g_ImplementationHelper variable
g_ImplementationHelper = unohelper.ImplementationHelper ()
# add the FormatFactory class to the implementation container,
# which the loader uses to register/instantiate the component.
g_ImplementationHelper.addImplementation (ImpressRunner, implementation_name, implementation_services)
La variable implementation_name contient le nom interne que nous donnons à notre extension. C'est sous ce nom, qui doit être unique, que nous la référencerons par la suite dans la configuration du Job et d’OOo. La liste implementation_services énumère les services que nous implémentons explicitement. Dans notre cas, nous n'avons que notre com.sun.star.task.Job.
OpenOffice.org et pyUNO fournissent un bon nombre d'outils facilitant la déclaration des services. Ainsi, la méthode addImplementation de g_ImplementationHelper ne prend que 3 arguments pour déclarer un service : le nom de la classe (ImpressRunner), le nom d'implémentation (implementation_name) et la liste des services (implementation_services).
Une fois ces formalités structurelles remplies, nous pouvons nous attacher à notre fonctionnalité Ã
proprement parler et coder la classe elle-même :
class ImpressRunner(unohelper.Base, XJob):
   def __init__ (self, ctx):
       self.ctx = ctx
   def execute(self, args):
       tools = OOoTools(self.ctx)
       desktop = tools.getDesktop()
       # get the current document
       document = self.desktop.getCurrentComponent()
       if document.supportsService("com.sun.star.presentation.PresentationDocument"):
           # the document is an impress document
           if document.DocumentInfo.getUserFieldValue(0) == "autostart":
               # the metadata is there !!
               # launch the presentation
               document.Presentation.start()
       return
A l'initialisation, notre classe reçoit le contexte UNO (ctx). Sans entrer dans les détails, retenons que ce contexte est la base de tous les appels ultérieurs concernant UNO. Nous le stockons donc pour un usage ultérieur.
Comme nous le verrons plus tard, la méthode execute() va être appelée suivant le contexte du Job que nous définirons. Nous commençons par instancier une classe OOoTools à laquelle nous passons le contexte ctx. Cette classe implémente des appels types et des raccourcis pour obtenir les objets usuels d'une extension. Nous nous en servons dans notre cas pour simplement récupérer l'objet desktop, qui est le conteneur de tous les autres composants OOo. Le lecteur curieux pourra aller l'analyser dans le code de l'extension.
Une fois notre desktop obtenu, nous accédons au document actif en appelant la méthode getCurrentComponent().
A ce moment, nous devons tester si nous avons bien un document Impress en cours d'ouverture. Nous le faisons en appelant la méthode supportsService de notre document sur le service de base d'un document Impress (com.sun.star.presentation.PresentationDocument).
Si nous sommes dans ce cas, alors, nous récupérons la première valeur (getUserFieldValue(0)) des variables utilisateurs (DocumentInfo). Nous avons donc fait au plus simple et sommes conscients qu'ici un bon nombre d'améliorations sont possibles pour rendre le processus plus robuste.
Si l'auteur du document a pris soin de remplir cette case du menu Fichier -> Propriétés -> Utilisateur -> Info1 par autostart, alors nous pouvons démarrer notre slideshow. Il nous suffit pour cela de lancer la méthode start() de l'objet Presentation de notre document.
Packaging et déploiement
Notre extension va être déployée comme un Job et nous devons en fournir le fichier job.xcu de paramétrage dans notre extension .oxt :
<node oor:name="Jobs">
<node oor:name="ImpressRunnerJob" oor:op="replace">
<prop oor:name="Service">
<value>org.openoffice.extensions.indesko.ImpressRunner</value>
</prop>
</node>
</node>
<node oor:name="Events">
<node oor:name="OnLoad" oor:op="replace">
<node oor:name="JobList">
<node oor:name="ImpressRunnerJob" oor:op="replace"/>
</node>
</node>
</node>
La déclaration se fait en deux temps. Tout d'abord, nous définissons un alias pour notre job ImpressRunnerJob et indiquons le nom du service concerné (org.openoffice.extensions.indesko.ImpressRunner).
Il s'agit, comme nous pouvons le remarquer, du nom d'implémentation (implemantation_name) que nous avons défini dans notre code Python. Puis, nous associons, à l'événement OnLoad, cet alias ImpressRunnerJob en le déclarant dans la liste des jobs.
Pour être complet, le fichier manifest.xml doit être défini et énumérer les deux fichiers de notre extension :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
<manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data"
manifest:full-path ="job.xcu"/>
<manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python"
manifest:full-path ="ImpressRunner.py"/>
</manifest:manifest>
Une fois compressée et renommée en .oxt, notre extension est déployable par le menu Outils -> Gestionnaire des Extensions. Le Job sera lancé à chaque ouverture de document et lancera une
présentation si les conditions sont remplies.
Cette extension n'est qu'une première version et de nombreuses améliorations sont possibles comme par exemple proposer un assistant au créateur de la présentation pour remplir la métadonnée ou un message à l'utilisateur demandant confirmation du lancement automatique de la présentation, un peu comme
les macros...
Nous avons donc pu, au travers de cet exemple, illustrer la puissance de pyUNO qui permet d'accéder à toute la richesse de l'API comme la définition de services tout en conservant une réelle souplesse et facilité d'utilisation [4-2]. Le code que nous avons exposé ici est disponible sur le site de la communauté [4-3] et nous vous invitons à le consulter.
Références partie 4
[4-1] http://api.openoffice.org/docs/DevelopersGuide/Components/Components.xhtml#1_7_2_Jobs
[4-2] http://wiki.services.openoffice.org/wiki/Extensions_development_python
[4-3] http://fr.openoffice.org/Documentation/Outils/ImpressRunner.oxt
Conclusion
Notre tour de piste s'achève et le vrai travail ne fait que commencer pour vous. Nous vous invitons à décortiquer le code complet des extensions que nous venons de présenter, ainsi que les nombreux exemples disponibles sur le site francophone
d'OpenOffice.org et le projet Extensions. Nous avons présenté quelques exemples en OOoBasic et pyUNO. N'hésitez pas à vous plonger dans d'autres langages supportés si vous préférez.
Les domaines et possibilités d'action sur OpenOffice.org sont pratiquement sans limites, la documentation abondante et la communauté prêtes à vous accompagner dans la découverte touffue de l'API. La seule limite restera votre imagination et votre volonté de dompter la bête. N'oubliez pas, vous commandez et OpenOffice.org est à vos ordres
Retrouvez cet article dans : Linux Pratique Hors série 9

