[ Previous document | Content Table | Next document ]
Draw and Impress are vector-oriented applications with the ability to create drawings and presentations. The drawing capabilities of Draw and Impress are identical. Both programs support a number of different shape types, such as rectangle, text, curve, or graphic shapes, that can be edited and arranged in various ways. Impress offers a presentation functionality where Draw does not. Impress is the ideal application to create and show presentations. It supports special presentation features, such as an enhanced page structure, presentation objects, and many slide transition and object effects. Draw is especially adapted for printed or standalone graphics, whereas Impress is optimized to fit screen dimensions and offers effects for business presentations.
The following diagrams show the document structure of Draw and Impress Documents.
In contrast to text documents and spreadsheet documents, the main content of drawing and presentation documents are their draw pages. Therefore the illustrations show the draw page container as integral part of the drawing and presentation document model. The drawing elements on the draw pages have to be created by the document service manager and are added to the draw pages afterwards.
Note the master pages and the layer manager, which are specific to drawings and presentations. Like for texts and spreadsheets, a controller is used to present the drawing in the GUI and services for styles and layout are available to handle overall document features such as styles.
Illustration 10.1: Drawing Document Overview |
In addition to drawing documents, a presentation document has special presentation aspects, which are shown on the lower left of Illustration 10.2 Presentation Document Overview. There is a presentation supplier to obtain a presentation object, which is used to start and stop presentations, it is possible to edit and run custom presentations and the page layout for presentation handouts is accessible through a handout master supplier.
Illustration 10.2: Presentation Document Overview |
The following example creates a simple organizational chart with two levels. It consists of five rectangle shapes and four connectors that connect the boxes on the second level with the root box on the first level.
Illustration 10.3: Sample Organigram |
The method getRemoteServiceManager()that is used in the example connects to the office. The 2 First Steps discussed this method. First an empty drawing document is loaded and retrieves the draw page object of slide number 1 to find the page dimensions. Then the organigram data is prepared and the shape sizes are calculated. The shapes are added in a for loop that iterates over the organigram data, and connectors are added for all shapes on the second level of the organigram. (Drawing/Organigram.java).
public void drawOrganigram() throws java.lang.Exception {
xRemoteServiceManager = this.getRemoteServiceManager(
"uno:socket,host=localhost,port=2083;urp;StarOffice.ServiceManager");
Object desktop = xRemoteServiceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop", xRemoteContext);
XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(
XComponentLoader.class, desktop);
PropertyValue[] loadProps = new PropertyValue[0];
XComponent xDrawComponent = xComponentLoader.loadComponentFromURL(
"private:factory/sdraw", "_blank", 0, loadProps);
// get draw page by index
com.sun.star.drawing.XDrawPagesSupplier xDrawPagesSupplier =
(com.sun.star.drawing.XDrawPagesSupplier)
UnoRuntime.queryInterface(
com.sun.star.drawing.XDrawPagesSupplier.class, xDrawComponent );
com.sun.star.drawing.XDrawPages xDrawPages = xDrawPagesSupplier.getDrawPages();
Object drawPage = xDrawPages.getByIndex(0);
com.sun.star.drawing.XDrawPage xDrawPage = (com.sun.star.drawing.XDrawPage)
UnoRuntime.queryInterface(
com.sun.star.drawing.XDrawPage.class, drawPage);
// find out page dimensions
com.sun.star.beans.XPropertySet xPageProps = (com.sun.star.beans.XPropertySet)
UnoRuntime.queryInterface(
com.sun.star.beans.XPropertySet.class, xDrawPage);
int pageWidth = AnyConverter.toInt(xPageProps.getPropertyValue("Width"));
int pageHeight = AnyConverter.toInt(xPageProps.getPropertyValue("Height"));
int pageBorderTop = AnyConverter.toInt(xPageProps.getPropertyValue("BorderTop"));
int pageBorderLeft = AnyConverter.toInt(xPageProps.getPropertyValue("BorderLeft"));
int pageBorderRight = AnyConverter.toInt(xPageProps.getPropertyValue("BorderRight"));
int drawWidth = pageWidth - pageBorderLeft - pageBorderRight;
int horCenter = pageBorderLeft + drawWidth / 2;
// data for organigram
String[][] orgUnits = new String[2][4];
orgUnits[0][0] = "Management"; // level 0
orgUnits[1][0] = "Production"; // level 1
orgUnits[1][1] = "Purchasing"; // level 1
orgUnits[1][2] = "IT Services"; // level 1
orgUnits[1][3] = "Sales"; // level 1
int[] levelCount = {1, 4};
// calculate shape sizes and positions
int horSpace = 300;
int verSpace = 3000;
int shapeWidth = (drawWidth - (levelCount[1] - 1) * horSpace) / levelCount[1];
int shapeHeight = pageHeight / 20;
int shapeX = pageWidth / 2 - shapeWidth / 2;
int levelY = 0;
com.sun.star.drawing.XShape xStartShape = null;
// get document factory
com.sun.star.lang.XMultiServiceFactory xDocumentFactory = (com.sun.star.lang.XMultiServiceFactory)
UnoRuntime.queryInterface(
com.sun.star.lang.XMultiServiceFactory.class, xDrawComponent);
// creating and adding RectangleShapes and Connectors
for (int level = 0; level <= 1; level++) {
levelY = pageBorderTop + 2000 + level * (shapeHeight + verSpace);
for (int i = levelCount[level] - 1; i > -1; i--) {
shapeX = horCenter -
(levelCount[level] * shapeWidth + (levelCount[level] - 1) * horSpace) / 2 +
i * shapeWidth + i * horSpace;
Object shape = xDocumentFactory.createInstance("com.sun.star.drawing.RectangleShape");
com.sun.star.drawing.XShape xShape = (com.sun.star.drawing.XShape)
UnoRuntime.queryInterface(
com.sun.star.drawing.XShape.class, shape);
xShape.setPosition(new com.sun.star.awt.Point(shapeX, levelY));
xShape.setSize(new com.sun.star.awt.Size(shapeWidth, shapeHeight));
xDrawPage.add(xShape);
// set the text
com.sun.star.text.XText xText = (com.sun.star.text.XText)
UnoRuntime.queryInterface(
com.sun.star.text.XText.class, xShape);
xText.setString(orgUnits[level][i]);
// memorize the root shape, for connectors
if (level == 0 && i == 0)
xStartShape = xShape;
// add connectors for level 1
if (level == 1) {
Object connector = xDocumentFactory.createInstance(
"com.sun.star.drawing.ConnectorShape");
com.sun.star.drawing.XShape xConnector = (com.sun.star.drawing.XShape)
UnoRuntime.queryInterface(
com.sun.star.drawing.XShape.class, connector);
xDrawPage.add(xConnector);
com.sun.star.beans.XPropertySet xConnectorProps = (com.sun.star.beans.XPropertySet)
UnoRuntime.queryInterface(
com.sun.star.beans.XPropertySet.class, connector);
xConnectorProps.setPropertyValue("StartShape", xStartShape);
xConnectorProps.setPropertyValue("EndShape", xShape);
// glue point positions: 0=top 1=left 2=bottom 3=right
xConnectorProps.setPropertyValue("StartGluePointIndex", new Integer(2));
xConnectorProps.setPropertyValue("EndGluePointIndex", new Integer(0));
}
}
}
}
If a document in OpenOffice.org is required, begin by getting the com.sun.star.frame.Desktop service from the service manager. The desktop handles all document components in OpenOffice.org among other things. It is discussed thoroughly in the chapter 7 Office Development. Office documents are often called components because they support the com.sun.star.lang.XComponent interface. An XComponent is a UNO object that can be disposed explicitly and broadcast an event to other UNO objects when this happens.
The Desktop loads new and existing components from a URL. The desktop has a com.sun.star.frame.XComponentLoader interface that has one single method to load and instantiate components from a URL into a frame:
com::sun::star::lang::XComponent loadComponentFromURL( [in] string aURL,
[in] string aTargetFrameName,
[in] long nSearchFlags,
[in] sequence< com::sun::star::beans::PropertyValue > aArgs )
The parameters in our context are the URL that describes the resource to be loaded, and the load arguments. For the target frame pass in "_blank" and set the search flags to 0. In most cases, you will not want to reuse an existing frame.
The URL can be a file: URL, an http: URL, an ftp: URL or a private: URL. The correct URL format is located in the load URL box at the function bar of OpenOffice.org. For new Draw documents, a special URL scheme is used. The scheme is "private:", followed by "factory" as the hostname and the resource is "sdraw" for OpenOffice.org Draw documents. Thus, for a new Draw document, use "private:factory/sdraw".
The load arguments are described in com.sun.star.document.MediaDescriptor. The properties AsTemplate and Hidden are boolean values and used for programming. If AsTemplate is true, the loader creates a new untitled document from the given URL. If it is false, template files are loaded for editing. If Hidden is true, the document is loaded in the background. This is useful to generate a document in the background without letting the user observe what is happening. For instance, use it to generate a document and print it out without previewing. Refer to 7 Office Development or other available options.
The introductory example shows how to load a drawing document. This snippet loads a new drawing document in hidden mode:
// the method getRemoteServiceManager is described in the chapter First Steps
mxRemoteServiceManager = this.getRemoteServiceManager();
// retrieve the Desktop object, we need its XComponentLoader
Object desktop = mxRemoteServiceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop", mxRemoteContext);
// query the XComponentLoader interface from the Desktop service
XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(
XComponentLoader.class, desktop);
// define load properties according to com.sun.star.document.MediaDescriptor
// the boolean property Hidden tells the office to open a file in hidden mode
PropertyValue[] loadProps = new PropertyValue[1];
loadProps[0] = new PropertyValue();
loadProps[0].Name = "Hidden";
loadProps[0].Value = new Boolean(true);
/* or simply create an empty array of com.sun.star.beans.PropertyValue structs:
PropertyValue[] loadProps = new PropertyValue[0]
*/
// load
com.sun.star.lang.XComponent xComponentLoader.loadComponentFromURL(
"private:factory/sdraw", "_blank", 0, loadProps);
The normal File – Save command for drawing documents can only store the current document in the native OpenOffice.org Draw format and its predecessors. There are other formats that can be stored through the File – Export option. This is mirrored in the API. Exporting in the current version of OpenOffice.org Draw and Impress is a different procedure than storing.
Documents are storable through their interface com.sun.star.frame.XStorable. The 7 Office Development discusses this in detail. An XStorable implements these operations:
boolean hasLocation()
string getLocation()
boolean isReadonly()
void store()
void storeAsURL( [in] string aURL, [in] sequence < com::sun::star::beans::PropertyValue > aArgs)
void storeToURL( [in] string aURL, [in] sequence < com::sun::star::beans::PropertyValue > aArgs)
The method names should be evident. The method storeAsUrl() is the exact representation of File – Save As, that is, it changes the current document location. In contrast, storeToUrl() stores a copy to a new location, but leaves the current document URL untouched. There are also store arguments. A filter name can be passed that tells OpenOffice.org to use older StarOffice Draw file formats. Exporting is a different matter as shown below. The property needed is FilterName which is a string argument that takes filter names defined in the configuration file:
<OfficePath>\share\config\registry\instance\org\openoffice\Office\TypeDetection.xml
In TypeDetection.xml, find <Filter/> elements, their cfg:name attribute contains the required strings for FilterName. The correct filter name for StarDraw 5.x files is "StarDraw 5.0". The following is the element in TypeDetection.xml that describes the StarDraw 5.0 document filter:
<Filter cfg:name="StarDraw 5.0">
<Installed cfg:type="boolean">true</Installed>
<UIName cfg:type="string" cfg:localized="true">
<cfg:value xml:lang="en-US">StarDraw 5.0</cfg:value>
</UIName>
<Data cfg:type="string">
10,draw_StarDraw_50,com.sun.star.drawing.DrawingDocument,,268435559,,5050,,
</Data>
</Filter>
The following method stores a document using this filter:
/** Store a document, using the StarDraw 5.0 Filter */
protected void storeDocComponent(XComponent xDoc, String storeUrl) throws java.lang.Exception {
XStorable xStorable = (XStorable)UnoRuntime.queryInterface(XStorable.class, xDoc);
PropertyValue[] storeProps = new PropertyValue[1];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "FilterName";
storeProps[0].Value = "StarDraw 5.0";
xStorable.storeAsURL(storeUrl, storeProps);
}
If an empty array of PropertyValue structs is passed, the native .odg format of OpenOffice.org is used.
Exporting is not a feature of drawing documents. There is a separate service available from the global service manager for exporting, com.sun.star.drawing.GraphicExportFilter. It supports three interfaces: com.sun.star.document.XFilter, com.sun.star.document.XExporter and com.sun.star.document.XMimeTypeInfo.
Illustration 10.4: GraphicExportFilter |
Exporting is a simple process. After getting a GraphicExportFilter from the ServiceManager, use its XExporter interface to inform the filter which draw page, shape or shape collection to export.
Method of com.sun.star.document.XExporter:
void setSourceDocument ( [in] com::sun::star::lang::XComponent xDoc)
The method name setSourceDocument() may be confusing. Actually, the method would allow exporting entire documents, however, it is only possible to export draw pages, single shapes or shape collections from a drawing document. Since these objects support the XComponent interface, the method specification allows maximum flexibility.
Next, run the method filter() at the XFilter interface. To interrupt the exporting process, call cancel() on the same interface.
Methods of com.sun.star.document.XFilter:
boolean filter( [in] sequence< com::sun::star::beans::PropertyValue > aDescriptor)
void cancel()
The method filter() takes a sequence of PropertyValue structs describing the filter parameters. The following properties from the com.sun.star.document.MediaDescriptor are supported:
|
Properties of com.sun.star.document.MediaDescriptor supported by GraphicExportFilter | |
|
Depending on the export filters supported by this component, this is the mime type of the target graphic file. The mime types currently supported are: image/x-MS-bmp | |
|
This property can been used if no MediaType exists with "Windows Metafile" or "Enhanced Metafile". FilterName has to be set to the extension of these graphic formats (WMF, EMF, BMP). | |
|
The target URL of the file that is created during export. | |
|
|
If necessary, use the interface XMimeTypeInfo to get all mime types supported by the GraphicExportFilter. It offers the following methods: boolean supportsMimeType( [in] string MimeTypeName ) sequence< string > getSupportedMimeTypeNames() XMimeTypeInfo is currently not supported by the GraphicExportFilter |
The following example exports a draw page xPage from a given document xDrawDoc: (Drawing/GraphicExportDemo.java)
//get draw pages
com.sun.star.drawing.XDrawPagesSupplier xPageSupplier = (com.sun.star.drawing.XDrawPagesSupplier)
UnoRuntime.queryInterface(com.sun.star.drawing.XDrawPagesSupplier.class, xDrawDoc);
com.sun.star.drawing.XDrawPages xDrawPages = xPageSupplier.getDrawPages();
// first page
Object page = xDrawPages.getByIndex(0);
com.sun.star.drawing.XDrawPage xPage = (com.sun.star.drawing.XDrawPage)UnoRuntime.queryInterface(
com.sun.star.drawing.XDrawPage.class, page);
Object GraphicExportFilter = xServiceFactory.createInstance(
"com.sun.star.drawing.GraphicExportFilter");
// use the XExporter interface to set xPage as source component
// for the GraphicExportFilter
XExporter xExporter = (XExporter)UnoRuntime.queryInterface(
XExporter.class, GraphicExportFilter );
XComponent xComp = (XComponent)UnoRuntime.queryInterface(XComponent.class, xPage);
xExporter.setSourceDocument(xComp);
// prepare the media descriptor for the filter() method in XFilter
PropertyValue aProps[] = new PropertyValue[2];
aProps[0] = new PropertyValue();
aProps[0].Name = "MediaType";
aProps[0].Value = "image/gif";
// for some graphic formats, e.g. Windows Metafile, there is no Mime type,
// therefore it is also possible to use the property FilterName with
// Filter names as defined in the file TypeDetection.xml (see "Storing")
/* aProps[0].Name = "FilterName";
aProps[0].Value = "WMF - MS Windows Metafile";
*/
aProps[1] = new PropertyValue();
aProps[1].Name = "URL";
aProps[1].Value = "file:///home/images/page1.gif";
// get XFilter interface and launch the export
XFilter xFilter = (XFilter) UnoRuntime.queryInterface(
XFilter.class, GraphicExportFilter);
xFilter.filter(aProps);
Printing is a common office functionality. Refer to Chapter 7 Office Development for additional information. The Draw document implements the com.sun.star.view.XPrintable interface for printing. It consists of three methods:
sequence< com::sun::star::beans::PropertyValue > getPrinter()
void setPrinter( [in] sequence< com::sun::star::beans::PropertyValue > aPrinter)
void print( [in] sequence< com::sun::star::beans::PropertyValue > xOptions)
To print to the standard printer without settings, use the snippet below with a given document xDoc:
// query the XPrintable interface from your document
XPrintable xPrintable = (XPrintable)UnoRuntime.queryInterface(XPrintable.class, xDoc);
// create an empty printOptions array
PropertyValue[] printOpts = new PropertyValue[0];
// kick off printing
xPrintable.print(printOpts);
There are two groups of properties involved in general printing. The first one is used with setPrinter() and getPrinter(),and controls the printer, the second one is passed to print() and controls the print job.
The method getPrinter() returns a sequence of PropertyValue structs describing the printer containing the properties specified in the service com.sun.star.view.PrinterDescriptor. It comprises the following properties:
|
Properties of com.sun.star.view.PrinterDescriptor | |
|
string — Specifies the name of the printer queue to be used. | |
|
com.sun.star.view.PaperOrientation. Specifies the orientation of the paper. | |
|
com.sun.star.view.PaperFormat. Specifies a predefined paper size or if the paper size is a user-defined size. | |
|
com.sun.star.awt.Size. Specifies the size of the paper in 1/100 mm. | |
|
boolean — Indicates if the printer is busy. | |
|
boolean — Indicates if the printer allows changes to PaperOrientation. | |
|
boolean — Indicates if the printer allows changes to PaperFormat. | |
|
boolean — Indicates if the printer allows changes to PaperSize. | |
The PrintOptions offer the following choices for a print job:
|
Properties of com.sun.star.view.PrintOptions | |
|
short — Specifies the number of copies to print. | |
|
string — If set, specifies the name of a file to print to. | |
|
boolean — Advises the printer to collate the pages of the copies. If true, a whole document is printed prior to the next copy, otherwise copies for each page are completed together. | |
|
string — Specifies the pages to print. It has the same format as in the print dialog of the GUI, for example, 1, 3, 4-7, 9. | |
The following method uses PrinterDescriptor and PrintOptions to print to a specific printer, and preselect the pages to print:
The following method uses both, PrinterDescriptor and PrintOptions, to print to a specific printer and preselect the pages to print:
protected void printDocComponent(XComponent xDoc) throws java.lang.Exception {
XPrintable xPrintable = (XPrintable)UnoRuntime.queryInterface(XPrintable.class, xDoc);
PropertyValue[] printerDesc = new PropertyValue[1];
printerDesc[0] = new PropertyValue();
printerDesc[0].Name = "Name";
printerDesc[0].Value = "5D PDF Creator";
xPrintable.setPrinter(printerDesc);
PropertyValue[] printOpts = new PropertyValue[1];
printOpts[0] = new PropertyValue();
printOpts[0].Name = "Pages";
printOpts[0].Value = "1-4,7";
xPrintable.print(printOpts);
}
In Draw documents, one slide is printed as one page on the printer by default. In the example above, slide one through four and slide seven are printed.
The printed drawing view (drawings, notes, handout pages, outline), the print quality (color, grayscale), the page options (tile, fit to page, brochure, paper tray) and additional options (page name, date, time, hidden pages) can all be controlled. 10.6.2 Drawing - Overall Document Features - Settings describes how these settings are used.
Illustration 10.5: DrawingDocument Structure |
Draw documents maintain their drawing content on draw pages, master pages and layers. If a new draw document is opened, it contains one slide that corresponds to a com.sun.star.drawing.DrawPage service. Switching to Master View brings up the master page handled by the service com.sun.star.drawing.MasterPage. The Layer View allows access to layers to structure your drawings. These layers can be controlled through com.sun.star.drawing.Layer and com.sun.star.drawing.LayerManager.
Draw and Impress documents supply their pages (slides) through the interface com.sun.star.drawing.XDrawPagesSupplier. The method com.sun.star.drawing.XDrawPagesSupplier:getDrawPages() returns a container of draw pages with a com.sun.star.drawing.XDrawPages interface that is derived from com.sun.star.container.XIndexAccess. That is, XDrawPages allows accessing, inserting and removing pages of a drawing document:
type getElementType()
boolean hasElements()
long getCount()
any getByIndex(long Index)
com::sun::star::drawing::XDrawPage insertNewByIndex(long nIndex)
void remove(com::sun::star::drawing::XDrawPage xPage)
The example below demonstrates how to access and create draw and master pages. Layers will be described later.
XDrawPagesSupplier xDrawPagesSupplier = (XDrawPagesSupplier)UnoRuntime.queryInterface(
XDrawPagesSupplier.class, xComponent);
// XDrawPages inherits from com.sun.star.container.XIndexAccess
XDrawPages xDrawPages = xDrawPagesSupplier.getDrawPages();
// get the page count for standard pages
int nPageCount = xDrawPages.getCount();
// get draw page by index
XDrawPage xDrawPage = (XDrawPage)UnoRuntime.queryInterface(XDrawPage .class,
xDrawPages.getByIndex(nIndex));
/* create and insert a draw page into the given position,
the method returns the newly created page
*/
XDrawPage xNewDrawPage = xDrawPages.insertNewByIndex(0);
// remove the given page
xDrawPages.remove( xDrawPage );
/* now repeat the same procedure as described above for the master pages,
the main difference is to get the XDrawPages from the XMasterPagesSupplier
interface
*/
XMasterPagesSupplier xMasterPagesSupplier = (XMasterPagesSupplier)UnoRuntime.queryInterface(
XMasterPagesSupplier.class, xComponent);
XDrawPages xMasterPages = xMasterPagesSupplier.getMasterPages();
// xMasterPages can now be used in the same manner as xDrawPages is used above
Each draw page always has one master page. The interface
com.sun.star.drawing.XMasterPageTarget offers methods to get and set the master page that is correlated to a draw page.
// query for MasterPageTarget
XMasterPageTarget xMasterPageTarget = (XMasterPageTarget)UnoRuntime.queryInterface(
XMasterPageTarget.class, xDrawPage);
// now we can get the corresponding master page
XDrawPage xMasterPage = xMasterPageTarget.getMasterPage();
/* this method now sets a new master page,
it is important to mention that the applied page must be part of the MasterPages
*/
xMasterPageTarget.setMasterPage(xMasterPage);
It is possible to copy pages using the interface com.sun.star.drawing.XDrawPageDuplicator of drawing or presentation documents.
Methods of com.sun.star.drawing.XDrawPageDuplicator:
com::sun::star::drawing::XDrawPage duplicate( [in] com::sun::star::drawing::XDrawPage xPage)
Pass a draw page reference to the method duplicate(). It appends a new draw page at the end of the page list, using the default naming scheme for pages, “slide n”.
All units and dimensions are measured in 1/100th of a millimeter. The coordinates are increasing from left to right, and from top to bottom. The upper-left position of a page is (0, 0).
The page size, margins and orientation can be determined using the following properties of a draw page (generic draw page):
|
Properties of com.sun.star.drawing.GenericDrawPage | |
|
long — Height of the page. | |
|
long — Width of the page. | |
|
long — Bottom margin of the page. | |
|
long — Left margin of the page. | |
|
long — Right margin of the page. | |
|
long — Top margin of the page. | |
|
com.sun.star.view.PaperOrientation. Determines if the printer output should be turned by 90°. Possible values are: PORTRAIT and LANDSCAPE. | |
Drawings consist of shapes on draw pages. Shapes are drawing elements, such as rectangles, circles, polygons, and lines. To create a drawing, get a shape by its service name at the ServiceFactory of a drawing document and add it to the appropriate DrawPage.
The code below demonstrates how to create shapes. It consists of a static helper method located in the class ShapeHelper and will be used throughout this chapter to create shapes. The parameter xComponent must be a reference to a loaded drawing document. The x, y, height and width are the desired position and size, and sShapeType expects a service name for the shape, such as "com.sun.star.drawing.RectangleShape". The method does not actually insert the shape into a page. It instantiates it and returns the instance to the caller.
Illustration 10.6: Shape |
The size and position of a shape can be set before adding a shape to a page. After adding the shape, change the shape properties through com.sun.star.beans.XPropertySet. (Drawing/Helper.java)
public static XShape createShape( XComponent xComponent,
int x, int y, int width, int height, String sShapeType) throws java.lang.Exception {
// query the document for the document-internal service factory
XMultiServiceFactory xFactory = (XMultiServiceFactory)UnoRuntime.queryInterface(
XMultiServiceFactory.class, xComponent);
// get the given Shape service from the factory
Object xObj = xFactory.createInstance(sShapeType);
Point aPos = new Point(x, y);
Size aSize = new Size(width, height);
// use its XShape interface to determine position and size before insertion
xShape = (XShape)UnoRuntime.queryInterface(XShape.class, xObj);
xShape.setPosition(aPos);
xShape.setSize(aSize);
return xShape;
}
|
|
Notice, the following restrictions: A shape cannot be inserted into multiple pages, and most methods do not work before the shape is inserted into a draw page. |
The previously declared method will be used to create a simple rectangle shape with a size of 10 cm x 5 cm that is positioned in the upper-left, and inserted into a drawing page.
// query DrawPage for XShapes interface
XShapes xShapes = (XShapes)UnoRuntime.queryInterface(XShapes.class, xDrawPage);
// create the shape
XShape xShape = createShape(xComponent, 0, 0, 10000, 5000, “com.sun.star.drawing.RectangleShape”);
// add shape to DrawPage
xShapes.add(xShape);
// set text
XText xText = (XText)UnoRuntime.queryInterface( XText.class, xShape );
xText.setString("My new RectangleShape");
// to be able to set Properties a XPropertySet interface is needed
XPropertySet xPropSet = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xShape);
xPropSet.setPropertyValue("CornerRadius", new Integer(1000));
xPropSet.setPropertyValue("Shadow", new Boolean(true));
xPropSet.setPropertyValue("ShadowXDistance", new Integer(250));
xPropSet.setPropertyValue("ShadowYDistance", new Integer(250));
// blue fill color
xPropSet.setPropertyValue("FillColor", new Integer(0xC0C0C0));
// black line color
xPropSet.setPropertyValue("LineColor", new Integer(0x000000));
xPropSet.setPropertyValue("Name", "Rounded Gray Rectangle");
The UML diagram in Illustration 10.3 describes all services that are included by the com.sun.star.drawing.RectangleShape service and provides an overview of properties that can be used with such a simple shape.
Illustration 10.7: RectangleShape |
Shape Types
|
|
The following table lists all shapes supported in Draw and Impress documents. They come from the com.sun.star.drawing. Each shape is based on com.sun.star.drawing.Shape. Additionally, there are five services in the module com.sun.star.drawing that most of the shapes have in common:
com.sun.star.drawing.Text, com.sun.star.drawing.LineProperties, com.sun.star.drawing.FillProperties and com.sun.star.drawing.ShadowProperties handle shape formatting, whereas com.sun.star.drawing.RotationDescriptor controls rotation and shearing. The section 10.3.2 Drawing - Working with Drawing Documents - Shapes - Shape Operations - General Drawing Properties below discusses shape formatting in more detail. Refer to the section 10.3.2 Drawing - Working with Drawing Documents - Shapes - Shape Operations for information on rotation and shearing.
|
|
The service com.sun.star.drawing.Text is different from other Text services. It consists of the service com.sun.star.drawing.TextProperties and the interface com.sun.star.text.XText that was introduced in the chapter 2 First Steps. Drawing text does not supports text contents other than paragraphs consisting of character strings. |
An x denotes which of these services are supported by each shape. The rightmost column shows the services, interfaces and properties that are specific for the various shapes.
|
ShapeType |
Text |
LineProperties |
FillProperties |
ShadowProperties |
RotationDescriptor |
supported services, exported interfaces, properties |
|
x |
x |
x |
x |
x |
included service: | |
|
x |
x |
|
x |
x |
included service: properties: | |
|
|
|
|
|
|
exported interface: | |
|
x |
x |
x |
x |
x |
properties: | |
|
x |
|
|
x |
x |
properties: | |
|
|
|
|
|
|
exported interfaces: | |
|
x |
x |
|
x |
x |
included service: | |
|
x |
x |
|
x |
x |
included service: properties: | |
|
|
|
|
|
|
properties: readonly properties: | |
|
x |
x |
|
x |
x |
included service: | |
|
|
|
|
|
|
| |
|
x |
x |
|
x |
x |
included service: | |
|
x |
x |
x |
x |
x |
included service: | |
|
x |
x |
x |
x |
x |
included service: | |
|
x |
x |
x |
x |
x |
properties: | |
|
x |
x |
x |
x |
x |
properties: | |
|
|
|
|
|
|
properties: |
Draw supports three different kinds of Bezier curves: OpenBezierShape, ClosedBezierShape and PolyPolygonBezierShape. They are all controlled by com.sun.star.drawing.PolyPolygonBezierDescriptor which is made up of the following properties:
|
Properties of com.sun.star.drawing.PolyPolygonBezierDescriptor | |
|
[readonly] com.sun.star.drawing.PolygonKind. Type of the polygon. Possible values are: LINE for a LineShape. POLY for a PolyPolygonShape. PLIN for a PolyLineShape. PATHLINE for an OpenBezierShape. PATHFILL for a ClosedBezierShape.
| |
|
struct com.sun.star.drawing.PolyPolygonBezierCoords. These are the bezier points of the polygon. The struct members are Coordinates and Flags, which are both sequences of sequences. The Coordinates sequence contains com.sun.star.awt.Point structs and the Flags sequence contains com::com.sun.star.drawing.PolygonFlags enums. Point members are X and Y. Possible PolygonFlags values are:
| |
|
com.sun.star.drawing.PolyPolygonBezierCoords. These are the untransformed bezier coordinates of the polygon. The property has the same type as PolyPolygonBezier. | |
The next Java example will demonstrate how to create a ClosedBezierShape that looks like the following picture. (Drawing/DrawingDemo.java)
XShape xPolyPolygonBezier = createShape( xComponent, 0, 0, 0, 0,
"com.sun.star.drawing.ClosedBezierShape");
// take care of the fact that the shape must have been added
// to the page before it is possible to apply changes
XShapes xShapes = (XShapes)UnoRuntime.queryInterface( XShapes.class, xDrawPage);
xShapes.add(xPolyPolygonBezier);
// now it is possible to edit the PropertySet
XPropertySet xShapeProperties = (XPropertySet)UnoRuntime.queryInterface(
XPropertySet.class, xPolyPolygonBezier);
// The following values are exemplary and provokes that a PolyPolygon of
// sixteen single polygons containing four points each is created. The
// PolyPolygon total point count will be 64.
// If control points are used they are allowed to appear as pair only,
// before and after such pair has to be a normal point.
// A bezier point sequence may look like
// this (n=normal, c=control) : n c c n c c n n c c n
int nPolygonCount = 16;
int nPointCount = 4;
int nWidth = 10000;
int nHeight = 10000;
PolyPolygonBezierCoords aCoords = new PolyPolygonBezierCoords();
// allocating the outer sequence
aCoords.Coordinates = new Point[nPolygonCount][];
aCoords.Flags = new PolygonFlags[nPolygonCount][];
int i, n, nY;
// fill the inner point sequence now
for (nY = 0, i = 0; i < nPolygonCount; i++, nY += nHeight / nPolygonCount) {
// create a polygon using two normal and two control points
// allocating the inner sequence
Point[] pPolyPoints = new Point[nPointCount];
PolygonFlags[] pPolyFlags = new PolygonFlags[nPointCount];
for (n = 0; n < nPointCount; n++)
pPolyPoints[n] = new Point();
pPolyPoints[0].X = 0;
pPolyPoints[0].Y = nY;
pPolyFlags [0] = PolygonFlags.NORMAL;
pPolyPoints[1].X = nWidth / 2;
pPolyPoints[1].Y = nHeight;
pPolyFlags[1] = PolygonFlags.CONTROL;
pPolyPoints[2].X = nWidth / 2;
pPolyPoints[2].Y = nHeight;
pPolyFlags [2] = PolygonFlags.CONTROL;
pPolyPoints[3].X = nWidth;
pPolyPoints[3].Y = nY;
pPolyFlags [3] = PolygonFlags.NORMAL;
aCoords.Coordinates[i] = pPolyPoints;
aCoords.Flags[i] = pPolyFlags;
}
try {
xShapeProperties.setPropertyValue("PolyPolygonBezier", aCoords);
} catch (Exception ex)
{
}
Moving and scaling of a shape can be done by using the corresponding methods getPosition(), setPosition(), getSize() and setSize() of the com.sun.star.drawing.XShape interface:
string getShapeType()
com::sun::star::awt::Point getPosition()
void setPosition( [in] com::sun::star::awt::Point aPosition)
com::sun::star::awt::Size getSize()
void setSize( [in] com::sun::star::awt::Size aSize)
Point and Size are IDL structs. In Java, these structs are mapped to classes with constructors that take values for the struct members. Therefore, when new is used to instantiate these classes, the coordinates and dimensions are passed to initialize the class members X, Y, Width and Height.
Most shapes, except OLE and group objects, can be rotated and sheared. All of these objects include the com.sun.star.drawing.RotationDescriptor service that has the properties RotateAngle and ShearAngle.
Setting the com.sun.star.drawing.RotationDescriptor rotates or shears a shape:
|
Properties of com.sun.star.drawing.RotationDescriptor | |
|
long — This is the angle for rotation of this shape in 1/100th of a degree. The shape is rotated counter-clockwise around the center of the bounding box. | |
|
long — This is the amount of shearing for this shape in 1/100th of a degree. The shape is sheared clockwise around the center of the bounding box. | |
|
|
Notice that the rotation works counter-clockwise, while shearing works clockwise. |
Illustration 10.9 Rotation and Shearing by 25 degrees |
The following example shows how a shape can be rotated by 25 degrees counterclockwise:
// xShape will be rotated by 25 degrees
XPropertySet xPropSet = (XPropertySet)UnoRuntime.queryInterface(
XPropertySet.class, xShape );
xPropSet.setPropertyValue( "RotateAngle", new Integer( 2500 ) );
Changing the size, rotation and shearing of an object can be done by using the transformation mechanism provided by OpenOffice.org. The matrix of our API is a standard homogenous 3x3 matrix that may be used together with the java.awt.geom.AffineTransform class from Java. The transformation received describes the actual values of the transformations as a linear combination of the single matrices. The basic object without transformation has a size of (1, 1) and a position of (0, 0), and is not rotated or sheared. Thus, to transform an object get its matrix and multiply from the left side to influence the current appearance. To set the whole transformation directly, build a combined matrix of the single values mentioned above and apply it to the object. (Drawing/ObjectTransformationDemo.java)
XPropertySet xPropSet = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xShape );
// take the current tranformation matrix
HomogenMatrix3 aHomogenMatrix3 = (HomogenMatrix3)xPropSet.getPropertyValue("Transformation");
java.awt.geom.AffineTransform aOriginalMatrix = new java.awt.geom.AffineTransform(
aHomogenMatrix3.Line1.Column1, aHomogenMatrix3.Line2.Column1,
aHomogenMatrix3.Line1.Column2, aHomogenMatrix3.Line2.Column2,
aHomogenMatrix3.Line1.Column3, aHomogenMatrix3.Line2.Column3 );
// rotate the object by 15 degrees
AffineTransform aNewMatrix1 = new AffineTransform();
aNewMatrix1.setToRotation(Math.PI /180 * 15);
aNewMatrix1.concatenate(aOriginalMatrix);
// and translate the object by 2cm on the x-axis
AffineTransform aNewMatrix2 = new AffineTransform();
aNewMatrix2.setToTranslation(2000, 0);
aNewMatrix2.concatenate(aNewMatrix1);
double aFlatMatrix[] = new double[6];
aNewMatrix2.getMatrix(aFlatMatrix);
// convert the flatMatrix to our HomogenMatrix3 structure
aHomogenMatrix3.Line1.Column1 = aFlatMatrix[0];
aHomogenMatrix3.Line2.Column1 = aFlatMatrix[1];
aHomogenMatrix3.Line1.Column2 = aFlatMatrix[2];
aHomogenMatrix3.Line2.Column2 = aFlatMatrix[3];
aHomogenMatrix3.Line1.Column3 = aFlatMatrix[4];
aHomogenMatrix3.Line2.Column3 = aFlatMatrix[5];
xPropSet.setPropertyValue("Transformation", aHomogenMatrix3);
The property ZOrder of the com.sun.star.drawing.Shape service defines the order a shape is drawn. That is, if there are many shapes on a page, the shape that has the lowest ZOrder value is drawn first, and the shape that has the highest ZOrder is drawn last. By using this property it is possible to bring an object to the back or front of a page. It is also possible to switch the order of two shapes as demonstrated in the following example: (Drawing/ChangeOrderDemo.java)
XPropertySet xPropSet1 = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xShape1);
XPropertySet xPropSet2 = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xShape2);
// get current positions
int nOrderOfShape1 = ((Integer)xPropSet1.getPropertyValue("ZOrder")).intValue();