Difference between revisions of "FR/Documentation/OpenOffice Writer"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (Créer, ouvrir un document writer)
m (Traduire le code Java en C++)
Line 243: Line 243:
 
         Sequence < ::com::sun::star::beans::PropertyValue >());
 
         Sequence < ::com::sun::star::beans::PropertyValue >());
 
</source>
 
</source>
 +
 +
=Managing Text=
 +
==Finding the Text  ==
 +
We show here how we can find the text, or more exacly the XText interface.
 +
<source lang="cpp"> 
 +
//Listing 13 Getting XText Interface
 +
// 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();
 +
</source>
 +
The more interesting thing is to do something visible (I mean to remove or to add text).
 +
 +
See also <idl>com.sun.star.text.XTextDocument</idl> and <idl>com.sun.star.text.XText</idl>.
 +
 +
==Writing any Text in the Document==
 +
The simplest way of writing text in a document is the setString method of the XText interface. This way gives us this code :
 +
<source lang="cpp">
 +
//Listing 14 Writing some Text in a OOoWriter Document
 +
// 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"));
 +
</source>
 +
But what happens if we replace the last line by the two below :
 +
<source lang="cpp">
 +
//Listing 15 More on setString Method (XText Interface)
 +
// C++
 +
    xText->setString(OUString::createFromAscii("Hello"));
 +
    xText->setString(OUString::createFromAscii(" All around the world"));
 +
</source>
 +
Answer : only « All around the world » is printed. That works as expected : setString is setString. Therefore if we want to put text and after add other text an other way has to be discovered.
 +
 +
See also <idl>com.sun.star.text.XTextDocument</idl> and <idl>com.sun.star.text.XText</idl>.
 +
 +
==Managing Text with XTextRange Interface==
 +
The XTextRange interface is able to manage text with a setString method but keeping the old text. For instance if you want to open a document, and to add text at the beginning a way is to use getStart() method like this :
 +
<source lang="cpp">
 +
//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 "));
 +
</source>
 +
The getEnd() method can be used too.
 +
 +
See also <idl>com.sun.star.text.TextRange</idl>.
 +
 +
We see here how to insert something at the beginning or at the end of a document. If you want to manage the location where inserting more accurately the XCursorText interface is your friend.
 +
 +
==The XTextCursor Interface ==
 +
The Developer's Guide states :
 +
The above code is not very flexible. To gain flexibility, create a text cursor that is a movable text range. Note that such a text cursor is not visible in the user interface. Since XTextCursor inherits from XTextRange, a cursor is an XTextRange and incorporates the methods of an XTextRange:
 +
<pre>
 +
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)
 +
</pre>
 +
As seen, the setString method is also available and works like the previous one.
 +
<source lang="cpp">
 +
//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"));
 +
</source>
 +
 +
See also <idl>com.sun.star.text.XTextCursor</idl>.
 +
 +
A new question : what happens if we use this code but with instanciating a second time the cursor variable between the two setString calls ?
 +
<source lang="cpp">
 +
//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"));
 +
</source>
 +
Answer : « all around the worldHello  » is written showing that when you initialize a XTextCursor, the cursor is always at the beginning of the document.
 +
 +
See also <idl>com.sun.star.text.XTextCursor</idl>, <idl>com.sun.star.text.XText</idl> and <idl>com.sun.star.text.XTextDocument</idl>.
 +
 +
If you want your text in the right place you can use this code :
 +
<source lang="cpp">
 +
//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"));
 +
</source>
 +
 +
 +
where the goRight method is used. This is not the right way to do : instanciating two times the xTextCursor variable. But this code shows us  what we can do with a cursor : move it. Of course goLeft method exists too. The corresponding IDL file is given now :
 +
<source lang="idl">
 +
//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 );
 +
};
 +
}; }; }; };
 +
</source>
 +
