FR/Documentation/OpenOffice Writer

From Apache OpenOffice Wiki
Jump to: navigation, search

Introduction

Dans ce chapitre, nous utilisons encore le code initial décrit dans une section précédente. Il consiste en un sous-programme “ooConnect ()” et un programme principal main().

  • Nous donnons pour commencer la fonction ooConnect() :
// Listing 0
// C++
#include <stdio.h>
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
// on ajoute la ligne ci-apres
#include <com/sun/star/frame/XComponentLoader.hpp>
 
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::bridge;
// ajouté aussi :
using namespace com::sun::star::frame;
 
using namespace rtl;
using namespace cppu;
 
// appel de la fonction de démarrage
Reference< XMultiServiceFactory > ooConnect(){
   // create the initial component context
   Reference< XComponentContext > rComponentContext = 
				defaultBootstrap_InitialComponentContext();
 
   // obtention du servicemanager à partir du context
   Reference< XMultiComponentFactory > rServiceManager = 
				rComponentContext->getServiceManager();
 
   // instantiate a sample service with the servicemanager.
   Reference< XInterface > rInstance =  rServiceManager->createInstanceWithContext(
         OUString::createFromAscii("com.sun.star.bridge.UnoUrlResolver" ),rComponentContext );
 
   // Query for the XUnoUrlResolver interface
   Reference< XUnoUrlResolver > rResolver( rInstance, UNO_QUERY );
   if( ! rResolver.is() ){
      printf( "Error: Couldn't instantiate com.sun.star.bridge.UnoUrlResolver service\n" );
      return NULL;
   }
   try {
      // resolve the uno-url
      rInstance = rResolver->resolve( OUString::createFromAscii(
         "uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" ) );
 
      if( ! rInstance.is() ){
         printf( "StarOffice.ServiceManager is not exported from remote counterpart\n" );
         return NULL;
      }
 
      // query for the simpler XMultiServiceFactory interface, sufficient for scripting
      Reference< XMultiServiceFactory > rOfficeServiceManager (rInstance, UNO_QUERY);
 
      if( ! rOfficeServiceManager.is() ){
            printf( "XMultiServiceFactory interface is not exported for StarOffice.ServiceManager\n" );
            return NULL;
        }       
        return rOfficeServiceManager;
   }
   catch( Exception &e ){
      OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
      printf( "Error: %s\n", o.pData->buffer );
      return NULL;
   }
   return NULL;
}

Note : vous devez éventuellement changer le port de "port=8100" avec "port=2083" pour les SDK récents (après 2.X).

Il serait bon de regarder aussi :

  1. les interfaces com.sun.star.uno.XComponentContext, com.sun.star.lang.XMultiComponentFactory, com.sun.star.uno.XInterface, com.sun.star.bridge.XUnoUrlResolver et com.sun.star.lang.XMultiServiceFactory,
  2. et aussi le service com.sun.star.bridge.UnoUrlResolver.
  • Nous donnons maintenant le programme principal à modifier (le "main()") :
Documentation caution.png N'oubliez pas de changer la chaîne de caractères "private:factory/scalc" en "private:factory/swriter".
// code C++
//Listing 0b Notre programme principal
int main( ) {
//retrouve une instance service manager distant avec notre ooConnect()
    Reference< XMultiServiceFactory > rOfficeServiceManager;
    rOfficeServiceManager = ooConnect();
    if( rOfficeServiceManager.is() ){
        printf( "Connecté avec succès à OpenOffice\n" );
    }
 
//get the desktop service using createInstance returns an XInterface type
    Reference< XInterface  > Desktop = rOfficeServiceManager->createInstance(
    OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
 
//demande de l'interface XComponentLoader interface
    Reference< XComponentLoader > rComponentLoader (Desktop, UNO_QUERY);
    if( rComponentLoader.is() ){
        	printf( "XComponentloader successfully instanciated\n" );
    	}
 
//get an instance of the spreadsheet
    Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/scalc"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
//*********************************
// c'est ici que l'on rajoute le code présenté dans ce chapitre;
//*********************************
    return 0;
}

Ce code est appelé un programme d'amorce ou de démarrage et utilise :

  1. les interfaces com.sun.star.lang.XMultiServiceFactory, com.sun.star.uno.XInterface, com.sun.star.frame.XComponentLoader et com.sun.star.lang.XComponent interfaces
  2. le service com.sun.star.frame.Desktop,
  3. la structure UNO com.sun.star.beans.PropertyValue.

Rappelez-vous que chaque fois que vous demandez une interface vous devez ajouter des lignes de code si elles n'existent pas dans le code source ainsi que dans le makefile. Je vais en général ajouter des commentaires pour éviter les omissions.

Documentation note.png Note importante : Le point le plus important dans la chaîne de compilation des exemples ci-après est que l'utilitaire cppumaker construira chacun des fichiers d'inclusion hpp et hdl que votre application utilisera. Le SDK ne fournit pas les fichiers hpp, mais vous devez les construire à partir des fichiers IDL qui eux sont fournis avec le SDK.
Documentation note.png Il est possible de construire tous les fichiers d'inclusion hpp lors de l'installation du SDK comme j'ai eu l'occasion de le mentionner pour l'installation sous Windows. C'est naturellement possible aussi avec les autres systèmes d'exploitation. En procédant ainsi il ne vous faudra plus modifier votre MakeFile (sauf peut-être le chemin pour atteindre ces fichiers).

Regardons maintenant les premières applications.

Utiliser le Dispatcher et enregistrer des Macros

La première chose que nous voulons examiner est l'utilisation du dispatcher avant l'utilisation directe des appels UNO dans la prochaine section. Si vous enregistrez des macros, vous obtenez du code OOoBasic qui utilise le dispatcher plutôt que les appels UNO directs. Voir la section The OpenOffice.org recorder and UNO dispatch calls pour une discussion sur l'enregistrement des commandes du dispatcher par rapport aux appels API.

Introduction

Par exemple si vous avez un document OOoWriter et que vous déclenchez l'enregistrement d'une macro pendant que vous insérez du texte et que vous le formatez, cela vous donne quelque chose qui doit ressembler à :

'Listing 2 OOoBasic and the Dispatcher with Macro Recorder
REM  *****  BASIC  *****
 
sub Main
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
 
rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Text"
args1(0).Value = "demo de macro"
 
dispatcher.executeDispatch(document, ".uno:InsertText", "", 0, args1())
 
rem ----------------------------------------------------------------------
dim args2(0) as new com.sun.star.beans.PropertyValue
args2(0).Name = "Bold"
args2(0).Value = true
 
dispatcher.executeDispatch(document, ".uno:Bold", "", 0, args2())
 
rem ----------------------------------------------------------------------
dim args4(2) as new com.sun.star.beans.PropertyValue
args4(0).Name = "FontHeight.Height"
args4(0).Value = 14
args4(1).Name = "FontHeight.Prop"
args4(1).Value = 100
args4(2).Name = "FontHeight.Diff"
args4(2).Value = 0
 
dispatcher.executeDispatch(document, ".uno:FontHeight", "", 0, args4())
 
end sub

Ce code est très caractéristique de l'utilisation du dispatcher. Comment traduire ce code en C++ ? Le problème est de prendre en compte le dispatcher.

La première étape est d'obtenir l'interface com.sun.star.frame.XDispatcherHelper à partir du service com.sun.star.frame.DispatcherHelper.

//Listing 3 Demande de l'interface XDispatchHelper
// C++
Reference< XDispatchHelper > rDispatchHelper = Reference< XDispatchHelper >
				( rOfficeServiceManager->createInstance(
                              OUString( RTL_CONSTASCII_USTRINGPARAM(
                              "com.sun.star.frame.DispatchHelper" ))), UNO_QUERY );

Vous pouvez trouver plus d'explications ici (si vous n'êtes pas débutant) et vous comprendrez alors ce listing.

