Writer/API/Overview

From Apache OpenOffice Wiki
< Writer(Redirected from Programming OooWriter)
Jump to: navigation, search

Writer Icon.png

Writer Project

Please view the guidelines
before contributing.

Popular Subcategories:

Internal Documentation:

API Documentation:

Ongoing Efforts:

Sw.OpenOffice.org


Edit-find-replace.png This article needs to be checked for accuracy and style.

In this chapter, we use again the starting code described in previous chapter. It consists of a subprogram “ooConnect()” and a main(). Starting with this code consists in adding new code in the main() where « add code here » is quoted in red. We give for the third time the main program :

//Listing 0b Again our starting main Code
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 spreadsheet
    Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
	OUString::createFromAscii("private:factory/scalc"),
        OUString::createFromAscii("_blank"),
        0,
        Sequence < ::com::sun::star::beans::PropertyValue >());
// add code here
    return 0;
}

This code is called a bootstrap and uses :

  1. com.sun.star.lang.XMultiServiceFactory, com.sun.star.uno.XInterface, com.sun.star.frame.XComponentLoader and com.sun.star.lang.XComponent interfaces
  2. com.sun.star.frame.Desktop service
  3. com.sun.star.beans.PropertyValue structure.

Remember each time you query for an interface you have to add code lines (if they don't exist) in the source code and a line in the makefile. I will generally add comments to prevent omissions. You can find more explanations here (if you are not a beginner).

Documentation note.png Important Note : The more important point in the compilation chain of the examples above is that cppumaker will construct every hpp and hdl files you need in your application. The SDK doesn't provide every hpp files, but you have to construt them starting from IDL files provided by SDK.
Documentation note.png It is possible to construct all the hpp files when installing the SDK as mentioned in a Windows installation. It's also possible with other OS. In doing so, you don't need modifying your MakeFile.

We remember the reader that for the examples below we use the “[OpenOffice.org1.1_SDK]/examples/DevelopersGuide/ProfUNO/CppBinding” example. Our code is put in “office_connect.cxx” file. If needed, comments in the code indicate what to add into the makefile and into the source code. The function ooConnect() is also used and not presented here : we have already studied such a function, so it should be quite familiar to us by now. If not, have a look in previous chapter.

If you are familiar with OOoBasic you can have a look here

Using the Dispatcher and recording Macros

The first way we want to examine is the use of the dispatcher before using direct UNO calls in next section. This is a very straightforward way but probably internationalization dependent. If you record a macro, you obtain a OOoBasic code which uses the dispatcher instead of direct UNO call. See The OpenOffice.org recorder and UNO dispatch calls section for a discussion on recording UNO Dispatch commands versus writing API calls.

Introduction

For instance if you have a OOoWriter document, and you record a macro when inserting text and formating it, you obtain something like:

'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

How to translate such a code in C++ ? The problem is to handle the dispatcher.

The first step is to obtain a com.sun.star.frame.XDispatchHelper interface.

//Listing 3 Querying the XDispatchHelper Service
// C++
Reference< XDispatchHelper > rDispatchHelper = Reference< XDispatchHelper >
				( rOfficeServiceManager->createInstance(
                              OUString( RTL_CONSTASCII_USTRINGPARAM(
                              "com.sun.star.frame.DispatchHelper" ))), UNO_QUERY );

(See also com.sun.star.frame.DispatchHelper service) You can find more explanations here (if you are not a beginner) and you will understand this listing.

The second step is to obtain the com.sun.star.frame.XFrame interface starting from Desktop and after obtaining a com.sun.star.frame.XDispatchProvider starting from the previous frame (it seems very important to start from frame).

//Listing 4 Obtaining a XFrame Service
// C++
Reference< XFrame > rFrame=rDesktop->getCurrentFrame();
 
Reference< XDispatchProvider > rDispatchProvider(rFrame,UNO_QUERY);

The third step is to declare your array (Sequence in C++) of “PropertValue” and gives the values :

//Listing 5 The Property pair Name/Value 
// C++
	Sequence < PropertyValue > args1(1);
 
	args1[0].Name = OUString::createFromAscii("Text");
	args1[0].Value <<= OUString::createFromAscii("demo de macro");

and the final step is to call the dispatcher :

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

The rest of OOoBasic code can be now easily translated as shown below :

//Listing 7 Other Dispatch Calls
// 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);

Dispatcher and Internationalization

One of the problem you will encounter with this programming style is : how can we write such programs running everywhere in the world ? If you work with a French OOo and record a macro you will encounter properties' values but in French. For instance, if I record a macro when inserting an image I obtain the OOoBasic code :

'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

where you guess I use a French OpenOffice.org version. If you directly translate this code in C++ you obtain :

//Listing 9 Inserting an 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);

which works properly. Translating it in English still work with my French OOo :

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

But we cannot avoid the question : does the first French version work on all computers ? I have no answer. I suppose the English version works everywhere. And impossible to avoid this second query : how can I know the « <tous les Formats> » is translated by « <All Formats> » in English ?

Creating, opening a Writer Document

We first create a new OOowriter document. That can be done with this below code (see com.sun.star.lang.XComponent):

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

while opening an existing document is done with :

//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 com.sun.star.text.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();

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

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

Writing any Text in the Document

The simplest way of writing text in a document is the setString method of the com.sun.star.text.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.

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 service and com.sun.star.text.XTextRange, com.sun.star.text.XTextDocument, com.sun.star.text.XText interfaces.

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 com.sun.star.text.XTextCursor interface inherits from com.sun.star.text.XTextRange interface, a cursor is an com.sun.star.text.XTextRange interface and incorporates then the methods of an com.sun.star.text.XTextRange interface:

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

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

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 (of type com.sun.star.text.XTextCursor). 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 (see also com.sun.star.text.TextCursor). 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 com.sun.star.text.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 com.sun.star.text.XWordCursor interface 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.

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 com.sun.star.text.XText interface. It takes an com.sun.star.text.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 com.sun.star.text.XTextRange could be any XTextRange. The com.sun.star.text.XTextCursor is an com.sun.star.text.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 com.sun.star.text.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 (see also com.sun.star.text.XWordCursor interface):

//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 com.sun.star.text.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);

Accessing the Cursor Properties

If we want to go further and to use a bold font for instance we need to access the cursor properties. We give an example which start from previous code and put the text added in bold. This can be done with observing that previous code insert a text with last parameter as true. That means the inserted text is selected. If we only change the properties of the cursor it will change the text. Then only adding the above code to listing 22 (see the corresponding com.sun.star.beans.XPropertySet interface, and com.sun.star.awt.FontWeight constants):

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

puts « we are here  » in bold. As already seen here we are confronted here again with constants. BOLD is a constant. It comes from the above IDL file :

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

And the comment in the program indicates how to use these constants.

Accessing a Bookmark

In a document I put a bookmark named « Signet1 ». Then I try to reach it with a program and add text at its place. It can be done with this piece of code :

//Listing 25 Reaching a named Bookmark
// 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);

Note that Robert MEAILLE has posted a procedure to achieve this task here : oooforum

See also com.sun.star.text.XBookmarksSupplier and com.sun.star.text.XTextContent.

I explain how to use this procedure by first presenting the procedure and second providing a call to reach a named bookmark.

 
//Listing 26 Sub to reach a named Bookmark
// 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 >() ) ; 
	} 
}

