The primary function of Draw and Impress documents is to contain graphical data, which is stored in draw pages. The primary draw-page functionality is implemented by a GenericDrawPage. There are two types of draw pages-the MasterPage and the DrawPage. Both draw-page types implement the GenericDrawPage and are therefore able to hold and manipulate the same content.
A master page acts as a common background for zero or more draw pages. Each draw page may link to one master page. Each master page is constrained as follows :
A master page, unlike a regular draw page, may not link to a master page.
A master page may not be removed from a document if any draw page links to it.
Modifications made to a master page are immediately visible on every draw page that uses that master page.
The method getMasterPages() returns the document's collection of master pages. The method getDrawPages() returns the document's collection of draw pages. Both methods return the same object type; they differ only in how their contents are used (see Table 1 ).
Method | Description |
---|---|
insertNewBylndex(Long) | Create and insert a new draw page at the specified index. |
hasByName(String) | Return True if the named page exists. |
hasElements() | Return True if any draw pages exist. |
remove(DrawPage) | Remove a specific draw page. |
getCount() | Return the number of contained objects as a Long Integer. |
getBylndex(Long) | Get the specified draw page. |
getByName(String) | Get the specified draw page. |
duplicate(DrawPage) | Duplicate the DrawPage and return the new DrawPage. |
hasElements() | Return True if there are draw pages to return. |
Each draw page has a name , which you can access by using the methods getName() and setName(). A draw page that is not a master supports the methods getMasterPage() and setMasterPage() to get and set the master page. Listing 2 demonstrates enumerating the document's draw pages and their corresponding master pages.
Sub getPages() Dim s$ s = s & getPagesInfo(ThisComponent.getDrawPages(), "Draw Pages") s = s & CHR$(10) s = s & getPagesInfo(ThisComponent.getMasterPages(), "Master Pages") MsgBox s, 0, "Pages" End Sub Function getPagesInfo(oDPages, sType$) As String Dim i%, s$ Dim oDPage, oMPage s = s & "*** There are " & oDPages.getCount() & " " & sType & CHR$(10) For i = 0 To oDPages.getCount()-1 oDPage = oDPages.getByIndex(i) s = s & "Page " & i & " = '" & oDPage.getName() & " ' " If NOT oDPage.supportsService("com.sun.star.drawing.MasterPage") Then oMPage = oDPage.getMasterPage() s = s & " master = " If NOT IsNull(oMPage) AND NOT IsEmpty(oMPage) Then s = s & "'" & oMPage.getName() & " ' " End If End If s = s & CHR$(10) Next getPagesInfo = s End Function
Although you can get a draw page based on its name, you can have more than one draw page with the same name. If multiple draw pages use the same name and you retrieve the draw page based on the name, it is not specified which draw page is returned. The macro in Listing 3 , which searches for a draw page with a specific name, is used in numerous places in this chapter.
Function createDrawPage(oDoc, sName$, bForceNew As boolean) As Variant Dim oPages 'All of the draw pages Dim oPage 'A single draw page Dim i% 'General index variable oPages = oDoc.getDrawPages() If oPages.hasByName(sName) Then REM If we require a new page then delete REM the page and get out of the for loop. If bForceNew Then oPages.remove(oPages.getByName(sName)) Else REM Did not request a new page so return the found page REM and then get out of the function. createDrawPage = oPages.getByName(sName) Exit Function End If End If REM Did not find the page, or found the page and removed it. REM Create a new page, set the name, and return the page. oPages.insertNewByIndex(oPages.getCount()) oPage = oPages.getByIndex(oPages.getCount()-1) oPage.setName(sName) createDrawPage = oPage End Function
Both regular and master draw pages support the GenericDrawPage service. As its name implies, the GenericDrawPage service provides the primary generic drawing functionality. Writer and Calc documents provide specific styles for formatting entire pages. Draw pages, however, use the properties shown in Table 2 .
Property | Description |
---|---|
BorderBottom | Bottom border in 1/100 mm, represented as a Long Integer. |
BorderLeft | Left border in 1/100 mm, represented as a Long Integer. |
BorderRight | Right border in 1/100 mm, represented as a Long Integer. |
BorderTop | Top border in 1/100 mm, represented as a Long Integer. |
Height | Height in 1/100 mm, represented as a Long Integer. |
Width | Width in 1/100 mm, represented as a Long Integer. |
Number | Draw page number as a Short Integer. This read-only value labels the first page 1. |
Orientation | Page orientation as a com.sun.star.view.PaperOrientation enumeration. Two values are supported-PORTRAIT and LANDSCAPE. |
UserDefinedAttributes | User-defined XML attributes. |
IsBackgroundDark | True if the averaged background fill color 's luminance is below a specified threshold value. |
The primary purpose of a draw page is to contain shapes . The methods addShape(Shape) and removeShape (Shape) add and remove a shape from a document. Before a shape can be added to a draw page, it must be created by the document. Each line produced by Listing 4 and shown in Figure 1 is a separate, unrelated shape. You can indepently manipulate each of these shapes.
Sub drawFirstGraphic() Dim oPage 'Page on which to draw Dim oShape 'Shape to insert Dim oPoint 'Initial start point of the line Dim oSize 'Width and height of the line Dim i% 'Index variable Dim n% 'Number of iterations to perform oPage = createDrawPage(ThisComponent, "Test Draw", True) n = 20 For i = 0 To n oShape = ThisComponent.createInstance("com.sun.star.drawing.LineShape") oShape.LineColor = RGB( 255, 0, i+20 ) oShape.LineWidth = 20 oPoint = oShape.Position oPoint.X = oPage.Width / 4 oPoint.Y = i * oPage.Height / n / 4 oShape.Position = oPoint oSize = oShape.Size oSize.Height = (oPage.Height - 2 * i * oPage.Height / n) / 4 oSize.Width = oPage.Width / 2 oShape.Size = oSize oPage.add(oShape) Next End Sub
The macro in Listing 4 creates 20 independent lines. You can group shapes together and then manipulate them as a single shape. The method group(XShapes) accepts a collection of shapes and turns them into a single group ; an XShapeObject is returned. The macro in Listing 5 starts by calling Listing 4 and then it adds all of the lines to a single group.
Sub groupShapes Dim oPage 'Page on which to draw Dim oShapes 'Shapes to group Dim i% 'Index variable REM Create the shapes! drawFirstGraphic() oPage = ThisComponent.getDrawPages().getByName("Test Draw") REM Create a shape collection object to group the shapes oShapes = createUnoService("com.sun.star.drawing.ShapeCollection") For i = 0 To oPage.getCount()-1 oShapes.add(oPage.getByIndex(i)) Next oPage.group(oShapes) End Sub
When several shapes are grouped together using the group() method, the entire group is added as a single shape into the draw page, which you can retrieve by using oPage.getByIndex(). It's no longer possible to select a single line and independently manipulate it. To convert a group of shapes back to independent shapes, use the ungroup (XShapeObject) method. The ungroup() method removes the objects from the group and adds them back to the draw page as individual objects (see Listing 6 ).
Sub unGroupShapes Dim oPage 'Page on which to draw Dim oShape 'Single shape Dim i% 'Index variable oPage = ThisComponent.getDrawPages().getByName("Test Draw") For i = 0 To oPage.getCount()-1 oShape = oPage.getByIndex(i) If oShape.supportsService("com.sun.star.drawing.GroupShape") Then oPage.ungroup(oShape) End If Next End Sub
Although shapes that are grouped together are manipulated as one shape, they are really a collection of shapes. The combine(XShapes) method, on the other hand, converts each shape into a PolyPolygonBezierShape and then combines them into one PolyPolygonBezierShape. See Listing 7 . The new shape is added to the draw page, and the original shapes are removed and deleted. The split(XShape) method converts the shape to a PolyPolygonBezierShape (if it is not already) and then the shape is split into several shapes of type PolyPolygonBezierShape. The new shapes are added to the draw page and the original shape is removed and deleted.
Sub combineShapes Dim oPage, oShapes, i% REM Create the shapes! drawFirstGraphic() oPage = ThisComponent.getDrawPages().getByName("Test Draw") oShapes = createUnoService("com.sun.star.drawing.ShapeCollection") For i = 0 To oPage.getCount()-1 oShapes.add(oPage.getByIndex(i)) Next oPage.combine(oShapes) End Sub
The bind(XShapes) method is similar to combine() except that the individual shapes are connected before they are combined. The output from Listing 7, therefore, is the same as Figure 1. Listing 8 , on the other hand, produces the output in Figure 2 . The shapes are connected by a line, each of which is really a Bezier curve.
Sub bindShapes() Dim oPage, oShapes, i% REM Create the shapes! drawFirstGraphic() oPage = ThisComponent.getDrawPages().getByName("Test Draw") oShapes = createUnoService("com.sun.star.drawing.ShapeCollection") For i = 0 To oPage.getCount()-1 oShapes.add(oPage.getByIndex(i)) Next oPage.bind(oShapes) End Sub
The unbind(XShape) method converts the shape to a PolyPolygonBezierShape (if it is not already) and then each line segment is converted to a new PolyPolygonBezierShape. The original shape is removed from the draw page and deleted. If unbind() is used on the shape in Figure 2, the output still looks like Figure 2, but 776 shapes are used.
Tip | The methods group() and ungroup() act like "undo" for each other. The methods bind() and combine() are not "undo" for unbind() and split(), primarily because each shape is converted to a PolyPolygonBezierShape. |