FR/Documentation/Fichiers IDL et C++

From Apache OpenOffice Wiki
Jump to: navigation, search

(Cette introduction est faite avec l'aide de :http://udk.openoffice.org/cpp/man/component_tutorial.html ) Vous devez commencer à être habitué si vous êtes parvenus jusqu'ici en lisant tous les chapitres précédents à la terminologie service/interface qui prévaut pour la programmation UNO. Cette terminologie n'étant pas universelle, je me permet d'en rappeler quelques éléments.


Services et Interfaces

Introduction

Voir http://api.openoffice.org/basic/man/tutorial/tutorial.pdf (chapitre 2) Dans API OpenOffice, un "service" est un concept abstrait qui fournit certaines interfaces et propriétés/attributs. Comme le souligne le Guide du développeur : “les propriétés sont des données dans un objet qui sont triées par nom sur une interface générique pour un accès de la propriété”. Il serait mieux de distinguer attribut et propriété. Mais nous ne le faisons pas pour le moment.

Comme on peut le voir en Figure 8, un service possède plusieurs propriétés et une interface correspond à plusieurs méthodes qui trouvent un moyen de changer les propriétés. Prenons une voiture pour illustrer ces concepts. La voiture fournit deux interfaces concrètes : XAccelerationControl et XDrivingDirection. Deux méthodes d'exportation d'interface, la première pour accélérer et ralentir, la seconde pour faire tourner la voiture à droite ou à gauche (voir Figure 9). Pourquoi deux (ou plusieurs) interfaces ? C'est seulement pour réunir des fonctionnalités caractéristiques. Pensez à une vraie voiture où ces interfaces sont séparées (le volant d'un côté et les pédales de l'autre) et ce qui se passerait si seulement les pieds dirigeaient ces deux interfaces ?

Dans API OpenOffice, les modules groupent des services, des interfaces, des types, des énumérations et autres structures données (voir Figure 10). C'est impossible de comprendre un tel dessin sans se poser un certain nombre de questions et, en particulier, comment est-ce que nous voyons ce module quand il est utilisé dans un programme ?


Pour répondre à cette question, nous choisissons OOoBasic :

'Listing 1
REM  *****  BASIC  *****
'en premier, créez le service
oSimpleComponent = CreateUnoService( "my_module.MyService1" )
'call the unique method
oSimpleComponent.methodOne()
....
'first create the service
oSimpleComponent2 = CreateUnoService( "my_module.MyService2" )
'call one of both method
oSimpleComponent.methodTwo()
...

Les règles de Danny Brewer Les services sont similaires aux objets en java.

  1. Un service peut hériter de rien ou d'un autre service. (auquel on peut appliquer récursivement cette règle)
  2. Un service peut inclure zéro ou plusieurs services. (auxquels on peut appliquer récursivement ces règles)
  3. Un service peut exporter des interfaces.
  4. Un service peut avoir des propriétés.
  5. Une interface peut hériter d'aucune ou d'une autre interface (à laquelle on peut appliquer récursivement cette règle).
  6. Une interface peut inclure zéro ou plusieurs interfaces (auxquelles on peut appliquer récursivement ces règles).
  7. Une interface peut exécuter des méthodes.
  8. Une interface est toujours nommées par un nom commençant par un X.

De ces règles vous pouvez déduire que les méthodes sont TOUJOURS trouvées dans des interfaces, et les propriétés sont TOUJOURS trouvées dans des services.

Specification IDL

Les interfaces utilisent un spécial langage de définition de l'Interface (IDL). UNO utilise UNO-IDL comme le langage de définition de l'interface. Le Langage de définition de l'Interface (IDL) est un langage descriptif (et non un langage de programmation) décrivant l'existence des interfaces qui seront rendues effectives par les objets. Avec IDL, vous définissez le nom de l'interface, les noms de chacun des attributs et méthodes. Une fois que vous avez créé les fichiers IDL, vous pouvez utiliser un compilateur IDL pour générer les fichiers d'en-tête dans le langage de programmation C++. La façon de spécifier des modules simples avec IDL est si claire que nous choisissons de commencer en premier seulement des exemples.

Specifier une interface

Nous prenons comme exemple, l'interface XdrivingDirection de la Figure 9.

//Listing 2 Interface imaginaire XDrivingDirection
// IDL
interface XDrivingDirection
	{
		void turnLeft();
		void turnRight();
	};

Spécifier un service

L'exemple de la Figure 9 est toujours utilisé, voici la spécification IDL correspondante :

//Listing 3 Spécification d'un service « car »
// IDL
interface XDrivingDirection
	{
		void turnLeft();
		void turnRight();
	};
interface XaccelerationControl
	{
		void speedUp();
		void slowDown();
	};
service car
	{
		// exported interfaces:
		interface XdrivingDirection;
		interface XaccelerationControl;
		[attribute] float speed; 
		[attribute] float angle;
	};

Nous voyons apparaître un type float et nous donnons d'autres types IDL plus loin.

Spécifier un module

Les modules sont un moyen de regrouper des services. Cette notion correspond plutôt à une bibliothèque et n'a que peu d'importance pour le programmeur C++ (sauf s'il désire réaliser des extensions composants ou addin par exemple). Nous donnons quand même ici la spécification IDL correspondant à un module :

//Listing 4 Spécification IDL du module my_module
// IDL
module my_module
	{
	interface Xsomething
		{
			void methodone();
		};
	service my_service1
		{
			// exported interfaces:
			interface Xsomething;
		};
	interface XsomethingElse
		{
			void methodTwo();
			void methodThree();
		};
	service my_service2
		{
			// exported interfaces:
			interface XsomethingElse;
		};
};

Plus loin avec IDL

Les types IDL sont décrits dans le tableau ci-dessous :

char

16-bit unicode character type

boolean

boolean type; true and false

byte

8-bit ordinal integer type

short

signed 16-bit ordinal integer type

unsigned short

unsigned 16-bit ordinal integer type

long

signed 32-bit ordinal integer type

unsigned long

unsigned 32-bit integer type

hyper

signed 64-bit ordinal integer type

unsigned hyper

unsigned 64-bit ordinal integer type

float

processor dependent float

double

processor dependent double

string

string of 16-bit unicode characters

any

universal type, takes every fundamental or compound UNO type, similar to Variant in other environments or Object in Java

void

Indicates that a method does not provide a return value

Les méthodes peuvent avoir des arguments. Chaque argument dans la liste des arguments doit commencer avec un des drapeaux de direction [in], [out] ou [inout] avant qu'un type connu et identificateur pour l'argument soit donné. Nous donnons un exemple que nous rencontrerons souvent dans ce document , un compteur :

//Listing 5 Module IDL décrivant un compteur
// IDL
module my_module
{
  interface XSomething 
  {
	long getCount();
	void setCount( [in] long nCount );
	long increment();
	long decrement();
  };
  service MyService
  {
    interface XSomething;
  };
};

Une interface peut être dérivée à partir d'une interface de base. Une interface dérivée peut déclarer ses propres attributs et ses méthodes. Les attributs et méthodes hérités ne peuvent pas être redéfinies dans l'interface dérivée. Un exemple d'héritage de l'interface :

//Listing 6 Héritage dog de annimal
//IDL
interface animal {
	attribute long age;
};
interface dog : animal {
	attribute short leg;
}

L'héritage multiple est aussi possible

interface dog : animal, friend {

L'héritage dans le service est présenté dans le prochain chapitre. Dans la terminologie objet OOo, il y a une différence entre attribut et propriété, différence qui se manifeste par leurs façons respectives d'y accéder. On accède aux propriétés avec setPropertyValue(PropertyName,Any) alors qu'on accède aux attributs avec la méthode set/get(AttributeName). Nous avons déjà rencontré la manipulation des propriétés lors de l'examen des formes.

Collecter de l'information UNO avec les fichiers IDL

Il y a plusieurs possibilités pour trouver de l'information sur UNO. La première est d'utiliser OOoBasic et l'outil XRay de Bernard Marcelly (disponible ici http://www.ooomacros.org/dev.php#101416). Point négatif : OOoBasic ne montre pas les propriétés et les méthodes exactes, quelques unes sont rajoutées parce qu'elles sont disponibles en OooBasic. L'autre possibilité est d'aller à l'adresse internet suivante : http://api.openoffice.org/docs/common/ref/index-files/index-1.html qui fournit la même information mais probablement de manière plus lisible. Nous avons fourni des exemples dans les chapitres antérieurs (en particulier chapitre 8...) et normalement le lecteur a des compétences sur le sujet. Le point de vue de Danny Brewer Néanmoins, il est important de comprendre le concept d'un "service" dans les documents sur l'API. Un service est juste une façon de grouper...

  1. d'autres services encore
  2. des interfaces

La partie (1) “d'autres services encore”, signifie bien sûr, qu'il y a même plus d'interfaces disponibles au service original. Laissez moi vous montrer différents exemples.

SpreadsheetDocument est un service. SpreadsheetDocument hérite du service OfficeDocument.

Par conséquent, l'ensemble combiné d'interfaces de SpreadsheetDocument et OfficeDocument est accessible à un document de la Feuille de calcul (qui est bien sûr un SpreadsheetDocument).

Donc, bien que le composant chargé depuis l'URL retourne une interface, cette interface représente un service sous-jacent qui est un SpreadsheetDocument. En regardant les documents de l'API, vous pouvez dire quelles interfaces valides vous pouvez mettre en oeuvre. SpreadsheetDocument possède un service XSpreadsheetDocument. OfficeDocument possède un service XPrintable et XStorable. Comme SpreadsheetDocument est hérité de OfficeDocument, il est aussi valide de demander soit l'interface XPrintable soit l'interface XStorable à partir de ce service SpreadsheetDocument.

Maintenant, remplaçons dans le paragraphe précédent, les documents tableurs par les documents textes et tout le discours précédent est encore valide. Comment expliquer ce qu'est un service sous-jacent ?

Il n'y a pas de formules magique pour cela. En principe, c'est évident. Si vous démarrez un tableur, par exemple, alors vous avez le service SpreadsheetDocument.

De la même façon, si je crée un objet par son nom de service.....

' obtention d'un service en OOoBasic
oShape = oDoc.createUnoService( "com.sun.star.drawing.EllipseShape" )

alors je sais quel service c'est, parce que j'ai donné le nom du service dans l'instruction.

Oui, vous pouvez toujours dire quelles interfaces sont disponibles si vous savez le nom du service, et ce, seulement en regardant la documentation de l'API. Aucune hypothèse. Aucun besoin de XRay. C'est une science absolue. Les multiples interfaces valides sont les interfaces du service lui-même, et de tous les services qui seront hérités de ce service.

Dans certains cas, il est évident de savoir quels services vous avez.

Si vous appelez getCellRangeByName(), alors vous obtenez un service SheetCellRange. Si vous appelez getCellByPosition(), alors vous avez un service SheetCell. Beaucoup de choses identiques sont disponibles dans ces deux services SheetCell et SheetCellRange, mais ils sont de nature différents. Le service SheetCellRange représente un groupe rectangulaire de cellules tandis que le service SheetCell concerne une cellule unique. Il y a évidemment des choses que l'on peut faire avec une cellule unique mais pas avec un groupe de cellule.

Il y a aussi d'autres possibilités. Si vous obtenez un service com.sun.star.table.CellRange à partir d'une table sous OOoWriter ce sera différent que si vous l'obtenez depuis une feuille de calcul, puisque ce sera un com.sun.star.sheet.SheetCellRange. Le service SheetCellRange est une version étendue du service CellRange. Lequel des deux services est obtenu dépend donc si votre demande getCellRangeByName() est réalisée à partir d'une table ou à partir d'une feuille de calcul.

Parfois, spécialement pour l'application OooWriter, seul le guide du développeur est une aide précieuse, donnant des informations sur les services obtenus à partir d'autres services et des appels API. Mais il est toujours vrai que lorsque l'on connaît le service que l'on a, on peut en déduire directement, seulement à partir de la documentation de l'API toutes les interfaces qu'il est possible de demander. Pas d'essais inutiles, c'est une science exacte.

Un exemple concret

Les fichiers IDL sont disponibles avec dans le dossier <OpenOffice.org1.1_SDK>/idl/. Évidemment, le problème avec cette solution est que nous voyons uniquement l'API UNO du SDK installé, lequel peut être légèrement différent de notre Openoffice.org. Cependant, nous expliquerons cette possibilité après avoir mentionné juste une autre solution : l'exploration de la base de registres (voir chapitre 10) On veut maintenant montrer un exemple. On commence à partir d'un

com::sun::star::document::OfficeDocument et du nom du service, on en déduit sa position dans l'arborescence <OpenOffice.org1.1_SDK>/idl/com/sun/star/document/OfficeDocument.idl

Ce fichier est présenté ci-dessous, (sans les commentaires) :

//Listing 7
//IDL
service OfficeDocument
{
	interface com::sun::star::frame::XModel;
    interface com::sun::star::util::XModifiable;
	interface com::sun::star::frame::XStorable;
	interface com::sun::star::view::XPrintable;
    [optional] interface XEventBroadcaster;
	[optional] interface XEventsSupplier;
    [optional] interface XDocumentInfoSupplier;
    [optional] interface XViewDataSupplier;
    [optional] interface com::sun::star::view::XPrintJobBroadcaster;
	[property, optional] boolean AutomaticControlFocus;
	[property, optional] boolean ApplyFormDesignMode;
};

Si on examine maintenant le ::com::sun::star::text::TextDocument on trouve dans <OpenOffice.org1.1_SDK>/idl/com/sun/star/text/TextDocument.idl

//Listing 8
service TextDocument
{
	service com::sun::star::document::OfficeDocument;
	interface com::sun::star::text::XTextDocument;
	interface com::sun::star::util::XSearchable;
	interface com::sun::star::util::XRefreshable;
	....
};

Comme on peut voir, ce service TextDocument contient le service OfficeDocument.


Cette dépendance est en fait un héritage. La représentation complète UML de cet exemple peut être trouvée dans le guide de développeur : http://api.openoffice.org/docs/DevelopersGuide/FirstSteps/FirstSteps.htm

Il est grand temps maintenant d'aller plus loin dans notre exemple et de fournir du code avec commentaires. Pour cela nous allons prendre du code déjà abordé (voir the Corresponding Writer Code).

 
//Listing 9 Writer Example
//C++
    OUString sDocUrl;
    osl::FileBase::getFileURLFromSystemPath(
                 OUString::createFromAscii("/home/smoutou/Documents/demo.sxw"),sDocUrl);
 
    Reference< XComponent > xWriterComponent = 
                    rComponentLoader->loadComponentFromURL(
	    sDocUrl,
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
 
   Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);

xWriterComponent nous donne le service TextDocument et ainsi aussi le service OfficeDocument comme déjà expliqué. XTextDocument est une Interface du service TextDocument. Le fichier XTextDocument.idl nous montre la méthode getText mais nous ne savons pas quels sont les nouveaux services disponibles. Seulement deux moyens pour savoir cela : Internet XText interface nous donne la réponse : le service is com.sun.star.text.Text. L'autre manière est d'utiliser un outil de Reflection comme décrit plus tard dans this section.

//Listing 10 Writer Example (continuation)
//C++
    Reference< XText > xText = xTextDocument->getText();

On essaie d'obtenir l'interface XTextCursor

//Listing 11 Writer Example (continuation)
//C++
Reference< XTextCursor> xTextCursor = xText->createTextCursor();

Mais comment expliquer ce code ? Cherchant dans le fichier XText.idl nous montre seulement deux méthodes :

//Listing 12 XText Interface IDL file
// IDL
module com {  module sun {  module star {  module text {  
interface XText: com::sun::star::text::XSimpleText
{ 
	void insertTextContent( [in] com::sun::star::text::XTextRange xRange, 
			 [in] com::sun::star::text::XTextContent xContent, 
			 [in] boolean bAbsorb ) 
			raises( com::sun::star::lang::IllegalArgumentException ); 
	void removeTextContent( [in] com::sun::star::text::XTextContent xContent ) 
			raises( com::sun::star::container::NoSuchElementException ); 
 
}; 
}; }; }; };

Mais si vous regardez plus en détail dans ce fichier IDL, vous verez l'héritage de XSimpleText. Est-ce que la méthode createTextCursor est ici ? Oui, comme vous pouvez le voir.

 
//Listing 13 XSimpleText Interface IDL file
// IDL
module com {  module sun {  module star {  module text {  
interface XSimpleText: com::sun::star::text::XTextRange
{ 
	com::sun::star::text::XTextCursor createTextCursor(); 
	com::sun::star::text::XTextCursor createTextCursorByRange( [in] com::sun::star::text::XTextRange aTextPosition ); 
    [oneway] void insertString( [in] com::sun::star::text::XTextRange xRange, 
			 [in] string aString, 
			 [in] boolean bAbsorb ); 
 	void insertControlCharacter( [in] com::sun::star::text::XTextRange xRange, 
			 [in] short nControlCharacter, 
			 [in] boolean bAbsorb ) 
			raises( com::sun::star::lang::IllegalArgumentException ); 
 
};
}; }; }; };

Quels sont les services disponibles ici ? J'ai utilisé un outil de reflection qui me donne :

******** Services : 8
com.sun.star.text.TextSortable
com.sun.star.style.ParagraphPropertiesComplex
com.sun.star.style.ParagraphPropertiesAsian
com.sun.star.style.ParagraphProperties
com.sun.star.style.CharacterPropertiesComplex
com.sun.star.style.CharacterPropertiesAsian
com.sun.star.style.CharacterProperties
com.sun.star.text.TextCursor

Vous pouvez probablement trouver chacun d'entre eux via internet mais ce sera une tâche longue et fastidieuse : de bonnes raisons d'expliquer les services de reflexion plus loin dans ce chapitre.

Oui, vous devez parcourir de tels chemins pour trouver quoi faire en programmant. Heureusement il y a plus court en utilisant les exemples du SDK. Mais la plupart d'entre eux sont en Java, mais je dois avouer avoir trouvé beaucoup d'inspiration dans ces exemples même si je ne suis pas un programmeur Java.

IDL et C++

Ce problème est développé dans le guide du développeur ici.

Obtention d'une interface en C++

En C++, vous avez seulement des variables de type interface. Un des problèmes les plus souvent rencontrés met en oeuvre une interface. Ce problème se produit très rarement dans OooBasic mais très souvent dans C++/Java. On peut trouver un exemple dans le chapitre 2 et beaucoup d'autres dans le 3. Comme exemple, on suppose qu'on a obtenu un service com::sun::star::document::officeDocument. En général, c'est fait par quelque chose comme :

//Listing 14
//C++
Reference<com::sun::star::document::officeDocument> OfDoc = something_to_get_this_service();

ou

//Listing 15
//C++
using namespace com::sun::star::document;
....
Reference<officeDocument> OfDoc = something_to_get_this_service();

et nous voulons mettre en oeuvre l'interface XStorable pour sauver notre document. Trois étapes sont impliquées dans cette action :

1) Ajoutez la ligne de votre code pour la demande de l'interface

// C++
// query from com::sun::star::frame::XStorable interface
	Reference< XStorable > oToStore (OfDoc, UNO_QUERY);

2) Ajouter à l'aide d'une directive d'inclusion les fichiers hpp correspondants. Il faut ajouter aussi les espaces de nommage correspondants. L'inclusion est faite par :

//C++
	#include <com/sun/star/frame/XStorable.hpp>

et la gestion des espaces de nommage par :

//C++
	using namespace com::sun::star::frame;

3) Ajouter les types correspondants dans le makefile comme montré ci-dessous dans la ligne com.sun.star.frame.XStorable \ qui est ajoutée

