Difference between revisions of "Writer/API/Overview"
SergeMoutou (Talk | contribs) m (→See also) |
SergeMoutou (Talk | contribs) m (→Java Inspector 1.0) |
||
Line 705: | Line 705: | ||
[[Image:ch7Inspector4.png|The New Object Inspector (Java)]] | [[Image:ch7Inspector4.png|The New Object Inspector (Java)]] | ||
− | The corresponding automatically generated C++ code is : | + | The corresponding automatically generated C++ code is shown below (with <idl>com.sun.star.uno.Interface</idl>, <idl>com.sun.star.frame.XModel</idl>, <idl>com.sun.star.frame.XController</idl>, <idl>com.sun.star.view.XSelectionSupplier</idl>, <idl>com.sun.star.container.XIndexAccess</idl> and <idl>com.sun.star.text.XTextRange</idl> interfaces) : |
<source lang="cpp"> | <source lang="cpp"> |
Revision as of 18:44, 12 March 2009
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 1 Our starting Code // 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 >()); // add code here return 0; }
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.
You can find more explanations here (if you are not a beginner).
If you are familiar with OOoBasic you can have a look here
Contents
- 1 Using the Dispatcher and recording Macros
- 2 Creating, opening a Writer Document
- 3 Managing Text
- 4 Accessing the Cursor Properties
- 5 Accessing a Bookmark
- 6 Tables in a Writer Document
- 7 Translating Java Code into C++ (Page Properties)
- 8 Translating Java Code into C++ (inserting an Image)
- 9 Going further with Inspector
- 10 See also
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:
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).
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
Here is a screenshot of part of IDL-tree:
The corresponding automatically generated C++ code is shown below (with com.sun.star.uno.Interface, 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; }
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.
![]() |
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
- Text Documents in Developer's Guide
- Text Documents with OOoBasic
- C++ and UNO tutorial
- Using OOoBasic
- Writing a Program to Control OpenOffice.org, by Franco Pingiori — Part 1 and Part 2, Linux Journal
- Text cursor in OOoBasic
- The new Object Inspector and Object Inspectors Comparison
- Discussion_of_Bibliographic_-_Writer_proposals