OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

How to get current selected shape(s) in a drawing by Java

 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API
View previous topic :: View next topic  
Author Message
Jick
Guest





PostPosted: Wed Jun 09, 2004 3:24 am    Post subject: How to get current selected shape(s) in a drawing by Java Reply with quote

Hi, I am a newbie in OOo and I started working with OpenOffice API 3 days before.

I have a question about Drawing.

How to get the current selected shape(s) in a drawing by Java?

I have read through the document and I found that the following classes MAY BE useful, but I have no ideas in using them to complete my task.

XSelectionSupplier, XModel


Thank you for your help Smile
Jick
Back to top
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Wed Jun 09, 2004 11:27 am    Post subject: Reply with quote

Here is a simple example in Basic....
Code:
Sub Main
   oDrawDoc = ThisComponent
'   oDrawPage = oDrawDoc.drawPages( 0 )
   
   oController = oDrawDoc.getCurrentController()
   
   oSelection = oController.getSelection()
   
   If IsEmpty( oSelection ) Then
      MsgBox( "Nothing selected." )
   ElseIf HasUnoInterfaces( oSelection, "com.sun.star.drawing.XShapes" ) Then
      MsgBox( "There are " + CSTR( oSelection.getCount() ) + " shapes selected." )
   Else
      MsgBox( oSelection.Dbg_Properties )
   EndIf
End Sub


Please Try the above Basic program by copy/paste it into the Basic IDE and running it in a Draw document.

In Java, nothing is ever this easy.

From the document model (represented by oDrawDoc in above example), do a queryInterface to obtain the XModel interface.

Once you have the XModel interface, call its getCurrentController() method. So far, all this queryInterface and calling getCurrentController() is represented by the Basic statement (above) that says...
oController = oDrawDoc.getCurrentController()

Once you have one of the model's controllers, you can do a queryInterface on it to obtain the XSelectionSupplier interface. Then call the getSelection() method. These operations are represented by the Basic statement....
oSelection = oController.getSelection()

The selection object can represent a number of things in various documents. In a Drawing, it always returns an Indexed collection of selected Shapes. So you can queryInterface to obtain the XIndexAccess interface. Then you are able to call the getCount() or getByIndex() methods.

Hope that helps.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
MuiFull
General User
General User


Joined: 09 Jun 2004
Posts: 16

PostPosted: Wed Jun 09, 2004 5:10 pm    Post subject: Reply with quote

Thank you much Danny
It works!!~~~ Surprised Surprised !~
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Wed Jun 09, 2004 5:23 pm    Post subject: Reply with quote

It's always exciting to cross over some mountain of accomplishment getting a first program to work. Getting your first OOo program to work from Java is no small task. But after this it gets easier. You have to learn to navigate the API docs.

1. Services always contain properties, but never methods.
2. Interfaces always contain methods, but never properties.
3. Services can implement any number of interfaces.
4. Services can inherit from one service.
5. Interfaces can inherit from an interface.

Now putting all of the above rules together, if you have one service, say the DrawingDocument, you can apply all of the above rules and discover all of the methods that can be called, and properties that can be accessed directly from the DrawingDocument.

In Java, to call a method you first have to queryInterface to obtain the interface. In other languages like OOo Baisc, or Python, or Visual Basic, you just call the method or access the property.

In Java, to access a property, you have to querty for the XPropertySet interface and call setProperty() or getProperty().

Hope this helps.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
MuiFull
General User
General User


Joined: 09 Jun 2004
Posts: 16

PostPosted: Wed Jun 09, 2004 6:40 pm    Post subject: Reply with quote

Thank you very much for your help. Actually I found difficulties in translating the Basic examples into Java. For example, I notice that you have written a function to clone shape via clipboard in Basic:

DannyB 's coding:

Code:
Function CloneShapeViaClipboard( oDrawDoc, oShape )
   ' Get a dispatcher, because we'll need it later.
   oDispatcher = createUnoService( "com.sun.star.frame.DispatchHelper" )
   
   ' Get an empty collection of shapes.  We'll need it lager.
   oEmptyShapeCollection = createUnoService( "com.sun.star.drawing.ShapeCollection" )
   
   ' Get the document's controller
   oDrawDocView = oDrawDoc.getCurrentController()
   
   ' From the controller, Select the shape that was passed in as the parameter.
   ' If you were to stop right now and look, you would see that the drawing
   '  selection has changed so that only the shape is now selected
   '  with little green handles around it.
   oDrawDocView.select( oShape )
   
   ' Copy whatever is selected.
   oDispatcher.executeDispatch( oDrawDocView.Frame, ".uno:Copy", "", 0, Array() )
   
   ' Select nothing -- i.e. an empty collection of shapes.
   ' If you stopped the macro right now and looked at the drawing -- nothing is selected.
   oDrawDocView.select( oEmptyShapeCollection )
   
   ' Now paste whatever is in the clipboard (the shape parameter) onto current page.
   oDispatcher.executeDispatch( oDrawDocView.Frame, ".uno:Paste", "", 0, Array() )
   ' After a Paste, the current selection is whatever we just pasted.
   
   ' Get the selection.
   ' What is selected is the NEW shape we just pasted.
   oSelection = oDrawDocView.getSelection()
   ' The selection is an array of shapes.
   ' Since there was only one shape on the clipboard, only one shape is selected.
   ' Get the first shape from the array.
   oPastedShape = oSelection( 0 )
   
   ' Select nothing -- i.e. an empty collection of shapes.
   ' If you stopped the macro right now and looked at the drawing -- nothing is selected.
   oDrawDocView.select( oEmptyShapeCollection )
   
   ' Return it as the function result.
   CloneShapeViaClipboard() = oPastedShape
End Function

I also want to write this function in Java. However, I can't find the class DispatchHelper and ShapeCollection. Could you teach me how to do so in Java and how can I learn OOo programming in an effective way?
Back to top
View user's profile Send private message
petr.zeman
General User
General User


Joined: 27 May 2004
Posts: 9

PostPosted: Thu Jun 10, 2004 3:28 am    Post subject: dispatch in Java Reply with quote

Next code is runing in my application. I found tips for that on this forum.