La deuxième étape est d'obtenir l'interface com.sun.star.frame.XFrame en partant de la variable Desktop (bureau) et ensuite d'obtenir l'interface com.sun.star.frame.XDispatchProvider en partant de la variable frame qui contient l'interface com.sun.star.frame.XFrame (cela semble très important de partir de la variable frame).

//Listing 4 Obtenir une interface XFrame
// C++
Reference< XFrame > rFrame=rDesktop->getCurrentFrame();
 
Reference< XDispatchProvider > rDispatchProvider(rFrame,UNO_QUERY);

La troisième étape est de déclarer votre tableau (Sequence en C++) de “PropertValue” et de donner les valeurs :

//Listing 5 Les couples Name/Value des propriétés
// C++
	Sequence < PropertyValue > args1(1);
 
	args1[0].Name = OUString::createFromAscii("Text");
	args1[0].Value <<= OUString::createFromAscii("demo de macro");

et l'étape finale est d'appeler le dispatcher :

//Listing 6 Appel du Dispatcher
// C++
	rDispatchHelper->executeDispatch(rDispatchProvider,
			OUString::createFromAscii(".uno:InsertText"),
			OUString::createFromAscii(""),
			0,
			args1);

Le reste du code OOoBasic peut être facilement traduit comme montré ci-dessous :

//Listing 7 Autres appels du Dispatch
// C++
args1[0].Name = OUString::createFromAscii("Bold");
	args1[0].Value <<=(sal_Bool)true;
	rDispatchHelper->executeDispatch(rDispatchProvider,
			OUString::createFromAscii(".uno:Bold"),
			OUString::createFromAscii(""),
			0,
			args1);
 
	args1.realloc(3);
	args1[0].Name = OUString::createFromAscii("FontHeight.Height");
	args1[0].Value <<= (sal_Int32)14;
	args1[1].Name = OUString::createFromAscii("FontHeight.Prop");
	args1[1].Value <<= (sal_Int32)100;
	args1[2].Name = OUString::createFromAscii("FontHeight.Diff");
	args1[2].Value <<= (sal_Int32)0;
	rDispatchHelper->executeDispatch(rDispatchProvider,
			OUString::createFromAscii( ".uno:FontHeight"),
			OUString::createFromAscii(""),
			0,
			args1);

Le Dispatcher et l'Internationalization

Un des problèmes que vous rencontrerez avec ce style de programmation est : comment puis-je écrire de tels programmes pouvant tourner sur n'importe quelle machine dans le monde entier ? Si vous travaillez en français, comme je le fais, et que vous enregistrez une macro, vous allez rencontrer des valeur de propriétés en français. Par exemple, si j'enregistre une insertion d'image, j'obtiens le code OOoBasic :

'Listing 8 Inserting an Image (OOoBasic)
REM  *****  BASIC  *****
 
sub Main
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
 
rem ----------------------------------------------------------------------
dim args1(3) as new com.sun.star.beans.PropertyValue
args1(0).Name = "FileName"
args1(0).Value = "file:///home/smoutou/PhotoPCB2.jpg"
args1(1).Name = "FilterName"
args1(1).Value = "<Tous les formats>"
args1(2).Name = "AsLink"
args1(2).Value = false
args1(3).Name = "Style"
args1(3).Value = "Image"
 
dispatcher.executeDispatch(document, ".uno:InsertGraphic", "", 0, args1())
 
end sub

qui montre clairement du français. Si vous traduisez directement ce code comme expliqué plus haut, vous obtenez :

//Listing 9 Insertion d'une Image (C++ French Version)
// C++
....
	Sequence < PropertyValue > args1(4);
	args1[0].Name = OUString::createFromAscii("FileName");
	args1[0].Value <<= OUString::createFromAscii("file:///home/smoutou/PhotoPCB2.jpg");
	args1[1].Name = OUString::createFromAscii("FilterName");
	args1[1].Value <<= OUString::createFromAscii("<Tous les formats>");
	args1[2].Name = OUString::createFromAscii("AsLink");
	args1[2].Value <<=(sal_Bool)false;
	args1[3].Name = OUString::createFromAscii("Style");
	args1[3].Value <<= OUString::createFromAscii("Image");
 
	rDispatchHelper->executeDispatch(rDispatchProvider,
			OUString::createFromAscii(".uno:InsertGraphic"),
			OUString::createFromAscii(""),
			0,
			args1);

qui fonctionne correctement. Si je traduis le français du programme en anglais, cela fonctionne aussi sur ma version française d'OpenOffice :

//Listing 10 Inserting an Image (C++ English Version)
// C++
	args1[1].Name = OUString::createFromAscii("FilterName");
	args1[1].Value <<= OUString::createFromAscii("<All formats>");
	....
	args1[3].Name = OUString::createFromAscii("Style");
	args1[3].Value <<= OUString::createFromAscii("Graphics");
	....

Mais nous ne pouvons pas éviter la question : est-ce que la première version en français marche sur tous les ordinateurs ? Je n'ai pas de réponse. Je suppose que la version anglaise fonctionne partout. Il m'est impossible aussi d'éviter cette seconde question : comment puis-je savoir que « <tous les Formats> » est traduit par « <All Formats> » en anglais ?

Créer, ouvrir un document writer

On commence par ouvrir un nouveau document OOowriter. Cela peut être fait avec le code ci-dessous (voir l'interface com.sun.star.lang.XComponent et la structure com.sun.star.beans.PropertyValue) :

//Listing 11 Obtaining a blank OOoWriter Document
// C++
//get an instance of the OOowriter document
    Reference< XComponent > xWriterComponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/swriter"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());

tandis que l'ouverture d'un document existant se fait par :

//Listing 12 Obtaining a blank OOoWriter Document
// C++
//get an instance of the OOowriter document
    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 >());

Gestion du texte

Trouver le texte