What can really be done with this interface is given in [OpenOffice.org1.1_SDK]/idl/com/sun/star/text/TextCursor.idl service. In fact [[Constructing_Helpers#Reflection_Helper|introspection]]  of XTextCursor shows me the methods below are available :
 +
<pre>
 +
...
 +
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)
 +
...
 +
</pre>
 +
But as usual they are not directely available, and a UNO_QUERY is required. To give an example where we use a gotoEndOfWord, we first modify the program to read a file instead of creating a blank file and then ask a XWordCursor interface :
 +
<source lang="cpp">
 +
//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"));
 +
</source>
 +
Have a look to XWordCursor.idl file to learn what is possible to do with xWordCursor variable in the previous example. To go further have a look at [[IDL_Files_and_Cpp#Translating_OOoBasic_programs_into_C.2B.2B | Translating OOoBasic programs into C++.]]
 +
 +
See also <idl>com.sun.star.text.XTextDocument</idl> and <idl>com.sun.star.text.XWordCursor</idl>.
 +
 +
==The insertString Method==
 +
The Developer's Guide states :
 +
The cursor can be told where it is required and the string content can be set later. This does have a drawback. After setting the string, the inserted string is always selected. That means further text can not be added without moving the cursor again. Therefore the most flexible method to insert strings by means of a cursor is the method insertString() in XText. It takes an XTextRange as the target range that is replaced during insertion, a string to insert, and a boolean parameter that determines if the inserted text should be absorbed by the cursor after it has been inserted. The XTextRange could be any XTextRange. The XTextCursor is an XTextRange, so it is used here:
 +
<pre>
 +
void insertString( [in] com::sun::star::text::XTextRange xRange,
 +
[in] string aString,
 +
[in] boolean bAbsorb)
 +
</pre>
 +
To insert text sequentially the bAbsorb parameter must be set to false, so that the XTextRange collapses at the end of the inserted string after insertion. If bAbsorb is true, the text range selects the new inserted string. The string that was selected by the text range prior to insertion is deleted.
 +
 +
Consider the use of insertString() below:
 +
<source lang="cpp">
 +
//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);
 +
</source>
 +
This program take the third word and remplace it with «We are here». At first I want to use something like
 +
<pre>
 +
xTextRange = xWordCursor->getStart();
 +
</pre>
 +
to retrieve the XTextRange interface I need in the insertString. It only partially works because the selecting information was losed and then I was never able to replace the word selected by the instruction :
 +
<pre>
 +
xWordCursor->gotoNextWord(true);
 +
</pre>
 +
  
 
=Traduire le code Java en C++=
 
=Traduire le code Java en C++=

Revision as of 12:08, 8 July 2008

Dans ce chapitre, nous utilisons encore le code initial décrit dans chapitre 3.3. Il consiste en un sous-programme “ooConnect ()” et un programme principal main(). Travailler avec ce code consiste à ajouter le nouveau code dans le programme principal. Nous donnons pour la troisième fois le programme principal :

//Listing 1
// C++ 
// adapted for OOoWriter
int main( ) {
//retrieve an instance of the remote service manager
    Reference< XMultiServiceFactory > rOfficeServiceManager;
    rOfficeServiceManager = ooConnect();
    if( rOfficeServiceManager.is() ){
        printf( "Connected sucessfully to the office\n" );
    }
 
//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);
    if( rComponentLoader.is() ){
        	printf( "XComponentloader successfully instanciated\n" );
    	}
 
//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 >());
// AJOUTER votre code ici
    return 0;
}

Nous rappelons au lecteur que les exemples ci-dessous, prennent comme code de départ l'exemple “<OpenOffice.org1.1_SDK>/examples/DevelopersGuide/ProfUNO/CppBinding”. Notre code est mis dans “office_connect.cxx” et nous ajoutons ce que vous trouvez comme commentaires dans le code (directives d'inclusions et définitions des espaces de nommage) ainsi que dans le makefile (en général pour créer les fichiers hpp et hxx).

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 XDispatcherHelper.

//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 (en anglais) (si vous n'êtes pas débutant) et vous comprendrez alors ce listing.

La deuxième étape est d'obtenir l'interface XFrame en partant de la variable Desktop (bureau) et après d'obtenir l'interface XDispatchProvider starting en partant de la variable frame qui contient le service 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 :

//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 >());

Managing Text

Finding the Text

We show here how we can find the text, or more exacly the XText interface.

 
//Listing 13 Getting XText Interface
// 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();

The more interesting thing is to do something visible (I mean to remove or to add text).

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

Writing any Text in the Document

The simplest way of writing text in a document is the setString method of the XText interface. This way gives us this code :

//Listing 14 Writing some Text in a OOoWriter Document
// 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"));

But what happens if we replace the last line by the two below :

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

Answer : only « All around the world » is printed. That works as expected : setString is setString. Therefore if we want to put text and after add other text an other way has to be discovered.

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

Managing Text with XTextRange Interface

The XTextRange interface is able to manage text with a setString method but keeping the old text. For instance if you want to open a document, and to add text at the beginning a way is to use getStart() method like this :

//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 "));

The getEnd() method can be used too.

See also com.sun.star.text.TextRange.

We see here how to insert something at the beginning or at the end of a document. If you want to manage the location where inserting more accurately the XCursorText interface is your friend.

The XTextCursor Interface

The Developer's Guide states : The above code is not very flexible. To gain flexibility, create a text cursor that is a movable text range. Note that such a text cursor is not visible in the user interface. Since XTextCursor inherits from XTextRange, a cursor is an XTextRange and incorporates the methods of an 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)

As seen, the setString method is also available and works like the previous one.

//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"));

See also com.sun.star.text.XTextCursor.

A new question : what happens if we use this code but with instanciating a second time the cursor variable between the two setString calls ?

//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"));

Answer : « all around the worldHello  » is written showing that when you initialize a XTextCursor, the cursor is always at the beginning of the document.

See also com.sun.star.text.XTextCursor, com.sun.star.text.XText and com.sun.star.text.XTextDocument.

If you want your text in the right place you can use this 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"));


where the goRight method is used. This is not the right way to do : instanciating two times the xTextCursor variable. But this code shows us what we can do with a cursor : move it. Of course goLeft method exists too. The corresponding IDL file is given now :

//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 );
};
}; }; }; };