# Listing 16 Makefile 
# makefile
# added com.sun.star.frame.XStorable
TYPES := \
	com.sun.star.uno.XNamingService \
	....
	com.sun.star.uno.XAggregation \
	com.sun.star.frame.XStorable \
	com.sun.star.lang.XMain \ 
    ...
    com.sun.star.container.XHierarchicalNameAccess

Apprendre à réaliser ces trois étapes est essentiel pour une programmation en C++ : il vous sera impossible de réaliser un programme sans demander à un moment donné une interface ou un service. Ce problème de demande d'interface a déjà été abordé aux chapitres 3 et 4. Un autre problème technique est la correspondance des types : vous avez un fichier IDL, comment sont compilés les types ? La prochaine section aborde le sujet et peut être évitée pour une première lecture : allez donc alors au chapitre 6.

Obtenir une Interface àl'aide de XMultiServiceFactory

On a déjà rencontré cela plusieurs fois, ainsi cela doit vous être familier. Mais, puisque nous n'avons pas discuté toutes les étapes en détail, je vais maintenant m'y consacrer et montrer comment cela fonctionne.

La section précédente n'aborde le problème de l'obtention d'interfaces lorsqu'elles sont directement disponibles parceque le service correspondant est disponible. Par exemple le code ci-dessous ne décrit qu'une flèche de la figure ci-dessous et ainsi obtenir une interface XModel à partir de l'interface XTextDocument est un simple appel UNO_QUERY (dernière ligne du listing).