Nous commençons par montrer comment on peut trouver le texte ou plus exactement l'interface com.sun.star.text.XText (voir aussi l'indispensable interface com.sun.star.text.XTextDocument).

 
//Listing 13 Obtenir l'interface XText
// C++
// Don't forget to add : using namespace com::sun::star::text;
// Don't forget to add : #include <com/sun/star/text/XTextDocument.hpp>
// Don't forget to add "com.sun.star.text.XTextDocument \" in the makefile
// Don't forget to add : #include <com/sun/star/text/XText.hpp>
// Don't forget to add "com.sun.star.text.XText \" in the makefile
 
//get an instance of the OOowriter document
    Reference< XComponent > xWriterComponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/swriter"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
    Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
    Reference< XText > xText = xTextDocument->getText();

La chose la plus intéressante est de faire des choses visibles (je veux dire ajouter ou retirer du texte).

Ecrire du texte dans le document

La manière la plus simple pour écrire du texte dans un document et la méthode setString de l'interface com.sun.star.text.XText. Cela nous donne en l'occurrence ce code :

//Listing 14 Ecrire du texte dans un document OOoWriter
// C++
// Don't forget to add : using namespace com::sun::star::text;
// Don't forget to add : #include <com/sun/star/text/XTextDocument.hpp>
// Don't forget to add "com.sun.star.text.XTextDocument \" in the makefile
// Don't forget to add : #include <com/sun/star/text/XText.hpp>
// Don't forget to add "com.sun.star.text.XText \" in the makefile
 
//get an instance of the OOowriter document
    Reference< XComponent > xWriterComponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/swriter"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
    Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
    Reference< XText > xText = xTextDocument->getText();
    xText->setString(OUString::createFromAscii("Hello"));

Qu'arrive-t-il si l'on remplace la dernière ligne par les deux ci-dessous :

//Listing 15 More on setString Method (XText Interface)
// C++
    xText->setString(OUString::createFromAscii("Hello")); 
    xText->setString(OUString::createFromAscii(" All around the world"));

Réponse : seulement : only « All around the world » est écrit. Cela fonctionne donc comme attendu : setString est setString. Ainsi si vous voulez mettre du texte derrière un autre texte une autre méthode doit être découverte.

Voir aussi com.sun.star.text.XTextDocument.

Gérer du texte avec l'interface XTextRange

L'interface XTextRange est capable de gérer le texte avec une méthode setString mais en gardant l'ancien texte. Par exemple si vous voulez ouvrir un document (contenant du texte) et ajouter du texte au tout début, faites comme ceci :

//Listing 16 Using the XTextRange Interface 
// 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);
    Reference< XText > xText = xTextDocument->getText();
 
    Reference<XTextRange> xTextRange = xText->getStart();
    xTextRange->setString(OUString::createFromAscii("Start here "));

La méthode getEnd() peut être aussi utilisée.

Voir aussi le service com.sun.star.text.TextRange et les interfaces com.sun.star.text.XTextRange, com.sun.star.text.XTextDocument, com.sun.star.text.XText ainsi que la structure com.sun.star.beans.PropertyValue.

Nous voyons ainsi comment insérer du texte au tout début et devinons comment l'insérer à la fin. Mais si vous voulez gérer la place exacte où vous voulez insérer votre texte alors l'interface com.sun.star.text.XCursorText est votre amie.

L'interface XTextCursor

Le Developer's Guide indique : le code ci-dessus n'est pas flexible. Si vous voulez gagner en flexibilité, créez un curseur de texte qui est une zone de texte (text range) mouvante. Comme l'interface com.sun.star.text.XTextCursor hérite de l'interface com.sun.star.text.XTextRange, un curseur est un com.sun.star.text.XTextRange et incorpore donc les méthodes d'un XTextRange:

com::sun::star::text::XText getText()
com::sun::star::text::XTextRange getStart()
com::sun::star::text::XTextRange getEnd()
string getString()
void setString( [in] string aString)

Comme déjà vu, la méthode setString est aussi disponible et fonctionne toujours de la même manière.

//Listing 17 More on setString Method (XTextCursor Interface)
// C++
//get an instance of the OOowriter document
    Reference< XComponent > xWriterComponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/swriter"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
    Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
    Reference< XText > xText = xTextDocument->getText();
    Reference< XTextCursor> xTextCursor = xText->createTextCursor();
    xTextCursor->setString(OUString::createFromAscii("Hello")); 
    xTextCursor->setString(OUString::createFromAscii(" All around the world"));

Une nouvelle question : qu'arrive-t-il si l'on utilise ce code mais sans instancier une deuxième fois la variable cursor entre deux appels setString ?

//Listing 18 More on setString Method (XTextCursor interface)
// C++
//get an instance of the OOowriter document
    Reference< XComponent > xWriterComponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/swriter"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
    Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
    Reference< XText > xText = xTextDocument->getText();
    Reference< XTextCursor> xTextCursor = xText->createTextCursor();
    xTextCursor->setString(OUString::createFromAscii("Hello ")); 
    xTextCursor = xText->createTextCursor(); // added
    xTextCursor->setString(OUString::createFromAscii("All around the world"));

Réponse : « all around the worldHello  » est écrit montrant que quand vous initialisez une interface XTextCursor, le curseur est toujours au début du document.

Voir aussi com.sun.star.text.XTextCursor, com.sun.star.text.XText et com.sun.star.text.XTextDocument.

Si vous voulez votre texte à la place adéquate, vous pouvez utiliser ce code :

//Listing 19 More on goRight Method (XTextCursor Interface)
// C++
//get an instance of the OOowriter document
    Reference< XComponent > xWriterComponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/swriter"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
    Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
    Reference< XText > xText = xTextDocument->getText();
    Reference< XTextCursor> xTextCursor = xText->createTextCursor();
    xTextCursor->setString(OUString::createFromAscii("Hello ")); 
    xTextCursor = xText->createTextCursor();
    xTextCursor ->goRight(6,0); // added to move the cursor
    xTextCursor->setString(OUString::createFromAscii("All around the world"));

où la méthode goRight est utilisée. Ce n'est pas la bonne façon de faire, instancier deux fois la variable xTextCursor. Mais ce code nous montre ce que l'on peut faire avec un curseur : le déplacer. Bien sûr la méthode goLeft existe aussi. Le fichier IDL correspondant est montré maintenant :

//Listing 20 XTextCursor Interface
// IDL
module com {  module sun {  module star {  module text {
interface XTextCursor: com::sun::star::text::XTextRange
{
	/** sets the end of the position to the start.*/
	[oneway] void collapseToStart();
	/** sets the start of the position to the end.*/
	[oneway] void collapseToEnd();
	/** determines if the start and end positions are the same.*/
	boolean isCollapsed();
	/** moves the cursor the specified number of characters to the left.*/
	boolean goLeft( [in] short nCount,
			 [in] boolean bExpand );
	/** moves the cursor the specified number of characters to the right.*/
	boolean goRight( [in] short nCount,
			 [in] boolean bExpand );
	/** moves the cursor to the start of the text.*/
	void gotoStart( [in] boolean bExpand );
	/** moves the cursor to the end of the text.*/
	void gotoEnd( [in] boolean bExpand );
	/** moves or expands the cursor to a specified <type>TextRange</type>.*/
	void gotoRange( [in] com::sun::star::text::XTextRange xRange,
			 [in] boolean bExpand );
};
}; }; }; };