(See also 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 and com.sun.star.document.XDocumentInsertable).

Replace Listing 25 with Listing 26 and Listing 27 above and it works like first code:

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

Tables in a Writer Document

To go further, we tackle the problem of inserting a table in a writer document. Creating and managing a table can be found here.

Translating Java Code into C++ (Page Properties)

To go further, have a look here where we can find a Java example translated in C++.

Translating Java Code into C++ (inserting an Image)

A second example : insert image contents in a Writer document (in Java) has been published in OOoForum : insert image contents in a Writer document

We can see in that example, the job is done with dispatcher : then Listing 9 and Listing 10 above show how it works in C++.

Going further with Inspector

Java Inspector 1.0

The new object inspector is able to generate Java or C++ or OOoBasic code. In order to try inspector ability to generate C++ code, we want to use it for the following problem : obtaining the selected text from a writer document. Here is a screenshot:

Ch7Inspector5.png

See the corresponding problem in OOoBasic here.

IDL-tree : I will name IDL-tree in this document the methods/properties/interfaces/services tree. In other words, the new object inspector allows you to traverse an IDL-tree top to bottom. Top is in general the document and bottom the method you want to invoke. I have already tackled IDL-Tree in this document but without naming it as a tree. See for instance in XIntrospection Interface and particularly the schematic representation : you don't see a tree, but note that starting from XIDLMethod you have three branches (because the three XIDLMethod are the same). See more on IDL-tree in this document

Path of IDL-tree with a textual Description

After lauching the new object inspector, we can traverse the IDL-tree as described below and also shown after in the corresponding image.

MyDocument ->methods
  ->com.sun.star.frame.XController getCurrentController()
    ->xController->methods
      -> Any getSelection
        ->XInterface
          ->methods
           -> Any getByIndex
            -> XTextRange
             ->getString
Documentation note.png Note 1 : when double clicking on getByIndex an index is required and then asked in a dialog. For us it is 0 the first (and only one) index of the text range.
Documentation note.png Note 2 : try to see the relation between the tree notation above and the image below. To obtain the result "Hello World" you have to invoke getString with Inspector.
Documentation note.png Note 3 : Programming OpenOffice.org is first to learn how to find a path in the IDL-Tree. There is a lot of branches but most of them are useless for your programming problem. You have to choose the branches you want to develop.

Path of IDL-tree with a Introspection Tool

Here is a screenshot of part of IDL-tree:

The New Object Inspector (Java)

The corresponding automatically generated C++ code is shown below (with 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 and com.sun.star.text.XTextRange interfaces) :

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

This code doesn't work properly because of a fault on the "Any" type management. I have modified the code as shown below :

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

You can see how the Any type is managed with two steps. I have put old code in comment and added code to print out the getString result. To retrieve the default opened document this code is added :

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 The other problem is with include statements : they are not properly generated.


All problems met in this section convinced me to write a separate chapter on the new object inspector and C++.

Java Inspector 2

The new object inspector 2.0.0 is available since january 2009 (beta version). Few tries under Linux and under Windows show me that this inspector is still under construction. It generate correctly Java and Basic programs but not C++. With C++ the problem is, the same code is always generated independantly of your location in the IDL tree.

Documentation caution.png I am unable to travel the same IDL-Tree with the new Inspector 2.0
MyDocument ->methods
  ->com.sun.star.frame.XController getCurrentController()
    ->xController->methods
      -> Any getSelection
        ->XInterface
          ->methods
           -> Any getByIndex <--------- broken here !!!!!
            -> XTextRange
             ->getString

The getByIndex invoke is unable to take my index 0. Have the old Java Inspector to hand if you want to work with C++. SergeMoutou 20:06, 6 February 2009 (UTC)

More on comparison between both versions : Object Inspector Comparison

See also

Personal tools