//Listing 19 Simple UNO_QUERY call
// C++
OUString sDocUrl;
    osl::FileBase::getFileURLFromSystemPath(
                 OUString::createFromAscii("/home/smoutou/Documents/demo.sxw"),sDocUrl);
    Reference< XComponent > xWriterComponent = rComponentLoader->loadComponentFromURL(
	sDocUrl,
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
 
    Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
// Don't forget to include #include <com/sun/star/frame/XModel.hpp>
    Reference < XModel > xModel (xTextDocument,UNO_QUERY);
SimpleUNOQUERY.png

Mais comment pouvez-vous obtenir une interface si le service correspondant n'est pas directement disponible ?

Premier cas : une méthode de votre interface vous permet d'obtenir directement la nouvelle interface. C'était le cas du Listing 11 de ce chapitre. Dans ce cas le fichier hdl correpondant n'est pas requis et je n'ai pas trouvé de moyen simple pour trouver les nouveaux services disponibles sans outil de reflection !

Second cas : aucune méthode de votre interface peut vous aider. Il vous faut demander un service avant d'obtenir l'interface. Cela peut être fait en deux ou trois étapes. J'ai déjà utilisé ces deux stymes. Regardez dans le listing :

//Listing 20 Getting an Interface with XMultiServiceFacory
// C++
    Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
 
    Reference<XMultiServiceFactory> oDocMSF (xTextDocument,UNO_QUERY);
// Don't forget to add #include <com/sun/star/text/XTextTable.hpp>
    Reference <XTextTable> xTable (oDocMSF->createInstance(
			OUString::createFromAscii("com.sun.star.text.TextTable")),UNO_QUERY);

qui utilise le style "deux instructions. Avec le style "trois instructions", on obtient l'interface comme présenté ci-dessous :

//Listing 21 Inserting a Table in a OOoWriter Document
// C++
    Reference<XMultiServiceFactory> oDocMSF (xTextDocument,UNO_QUERY);
 
	Reference< XInterface > textTable = oDocMSF->createInstance(
	               OUString::createFromAscii("com.sun.star.text.TextTable") );
// Don't forget to add #include <com/sun/star/text/XTextTable.hpp>
	Reference< XTextTable > xTable(textTable, UNO_QUERY);

Notez que ces deux méthodes nécessitent une directive d'inclusion (et donc la construction) du fichier hpp correspondant (ici XtextTable.hpp) mais pas pour le service parcequ'on l'obtient par une méthode (nammée « createInstance » dans ce cas). Nous donnons un schéma pour résumer ce dont nous avons parlé.

ComplexUNOQUERY.png

Dernière question : est-il possible de partir de l'interface XMultiServiceFactory pour obtenir n'importe quelle interface ? La réponse es non. Regardez le code ci-dessous où j'ai pris rOfficeServiceManager au lieu de oDocMSF parceque c'est une interface XmultiServiceFactory aussi.

//Listing 22 Wrong code
// C++
//  Reference<XMultiServiceFactory> oDocMSF (xTextDocument,UNO_QUERY);
// using rOfficeServiceManager instead oDocMSF
	Reference< XInterface > textTable = rOfficeServiceManager->createInstance(
	               OUString::createFromAscii("com.sun.star.text.TextTable") );
	Reference< XTextTable > xTable(textTable, UNO_QUERY);
	if (!xTable.is()) {
		printf("Erreur creation XTextTable interface !\n");
	return 1;
    }

Ce code se compile mais donne une erreur d'exécution. Cela signifie que l'on ne peut pas utiliser n'importe quelle interface XMultiServiceFactory pour obtenir n'importe quelle autre Interface. Si vous travaillez avec un document demandez son interfac XMultiServiceFactory correspondante. A ce point seulement l'expérience peut vous aider.

Notez avant d'aller plus en avant qu'un code utilisé plusieurs fois jusqu'ici, peut trouver des explications même si l'interface XMultiServiceFactory n'est pas obtenue de façon standard :

//Listing 23 Classic code
// C++
int main( ) {
//retrieve an instance of the remote service manager
    Reference< XMultiServiceFactory > rOfficeServiceManager;
    rOfficeServiceManager = ooConnect();
 
//get the desktop service using createInstance returns an XInterface type
    Reference< XInterface  > Desktop = rOfficeServiceManager->createInstance(
    OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
//query for the XComponentLoader interface
    Reference< XComponentLoader > rComponentLoader (Desktop, UNO_QUERY);

Facile de retrouver le style "trois instructions" pou obtenir l'interface XcomponentLoader, pas vrai ?

Correspondances pour les modules et interfaces

Par exemple :

//Listing 153
// IDL 
module M 
{ struct E { long L; 
  }; 
};

est compilé en C++ comme

 
//Listing 154
// C++ 
namespace M 
{ struct E 
  { Long L; }; 
}

et on peut faire référence à E en dehors de M par M::E. D'autre part une instruction de nommage peut être utilisée pour référer cette structure simplement comme E :

//Listing 155
// C++ 
using namespace M; 
E e;
  e.L = 3;

Une autre alternative est d'employer la directive de nommage seulement pour M::E :

//Listing 156
// C++ 
using M::E;
  E e;
  e.L = 3;

Une interface est réalisée à l'aide d'une classe C++ qui contient les définitions des types, constantes et exceptions définies dans l'interface. L'exemple ci-dessous montre le comportement de cette correspondance pour une interface :

//Listing 157
// IDL
interface A{
  struct S {
    short field;
   };
 };

est compilée en :

 
//Listing 158
// C++
class SAL_NO_VTABLE A {
  struct S {
    short fiel;
  };
}; //A

On peut utiliser aussi :

//Listing 159
// Conformant uses
 A::S s; // declare a struct variable 
s.field = 3; // field access
// Non-conformant uses: 
// one cannot declare an instance of an interface class... 
A a; // ...nor declare a pointer to an interface class... 
A *p; // ...nor declare a reference to an interface class. 
void f(A &r);

Le service de Core reflection et son interface XIdlReflection

Beaucoup de points d'entrée pour l'introspection sont décrits dans le Developer's Guide. On en donne quelques unes et montrons le moyen d'en utiliser en C++.

L'interface XIdlReflection

Voir le CoreReflection Service in Developer's Guide. Cette interface est aussi décrite ici (en anglais).

The XIntrospection Interface

Cette interface est décrite ici (en anglais) avec des exemples de code. Un autre code est donné dans la section Constructing Helpers. Voir aussi Introducing the OpenOffice.org_API and OOoBasic Introspection and Developer's Guide.

Traduire des programmes OooBasic en C++

La traduction des programmes OooBasic en C++ n'est pas si immédiate que cela. Les interfaces et attributs vus par les programmes OooBasic sont construits à travers un pont (bridge) pour des questions de facilité. Alors ce qui est vu en OooBasic ne sera pas forcément vu en C++. Une des conséquences de tout cela est qu'il est impossible de réaliser cette traduction sans passer un peu de temps avec les fichiers IDL.

Quand j'ai abordé Writer, j'ai laissé le lecteur résoudre un certain nombre de problèmes (particulièrement les problèmes). Nous choisissons ces problèmes ici comme exemple. Nous commençons par donner le programme OOoBasic de départ.

'Listing 36 Simple OOoBasic program to translate
REM ****  OOoBasic
Dim MyDocument As Object, MyText As Object
Dim MyCursor As Object
MyDocument = ThisComponent
MyText = MyDocument.Text
MyCurseur= MyTexte.createTextCursor
MyCurseur.goRight(1, false) ' move right one character
MyCurseur.goLeft(2, true) ' select the two previous characters

Toutes les instructions OOoBasic pour bouger le curseur sont résumées dans le tableau ci-dessous :

OOoBasic instructions
Méthode Signification
goRight(n, false) bouge le curseur d'un nombre spécifié de caractères vers la droite
goLeft(n, false) bouge le curseur d'un nombre spécifié de caractères vers la gauche
gotoStart(false) bouge le curseur au début du texte
gotoEnd(false) bouge le curseur à la fin du texte
gotoStartOfParagraph(false) bouge le curseur au début du paragraphe courant
gotoEndOfParagraph(false) bouge le curseur à la fin du paragraphe courant
gotoNextParagraph(false) bouge le curseur au prochain paragraphe
gotoPreviousParagraph(false) bouge le curseur au précédent paragraphe
gotoNextWord(false) bouge le curseur au prochain mot
gotoPreviousWord(false) bouge le curseur au précédent mot
gotoStartOfWord(false) bouge le curseur au début du mot courant
gotoEndOfWord(false) bouge le curseur à la fin du mot courant
gotoNextSentence(false) bouge le curseur au début de la prochaine phrase
gotoPreviousSentence(false) bouge le curseur au début de la précédente phrase
gotoStartOfSentence(false) bouge le curseur au début de la phrase courante
gotoEndOfSentence(false) bouge le curseur à la fin de la phrase courante

Mais si vous voulez traduire l'utilisation de ces fonctions en C++, il vous faut obtenir les interfaces en partant de l'interface XtextCursor interface (voir plus bas en Listing 41). Cela rend la traduction difficile. Par exemple trois interfaces curseur différentes en utilisant les méthodes OOoBasic du programme de départ. Il est grand temps de montrer les fichiers IDL correspondants. First of all the XWordCursor interface is shown :

//Listing 37 XWordCursor interface (IDL file)
// IDL
module com {  module sun {  module star {  module text {  
interface XWordCursor: com::sun::star::text::XTextCursor
{ 
	boolean isStartOfWord(); 
	boolean isEndOfWord(); 
	boolean gotoNextWord( [in] boolean bExpand ); 
	boolean gotoPreviousWord( [in] boolean bExpand ); 
	boolean gotoEndOfWord( [in] boolean bExpand ); 
	boolean gotoStartOfWord( [in] boolean bExpand );  
}; 
}; }; }; };

L'interface XParagraphCursor est montrée :

//Listing 38 XParagraphCursor interface (IDL file)
// IDL
module com {  module sun {  module star {  module text {  
interface XParagraphCursor: com::sun::star::text::XTextCursor
{ 
    com::sun::star::text::XParagraphCursor::isStartOfParagraph
	boolean isStartOfParagraph(); 
	boolean isEndOfParagraph(); 
    com::sun::star::text::XParagraphCursor::gotoStartOfParagraph
	boolean gotoStartOfParagraph( [in] boolean bExpand ); 
    com::sun::star::text::XParagraphCursor::gotoEndOfParagraph
	boolean gotoEndOfParagraph( [in] boolean bExpand ); 
	boolean gotoNextParagraph( [in] boolean bExpand ); 
    com::sun::star::text::XParagraphCursor::gotoPreviousParagraph
	boolean gotoPreviousParagraph( [in] boolean bExpand ); 
 
}; 
}; }; }; };

et pour finir l'interface XSentenceCursor :

// Listing 39 XSentenceCursor interface (IDL file)
// IDL
module com {  module sun {  module star {  module text {  
interface XSentenceCursor: com::sun::star::text::XTextCursor
{ 
	boolean isStartOfSentence(); 
	boolean isEndOfSentence(); 
	boolean gotoNextSentence( [in] boolean Expand ); 
	boolean gotoPreviousSentence( [in] boolean Expand ); 
	boolean gotoStartOfSentence( [in] boolean Expand ); 
	boolean gotoEndOfSentence( [in] boolean Expand );  
}; 
 
//============================================================================= 
 
}; }; }; };

Si vous voulez savoir quelles interfaces vous pouvez demander il vous faut retrouver le service. Pour notre exemple c'est le service TextCursor. Voici son fichier IDL où vous voyez les interfaces que vous pouvez demander.

//Listing 40 TextCursor service (IDL file)
// IDL
module com {  module sun {  module star {  module text {
service TextCursor
{
	service com::sun::star::text::TextRange;
    interface com::sun::star::text::XTextCursor;
	[optional] interface com::sun::star::text::XWordCursor;
	[optional] interface com::sun::star::text::XSentenceCursor;
	[optional] interface com::sun::star::text::XParagraphCursor;
	interface com::sun::star::beans::XPropertySet;
	interface com::sun::star::beans::XPropertyState;
	interface com::sun::star::beans::XMultiPropertyStates;
	[optional] interface com::sun::star::document::XDocumentInsertable;
	[optional] interface com::sun::star::util::XSortable;
};
}; }; }; };

Si vous partez de nouveau du Listing 11 il vous faudra un UNO_QUERY pour obtenir l'interface XWordCursor.

//Listing 41 Using XwordCursor Interface
// C++
// Don't forget to add : #include <com/sun/star/text/XWordCursor.hpp>
// Don't forget to add "com.sun.star.text.XWordCursor \" in the makefile    
    Reference < XWordCursor > xWordCursor (xTextCursor,UNO_QUERY);
    xWordCursor->gotoNextWord(false); 
    xWordCursor->gotoNextWord(false); 
    xWordCursor->gotoNextWord(true);

La traduction peut probablement se faire automatiquement, mais un tel traducteur aurait besoin de connaissances sur les fichiers IDL.

En passant nous avons encore les huit services disponibles :

******** Services : 8
com.sun.star.text.TextSortable
com.sun.star.style.ParagraphPropertiesComplex
com.sun.star.style.ParagraphPropertiesAsian
com.sun.star.style.ParagraphProperties
com.sun.star.style.CharacterPropertiesComplex
com.sun.star.style.CharacterPropertiesAsian
com.sun.star.style.CharacterProperties
com.sun.star.text.TextCursor

Retour à la page d'accueil

Page d'accueil du développement C++ à l'aide du SDK

Voir aussi

Personal tools