Ce qui peut être réellement fait avec cette interface est donné dans le service <OpenOffice.org1.1_SDK>/idl/com/sun/star/text/TextCursor.idl (visible aussi ici com.sun.star.text.TextCursor. En fait l' introspection de com.sun.star.text.XTextCursor me montre que les méthodes ci-dessous sont disponibles :

...
boolean gotoPreviousParagraph([IN]boolean)
boolean gotoNextParagraph([IN]boolean)
boolean gotoEndOfParagraph([IN]boolean)
boolean gotoStartOfParagraph([IN]boolean)
boolean isEndOfParagraph()
boolean isStartOfParagraph()
boolean gotoStartOfWord([IN]boolean)
boolean gotoEndOfWord([IN]boolean)
boolean gotoPreviousWord([IN]boolean)
boolean gotoNextWord([IN]boolean)
boolean isEndOfWord()
boolean isStartOfWord()
boolean gotoEndOfSentence([IN]boolean)
boolean gotoStartOfSentence([IN]boolean)
boolean gotoPreviousSentence([IN]boolean)
boolean gotoNextSentence([IN]boolean)
boolean isEndOfSentence()
boolean isStartOfSentence()
void gotoRange([IN]com.sun.star.text.XTextRange,[IN]boolean)
void gotoEnd([IN]boolean)
void gotoStart([IN]boolean)
boolean goRight([IN]short,[IN]boolean)
boolean goLeft([IN]short,[IN]boolean)
...

Mais comme d'habitude tout n'est pas disponible d'un coup, il vous faudra des requêtes UNO_QUERY. Pour donner un exemple utilisant la méthode gotoEndOfWord, on commence par modifier le programme pour lire un fichier existant plutôt que de partir d'un fichier vierge et demandons une interface com.sun.star.text.XWordCursor :

//Listing 21 Using the XWordCursor Service when loading a File
// C++
// Don't forget to add : using namespace com::sun::star::text;
// Don't forget to add : #include <com/sun/star/text/XTextDocument.hpp>
// Don't forget to add "com.sun.star.text.XTextDocument \" in the makefile
// 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
// Don't forget to add : #include <osl/file.hxx>  
 
    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);
    Reference< XText > xText = xTextDocument->getText();
    Reference< XTextCursor> xTextCursor = xText->createTextCursor();
    Reference < XWordCursor > xWordCursor (xTextCursor,UNO_QUERY);
    xWordCursor->gotoEndOfWord(0);
    xWordCursor->setString(OUString::createFromAscii(" OK"));

Jetez un coup d'oeil sur le fichier com.sun.star.text.XWordCursor file pour apprendre ce qui est possible de faire avec la variable xWordCursor de l'exemple précédent. Pour aller plus loin aller à Traduire du OOoBasic en C++.

See also com.sun.star.text.XTextDocument and com.sun.star.text.XWordCursor.

La méthode insertString

Le Developer's Guide indique : le curseur peut être mis où cela est nécessaire et la chaîne de caractère positionnée après. Cela n'a aucun inconvénient. Après le positionnement de la chaîne, la chaîne insérée est toujours sélectionnée. Cela indique que du nouveau texte ne peut pas être inséré sans bouger le curseur une nouvelle fois. Ainsi la méthode la plus flexible pour insérer du texte à l'aide d'un curseur est la méthode insertString() de l'interface com.sun.star.text.XText. Elle prend un com.sun.star.text.XTextRange comme cible de la zone qui est remplacé durant l'insertion, une chaîne à insérer et un paramètre booléen qui détermine si le texte inséré doit être absorbé par le curseur après avoir été inséré. Le com.sun.star.text.XTextCursor est un com.sun.star.text.XTextRange, ainsi il est utilisé ici:

void insertString( [in] com::sun::star::text::XTextRange xRange, 
					[in] string aString, 
					[in] boolean bAbsorb) 

Pour insérer du texte séquentiellement le paramètre bAbsorb doit être positionné à false, ainsi le XTextRange se rétrécit à la fin de l'insertion. Si bAbsorb est true, la zone de texte sélectionne le nouveau texte inséré. La chaîne qui était sélectionnée par la zone de texte avant l'insertion est effacé.

Considerez l'utilisation de insertString() ci-dessous (consulter aussi les interfaces com.sun.star.text.XWordCursor, com.sun.star.text.XTextCursor, com.sun.star.text.XTextDocument et com.sun.star.text.XText) :

//Listing 22 The insertString Method
//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);
    Reference< XText > xText = xTextDocument->getText();
    Reference< XTextCursor> xTextCursor = xText->createTextCursor();
// 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);
// Use the XSimpleText interface to insert a word at the current cursor
// location, over-writing
// the current selection (the third word selected above) 
// a UNO query because xTextRange = xWordCursor->getStart(); doesn't work  
    Reference<XTextRange> xTextRange (xWordCursor,UNO_QUERY);
    xText->insertString(xTextRange,OUString::createFromAscii("We are here "),true);

Ce programme prend le troisième mot et le remplace par «We are here». En premier lieu, je voulais utiliser quelque chose comme

xTextRange = xWordCursor->getStart();

pour retrouver l'interface XTextRange dont j'avais besoin pour le insertString. Cela fonctionnait seulement de manière partielle parceque l'information de sélection était perdue et je n'étais pas capable de remplacer le mot sélectionné à l'aide de l'instruction :

xWordCursor->gotoNextWord(true);

Accéder aux propriétés du curseur

