2

Background:

I want to paste (like [CTRL+V]) anything (preferably image, shape) at the position I click or hover with the mouse (when using a key to activate). I don't know how to get the position on the document (X, Y) I clicked.

(Apache OpenOffice, SDraw-Document, OpenOffice BASIC Macro)

What I need:

  • Hint/Tip how to get the location from the mouse-click / mouse-position on the document. (Which class, listener, component I need)

Notes: Something like a com.sun.star.awt.XMouseClickHandler would be perfect, if the given oEvent gave me the X+Y of the document, where I clicked. (Maybe you know how to "activate" PopupTrigger? (com.sun.star.awt.MouseEvent))

My code so far:

I tried using the mentioned XMouseClickHandler to get X+Y. Sadly, X+Y refer to the relative position of the window and not the actual position a shape or text would have on the document.

Execution: My Sub Main is executed via a Menu-Button at the top. Then clicking anywhere will output (via MsgBox) the coordinates of that click.

Only Problem: Coordinates are relative to the corner of the window, not the corner of the document.

Global gListener As Object

Sub Main
  gListener = CreateUnoListener("Listener_","com.sun.star.awt.XMouseClickHandler")
  ThisComponent.CurrentController.addMouseClickHandler(gListener) 
End Sub

Sub Listener_mousePressed(oMouseEvent) As Boolean
   ThisComponent.CurrentController.removeMouseClickHandler(gListener)

   Msg = "Position: "
   Msg = Msg & oMouseEvent.X & "/" & oMouseEvent.Y
   MsgBox(Msg)

   REM :: I want something like:
   REM :: Msg = "Position: " & oMouseEvent.PositionOnDocument.X
   REM :: Msg = Msg & "/" & oMouseEvent.PositionOnDocument.Y
   REM :: MsgBox(Msg)
End Sub

My references:

All my information come from the official references/docs so far, since all my searches did not find anything helpful.

Thanks in advance.

Countryen
  • 31
  • 7
  • 1
    Please [edit] your question to show [the code you have so far](http://whathaveyoutried.com). You should include at least an outline (but preferably a [mcve]) of the code that you are having problems with, then we can try to help with the specific problem. You should also read [ask]. – Toby Speight Jun 05 '17 at 11:38
  • Is this basically the same question that was asked [here](https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=75214)? – Jim K Jun 05 '17 at 18:20
  • @JimK Yes it is - but the thread doesn't give an answer (I should not include it in the question, should I?) – Countryen Jun 05 '17 at 18:53
  • @TobySpeight Thanks for the advice, I've edited the question. Hope it's better now. If not, please show me where you need more information. – Countryen Jun 05 '17 at 18:57
  • Since the thread from the OpenOffice forum is closely related, it might have been good to mention it; but anyway, the question is better now because of your edits. – Jim K Jun 06 '17 at 08:39

2 Answers2

1

I finally found a way to get the exact coordinates of a mouse click (relative to the document). I managed to get the information from the StatusBar at the bottom, which usually shows the coordinates (for me in centimeters).

Here is the function I now use to get the position (X / Y):

REM // Warning: If there is currently a selection, the returning Point will instead show the coordinates of the selection!
Sub GetMousePositionOnDocument as com.sun.star.awt.Point
  Dim aPosition As New com.sun.star.awt.Point
  Dim o1, o2, o3, o4, o5, o6

  REM // First get AccessibleContext of the Window of the active Frame of the Application
  o1 = StarDesktop.ActiveFrame.ContainerWindow.AccessibleContext

  REM // 7th AC of o1 is the StatusBar at the bottom;
  o2 = o1.GetAccessibleChild(6).AccessibleContext

  REM // 2nd AC of o2 is the Position + Size of the Selection (e.g: "10,95 / 14,980,00 x 0,00") 
  o3 = o2.GetAccessibleChild(1)
  o4 = o3.GetText()

  REM // Taking out only the coordinates from o4
  REM // TODO: Check for negatives (longer)
  o5 = LEFT(o4, 4)
  o6 = MID(o4, 8, 5)

  aPosition.X = o5
  aPosition.Y = o6

  REM // Return
  GetMousePositionOnDocument = aPosition
End Sub

Note: This function is called inside my previous Listener_mousePressed from above.

Hopefully this will work for others, too.

How I found it?

I spent very much time on checking every single ApplicationContext of the Window(s) of ThisComponent and StarDesktop manually in the debugger.

This is the starting point for iterating through ThisDesktop if needed for other values. ThisComponent.CurrentController.Frame.ComponentWindow.AccessibleContext

Future Improvements

I "know" the indexes for the GetAccessibleChild()-Function because I inspected the debugger. There certainly are better ways to get to o3 and you should not expect everyone to have the same AccessibleContext's.

Countryen
  • 31
  • 7
0

It turns out that the DrawingDocumentDrawView service has a member called VisibleArea that helps. Subtract (actually add because they have the opposite sign) those coordinates from the mouse position to get the location relative to the document.

Here is an example that creates a rectangle at the location of the mouse click.

Sub Listener_mousePressed(oMouseEvent) As Boolean
   ThisComponent.CurrentController.removeMouseClickHandler(gListener)

   xpos = (oMouseEvent.X + ThisComponent.VisibleArea.X / 25.4) / 100
   ypos = (oMouseEvent.Y + ThisComponent.VisibleArea.Y / 25.4) / 100
   Msg = "Position: " & xpos & "/" & ypos
   MsgBox(Msg)
   InsertProcessShape(xpos, ypos)
End Sub

Sub InsertProcessShape(xpos, ypos)
   Dim oDoc As Object
   Dim oDrawPage As Object
   Dim oShape As Object
   Dim shapeGeometry(0) as new com.sun.star.beans.PropertyValue
   Dim oSize As new com.sun.star.awt.Size

   oSize.width = 3000
   oSize.height = 1000

   oDoc = ThisComponent
   odrawPage = oDoc.DrawPages(0)
   oShape = oDoc.createInstance("com.sun.star.drawing.CustomShape")
   shapeGeometry(0).Name = "Type"
   shapeGeometry(0).Value = "flowchart-process"
   oDrawPage.add(oShape)
   oShape.CustomShapeGeometry = shapeGeometry
   oShape.Size = oSize

   ' Position the object
   IN_TO_CM = 2540  ' converts 1/1000 cm to inches
   Dim aPosition As New com.sun.star.awt.Point
   aPosition.X = xpos * IN_TO_CM
   aPosition.Y = ypos * IN_TO_CM
   oShape.setposition(aPosition)
End Sub

To figure this out, I used xray. The formula may need to be fine-tuned. But the left-top corner of the rectangles seemed to go roughly where the mouse was clicked when I tested it, as intended.

InsertProcessShape is from https://forum.openoffice.org/en/forum/viewtopic.php?f=45&t=46682, plus some code from Listing 5.84 of Andrew Pitonyak's Macro Document.

Jim K
  • 12,824
  • 2
  • 22
  • 51
  • Thanks for the idea of adding the coordinates of the mouse click with the coordinates of the visible area. – Countryen Jun 06 '17 at 18:43
  • Maybe I don't understand the algorithm here but how is this going to work efficiently? When I test it, the shape sometimes is above my cursor, sometimes below. Also, will it not depend on zoom and orientation as well as other factors and never be 100% reliable to the actual mouse coordinates? (Sorry, first comment was kind of a mistake) – Countryen Jun 06 '17 at 19:15