xref: /trunk/main/oox/source/vml/vmlshape.cxx (revision ca5ec200)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "oox/vml/vmlshape.hxx"
25 
26 #include <com/sun/star/beans/PropertyValues.hpp>
27 #include <com/sun/star/awt/XControlModel.hpp>
28 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
29 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
30 #include <com/sun/star/drawing/XShapes.hpp>
31 #include <com/sun/star/graphic/XGraphic.hpp>
32 #include <rtl/math.hxx>
33 #include <rtl/ustrbuf.hxx>
34 #include "oox/core/xmlfilterbase.hxx"
35 #include "oox/drawingml/shapepropertymap.hxx"
36 #include "oox/helper/containerhelper.hxx"
37 #include "oox/helper/graphichelper.hxx"
38 #include "oox/helper/propertyset.hxx"
39 #include "oox/ole/axcontrol.hxx"
40 #include "oox/ole/axcontrolfragment.hxx"
41 #include "oox/ole/oleobjecthelper.hxx"
42 #include "oox/vml/vmldrawing.hxx"
43 #include "oox/vml/vmlshapecontainer.hxx"
44 #include "oox/vml/vmltextbox.hxx"
45 
46 namespace oox {
47 namespace vml {
48 
49 // ============================================================================
50 
51 using namespace ::com::sun::star::awt;
52 using namespace ::com::sun::star::drawing;
53 using namespace ::com::sun::star::graphic;
54 using namespace ::com::sun::star::uno;
55 
56 using ::oox::core::XmlFilterBase;
57 using ::rtl::OUString;
58 using ::rtl::OUStringBuffer;
59 
60 // ============================================================================
61 
62 namespace {
63 
64 const sal_Int32 VML_SHAPETYPE_PICTUREFRAME  = 75;
65 const sal_Int32 VML_SHAPETYPE_HOSTCONTROL   = 201;
66 
67 // ----------------------------------------------------------------------------
68 
lclGetAbsPoint(const Point & rRelPoint,const Rectangle & rShapeRect,const Rectangle & rCoordSys)69 Point lclGetAbsPoint( const Point& rRelPoint, const Rectangle& rShapeRect, const Rectangle& rCoordSys )
70 {
71     double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
72     double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
73     Point aAbsPoint;
74     aAbsPoint.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelPoint.X - rCoordSys.X) + 0.5 );
75     aAbsPoint.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelPoint.Y - rCoordSys.Y) + 0.5 );
76     return aAbsPoint;
77 }
78 
lclGetAbsRect(const Rectangle & rRelRect,const Rectangle & rShapeRect,const Rectangle & rCoordSys)79 Rectangle lclGetAbsRect( const Rectangle& rRelRect, const Rectangle& rShapeRect, const Rectangle& rCoordSys )
80 {
81     double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
82     double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
83     Rectangle aAbsRect;
84     aAbsRect.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelRect.X - rCoordSys.X) + 0.5 );
85     aAbsRect.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelRect.Y - rCoordSys.Y) + 0.5 );
86     aAbsRect.Width = static_cast< sal_Int32 >( fWidthRatio * rRelRect.Width + 0.5 );
87     aAbsRect.Height = static_cast< sal_Int32 >( fHeightRatio * rRelRect.Height + 0.5 );
88     return aAbsRect;
89 }
90 
91 } // namespace
92 
93 // ============================================================================
94 
ShapeTypeModel()95 ShapeTypeModel::ShapeTypeModel()
96 {
97 }
98 
assignUsed(const ShapeTypeModel & rSource)99 void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource )
100 {
101     moShapeType.assignIfUsed( rSource.moShapeType );
102     moCoordPos.assignIfUsed( rSource.moCoordPos );
103     moCoordSize.assignIfUsed( rSource.moCoordSize );
104     /*  The style properties position, left, top, width, height, margin-left,
105         margin-top are not derived from shape template to shape. */
106     maStrokeModel.assignUsed( rSource.maStrokeModel );
107     maFillModel.assignUsed( rSource.maFillModel );
108     moGraphicPath.assignIfUsed( rSource.moGraphicPath );
109     moGraphicTitle.assignIfUsed( rSource.moGraphicTitle );
110 }
111 
112 // ----------------------------------------------------------------------------
113 
ShapeType(Drawing & rDrawing)114 ShapeType::ShapeType( Drawing& rDrawing ) :
115     mrDrawing( rDrawing )
116 {
117 }
118 
~ShapeType()119 ShapeType::~ShapeType()
120 {
121 }
122 
getShapeType() const123 sal_Int32 ShapeType::getShapeType() const
124 {
125     return maTypeModel.moShapeType.get( 0 );
126 }
127 
getGraphicPath() const128 OUString ShapeType::getGraphicPath() const
129 {
130     return maTypeModel.moGraphicPath.get( OUString() );
131 }
132 
getCoordSystem() const133 Rectangle ShapeType::getCoordSystem() const
134 {
135     Int32Pair aCoordPos = maTypeModel.moCoordPos.get( Int32Pair( 0, 0 ) );
136     Int32Pair aCoordSize = maTypeModel.moCoordSize.get( Int32Pair( 1000, 1000 ) );
137     return Rectangle( aCoordPos.first, aCoordPos.second, aCoordSize.first, aCoordSize.second );
138 }
139 
getRectangle(const ShapeParentAnchor * pParentAnchor) const140 Rectangle ShapeType::getRectangle( const ShapeParentAnchor* pParentAnchor ) const
141 {
142     return pParentAnchor ?
143         lclGetAbsRect( getRelRectangle(), pParentAnchor->maShapeRect, pParentAnchor->maCoordSys ) :
144         getAbsRectangle();
145 }
146 
getAbsRectangle() const147 Rectangle ShapeType::getAbsRectangle() const
148 {
149     const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
150     return Rectangle(
151         ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maLeft, 0, true, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginLeft, 0, true, true ),
152         ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maTop, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginTop, 0, false, true ),
153         ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maWidth, 0, true, true ),
154         ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maHeight, 0, false, true ) );
155 }
156 
getRelRectangle() const157 Rectangle ShapeType::getRelRectangle() const
158 {
159     return Rectangle(
160         maTypeModel.maLeft.toInt32(),
161         maTypeModel.maTop.toInt32(),
162         maTypeModel.maWidth.toInt32(),
163         maTypeModel.maHeight.toInt32() );
164 }
165 
166 // ============================================================================
167 
ClientData()168 ClientData::ClientData() :
169     mnObjType( XML_TOKEN_INVALID ),
170     mnTextHAlign( XML_Left ),
171     mnTextVAlign( XML_Top ),
172     mnCol( -1 ),
173     mnRow( -1 ),
174     mnChecked( VML_CLIENTDATA_UNCHECKED ),
175     mnDropStyle( XML_Combo ),
176     mnDropLines( 1 ),
177     mnVal( 0 ),
178     mnMin( 0 ),
179     mnMax( 0 ),
180     mnInc( 0 ),
181     mnPage( 0 ),
182     mnSelType( XML_Single ),
183     mnVTEdit( VML_CLIENTDATA_TEXT ),
184     mbPrintObject( true ),
185     mbVisible( false ),
186     mbDde( false ),
187     mbNo3D( false ),
188     mbNo3D2( false ),
189     mbMultiLine( false ),
190     mbVScroll( false ),
191     mbSecretEdit( false )
192 {
193 }
194 
195 // ----------------------------------------------------------------------------
196 
ShapeModel()197 ShapeModel::ShapeModel()
198 {
199 }
200 
~ShapeModel()201 ShapeModel::~ShapeModel()
202 {
203 }
204 
createTextBox()205 TextBox& ShapeModel::createTextBox()
206 {
207     mxTextBox.reset( new TextBox );
208     return *mxTextBox;
209 }
210 
createClientData()211 ClientData& ShapeModel::createClientData()
212 {
213     mxClientData.reset( new ClientData );
214     return *mxClientData;
215 }
216 
217 // ----------------------------------------------------------------------------
218 
ShapeBase(Drawing & rDrawing)219 ShapeBase::ShapeBase( Drawing& rDrawing ) :
220     ShapeType( rDrawing )
221 {
222 }
223 
finalizeFragmentImport()224 void ShapeBase::finalizeFragmentImport()
225 {
226     // resolve shape template reference
227     if( (maShapeModel.maType.getLength() > 1) && (maShapeModel.maType[ 0 ] == '#') )
228         if( const ShapeType* pShapeType = mrDrawing.getShapes().getShapeTypeById( maShapeModel.maType.copy( 1 ), true ) )
229             maTypeModel.assignUsed( pShapeType->getTypeModel() );
230 }
231 
getShapeName() const232 OUString ShapeBase::getShapeName() const
233 {
234     if( maTypeModel.maShapeName.getLength() > 0 )
235         return maTypeModel.maShapeName;
236 
237     OUString aBaseName = mrDrawing.getShapeBaseName( *this );
238     if( aBaseName.getLength() > 0 )
239     {
240         sal_Int32 nShapeIdx = mrDrawing.getLocalShapeIndex( getShapeId() );
241         if( nShapeIdx > 0 )
242             return OUStringBuffer( aBaseName ).append( sal_Unicode( ' ' ) ).append( nShapeIdx ).makeStringAndClear();
243     }
244 
245     return OUString();
246 }
247 
getChildTypeById(const OUString &) const248 const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const
249 {
250     return 0;
251 }
252 
getChildById(const OUString &) const253 const ShapeBase* ShapeBase::getChildById( const OUString& ) const
254 {
255     return 0;
256 }
257 
convertAndInsert(const Reference<XShapes> & rxShapes,const ShapeParentAnchor * pParentAnchor) const258 Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const
259 {
260     Reference< XShape > xShape;
261     if( mrDrawing.isShapeSupported( *this ) )
262     {
263         /*  Calculate shape rectangle. Applications may do something special
264             according to some imported shape client data (e.g. Excel cell anchor). */
265         Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
266 
267         // convert the shape, if the calculated rectangle is not empty
268         if( ((aShapeRect.Width > 0) || (aShapeRect.Height > 0)) && rxShapes.is() )
269         {
270             xShape = implConvertAndInsert( rxShapes, aShapeRect );
271             if( xShape.is() )
272             {
273                 // set imported or generated shape name (not supported by form controls)
274                 PropertySet aShapeProp( xShape );
275                 if( aShapeProp.hasProperty( PROP_Name ) )
276                     aShapeProp.setProperty( PROP_Name, getShapeName() );
277 
278                 /*  Notify the drawing that a new shape has been inserted. For
279                     convenience, pass the rectangle that contains position and
280                     size of the shape. */
281                 bool bGroupChild = pParentAnchor != 0;
282                 mrDrawing.notifyXShapeInserted( xShape, aShapeRect, *this, bGroupChild );
283             }
284         }
285     }
286     return xShape;
287 }
288 
convertFormatting(const Reference<XShape> & rxShape,const ShapeParentAnchor * pParentAnchor) const289 void ShapeBase::convertFormatting( const Reference< XShape >& rxShape, const ShapeParentAnchor* pParentAnchor ) const
290 {
291     if( rxShape.is() )
292     {
293         /*  Calculate shape rectangle. Applications may do something special
294             according to some imported shape client data (e.g. Excel cell anchor). */
295         Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
296 
297         // convert the shape, if the calculated rectangle is not empty
298         if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) )
299         {
300             rxShape->setPosition( Point( aShapeRect.X, aShapeRect.Y ) );
301             rxShape->setSize( Size( aShapeRect.Width, aShapeRect.Height ) );
302             convertShapeProperties( rxShape );
303         }
304     }
305 }
306 
307 // protected ------------------------------------------------------------------
308 
calcShapeRectangle(const ShapeParentAnchor * pParentAnchor) const309 Rectangle ShapeBase::calcShapeRectangle( const ShapeParentAnchor* pParentAnchor ) const
310 {
311     /*  Calculate shape rectangle. Applications may do something special
312         according to some imported shape client data (e.g. Excel cell anchor). */
313     Rectangle aShapeRect;
314     const ClientData* pClientData = getClientData();
315     if( !pClientData || !mrDrawing.convertClientAnchor( aShapeRect, pClientData->maAnchor ) )
316         aShapeRect = getRectangle( pParentAnchor );
317     return aShapeRect;
318 }
319 
convertShapeProperties(const Reference<XShape> & rxShape) const320 void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const
321 {
322     ::oox::drawingml::ShapePropertyMap aPropMap( mrDrawing.getFilter().getModelObjectHelper() );
323     const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
324     maTypeModel.maStrokeModel.pushToPropMap( aPropMap, rGraphicHelper );
325     maTypeModel.maFillModel.pushToPropMap( aPropMap, rGraphicHelper );
326     PropertySet( rxShape ).setProperties( aPropMap );
327 }
328 
329 // ============================================================================
330 
SimpleShape(Drawing & rDrawing,const OUString & rService)331 SimpleShape::SimpleShape( Drawing& rDrawing, const OUString& rService ) :
332     ShapeBase( rDrawing ),
333     maService( rService )
334 {
335 }
336 
implConvertAndInsert(const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const337 Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
338 {
339     Reference< XShape > xShape = mrDrawing.createAndInsertXShape( maService, rxShapes, rShapeRect );
340     convertShapeProperties( xShape );
341     return xShape;
342 }
343 
344 // ============================================================================
345 
RectangleShape(Drawing & rDrawing)346 RectangleShape::RectangleShape( Drawing& rDrawing ) :
347     SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ) )
348 {
349 }
350 
351 // ============================================================================
352 
EllipseShape(Drawing & rDrawing)353 EllipseShape::EllipseShape( Drawing& rDrawing ) :
354     SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ) )
355 {
356 }
357 
358 // ============================================================================
359 
PolyLineShape(Drawing & rDrawing)360 PolyLineShape::PolyLineShape( Drawing& rDrawing ) :
361     SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" ) )
362 {
363 }
364 
implConvertAndInsert(const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const365 Reference< XShape > PolyLineShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
366 {
367     Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
368     // polygon path
369     Rectangle aCoordSys = getCoordSystem();
370     if( !maShapeModel.maPoints.empty() && (aCoordSys.Width > 0) && (aCoordSys.Height > 0) )
371     {
372         ::std::vector< Point > aAbsPoints;
373         for( ShapeModel::PointVector::const_iterator aIt = maShapeModel.maPoints.begin(), aEnd = maShapeModel.maPoints.end(); aIt != aEnd; ++aIt )
374             aAbsPoints.push_back( lclGetAbsPoint( *aIt, rShapeRect, aCoordSys ) );
375         PointSequenceSequence aPointSeq( 1 );
376         aPointSeq[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints );
377         PropertySet aPropSet( xShape );
378         aPropSet.setProperty( PROP_PolyPolygon, aPointSeq );
379     }
380     return xShape;
381 }
382 
383 // ============================================================================
384 
CustomShape(Drawing & rDrawing)385 CustomShape::CustomShape( Drawing& rDrawing ) :
386     SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.CustomShape" ) )
387 {
388 }
389 
implConvertAndInsert(const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const390 Reference< XShape > CustomShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
391 {
392     // try to create a custom shape
393     Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
394     if( xShape.is() ) try
395     {
396         // create the custom shape geometry
397         Reference< XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY_THROW );
398         xDefaulter->createCustomShapeDefaults( OUString::valueOf( getShapeType() ) );
399         // convert common properties
400         convertShapeProperties( xShape );
401     }
402     catch( Exception& )
403     {
404     }
405     return xShape;
406 }
407 
408 // ============================================================================
409 
ComplexShape(Drawing & rDrawing)410 ComplexShape::ComplexShape( Drawing& rDrawing ) :
411     CustomShape( rDrawing )
412 {
413 }
414 
implConvertAndInsert(const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const415 Reference< XShape > ComplexShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
416 {
417     XmlFilterBase& rFilter = mrDrawing.getFilter();
418     sal_Int32 nShapeType = getShapeType();
419     OUString aGraphicPath = getGraphicPath();
420 
421     // try to find registered OLE object info
422     if( const OleObjectInfo* pOleObjectInfo = mrDrawing.getOleObjectInfo( maTypeModel.maShapeId ) )
423     {
424         OSL_ENSURE( nShapeType == VML_SHAPETYPE_PICTUREFRAME, "ComplexShape::implConvertAndInsert - unexpected shape type" );
425 
426         // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here
427         if( pOleObjectInfo->mbDmlShape )
428             return Reference< XShape >();
429 
430         PropertyMap aOleProps;
431         Size aOleSize( rShapeRect.Width, rShapeRect.Height );
432         if( rFilter.getOleObjectHelper().importOleObject( aOleProps, *pOleObjectInfo, aOleSize ) )
433         {
434             Reference< XShape > xShape = mrDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ), rxShapes, rShapeRect );
435             if( xShape.is() )
436             {
437                 // set the replacement graphic
438                 if( aGraphicPath.getLength() > 0 )
439                 {
440                     Reference< XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath );
441                     if( xGraphic.is() )
442                         aOleProps[ PROP_Graphic ] <<= xGraphic;
443                 }
444 
445                 PropertySet aPropSet( xShape );
446                 aPropSet.setProperties( aOleProps );
447 
448                 return xShape;
449             }
450         }
451     }
452 
453     // try to find registered form control info
454     const ControlInfo* pControlInfo = mrDrawing.getControlInfo( maTypeModel.maShapeId );
455     if( pControlInfo && (pControlInfo->maFragmentPath.getLength() > 0) )
456     {
457         OSL_ENSURE( nShapeType == VML_SHAPETYPE_HOSTCONTROL, "ComplexShape::implConvertAndInsert - unexpected shape type" );
458         OUString aShapeName = getShapeName();
459         if( aShapeName.getLength() > 0 )
460         {
461             OSL_ENSURE( aShapeName == pControlInfo->maName, "ComplexShape::implConvertAndInsert - control name mismatch" );
462             // load the control properties from fragment
463             ::oox::ole::EmbeddedControl aControl( aShapeName );
464             if( rFilter.importFragment( new ::oox::ole::AxControlFragment( rFilter, pControlInfo->maFragmentPath, aControl ) ) )
465             {
466                 // create and return the control shape (including control model)
467                 sal_Int32 nCtrlIndex = -1;
468                 Reference< XShape > xShape = mrDrawing.createAndInsertXControlShape( aControl, rxShapes, rShapeRect, nCtrlIndex );
469                 // on error, proceed and try to create picture from replacement image
470                 if( xShape.is() )
471                     return xShape;
472             }
473         }
474     }
475 
476     // host application wants to create the shape (do not try failed OLE controls again)
477     if( (nShapeType == VML_SHAPETYPE_HOSTCONTROL) && !pControlInfo )
478     {
479         OSL_ENSURE( getClientData(), "ComplexShape::implConvertAndInsert - missing client data" );
480         Reference< XShape > xShape = mrDrawing.createAndInsertClientXShape( *this, rxShapes, rShapeRect );
481         if( xShape.is() )
482             return xShape;
483     }
484 
485     // try to create a picture object
486     if( aGraphicPath.getLength() > 0 )
487     {
488         Reference< XShape > xShape = mrDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GraphicObjectShape" ), rxShapes, rShapeRect );
489         if( xShape.is() )
490         {
491             OUString aGraphicUrl = rFilter.getGraphicHelper().importEmbeddedGraphicObject( aGraphicPath );
492             if( aGraphicUrl.getLength() > 0 )
493             {
494                 PropertySet aPropSet( xShape );
495                 aPropSet.setProperty( PROP_GraphicURL, aGraphicUrl );
496             }
497         }
498         return xShape;
499     }
500 
501     // default: try to create a custom shape
502     return CustomShape::implConvertAndInsert( rxShapes, rShapeRect );
503 }
504 
505 // ============================================================================
506 
GroupShape(Drawing & rDrawing)507 GroupShape::GroupShape( Drawing& rDrawing ) :
508     ShapeBase( rDrawing ),
509     mxChildren( new ShapeContainer( rDrawing ) )
510 {
511 }
512 
~GroupShape()513 GroupShape::~GroupShape()
514 {
515 }
516 
finalizeFragmentImport()517 void GroupShape::finalizeFragmentImport()
518 {
519     // basic shape processing
520     ShapeBase::finalizeFragmentImport();
521     // finalize all child shapes
522     mxChildren->finalizeFragmentImport();
523 }
524 
getChildTypeById(const OUString & rShapeId) const525 const ShapeType* GroupShape::getChildTypeById( const OUString& rShapeId ) const
526 {
527     return mxChildren->getShapeTypeById( rShapeId, true );
528 }
529 
getChildById(const OUString & rShapeId) const530 const ShapeBase* GroupShape::getChildById( const OUString& rShapeId ) const
531 {
532     return mxChildren->getShapeById( rShapeId, true );
533 }
534 
implConvertAndInsert(const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const535 Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
536 {
537     Reference< XShape > xGroupShape;
538     // check that this shape contains children and a valid coordinate system
539     ShapeParentAnchor aParentAnchor;
540     aParentAnchor.maShapeRect = rShapeRect;
541     aParentAnchor.maCoordSys = getCoordSystem();
542     if( !mxChildren->empty() && (aParentAnchor.maCoordSys.Width > 0) && (aParentAnchor.maCoordSys.Height > 0) ) try
543     {
544         xGroupShape = mrDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rxShapes, rShapeRect );
545         Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW );
546         mxChildren->convertAndInsert( xChildShapes, &aParentAnchor );
547         // no child shape has been created - delete the group shape
548         if( !xChildShapes->hasElements() )
549         {
550             rxShapes->remove( xGroupShape );
551             xGroupShape.clear();
552         }
553     }
554     catch( Exception& )
555     {
556     }
557     return xGroupShape;
558 }
559 
560 // ============================================================================
561 
562 } // namespace vml
563 } // namespace oox
564