Si l'on veut aller plus en avant et utiliser des caractères gras par exemple, on doit accéder aux propriétés des curseurs. Nous donnons un exemple qui part du code précédent et met le texte ajouter en gras. Cela peut être fait en remarquant que le code précédent insert un texte avec le dernier paramètre positionné à true. Cela signifie que la chaîne insérée est marquée. Si l'on change simplement une propriété du curseur, cela changera le texte. Ainsi seulement ajouter le code ci-dessous au listing 22 (voir l'interface com.sun.star.beans.XPropertySet, et les contantes com.sun.star.awt.FontWeight) :

//Listing 23 Setting Text in bold
//C++
// Don't forget to add : using namespace com::sun::star::beans;
// Don't forget to add : #include <com/sun/star/beans/XPropertySet.hpp>
// Don't forget to add "com.sun.star.beans.XPropertySet \" in the makefile
    Reference< XPropertySet> xCursorProps (xTextCursor,UNO_QUERY);
    Any cw;
// Don't forget to add : using namespace com::sun::star::awt::FontWeight;
// Don't forget to add : #include <com/sun/star/awt/FontWeight.hpp>
// Don't forget to add "com.sun.star.awt.FontWeight \" in the makefile
    cw <<= BOLD;
    xCursorProps->setPropertyValue(OUString::createFromAscii("CharWeight"),cw);

met « we are here  » en gras. Comme déjà vu ici nous sommes de nouveau confrontés à des constantes. BOLD est une constante. Elle provient du fichier IDL suivant (visible aussi en com.sun.star.awt.FontWeight) :

//Listing 24 Constants to set the Font Weight
//IDL
module com {  module sun {  module star {  module awt {  
constants FontWeight
{ 
	/** The font weight is not specified/known.     */	
	const float DONTKNOW = 0.000000; 
	/** specifies a 50% font weight.     */	
	const float THIN = 50.000000; 
	/** specifies a 60% font weight.     */	
	const float ULTRALIGHT = 60.000000; 
 	/** specifies a 75% font weight.     */	
	const float LIGHT = 75.000000; 
 	/** specifies a 90% font weight.    */	
	const float SEMILIGHT = 90.000000; 
	/** specifies a normal font weight.     */	
	const float NORMAL = 100.000000; 
	/** specifies a 110% font weight.     */	
	const float SEMIBOLD = 110.000000; 
 	/** specifies a 150% font weight.    */	
	const float BOLD = 150.000000; 
	/** specifies a 175% font weight.     */	
	const float ULTRABOLD = 175.000000; 
	/** specifies a 200% font weight.     */	
	const float BLACK = 200.000000; 
}; 
}; }; }; };

Et les commentaires dans le programme indiquent comment utiliser ces constantes.

Accéder à un signet

Si dans un document je met (avec les menus) un signet nommé « Signet1 ». Ensuite, j'essaie d'atteindre ce signet avec un programme et d'ajouter du text à cette place. Cela peut être fait avec ce morceau de code :

//Listing 25 Atteindre un signet nommé
// C++
// Don't forget to add : #include <com/sun/star/text/XBookmarksSupplier.hpp>
// Don't forget to add "com.sun.star.text.XBookmarksSupplier \" in the makefile
    Reference< XBookmarksSupplier> xBookmarksSupplier (xTextDocument,UNO_QUERY);
// Don't forget to add : using namespace com::sun::star::container;
    Reference< XNameAccess > xNameAccess = xBookmarksSupplier->getBookmarks();
    Any bookmark = xNameAccess->getByName(OUString::createFromAscii("Signet1"));
 
// Don't forget to add : #include <com/sun/star/text/XTextContent.hpp>
// Don't forget to add "com.sun.star.text.XTextContent \" in the makefile
    Reference< XTextContent >xTextContent (bookmark,UNO_QUERY);
    Reference< XTextRange > xTextRange2 = xTextContent->getAnchor();
    xText->insertString(xTextRange2,
				OUString::createFromAscii("My bookmark is here "),true);

Notez que Robert MEAILLE a posté une procédure pour réaliser cette tâche ici : oooforum

Voir aussi com.sun.star.text.XBookmarksSupplier et com.sun.star.text.XTextContent.

Je montre comment utiliser cette procédure en commençant par l'expliquer, et en l'utilisant ensuite.

 
//Listing 26 Procedure pour atteindre un signet nommé
// C++
/***************************************************************************** 
***************************************************************************** 
* 
* Simple client application for MailMerge, acces Boomark, print and close file. 
* by Robert MEAILLE 01/12/2005 
* 
***************************************************************************** 
*****************************************************************************/ 
void signet( OUString nameBookmark, OUString texte, Reference< XComponent > xComponent , long type ) 
{ 
	Reference< XBookmarksSupplier > xBookmarksSupplier (xComponent, UNO_QUERY); 
	if( !xBookmarksSupplier.is() ) 
	{ 
		printf( "XBookmarksSupplier Not successfully instanciated\n" ); 
	} 
 
	Reference< XNameAccess > xNamedBookmarks = xBookmarksSupplier->getBookmarks(); 
	Any xBookmark = xNamedBookmarks->getByName( nameBookmark ) ; 
	Reference< XTextContent > rBookmark (xBookmark, UNO_QUERY); 
	Reference< XTextRange > xTextRange = rBookmark->getAnchor() ; //->getStart() ; 
	Reference< XText > xText = xTextRange->getText() ; 
	Reference< XTextCursor > xTextCursor = xText->createTextCursorByRange( xTextRange ) ; 
	if( type == 0 ) // Insertion d'un texte au niveau d'un signet 
		xText->insertString( xTextRange, texte, 1 ) ; 
	else	 // Insertion d'un fichier niveau d'un signet 
	{ 
		Reference< XDocumentInsertable > xDocumentInsertable (xTextCursor, UNO_QUERY);
// Don't forget to add : #include <com/sun/star/document/XDocumentInsertable.hpp>
// Don't forget to add "com.sun.star.document.XDocumentInsertable \" in the makefile    
// Don't forget to add : using namespace com::sun::star::document;  		 
		xDocumentInsertable->insertDocumentFromURL( texte, 
					Sequence < ::	com::sun::star::beans::PropertyValue >() ) ; 
	} 
}

(Voir aussi com.sun.star.text.XTextContent, com.sun.star.text.XTextRange, com.sun.star.text.XText, com.sun.star.text.XTextCursor, com.sun.star.container.XNameAccess et com.sun.star.document.XDocumentInsertable).

Remplacez le Listing 25 avec le Listing 26 et le Listing 27 ci-après, et cela fonctionne comme le premier code présenté :

//Listing 27 Using a Bookmark with  R. MEAILLE's Code
// C++
....
signet( OUString::createFromAscii("Signet1"), 
		OUString::createFromAscii("My bookmark is here "),
 		xWriterComponent , 0); 
....

Tableaux dans un document Writer

Pour insérer un tableau dans un document Writer supposé ouvert, avec un curseur d'écriture positionné où vous voulez insérer ce tableau, nous montrons maintenant comment insérer un tableau de 4 lignes et 4 colonnes à l'aide de l'interface com.sun.star.text.XTextTable :

//Listing 28 Insérer un Tableau dans un document OOoWriter
// C++
// Saut à la fin du texte
   xTextCursor->gotoEnd(false);
 
// Create a new text table from the document's factory
// Don't forget to add : #include <com/sun/star/text/XTextTable.hpp>
// Don't forget to add "com.sun.star.text.XTextTable \" in the makefile
// getting MSF of the document
   Reference<XMultiServiceFactory> oDocMSF (xTextDocument,UNO_QUERY);
   Reference <XTextTable> xTable (oDocMSF->createInstance(
			OUString::createFromAscii("com.sun.star.text.TextTable")),UNO_QUERY);
   if (!xTable.is()) {
	printf("Erreur creation XTextTable interface !\n");
	return 1;
   }
 
// Specify that we want the table to have 4 rows and 4 columns
   xTable->initialize(4, 4);
   xTextRange = xText->getEnd();
 
// Don't forget to add : #include <com/sun/star/text/XTextContent.hpp>
// Don't forget to add "com.sun.star.text.XTextContent \" in the makefile
   Reference <XTextContent>xTextContent (xTable,UNO_QUERY);
 
// Insert the table into the document
   xText->insertTextContent(xTextRange, xTextContent,(unsigned char) 0);

Vous pouvez voir ci-dessous le tableau vide qui sera inséré dans votre document :

















Comme vous pouvez le constater l'interface com.sun.star.text.XTextTable est votre ami. Voyons en détail les méthodes fournies par cette interface à travers le fichier IDL correspondant :

//Listing 29 The XTextTable Service
// IDL
module com {  module sun {  module star {  module text { 
interface XTextTable: com::sun::star::text::XTextContent
{ 
	void initialize( [in] long nRows, 
			 [in] long nColumns ); 
	com::sun::star::table::XTableRows getRows(); 
	com::sun::star::table::XTableColumns getColumns(); 
	com::sun::star::table::XCell getCellByName( [in] string aCellName ); 
	sequence<string> getCellNames(); 
	com::sun::star::text::XTextTableCursor createCursorByCellName( [in] string aCellName );  
}; 
}; }; }; };

En lisant ce listing, on voit au moins deux autres interfaces intéressantes : com.sun.star.table.XCell et com.sun.star.text.XTextTableCursor que nous examinons maintenant.

//Listing 30 The XTextTableCursor Service
// IDL
module com {  module sun {  module star {  module text { 
interface XTextTableCursor: com::sun::star::uno::XInterface
{ 
	string getRangeName(); 
	boolean gotoCellByName( [in] string aCellName, 
			 [in] boolean bExpand ); 
	boolean goLeft( [in] short nCount, 
			 [in] boolean bExpand ); 
	boolean goRight( [in] short nCount, 
			 [in] boolean bExpand ); 
	boolean goUp( [in] short nCount, 
			 [in] boolean bExpand ); 
	boolean goDown( [in] short nCount, 
			 [in] boolean bExpand ); 
	void gotoStart( [in] boolean bExpand ); 
	void gotoEnd( [in] boolean bExpand ); 
	boolean mergeRange(); 
	boolean splitRange( [in] short nCount, 
			 [in] boolean bHorizontal );  
}; 
}; }; }; };

On sait maintenant comment naviguer à travers le tableau. Dans notre exemple ci-dessous, on va utiliser la méthode getCellByName pour atteindre une cellule particulière et obtenir l'interface com.sun.star.table.XCell correspondante.

//Listing 31 The XCell Service
// IDL
module com {  module sun {  module star {  module table {
interface XCell: com::sun::star::uno::XInterface
{
	string getFormula();
	void setFormula( [in] string aFormula );
	double getValue();
	void setValue( [in] double nValue );
	com::sun::star::table::CellContentType getType();
	long getError();
}; 
}; }; }; };

Nous donnons maintenant un programme pour changer les couleurs de fond dans le tableau et pour écrire quelque chose dans les cellules. Il est nécessaire d'ajouter le code du Listing 28 si vous désirez un fonctionnement complet. (voir aussi les interfaces com.sun.star.beans.XPropertySet et com.sun.star.table.XTableRows)

//Listing 32 Changer les couleurs de fond et écrire dans les cellules
// C++
 
// Get the property set of the text table
// Don't forget to add : using namespace com::sun::star::beans;
// Don't forget to add : #include <com/sun/star/beans/XPropertySet.hpp>
// Don't forget to add "com.sun.star.beans.XPropertySet \" in the makefile
   Reference<XPropertySet> xTableProps (xTable,UNO_QUERY);
   Any prop;
   prop <<= (sal_Bool)false;
   xTableProps->setPropertyValue(OUString::createFromAscii("BackTransparent"),prop);
   prop <<= (long)0x0000FF; // color blue
   xTableProps->setPropertyValue(OUString::createFromAscii("BackColor"),prop);
 
// I want to change the first row color
// Don't forget to add : using namespace com::sun::star::table;
// Don't forget to add : #include <com/sun/star/table/XTableRows.hpp>
// Don't forget to add "com.sun.star.table.XTableRows \" in the makefile
   Reference<XTableRows> xTableRows = xTable->getRows();
   Reference<XIndexAccess> theRows (xTableRows,UNO_QUERY);
   Reference<XPropertySet> xRowProps (theRows->getByIndex((short)0),UNO_QUERY);
   prop <<= (sal_Bool)false;
   xRowProps->setPropertyValue(OUString::createFromAscii("BackTransparent"),prop);
   prop <<= (long)0x000099;
   xRowProps->setPropertyValue(OUString::createFromAscii("BackColor"),prop);
 
// it's time to add some text now
   Reference<XCell> xCell = xTable->getCellByName(OUString::createFromAscii("A1"));
   xText = Reference<XText>(xCell,UNO_QUERY);
   xTextCursor = xText->createTextCursor();
   xTextCursor->setString(OUString::createFromAscii("Titre1"));   
   xCell = xTable->getCellByName(OUString::createFromAscii("A2"));
   xCell->setValue(17);
   xCell = xTable->getCellByName(OUString::createFromAscii("A3"));
   xCell->setValue(14);
   xCell = xTable->getCellByName(OUString::createFromAscii("A4"));
   xCell->setFormula(OUString::createFromAscii("=sum(<A2>|<A3>)"));
   xCell = xTable->getCellByName(OUString::createFromAscii("B1"));
   xText = Reference<XText>(xCell,UNO_QUERY);
   xTextCursor = xText->createTextCursor();
   Reference<XPropertySet> oCPS(xTextCursor,UNO_QUERY);
   prop <<= (long)0xFF0000; // color red  
   oCPS->setPropertyValue(OUString::createFromAscii("CharColor"),prop);
   xTextCursor->setString(OUString::createFromAscii("Titre2"));
   xCell = xTable->getCellByName(OUString::createFromAscii("B2"));
   xCell->setValue(20);
   xCell = xTable->getCellByName(OUString::createFromAscii("B3"));
   xCell->setValue(5);
   xCell = xTable->getCellByName(OUString::createFromAscii("B4"));
   xCell->setFormula(OUString::createFromAscii("=<B2>*<B3>"));

Le tableau ci-dessous nous montre le résultat correspondant avec un tel code :

Titre1

Titre2



17

20



14

5



31

100



Traduire le code Java en C++

On commence avec un exemple trouvé dans un OOoForum sous le nom : Setting the page properties/margins directly from java Voici le code java :

//Listing 114
// Java
// create new writer document and get text, then manipulate text 
 XComponent xWriterComponent = newDocComponent("swriter"); 
 XTextDocument xTextDocument = (XTextDocument)UnoRuntime.queryInterface(XTextDocument.class,xWriterComponent); 
 // Access the text document's multi service factory, which we will need for most of the 
 // following examples 
 mxDocFactory = (XMultiServiceFactory) UnoRuntime.queryInterface
		(XMultiServiceFactory.class,xTextDocument); 
 XText xText = xTextDocument.getText(); 
 // create a text cursor from the cells XText interface 
 XTextCursor xTextCursor = xText.createTextCursor(); 
 // Get the property set of the cell's TextCursor 
 XPropertySet xTextCursorProps = (XPropertySet)UnoRuntime.queryInterface
		(XPropertySet.class,xTextCursor); 
 // Page Style name 
 String pageStyleName= xTextCursorProps.getPropertyValue("PageStyleName").toString(); 
 // Get the StyleFamiliesSupplier interface of the document 
 XStyleFamiliesSupplier xSupplier = (XStyleFamiliesSupplier) UnoRuntime.queryInterface
		(XStyleFamiliesSupplier.class,xTextDocument); 
 // Use the StyleFamiliesSupplier interface to get the XNameAccess interface of the 
 // actual style families 
 XNameAccess xFamilies = (XNameAccess)UnoRuntime.queryInterface(XNameAccess.class,
		 xSupplier.getStyleFamilies()); 
 // Access the 'PageStyles' Family 
 XNameContainer xFamily = (XNameContainer) UnoRuntime.queryInterface
		(XNameContainer.class,xFamilies.getByName("PageStyles")); 
 // Insert the newly created style into the PageStyles family 
 XStyle xStyle= (XStyle) UnoRuntime.queryInterface(XStyle.class,xFamily.getByName
		(pageStyleName)); 
 // Get the property set of the TextCursor 
 XPropertySet xStyleProps = (XPropertySet)UnoRuntime.queryInterface
		(XPropertySet.class,xStyle); 
 xStyleProps.setPropertyValue("LeftMargin",new Short((short)1200)); 
 xStyleProps.setPropertyValue("RightMargin",new Short((short)1200)); 
 xStyleProps.setPropertyValue("BottomMargin",new Short((short)1200));

En consultant les interfaces correspondantes, com.sun.star.text.XTextDocument, com.sun.star.beans.XPropertySet, com.sun.star.style.XStyleFamiliesSupplier, com.sun.star.container.XNameContainer et com.sun.star.style.XStyle, on peut traduire en C++ ce qui donne :

//Listing 115
// C++
// create new writer document and get text, then manipulate text 
 
// N'oubliez pas d'ajouter : using namespace com::sun::star::text;
// N'oubliez pas d'ajouter : #include <com/sun/star/text/XTextDocument.hpp>
// N'oubliez pas d'ajouter "com.sun.star.text.XTextDocument \" in the makefile
 
// N'oubliez pas d'ajouter : using namespace com::sun::star::beans;
// N'oubliez pas d'ajouter : #include <com/sun/star/beans/XPropertySet.hpp>
// N'oubliez pas d'ajouter "com.sun.star.beans.XPropertySet \" in the makefile
// N'oubliez pas d'ajouter : using namespace com::sun::star::style;
// N'oubliez pas d'ajouter : #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
// N'oubliez pas d'ajouter "com.sun.star.style.XStyleFamiliesSupplier \" in the makefile
// N'oubliez pas d'ajouter : using namespace com::sun::star::container;
 
// N'oubliez pas d'ajouter : #include <com/sun/star/container/XNameContainer.hpp>
// N'oubliez pas d'ajouter "com.sun.star.container.XNameContainer \" in the makefile
 
// N'oubliez pas d'ajouter : #include <com/sun/star/style/XStyle.hpp>
// N'oubliez pas d'ajouter "com.sun.star.style.XStyle \" in the makefile
 
// the first line cannot be translated : already done in our main()
// XComponent xWriterComponent = newDocComponent("swriter"); 
 
	Reference < XTextDocument > xTextDocument (xWriterComponent,UNO_QUERY);
 // Access the text document's multi service factory, which we will need for most of the
 // following examples
	Reference< XMultiServiceFactory > mxDocFactory(xTextDocument,UNO_QUERY);
	Reference< XText > xText = xTextDocument->getText();
 // create a text cursor from the cells XText interface
	Reference< XTextCursor > xTextCursor = xText->createTextCursor(); 
 
 // Get the property set of the cell's TextCursor
	Reference< XPropertySet > xTextCursorProps(xTextCursor,UNO_QUERY); 
 
 // Page Style name 
 //*** I add a intermediate variable because of Any type returned by getPropertyValue 
	Any pageStyleName2 = xTextCursorProps->getPropertyValue
							(OUString::createFromAscii("PageStyleName"));
	OUString pageStyleName;
	pageStyleName2 >>= pageStyleName ;
 
  // Get the StyleFamiliesSupplier interface of the document
	Reference< XStyleFamiliesSupplier > xSupplier(xTextDocument,UNO_QUERY);
 
 // Use the StyleFamiliesSupplier interface to get the XNameAccess interface of the
 // actual style families
	Reference< XNameAccess > xFamilies(xSupplier->getStyleFamilies(),UNO_QUERY);
 
 // Access the 'PageStyles' Family 
	Reference< XNameContainer > xFamily(xFamilies->getByName
				(OUString::createFromAscii("PageStyles")),UNO_QUERY);
// Insert the newly created style into the PageStyles family
	Reference< XStyle > xStyle(xFamily->getByName(pageStyleName),UNO_QUERY);
 
 // Get the property set of the TextCursor 
	Reference< XPropertySet > xStyleProps(xStyle,UNO_QUERY);
	Any lm, rm, bm;
	lm<<=(short)1200; rm<<=(short)1200; bm<<=(short)1200;
	xStyleProps->setPropertyValue(OUString::createFromAscii("LeftMargin"),lm);
	xStyleProps->setPropertyValue(OUString::createFromAscii("RightMargin"),rm);
	xStyleProps->setPropertyValue(OUString::createFromAscii("BottomMargin"),bm);

Ma compétence sur le type "ANY" n'est pas assez complète, alors je ne trouve pas de moyen direct d'utiliser "Any" autre qu'en utilisant des variables intermédiaires. Voyez les trois dernières lignes par exemple.

Aller plus loin avec l'Inspector Java

Inspector Java 1.0

Je ne connais pas la façon de numéroter les versions de l'inspecteur Java, mais ce que j'appelle la version 1.0 correspond à la première version capable de gérer la génération de code.

The new object inspector est capable de générer du code Java, C++ ou OOoBasic. Dans le but de tester son aptitude à générer du code C++, nous allons l'utiliser dans le problème suivant : obtenir le texte sélectionné d'un document Writer. Voici une copie d'écran :

Ch7Inspector5.png

Voir aussi le problème correspondant en OOoBasic ici (en anglais).

Arbre IDL : J'appellerai un arbre IDL dans ce document l'arbre de parcours à travers les methods/properties/interfaces/services. En d'autres termes, le new object inspector nous permet de traverser un arbre IDL de haut en bas. Le haut est en général le document (mais pas forcément), et le bas est la méthode que l'on veut invoquer (invoke).

Documentation caution.png La difficulté de la programmation UNO est reportée ici sur la recherche d'un chemin à travers l'arbre IDL, pour résoudre le problème posé, et c'est pas toujours facile. Il existe d'abord plusieurs chemins et je ne suis pas sûr que le code généré soit d'égale qualité suivant les chemins choisis. Si vous n'avez jamais utilisé UNO, vous n'avez aucune chance de vous y retrouver dans tous ces chemins possibles. Cette section ne peut donc en aucun cas remplacer tout le reste du document.


Représentation textuelle d'un arbre IDL

Après lancement du new object inspector, on peut traverser l'arbre IDL comme décrit ci-dessous et aussi montré (en partie) dans la copie d'écran juste après.

MyDocument ->methods
  ->com.sun.star.frame.XController getCurrentController()
    ->xController->methods
      -> Any getSelection
        ->XInterface
          ->methods
           -> Any getByIndex
            -> XTextRange
             ->getString
Documentation note.png Note 1 : quand on double clique sur getByIndex un index est requis et donc demandé dans une boite de dialogue. Pour nous, c'est 0 le premier (et le seul) index de la zone de texte.
Documentation note.png Note 2 : essayez de voir la relation entre la notation en arbre et l'image ci-dessous. Pour obtenir le résultat "Hello World" il vous faut invoquet getString avec l'Inspector Java.

Représentation de type Introspection d'un arbre IDL

Voici en partie une copie d'écran pour l'arbre IDL :

The New Object Inspector (Java)

Utilisation du code C++ généré

Le code C++ correspondant automatiquement généré est montré plus loin en listing 115. Il utilise les interfaces com.sun.star.uno.XInterface, com.sun.star.frame.XModel, com.sun.star.frame.XController, com.sun.star.view.XSelectionSupplier, com.sun.star.container.XIndexAccess et com.sun.star.text.XTextRange interfaces).

