Libre Office Macro ================== The other day, I saw a post on medium with the title "Are You Smart Enough To Find The Radius". Solving it is not very difficult if you have finished high-school and have had no difficulties in geometry of the plan. This time, I want to upload a PDF file because I need to draw the shape, and the best way to draw it is to know the solution and to use a script. The languse I've chosen is JavaScript. To locate script written in JavaScript, edit them and find an example script, chhose: Tools->Macros->Organize Macros->JavaScript Now, in the opened dialog, you can find an example file under 'Library1' its name is 'Hello.js'. In the native editor, the text looks to faded for me, so I will use another editor, such as emacs. The location of scripts in JavaScript is: ~/.config/libreoffice/4/user/Scripts/javascript 'Hello1.js' is under directory 'Library1', which also contains a file named 'parcel-descriptor.xml'. I prefer LibreOffice to edit that file for me. So, I'm creating a new script from the dialog by standing on 'Library1', and pressing 'Create'. The macro's name is 'GeometryPuzzle'. The newly created script is a script adding the text "Hello World". I find there a little explanation about XSCRIPTCONTEXT, from which the script retrieves the document model, and a link to the developers guide. but is returns a "Page Not Found" error, so I use "https://api.libreoffice.org ". A great browser for that page is GNU Emacs, in which I can see everything clearly. I choose the Developer Guide from the content, then "7. Text Document" and from then scroll to "Drawing Shapes". A good example in Java for drawing shapes is the method "protected void DrawPageExample". Let the journey begin! ---------------------- The first thing I do is add some useful variables: the model, the text document property of the model, the text in the document, a cursor and the factory feature of the model to instantiate services. The first executable commands that are not class imports are: oDoc = UnoRuntime.queryInterface(XModel,XSCRIPTCONTEXT.getInvocationContext()); if ( !oDoc ) oDoc = XSCRIPTCONTEXT.getDocument(); xTextDoc = UnoRuntime.queryInterface(XTextDocument,oDoc); xText = xTextDoc.getText(); oCursor = xText.createTextCursor(); xFactory = UnoRuntime.queryInterface(XMultiServiceFactory,oDoc); The first argument of queryInterface is the interface name, you have to add a call to importClass with the exact path name. You will find them among the rest of "importClass" commands. The next step is to find a place for the shapes. The following lines create two more paragraph at the end of the document, and move the paragraph cursor to the penultimate paragraph: // Add 2 paragraph, and go to to one before the end oCursor.gotoEnd(false); xText.insertControlCharacter( oCursor, ControlCharacter.PARAGRAPH_BREAK, false); xText.insertControlCharacter( oCursor, ControlCharacter.PARAGRAPH_BREAK, false); xParagraphCursor = UnoRuntime.queryInterface(XParagraphCursor,oCursor); xParagraphCursor.gotoPreviousParagraph(false); The enumeration ControlCharacter has to be added to the imports. I find its full path the IDL Reference whose link is found under Content. This time I need a standard browser to search classes. Then, I add: importClass(Packages.com.sun.star.text.ControlCharacter); to the list of import commands. Now, it's time to choose shapes. Shapes are found in path i 'com.sun.stars.drawing'` the class names end with 'Shape'. The shapes to use are: * A polyline shape, with which I will draw two squares: a big one of size 2x2 and a small one of size 1x1 on the bottom and left sides of the big squares with a vertex inside. The relevnt class is * A circle, tangent to the upper and right sides of the big square and touching the upper-right vertex of the small square. The relevant class is EllipseShape. Now, about the polylines: The value of the "PolyPolygon" is "PointSequenceSequence", or a two-dimensional array. A Javascript array won't be accepted, but you can instantiate the array using "java.lang.reflect.Array.newInstance" method. That creates a Java array! The rest of the code is: // Create the shape interfacws polyLine1 = xFactory.createInstance("com.sun.star.drawing.PolyLineShape"); xPolyLine1 = UnoRuntime.queryInterface(XShape, polyLine1); circle = xFactory.createInstance("com.sun.star.drawing.EllipseShape"); xCircle = UnoRuntime.queryInterface(XShape, circle); // Set sizes for shapes. aSize = Size(); aSize.Height=aSize.Width=2000; xPolyLine1.setSize(aSize); diameter=Math.round(2000*(2-Math.sqrt(2))); aSize.Height=aSize.Width=diameter; xCircle.setSize(aSize); // Set location of each shape aPoint = Point(); aPoint.X = 100; aPoint.Y = 100; xPolyLine1.setPosition(aPoint); aPoint.X = 2100-diameter; aPoint.Y = 100; xCircle.setPosition(aPoint); //ArrayObj=xFactory.createInstance("java.lang.reflect.Array");//[[{"X":100,"Y":1500},{"X":100,"Y":500}]]; polyLineCoords = java.lang.reflect.Array.newInstance(Point,[1,8]); polyLineCoords[0][0] = Point(0,1000); polyLineCoords[0][1] = Point(0,0); polyLineCoords[0][2] = Point(2000,0); polyLineCoords[0][3] = Point(2000,2000); polyLineCoords[0][4] = Point(0,2000); polyLineCoords[0][5] = Point(0,1000); polyLineCoords[0][6] = Point(1000,1000); polyLineCoords[0][7] = Point(1000,2000); xPolyLine1Props = UnoRuntime.queryInterface(XPropertySet,xPolyLine1); xPolyLine1Props.setPropertyValue("AnchorType",TextContentAnchorType.AT_PARAGRAPH); xPolyLine1Props.setPropertyValue("Geometry", polyLineCoords); xCircleProps = UnoRuntime.queryInterface(XPropertySet,xCircle); xCircleProps.setPropertyValue("AnchorType", TextContentAnchorType.AT_PARAGRAPH); xCircleProps.setPropertyValue("FillStyle", FillStyle.NONE); // Use the XDrawPageSupplier interface from the document to add the // Draw Page xDrawPageSupplier=UnoRuntime.queryInterface(XDrawPageSupplier, oDoc); xShapes = UnoRuntime.queryInterface(XShapes,xDrawPageSupplier.getDrawPage()); xShapes.add(xPolyLine1); xShapes.add(xCircle); ========================================== The complete script can be found at gopher://zaibatsu.circumlunar.space/1/~zaphodb/phlog/GeometryPuzzle.js There are still some bugs in the code: at least if you try to add the 2 shapes to an empty document the circle is drawn out of the big square. But you can find a work around. I guess using a GroupShape will fix it.