Working with Shapes
We describe first our new starting code. Any procedures are added to simplify the listings given here (from Christian Junker).
[cpp]
//Listing 1 New sub to simplify Shape Management
// C++
// Don't forget to add : #include <com/sun/star/drawing/XShapes.hpp>
// Don't forget to add "com.sun.star.drawing.XShapes \" in the makefile
// Don't forget to add : using namespace com::sun::star::beans; // Don't forget to add : #include <com/sun/star/beans/XPropertySet.hpp> // Don't forget to add "com.sun.star.beans.XPropertySet \" in the makefile
// Christian Junker code void MakePosition(sal_Int32 x, sal_Int32 y, ::com::sun::star::awt::Point *Pos) {
Pos->X = x; Pos->Y = y; }
void MakeSize(sal_Int32 width, sal_Int32 height, ::com::sun::star::awt::Size *Size) { Size->Width = width; Size->Height = height; }
void DrawMe(Reference< XShape > &Shape, Reference< XDrawPage > &page, const char *shapename)
{
Reference< XShapes > Shapes(page, UNO_QUERY);
Shapes->add(Shape);
Reference< XPropertySet > shapeprops(Shape, UNO_QUERY);
shapeprops->setPropertyValue(OUString::createFromAscii("Name"),
makeAny(OUString::createFromAscii(shapename)));
}
With these procedures we start now from a rectangle shape : our new starting main code is then :
[cpp]
//Listing 2 Our new starting Code
int main( ) {
//retrieve an instance of the remote service manager
Reference< XMultiServiceFactory > rOfficeServiceManager; rOfficeServiceManager = ooConnect(); if( rOfficeServiceManager.is() ){ printf( "Connected sucessfully to the office\n" ); }
//get the desktop service using createInstance returns an XInterface type
Reference< XInterface > Desktop = rOfficeServiceManager->createInstance( OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
//query for the XComponentLoader interface
Reference< XComponentLoader > rComponentLoader (Desktop, UNO_QUERY); if( rComponentLoader.is() ){ printf( "XComponentloader successfully instanciated\n" ); }
//get an instance of the OOowriter document
Reference< XComponent > xcomponent = rComponentLoader->loadComponentFromURL(
OUString::createFromAscii("private:factory/sdraw"),
OUString::createFromAscii("_blank"), 0, Sequence < ::com::sun::star::beans::PropertyValue >());
// added code here Reference< XDrawPagesSupplier > rDrawDoc(xcomponent, UNO_QUERY);
// query the XDrawPages Interface Reference< XDrawPages > rDrawPages = rDrawDoc->getDrawPages();
// query the XIndexAccess Interface Reference< XIndexAccess > rPageIndexAccess(rDrawPages, UNO_QUERY);
Any DrawPage = rPageIndexAccess->getByIndex(0);
// Query the XDrawPage Interface Reference< XDrawPage > rDrawPage(DrawPage, UNO_QUERY); // query for the XNamed Interface Reference< XNamed > rNamed(DrawPage, UNO_QUERY); rNamed->setName(OUString::createFromAscii("My first page"));
Reference< XMultiServiceFactory > DocFactory(xcomponent, UNO_QUERY);
Point *Pos = new (Point); Size *TheSize = new ( Size );
Reference< XInterface > RectangleShape = DocFactory->createInstance( OUString::createFromAscii("com.sun.star.drawing.RectangleShape") ); Reference< XShape > rRectShape(RectangleShape, UNO_QUERY); MakePosition(2000, 6000, Pos); MakeSize(7000, 2000, TheSize); rRectShape->setPosition(*Pos); rRectShape->setSize(*TheSize); DrawMe(rRectShape, rDrawPage, "My TextShape");
// add code here
return 0;
} This code draws a blue colored rectangle.
Contents
Shape's Properties
Background Colors and Shape Colors
The shape is usually created with a default background color and and a uniform (solid) color. It is possible to change this. We search how, and then begin with a look to <OpenOffice.org1.1_SDK>/idl/com/sun/star/drawing/fillstyle.idl file :
//Listing 3 Fillstyle IDL File // IDL module com { module sun { module star { module drawing { enum FillStyle { NONE, SOLID, GRADIENT, HATCH, BITMAP }; }; }; }; };
This problem has been already tackled in To go further : the Enumeration values Problem : we can deduce from this IDL file that our constants in C++ are : FillStyle_NONE, FillStyle_SOLID, ... and FillStyle_BITMAP and we have to construct the corresponding hpp and hxx files.
The second problem is how to translate this OOoBasic piece of code :
[oobas]
'Listing 4 How to translate this OOoBasic Code ?
REM ***** BASIC *****
MaForme.FillColor = RGB(255,200,255)
MaForme.FillStyle = com.sun.star.drawing.FillStyle.NONE
To put it differently, is the FillStyle a property and what about FillColor ? To search an answer we return to IDL file with FillProperties.idl :
//Listing 5 Fillproperties IDL File // IDL module com { module sun { module star { module drawing { service FillProperties { [property] com::sun::star::drawing::FillStyle FillStyle; [property] long FillColor; [property] short FillTransparence; [property] string FillTransparenceGradientName; [optional, property] com::sun::star::awt::Gradient FillTransparenceGradient; [property] string FillGradientName; [optional, property] com::sun::star::awt::Gradient FillGradient; [property] string FillHatchName; [optional, property] com::sun::star::drawing::Hatch FillHatch; [property] string FillBitmapName; [optional, property] com::sun::star::awt::XBitmap FillBitmap; [optional, property] string FillBitmapURL; [property] short FillBitmapOffsetX; [property] short FillBitmapOffsetY; [property] short FillBitmapPositionOffsetX; [property] short FillBitmapPositionOffsetY; [property] com::sun::star::drawing::RectanglePoint FillBitmapRectanglePoint; [property] boolean FillBitmapLogicalSize; [property] long FillBitmapSizeX; [property] long FillBitmapSizeY; [property] com::sun::star::drawing::BitmapMode FillBitmapMode; [property] boolean FillBackground; }; }; }; }; };
The both first properties seem interesting for us. We begin with FillColor. If we add this code we obtain a rectangle with an other color.
[cpp]
//Listing 6 Coloring the Shape Background
// C++
// Don't forget to add : using namespace com::sun::star::beans;
// Don't forget to add : #include <com/sun/star/beans/XPropertySet.hpp>
// Don't forget to add "com.sun.star.beans.XPropertySet \" in the makefile
// Get the property set of the rRectShape
Reference< XPropertySet > rShapeProps(rRectShape,UNO_QUERY);
Any color;
color<<=(long)0xFF00; //green
rShapeProps->setPropertyValue(OUString::createFromAscii("FillColor"),color);
The color is defined in RGB : one octet for each : 0xff0000 is red, 0x00ff00 is green and 0x0000ff is blue.
It's time to remove the background color with the FillStyle_NONE constant. Simply add this code :
[cpp]
//Listing 7 Removing the Shape Background
// C++
// Don't forget to add : #include <com/sun/star/drawing/FillStyle.hpp>
// Don't forget to add "com.sun.star.drawing.FillStyle \" in the makefile
Any FillStyle; FillStyle <<= FillStyle_NONE; rShapeProps->setPropertyValue(OUString::createFromAscii("FillStyle"),FillStyle); We stop here but there is a lot to do with other FillStyle constants.
Shape and Shadow
Shadow is described by ShadowProperties.idl file :
// IDL module com { module sun { module star { module drawing { service ShadowProperties { [property] boolean Shadow; [property] long ShadowColor; [property] short ShadowTransparence; [property] long ShadowXDistance; [property] long ShadowYDistance; }; }; }; }; };
Then the corresponding C++ code to manipulate these properties could be :
[cpp]
//Listing 8 Shadowing a Shape
// C++
// Shadow
Any ShadowProperties[4];
ShadowProperties[0] <<= (sal_Bool)true;
ShadowProperties[1] <<= (long) 0xFF0000; // red
ShadowProperties[2] <<= (long) 300;
ShadowProperties[3] <<= (long) 300;
rShapeProps->setPropertyValue(OUString::createFromAscii("Shadow"),ShadowProperties[0]);
rShapeProps->setPropertyValue(OUString::createFromAscii("ShadowColor"),
ShadowProperties[1]);
rShapeProps->setPropertyValue(OUString::createFromAscii("ShadowXDistance"),
ShadowProperties[2]);
rShapeProps->setPropertyValue(OUString::createFromAscii("ShadowYDistance"),
ShadowProperties[3]);
This code adds a red shadow at the rectangle shape.
Shape's Rotation and sharing
The corresponding IDL file is
// IDL module com { module sun { module star { module drawing { service RotationDescriptor { /** This is the angle for rotation of this Shape. The shape is rotated counter-clockwise around the center of the bounding box. */ [property] long RotateAngle; [optional, property] long ShearAngle; }; }; }; }; };
The angle is given in 1/100° starting from an horizontal line.
[cpp]
//Listing 9 Rotating a Shape
// C++
Any Angle;
Angle <<= (long)3000; // 30 degres
rShapeProps->setPropertyValue(OUString::createFromAscii("RotateAngle"),Angle);
which gives a 30° rotation.
Line Style
The corresponding IDL files are :
//Listing 10 Lineproperties IDL file // IDL module com { module sun { module star { module drawing { service LineProperties { [property] com::sun::star::drawing::LineStyle LineStyle; [property] com::sun::star::drawing::LineDash LineDash; [property] long LineColor; [property] short LineTransparence; [property] long LineWidth; [property] com::sun::star::drawing::LineJoint LineJoint; [optional, property] string LineStartName; [optional, property] com::sun::star::drawing::PolyPolygonBezierCoords LineStart; [optional, property] com::sun::star::drawing::PolyPolygonBezierCoords LineEnd; [optional, property] boolean LineStartCenter; [optional, property] long LineStartWidth; [optional, property] boolean LineEndCenter; [optional, property] long LineEndWidth; }; }; }; }; };
completed with :
//Listing 11 LineStyle Enumeration // IDL module com { module sun { module star { module drawing { enum LineStyle { NONE, SOLID, DASH }; }; }; }; };
We give the significance of these constants :
- line styles
Constant | Signification |
NONE | Line is not visible |
SOLID | continuous line (default value) |
DASH | Dash line; LineDash property is controling the dash's shape |
We give now the LineDash properties with an IDL file
//Listing 12 IDL File : Linedash // IDL module com { module sun { module star { module drawing { struct LineDash { com::sun::star::drawing::DashStyle Style; short Dots; long DotLen; short Dashes; long DashLen; long Distance; }; }; }; }; };
and their meaning :
- lineDash properties
Proprerty | Signification |
Style | A constant ( com.sun.star.drawing.DashStyle.xxx) gives the dash style |
Dots | How many dots |
DotLen | Dot length in 1/100 mm |
Dashes | How many dashes |
DashLen | Dash length in 1/100 mm |
Distance | distance between dots in 1/100 mm |
The dash styles are given
//Listing 13 DashStyle IDL File // IDL module com { module sun { module star { module drawing { enum DashStyle { RECT, ROUND, RECTRELATIVE, ROUNDRELATIVE }; }; }; }; };
Here is an example in C++ which uses a line style :
[cpp]
//Listing 14 Modifying a Line Style : en Example
// C++
// Line dash
// Don't forget to add : #include <com/sun/star/drawing/LineDash.hpp>
// Don't forget to add "com.sun.star.drawing.LineDash \" in the makefile
// Don't forget to add : #include <com/sun/star/drawing/LineStyle.hpp>
// Don't forget to add "com.sun.star.drawing.LineStyle \" in the makefile
LineDash *Tirets = new (LineDash);
Tirets->Style = DashStyle_RECT;
Tirets->Dots = 3; Tirets->DotLen = 50; Tirets->Dashes = 2; Tirets->DashLen = 200; Tirets->Distance = 150;
Any LineStyle,LineDash,LineWidth; LineStyle <<= LineStyle_DASH; rShapeProps->setPropertyValue(OUString::createFromAscii("LineStyle"),LineStyle); LineDash <<= *Tirets; rShapeProps->setPropertyValue(OUString::createFromAscii("LineDash"),LineDash); color <<= (long)0xFF00; rShapeProps->setPropertyValue(OUString::createFromAscii("LineColor"),color); LineWidth <<= (long) 50; rShapeProps->setPropertyValue(OUString::createFromAscii("LineWidth"),LineWidth); Adding this code to the previous one, gives this figure :
Drawing Shapes
Polyline Shape
When working with polyline the first question we have to answer is what is a Sequence < Sequence < Point >> ? We give the IDL description :
//Listing 15 PointSequenceSequence IDL File // IDL module com { module sun { module star { module drawing { typedef sequence<PointSequence> PointSequenceSequence; }; }; }; };
What is a PointSequence ?
//Listing 16 PointSequence IDL File // IDL module com { module sun { module star { module drawing { typedef sequence<com::sun::star::awt::Point> PointSequence; }; }; }; };
We can have a look at PolyLineShape now :
//Listing 17 PolyLineShape IDL File // IDL module com { module sun { module star { module drawing { service PolyLineShape { service com::sun::star::drawing::Shape; service com::sun::star::drawing::LineProperties; service com::sun::star::drawing::PolyPolygonDescriptor; service com::sun::star::drawing::Text; service com::sun::star::drawing::ShadowProperties; service com::sun::star::drawing::RotationDescriptor; }; }; }; }; };
The last IDL file we have to inspect is the PolyPolygonDescriptor service :
//Listing 18 PolyPolygonDescriptor IDL File // IDL module com { module sun { module star { module drawing { service PolyPolygonDescriptor { [readonly, property] com::sun::star::drawing::PolygonKind PolygonKind; [property] com::sun::star::drawing::PointSequenceSequence PolyPolygon; [property] com::sun::star::drawing::PointSequenceSequence Geometry; }; }; }; }; };
where we see the PolyPolygon is a property. These files allow us to draw any tips :
first construct a Sequence< Sequence< Point >> and put values in it
second transform it in an Any variable
third, use the XPropertySet to gives a value to the property "PolyPolygon"
This conduct us to the following example
[cpp]
//Listing 19 Using a Polyline Shape
// C++
Sequence< Sequence< Point > > PointsSeqSeq(2);
Sequence< Point > PointsArray(4);
//Size *TheSize = new ( Size );
Reference< XInterface > PolyLineShape = DocFactory->createInstance( OUString::createFromAscii("com.sun.star.drawing.PolyLineShape") ); Reference< XShape > rPolyLineShape(PolyLineShape, UNO_QUERY); MakePosition(1100, 8000, &PointsArray[0]); MakePosition(1500, 6000, &PointsArray[1]); MakePosition(1900, 8000, &PointsArray[2]); MakePosition(2300, 6000, &PointsArray[3]);
PointsSeqSeq[0]=PointsArray;
PointsArray.realloc(5); MakePosition(1100, 9000, &PointsArray[0]); MakePosition(1500, 7000, &PointsArray[1]); MakePosition(1900, 9000, &PointsArray[2]); MakePosition(2300, 7000, &PointsArray[3]); MakePosition(2700, 9000, &PointsArray[4]); PointsSeqSeq[1]=PointsArray;
DrawMe(rPolyLineShape, rDrawPage, "");
Any PropspolyPoly; PropspolyPoly <<= PointsSeqSeq; Reference< XPropertySet > rPolyShapeProps(rPolyLineShape,UNO_QUERY); rPolyShapeProps->setPropertyValue(OUString::createFromAscii("PolyPolygon"),PropspolyPoly); When running, this example gives a figure presented below : If you replace “PolyLineShape” with “PolyPolygonShape” in the previous code, you obtain the same shape but closed (and by default filled).
Bezier Shape
Let us begin describing the Bezier's struct : PolyPolygonBezierCoords is presented now :
//Listing 20 PolyPolygonBezierCoords IDL File // IDL module com { module sun { module star { module drawing { struct PolyPolygonBezierCoords { // DocMerge: empty anyway com::sun::star::drawing::PointSequenceSequence Coordinates; // DocMerge: empty anyway com::sun::star::drawing::FlagSequenceSequence Flags; }; }; }; }; };
PointSequenceSequence has been already encountered in the previous chapter. More precision on flags is expected. Again the IDL file will give us this information :
//Listing 21 PolygonFlags enumeration : IDL File // IDL module com { module sun { module star { module drawing { enum PolygonFlags { NORMAL, SMOOTH, CONTROL, SYMMETRIC }; }; }; }; };
The service ClosedBezierShape is interesting :
//Listing 22 ClosedBezierShape Service : IDL File // IDL module com { module sun { module star { module drawing { service ClosedBezierShape { service com::sun::star::drawing::Shape; service com::sun::star::drawing::LineProperties; service com::sun::star::drawing::FillProperties; service com::sun::star::drawing::PolyPolygonBezierDescriptor; service com::sun::star::drawing::Text; service com::sun::star::drawing::ShadowProperties; service com::sun::star::drawing::RotationDescriptor; }; }; }; }; };
and also the PolyPolygonDescriptor :
//Listing 23 PolyPolygonBezierDescriptor Service : IDL File // IDL module com { module sun { module star { module drawing { service PolyPolygonBezierDescriptor { [readonly, property] com::sun::star::drawing::PolygonKind PolygonKind; [property] com::sun::star::drawing::PolyPolygonBezierCoords PolyPolygonBezier; [property] com::sun::star::drawing::PolyPolygonBezierCoords Geometry; }; }; }; }; };
Again as in previous chapter, what we see are properties. We have never encounter the first (PolygonKind) and then give the corresponding IDL file :
//Listing 24 PolygonKind Enumeration : IDL File // IDL module com { module sun { module star { module drawing { enum PolygonKind { /** This is the PolygonKind for a LineShape. */ LINE, /** This is the PolygonKind for a PolyPolygonShape. */ POLY, /** This is the PolygonKind for a PolyLineShape. */ PLIN, /** This is the PolygonKind for an OpenBezierShape. */ PATHLINE, /** This is the PolygonKind for a ClosedBezierShape. */ PATHFILL, /** This is the PolygonKind for an OpenFreeHandShape. */ FREELINE, /** This is the PolygonKind for a ClosedFreeHandShape. */ FREEFILL, /** This is the PolygonKind for a PolyPolygonPathShape. */ PATHPOLY, /** This is the PolygonKind for a PolyLinePathShape. */ PATHPLIN }; }; }; }; };
Note this property is read only. We have left comments to understand the values' significance, difficult to guess with only their name.
The following code draw a Bezier closed shape :
[cpp]
//Listing 25 Bezier Shape : an Example
// C++
// Bezier
// Don't forget to add : #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
// Don't forget to add "com.sun.star.drawing.PolyPolygonBezierCoords \" in the makefile
struct PolyPolygonBezierCoords BezierCords;
// we suppose we use the previous declarations of PointsSeqSeq and PointsArray // (previous chapter on PolyPolygonShape) : we then only realloc
PointsSeqSeq.realloc(1); PointsArray.realloc(4);
MakePosition(1000, 1000, &PointsArray[0]); MakePosition(3000, 4000, &PointsArray[1]); MakePosition(3000, 4000, &PointsArray[2]); MakePosition(5000, 1000, &PointsArray[3]); PointsSeqSeq[0]=PointsArray; BezierCords.Coordinates = PointsSeqSeq;
// Don't forget to add : #include <com/sun/star/drawing/FlagSequenceSequence.hpp> // Don't forget to add "com.sun.star.drawing.FlagSequenceSequence \" in the makefile // Don't forget to add : #include <com/sun/star/drawing/FlagSequence.hpp> // Don't forget to add "com.sun.star.drawing.FlagSequence \" in the makefile FlagSequenceSequence flagsSeqSeq(1); FlagSequence flagsSeq(4);
// Don't forget to add : #include <com/sun/star/drawing/PolygonFlags.hpp> // Don't forget to add "com.sun.star.drawing.PolygonFlags \" in the makefile flagsSeq[0] = PolygonFlags_NORMAL; flagsSeq[1] = PolygonFlags_CONTROL; flagsSeq[2] = PolygonFlags_CONTROL; flagsSeq[3] = PolygonFlags_NORMAL; flagsSeqSeq[0] = flagsSeq; BezierCords.Flags = flagsSeqSeq; // PolyPolygonBezier is a property => construct a Any type; Any ClosedBezierProperty; ClosedBezierProperty <<= BezierCords; // create the PolyPolygonBezierShape Service Reference< XInterface > closedBezierShape = DocFactory->createInstance( OUString::createFromAscii("com.sun.star.drawing.ClosedBezierShape") ); Reference< XShape > rClosedBezierShape(closedBezierShape, UNO_QUERY); if (! rClosedBezierShape.is()) printf("****Pb with Bezier\n"); DrawMe(rClosedBezierShape, rDrawPage, ""); // Adjust the properties : Reference< XPropertySet > rClosedBezierShapeProps(rClosedBezierShape,UNO_QUERY); rClosedBezierShapeProps->setPropertyValue(OUString::createFromAscii
("PolyPolygonBezier"), ClosedBezierProperty);
It is possible to replace “ClosedBezierShape” with “OpenBezierShape” and obtain an open shape. When reading the PolyPolygonBezierShape.idl file I deduce I have only to replace “ClosedBezierShape” with “PolyPolygonBezierShape to have an open Bezier Shape. But it doesn't work and I don't know why for the moment. Andrew Pitonyak writes in his book : “Not all combinations of points and flags are valid” and I suppose I have a false combination.
Connectors and glues points
//Listing 26 XGluePointsSupplier IDL File // IDL module com { module sun { module star { module drawing { interface XGluePointsSupplier: com::sun::star::uno::XInterface { com::sun::star::container::XIndexContainer getGluePoints(); }; }; }; }; };
To do : to continue