// Listing 115
// C++
#include "com/sun/star/view/XSelectionSupplier.hpp"
#include "rtl/ustring.hxx"
#include "sal/config.h"
#include "sal/types.h"
 
namespace css = com::sun::star;
using namespace rtl;
 
//...
void codesnippet(const css::uno::Reference<css::uno::XInterface>& _oUnoEntryObject ){{
	css::uno::Reference<css::frame::XModel> xModel( _oUnoEntryObject, css::uno::UNO_QUERY_THROW);
	css::uno::Reference<css::frame::XController> xController = xModel->getCurrentController();
	css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier( xController, css::uno::UNO_QUERY_THROW);
	css::uno::Reference<XInterface> oSelection = xSelectionSupplier->getSelection();
	css::uno::Reference<css::container::XIndexAccess> xIndexAccess( oSelection, css::uno::UNO_QUERY_THROW);
	css::uno::Reference<XInterface> oIndex = xIndexAccess->getByIndex(0);
	css::uno::Reference<css::text::XTextRange> xTextRange( oIndex, css::uno::UNO_QUERY_THROW);
	OUString sString = xTextRange->getString();
}
//...

Ce code ne fonctionne malheureusement pas correctement à cause de la mauvaise façon de gérer le type "Any" dans l'Inspcteur Java (c'est un code Java en développement qui est destiné à être porté en C++ un jour) :