What can really be done with this interface is given in [OpenOffice.org1.1_SDK]/idl/com/sun/star/text/TextCursor.idl service. In fact introspection of XTextCursor shows me the methods below are available :

...
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)
...

But as usual they are not directely available, and a UNO_QUERY is required. To give an example where we use a gotoEndOfWord, we first modify the program to read a file instead of creating a blank file and then ask a XWordCursor interface :

//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"));

Have a look to XWordCursor.idl file to learn what is possible to do with xWordCursor variable in the previous example. To go further have a look at Translating OOoBasic programs into C++.

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

The insertString Method

The Developer's Guide states : The cursor can be told where it is required and the string content can be set later. This does have a drawback. After setting the string, the inserted string is always selected. That means further text can not be added without moving the cursor again. Therefore the most flexible method to insert strings by means of a cursor is the method insertString() in XText. It takes an XTextRange as the target range that is replaced during insertion, a string to insert, and a boolean parameter that determines if the inserted text should be absorbed by the cursor after it has been inserted. The XTextRange could be any XTextRange. The XTextCursor is an XTextRange, so it is used here:

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

To insert text sequentially the bAbsorb parameter must be set to false, so that the XTextRange collapses at the end of the inserted string after insertion. If bAbsorb is true, the text range selects the new inserted string. The string that was selected by the text range prior to insertion is deleted.

Consider the use of insertString() below:

//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);

This program take the third word and remplace it with «We are here». At first I want to use something like

xTextRange = xWordCursor->getStart();

to retrieve the XTextRange interface I need in the insertString. It only partially works because the selecting information was losed and then I was never able to replace the word selected by the instruction :

xWordCursor->gotoNextWord(true);


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 C++ cela 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.

Personal tools