/**
* Query the frame for right interface which provides access to all
* available dispatch objects.
*
* private XDispatchProvider getXDispatchProvider
*
* return
*/
private XDispatchProvider getXDispatchProvider() {
if (xDispatchProvider == null) {
XController xController = getModelController();
XFrame xFrame = xController.getFrame();
xDispatchProvider = (XDispatchProvider) UnoRuntime.queryInterface(
XDispatchProvider.class, xFrame);
}
return xDispatchProvider;
}
/**
* Create and parse a valid URL
*
* private URL getURL
*
* @param pURL
* @return @throws
* Exception
*/
private URL getURL(String pURL) throws Exception {
// Create and parse a valid URL
// Note: because it is an in/out parameter we must use an array of URLs
XURLTransformer xParser = (XURLTransformer) UnoRuntime.queryInterface(
XURLTransformer.class, xRemoteServiceManager
.createInstanceWithContext(
"com.sun.star.util.URLTransformer",
xRemoteContext));
URL[] aParseURL = new URL[1];
aParseURL[0] = new com.sun.star.util.URL();
aParseURL[0].Complete = pURL;
xParser.parseStrict(aParseURL);
return aParseURL[0];
}
/**
* public boolean dispatch
*
* @param pOperationURL
* @return boolean
* @throws Exception
*/
public boolean dispatch(String pOperationURL) throws Exception {
URL aURL = getURL(pOperationURL);
XDispatchProvider mxFrame = getXDispatchProvider();
XDispatch xDispatcher = mxFrame.queryDispatch(aURL, "",
FrameSearchFlag.GLOBAL);
if (xDispatcher != null) {
xDispatcher.dispatch(aURL, new PropertyValue[0]);
return true;
} else {
return false;
}
}
// ------------------------------
// base calling OO's function (dispatch)
// ------------------------------
private static final String UNO_DISPATCH = ".uno:";
private static final String UNO_COPY_TO_CLIPBOARD = UNO_DISPATCH + "Copy";
protected void copyToClipBoard() {
try {
dispatch(UNO_COPY_TO_CLIPBOARD);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

You can find very good information for using dispatch on "http://framework.openoffice.org/files/documents/25/1042/commands_11beta.html"
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Thu Jun 10, 2004 6:05 am    Post subject: Reply with quote

Jick wrote:
Thank you very much for your help. Actually I found difficulties in translating the Basic examples into Java. For example, I notice that you have written a function to clone shape via clipboard in Basic:


The OOo API is the same no matter what programming language you use. Therefore, anything done in Basic can be done the same way in Java. The major differences are
1. Java is very cumbersome for OOo work because of the constant need to UnoRuntime.queryInterface to always obtain the right interface before you can call a method.
2. OOo Basic has some built in convenience features that you need to know about in order to properly translate code.

Jick wrote:
I also want to write this function in Java. However, I can't find the class DispatchHelper and ShapeCollection.
' Get a dispatcher, because we'll need it later.
oDispatcher = createUnoService( "com.sun.star.frame.DispatchHelper" )

' Get an empty collection of shapes. We'll need it lager.
oEmptyShapeCollection = createUnoService( "com.sun.star.drawing.ShapeCollection" )

Could you teach me how to do so in Java and how can I learn OOo programming in an effective way?


The services are exactly what is named. Here they are in the API documentation.
com.sun.star.frame.DispatchHelper
com.sun.star.drawing.ShapeCollection
In Java you would just create these services, as I did in Basic. The real trick is understanding how to translate from OOo Basic.

Basic has a function createUnoService() which you see in the two lines of code (above). This function is a convenient way to create an object, such as...
oDispatcher = createUnoService( "com.sun.star.frame.DispatchHelper" )
Anytime you see the Basic...
x = createUnoService( y )
this is equivalent to... in Basic...
x = oServiceManager.createInstance( y )
but in Java, more cumbersome...
Code:

Object oServiceManager = ...obtain service manager when first connecting...
// obtain the right interface...
XMultiServiceFactory oServiceManager_xMultiServiceFactory =
    (XMultiServiceFactory)
    UnoRuntime.queryInterface( XMultiServiceFactory.class, oServiceManager );
//
Object x = oServiceManager_xMultiServiceFactory.createInstance( y )

Then of course, before you can use x, you need to queryInterface for the right interface on x.


Here are a few ideas that may help.

I find the Java examples difficult to read because of the clutter with the queryInterface. So I attempt to reduce that and make it as brief as possible. I create a class with a bunch of static methods. One method to "queryInterface" for every possible type of interface that I need in my program. Let's suppose I need the interfaces... XFoo, XBar and XBaz. I would create three static methods in this special class.

Code:
class QI {
   static XFoo xFoo( Object o ) {
      return (XFoo) UnoRuntime.queryInterface( XFoo.class, o );
   }

   static XBar xBar( Object o ) {
      return (XBar) UnoRuntime.queryInterface( XBar.class, o );
   }

   static XBaz xBaz( Object o ) {
      return (XBaz) UnoRuntime.queryInterface( XBaz.class, o );
   }


Now later on, when I'm coding, suppose I have an object variable...

Object oFrob = ...get object from something...

But I now need to call methodFoo1() and methodFoo2() from the XFoo interface of oFrob. Then I will need to call methodBar4() from the XBar interface. In all cases, I will make the prefix of the variable be the same, to emphasize that the variables point to the same "service" (but in reality they might point to different implementation objects).

Code:
Object oFrob = ....something...
XFoo  oFrob_xFoo = QI.xFoo( oFrob );
XBar  oFrob.xBar = QI.xBar( oFrob );
oFrob_xFoo.methodFoo1( a, b, c );
oFrob_xFoo.methodFoo2( x, y );
oFrob.xBar.methodBar4( 123 );

See how compact and readable that is? Almost like Basic. There are three variables, but they all begin with oFrob, so they are the "same" variable, just different interfaces of it.

See how much shorter is...
XFoo oFrob_xFoo = QI.xFoo( oFrob );
than...
XFoo oFrob_xFoo = (XFoo) UnoRuntime.queryInterface( XFoo.class, oFrob );

Using this technique, in my Java code, instead of this like you would see in the Developer's Guide...
Code:
Object oServiceManager = ...obtain service manager when first connecting...
// obtain the right interface...
XMultiServiceFactory oServiceManager_xMultiServiceFactory =
    (XMultiServiceFactory)
    UnoRuntime.queryInterface( XMultiServiceFactory.class, oServiceManager );
//
Object x = oServiceManager_xMultiServiceFactory.createInstance( y )


I would write...
Code:
Object oServiceManager = ...obtain service manager when first connecting...
XMultiServiceFactory oServiceManager_xMSF = QI.xMultiServiceFactory( oServiceManager );
Object x = oServiceManager_xMSF.createInstance( y );


Both variables
oServiceManager
oServiceManager_xMSF
point to the same "service", they just have different types. One is "Object", and the other is "XMultiServiceFactory".

Now you could write your own Java function like Basic's "createUnoService". Then when you see a line of Basic like...

x = createUnoService( y )

In Java you could write...

x = MyUtils.createUnoService( y );

Where MyUtils is a class like the QI class, that has a static method like createUnoService().

In Basic you also see use of a function called CreateUnoStruct(). This simply creates a structure. For instance in Basic...
oPropertyValue = createInstance( "com.sun.star.beans.PropertyValue" )
In Java you would write...
import com.sun.star.beans.*;
PropertyValue oPropertyValue = new PropertyValue();

In Basic, there is a global variable StarDesktop. This contains the Desktop object. So in Basic, when you see...

oDoc = StarDesktop.loadComponentFromURL( "...url...", "_blank", 0, Array() )

this is just the loadComponentFromURL on some interface of the Desktop object. You could create your own global StarDesktop variable, or you could put a simplified "loadComponentFromURL()" method into a "MyUtils" type of class. There are a variety of ways to make your main code more readable than the Developer's Guide examples. The biggest, IMHO, is to reduce the clutter of the queryInterface business. You cannot avoid the queryInterface, so it is best to make it as little of a distraction as possible.


I would also highly recommend that you play with the many Basic examples here on OOo Forum. You should now be able to figure out how to translate them into Java. Still, there is nothing faster than Basic for doing a quick experiment. You're trying to figure out some portion of the API, you think you know it, but you can devise a very quick test in OOo Basic, without any burden of the queryInterface.


Oh, yeah. There is one more thing that can help you simplify Java code. (By simplify, I mean the main code concept -- not necessarily result in less lines of overall code.)

One thing that is frequently done is to manipulate property values. For instance, in Basic...

x = oObject.SomeProperty

or

oObject.SomeProperty = x

In Java you have to queryInterface the oObject for the XPropertySet interface, and then call either setPropertyValue() or getPropertyValue().

In your MyUtils class, or whatever tools you build for yourself, you could create a method that is used like this...

long x = MyUtils.getPropertyValue( oObject, "SomeProperty" );
MyUtils.setPropertyValue( oObject, "SomeProperty", x );

This helps a lot because setting and getting property values is done so frequently. Furthermore, some properties are so frequently accessed that I even add an additional layer like this...

Code:
static long getHairColor( Object o ) {
   return MyUtils.getPropertyValue( o, "HairColor" );
}
static void setHairColor( Object o, long nColor ) {
   MyUtils.setPropertyValue( o, "HairColor", nColor );
}


Thus, I can easily access many properties of a drawing shape, for example...

x = getFillColor( oShape );
x = getPosition( oShape );
x = getSize( oShape );
x = getSizeHeight( oShape );
x = getLineStyle( oShape );
etc.
but with short, simple, easily read code.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
MuiFull
General User
General User


Joined: 09 Jun 2004
Posts: 16

PostPosted: Thu Jun 10, 2004 5:58 pm    Post subject: Reply with quote

Thank you very much petr.zeman and DannyB!~~!! Very Happy Very Happy

I now have a clearer understanding of using Dispatch (the link is very useful Smile) and the translation from Basic to Java

I think it's better for me to start by playing with Basic~~

Actually I didn't reallize the meaning of queryInterface before and this make me get confuse when I read the code provided in Developer's guide. But I now know what 's going on after reading DannyB's post

Thank you for your great help again~!!!
Razz Razz

Best regards
Jick
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Fri Jun 11, 2004 6:39 am    Post subject: Reply with quote

Think of queryInterface as a "typecast".

You use it to "cast" to a different interface of a service. (A service is an abstraction, not an object.)

You cannot just do a java typecast to change between different interfaces. Because queryInterface, while sort of like a typecast, it actually may return a different implementation object! A service is an abstraction of potentially more than one object.

The "Plugh" service may be one object in this release, and three objects in the next release, and then two objects in the release after that. But as long as you use queryInterface to "typecast" to different interfaces of the Plugh service, you don't really care about how many implementation objects make up the Plugh service.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
petr.zeman
General User
General User


Joined: 27 May 2004
Posts: 9

PostPosted: Tue Jun 15, 2004 5:50 am    Post subject: How to set property "HeaderText" for PageStyle< Reply with quote

Hi Moderator,

I wrote java-code for creating report with usign sheet-template. I had no problem with most of functions, but I came to grief with setting sheet's header/footer. I tried a lot of variants, searched any help on this forum, Internet general, without success.The problem is in this part of my code:

Code:

xStyleProps.setPropertyValue("HeaderIsOn", new Boolean(true));
Object o = xStyleProps.getPropertyValue("HeaderText");
if (o == null)
//  System.out.println("o is null");
else
// System.out.println("o is " + o.getClass().getName());
  XText xftl = (XText) UnoRuntime.queryInterface(XText.class, o);
   ....
}


Object 'o' is not null, it's class name is "Any", but I can't find the way to XText object to set string-value. I failed with 'setPropertyValue' too.

Do you know resolve this problem?

Thank you for your help

Petr.Z.
_________________
gi/os
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Tue Jun 15, 2004 5:58 am    Post subject: Reply with quote

Sorry, I don't know how to solve the problem. You might get an answer if you start a new thread that asks this question.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group