void codesnippet(const css::uno::Reference<css::uno::XInterface>& _oUnoEntryObject ){
css::uno::Reference<css::frame::XModel> xModel( _oUnoEntryObject, css::uno::UNO_QUERY_THROW);
	css::uno::Reference<css::frame::XController> xController = xModel->getCurrentController();
	css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier( xController, css::uno::UNO_QUERY_THROW);
//	css::uno::Reference<XInterface> oSelection = xSelectionSupplier->getSelection();
	Any Selection = xSelectionSupplier->getSelection();
	Reference<XInterface> oSelection(Selection,css::uno::UNO_QUERY_THROW);
	css::uno::Reference<css::container::XIndexAccess> xIndexAccess( oSelection, css::uno::UNO_QUERY_THROW);
//	css::uno::Reference<XInterface> oIndex = xIndexAccess->getByIndex(0);
	Any Index = xIndexAccess->getByIndex(0);
	css::uno::Reference<XInterface> oIndex(Index,css::uno::UNO_QUERY_THROW);
	css::uno::Reference<css::text::XTextRange> xTextRange( oIndex, css::uno::UNO_QUERY_THROW);
	OUString sString = xTextRange->getString();
	OString OStr = OUStringToOString( sString, RTL_TEXTENCODING_ASCII_US );
	printf( "OUStr was : %s\n", OStr.pData->buffer );
}

Vous pouvez voir comment le type Any est géré en deux étapes dans ce nouveau code modifié à la main. J'ai mis le vieux code en commentaire et ajouté un peu de code pour afficher le résultat du texte sélectionné. Pour retrouver le document ouvert par défaut, on ajoute simplement ce code :

main( ) {
//retrieve an instance of the remote service manager
	Reference< XMultiServiceFactory > xServiceManager;
    	xServiceManager = ooConnect();
    	if( xServiceManager.is() ){
        	printf( "Connected sucessfully to the office\n" );
    	}
//get the desktop service using createInstance returns an XInterface type
    	Reference< XInterface  > Desktop = xServiceManager->createInstance(
    		OUString::createFromAscii( "com.sun.star.frame.Desktop" ));	
//query the XDesktop Interface
	Reference< XDesktop > xDesktop (Desktop, UNO_QUERY);
	Reference< XComponent > xcomponent = xDesktop->getCurrentComponent(); 	
// call Inspector code
        codesnippet(xcomponent);
	return 0;
}
Documentation caution.png L'autre problème est avec les directives d'inclusions : elles ne sont pas toujours toutes générées.


Tous les problèmes rencontrés dans cette section m'ont décidé d'écrire un chapitre séparé sur the new object inspector et le C++.

Java Inspector 2

The new object inspector 2.0.0 est disponible depuis Janvier 2009 en version béta. Quelques essais sous Linux et sous Windows montrent très bien que cet inspecteur est en version de développement. Il semble générer à peu près correctement le code Java et OOoBasic mais pas le C++. Avec le C++, le problème est que, le même code est toujours généré de manière indépendante de l'endroit où vouv vous trouvez dans l'arbre IDL.

Documentation caution.png Je suis incapable de traverser le même arbre IDL avec le nouvel Inspector 2.0
MyDocument ->methods
  ->com.sun.star.frame.XController getCurrentController()
    ->xController->methods
      -> Any getSelection
        ->XInterface
          ->methods
           -> Any getByIndex <--------- IMPOSSIBLE ICI !!!!!
            -> XTextRange
             ->getString

Invoker getByIndex et vous verrez qu'il est incapable de prendre mon index quelque soit sa valeur. Gardez donc l'ancien Inspecteur Java sous la main si vous voulez travailler avec le C++. SergeMoutou 20:06, 6 February 2009 (UTC)

Plus sur la comparaison des deux version : Object Inspector Comparison en Anglais

Retour à la page d'accueil

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


Voir aussi

Personal tools