bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / draw / shapeimport.cxx
blobc8dc20cade861e39691719c68685c12f32d26d35
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/debug.hxx>
22 #include <com/sun/star/text/PositionLayoutDir.hpp>
23 #include <com/sun/star/chart/XChartDocument.hpp>
25 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
26 #include <osl/diagnose.h>
28 #include <list>
30 #include <xmloff/shapeimport.hxx>
31 #include <xmloff/xmltkmap.hxx>
32 #include <xmloff/xmlnmspe.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include "ximpstyl.hxx"
35 #include "ximpshap.hxx"
36 #include "sdpropls.hxx"
37 #include <xmloff/xmlprmap.hxx>
38 #include "ximp3dscene.hxx"
39 #include "ximp3dobject.hxx"
40 #include "ximpgrp.hxx"
41 #include "ximplink.hxx"
43 #include <map>
44 #include <vector>
46 using namespace ::std;
47 using namespace ::com::sun::star;
48 using namespace ::xmloff::token;
50 struct ltint32
52 bool operator()(const sal_Int32 p, sal_Int32 q) const
54 return p < q;
58 typedef std::map<sal_Int32,com::sun::star::uno::Reference< com::sun::star::drawing::XShape >,ltint32> IdShapeMap;
60 struct ConnectionHint
62 com::sun::star::uno::Reference< com::sun::star::drawing::XShape > mxConnector;
63 bool bStart;
64 OUString aDestShapeId;
65 sal_Int32 nDestGlueId;
68 struct XShapeCompareHelper
70 bool operator()(com::sun::star::uno::Reference < com::sun::star::drawing::XShape > x1,
71 com::sun::star::uno::Reference < com::sun::star::drawing::XShape > x2 ) const
73 return x1.get() < x2.get();
77 /** this map store all glue point id mappings for shapes that had user defined glue points. This
78 is needed because on insertion the glue points will get a new and unique id */
79 typedef std::map<sal_Int32,sal_Int32,ltint32> GluePointIdMap;
80 typedef std::map< com::sun::star::uno::Reference < com::sun::star::drawing::XShape >, GluePointIdMap, XShapeCompareHelper > ShapeGluePointsMap;
82 /** this struct is created for each startPage() call and stores information that is needed during
83 import of shapes for one page. Since pages could be nested ( notes pages inside impress ) there
84 is a pointer so one can build up a stack of this structs */
85 struct XMLShapeImportPageContextImpl
87 ShapeGluePointsMap maShapeGluePointsMap;
89 uno::Reference < drawing::XShapes > mxShapes;
91 struct XMLShapeImportPageContextImpl* mpNext;
94 /** this class is to enable adding members to the XMLShapeImportHelper without getting incompatible */
95 struct XMLShapeImportHelperImpl
97 // context for sorting shapes
98 ShapeSortContext* mpSortContext;
100 IdShapeMap maShapeIds;
102 std::vector<ConnectionHint> maConnections;
104 // #88546# possibility to switch progress bar handling on/off
105 bool mbHandleProgressBar;
107 // stores the capability of the current model to create presentation shapes
108 bool mbIsPresentationShapesSupported;
111 XMLShapeImportHelper::XMLShapeImportHelper(
112 SvXMLImport& rImporter,
113 const uno::Reference< frame::XModel>& rModel,
114 SvXMLImportPropertyMapper *pExtMapper )
115 : mpPageContext(NULL),
116 mxModel(rModel),
118 mpPropertySetMapper(0L),
119 mpPresPagePropsMapper(0L),
120 mpStylesContext(0L),
121 mpAutoStylesContext(0L),
122 mpGroupShapeElemTokenMap(0L),
123 mpFrameShapeElemTokenMap(0L),
124 mp3DSceneShapeElemTokenMap(0L),
125 mp3DObjectAttrTokenMap(0L),
126 mp3DPolygonBasedAttrTokenMap(0L),
127 mp3DCubeObjectAttrTokenMap(0L),
128 mp3DSphereObjectAttrTokenMap(0L),
129 mp3DSceneShapeAttrTokenMap(0L),
130 mp3DLightAttrTokenMap(0L),
131 mpPathShapeAttrTokenMap(0L),
132 mpPolygonShapeAttrTokenMap(0L),
133 msStartShape("StartShape"),
134 msEndShape("EndShape"),
135 msStartGluePointIndex("StartGluePointIndex"),
136 msEndGluePointIndex("EndGluePointIndex"),
138 mrImporter( rImporter )
140 mpImpl = new XMLShapeImportHelperImpl();
141 mpImpl->mpSortContext = 0;
143 // #88546# init to sal_False
144 mpImpl->mbHandleProgressBar = false;
146 mpSdPropHdlFactory = new XMLSdPropHdlFactory( rModel, rImporter );
148 // set lock to avoid deletion
149 mpSdPropHdlFactory->acquire();
151 // construct PropertySetMapper
152 rtl::Reference < XMLPropertySetMapper > xMapper = new XMLShapePropertySetMapper(mpSdPropHdlFactory, false);
153 mpPropertySetMapper = new SvXMLImportPropertyMapper( xMapper, rImporter );
154 // set lock to avoid deletion
155 mpPropertySetMapper->acquire();
157 if( pExtMapper )
159 rtl::Reference < SvXMLImportPropertyMapper > xExtMapper( pExtMapper );
160 mpPropertySetMapper->ChainImportMapper( xExtMapper );
163 // chain text attributes
164 mpPropertySetMapper->ChainImportMapper(XMLTextImportHelper::CreateParaExtPropMapper(rImporter));
165 mpPropertySetMapper->ChainImportMapper(XMLTextImportHelper::CreateParaDefaultExtPropMapper(rImporter));
167 // construct PresPagePropsMapper
168 xMapper = new XMLPropertySetMapper(aXMLSDPresPageProps, mpSdPropHdlFactory, false);
169 mpPresPagePropsMapper = new SvXMLImportPropertyMapper( xMapper, rImporter );
170 // set lock to avoid deletion
171 mpPresPagePropsMapper->acquire();
173 uno::Reference< lang::XServiceInfo > xInfo( rImporter.GetModel(), uno::UNO_QUERY );
174 const OUString aSName( "com.sun.star.presentation.PresentationDocument" );
175 mpImpl->mbIsPresentationShapesSupported = xInfo.is() && xInfo->supportsService( aSName );
178 XMLShapeImportHelper::~XMLShapeImportHelper()
180 DBG_ASSERT( mpImpl->maConnections.empty(), "XMLShapeImportHelper::restoreConnections() was not called!" );
182 // cleanup factory, decrease refcount. Should lead to destruction.
183 if(mpSdPropHdlFactory)
185 mpSdPropHdlFactory->release();
186 mpSdPropHdlFactory = 0L;
189 // cleanup mapper, decrease refcount. Should lead to destruction.
190 if(mpPropertySetMapper)
192 mpPropertySetMapper->release();
193 mpPropertySetMapper = 0L;
196 // cleanup presPage mapper, decrease refcount. Should lead to destruction.
197 if(mpPresPagePropsMapper)
199 mpPresPagePropsMapper->release();
200 mpPresPagePropsMapper = 0L;
203 if(mpGroupShapeElemTokenMap) delete mpGroupShapeElemTokenMap;
204 if(mpFrameShapeElemTokenMap) delete mpFrameShapeElemTokenMap;
206 if(mpPolygonShapeAttrTokenMap) delete mpPolygonShapeAttrTokenMap;
207 if(mpPathShapeAttrTokenMap) delete mpPathShapeAttrTokenMap;
208 if(mp3DSceneShapeElemTokenMap) delete mp3DSceneShapeElemTokenMap;
209 if(mp3DObjectAttrTokenMap) delete mp3DObjectAttrTokenMap;
210 if(mp3DPolygonBasedAttrTokenMap) delete mp3DPolygonBasedAttrTokenMap;
211 if(mp3DCubeObjectAttrTokenMap) delete mp3DCubeObjectAttrTokenMap;
212 if(mp3DSphereObjectAttrTokenMap) delete mp3DSphereObjectAttrTokenMap;
213 if(mp3DSceneShapeAttrTokenMap) delete mp3DSceneShapeAttrTokenMap;
214 if(mp3DLightAttrTokenMap) delete mp3DLightAttrTokenMap;
216 // Styles or AutoStyles context?
217 if(mpStylesContext)
219 mpStylesContext->Clear();
220 mpStylesContext->ReleaseRef();
223 if(mpAutoStylesContext)
225 mpAutoStylesContext->Clear();
226 mpAutoStylesContext->ReleaseRef();
229 delete mpImpl;
232 const SvXMLTokenMap& XMLShapeImportHelper::GetGroupShapeElemTokenMap()
234 if(!mpGroupShapeElemTokenMap)
236 static const SvXMLTokenMapEntry aGroupShapeElemTokenMap[] =
238 { XML_NAMESPACE_DRAW, XML_G, XML_TOK_GROUP_GROUP },
239 { XML_NAMESPACE_DRAW, XML_RECT, XML_TOK_GROUP_RECT },
240 { XML_NAMESPACE_DRAW, XML_LINE, XML_TOK_GROUP_LINE },
241 { XML_NAMESPACE_DRAW, XML_CIRCLE, XML_TOK_GROUP_CIRCLE },
242 { XML_NAMESPACE_DRAW, XML_ELLIPSE, XML_TOK_GROUP_ELLIPSE },
243 { XML_NAMESPACE_DRAW, XML_POLYGON, XML_TOK_GROUP_POLYGON },
244 { XML_NAMESPACE_DRAW, XML_POLYLINE, XML_TOK_GROUP_POLYLINE },
245 { XML_NAMESPACE_DRAW, XML_PATH, XML_TOK_GROUP_PATH },
247 { XML_NAMESPACE_DRAW, XML_CONTROL, XML_TOK_GROUP_CONTROL },
248 { XML_NAMESPACE_DRAW, XML_CONNECTOR, XML_TOK_GROUP_CONNECTOR },
249 { XML_NAMESPACE_DRAW, XML_MEASURE, XML_TOK_GROUP_MEASURE },
250 { XML_NAMESPACE_DRAW, XML_PAGE_THUMBNAIL, XML_TOK_GROUP_PAGE },
251 { XML_NAMESPACE_DRAW, XML_CAPTION, XML_TOK_GROUP_CAPTION },
253 { XML_NAMESPACE_CHART, XML_CHART, XML_TOK_GROUP_CHART },
254 { XML_NAMESPACE_DR3D, XML_SCENE, XML_TOK_GROUP_3DSCENE },
256 { XML_NAMESPACE_DRAW, XML_FRAME, XML_TOK_GROUP_FRAME },
257 { XML_NAMESPACE_DRAW, XML_CUSTOM_SHAPE, XML_TOK_GROUP_CUSTOM_SHAPE },
259 { XML_NAMESPACE_DRAW, XML_CUSTOM_SHAPE, XML_TOK_GROUP_CUSTOM_SHAPE },
260 { XML_NAMESPACE_OFFICE, XML_ANNOTATION, XML_TOK_GROUP_ANNOTATION },
261 { XML_NAMESPACE_DRAW, XML_A, XML_TOK_GROUP_A },
263 XML_TOKEN_MAP_END
266 mpGroupShapeElemTokenMap = new SvXMLTokenMap(aGroupShapeElemTokenMap);
267 } // if(!mpGroupShapeElemTokenMap)
269 return *mpGroupShapeElemTokenMap;
272 const SvXMLTokenMap& XMLShapeImportHelper::GetFrameShapeElemTokenMap()
274 if(!mpFrameShapeElemTokenMap)
276 static const SvXMLTokenMapEntry aFrameShapeElemTokenMap[] =
278 { XML_NAMESPACE_DRAW, XML_TEXT_BOX, XML_TOK_FRAME_TEXT_BOX },
279 { XML_NAMESPACE_DRAW, XML_IMAGE, XML_TOK_FRAME_IMAGE },
280 { XML_NAMESPACE_DRAW, XML_OBJECT, XML_TOK_FRAME_OBJECT },
281 { XML_NAMESPACE_DRAW, XML_OBJECT_OLE, XML_TOK_FRAME_OBJECT_OLE },
282 { XML_NAMESPACE_DRAW, XML_PLUGIN, XML_TOK_FRAME_PLUGIN },
283 { XML_NAMESPACE_DRAW, XML_FLOATING_FRAME, XML_TOK_FRAME_FLOATING_FRAME},
284 { XML_NAMESPACE_DRAW, XML_APPLET, XML_TOK_FRAME_APPLET },
285 { XML_NAMESPACE_TABLE, XML_TABLE, XML_TOK_FRAME_TABLE },
286 XML_TOKEN_MAP_END
289 mpFrameShapeElemTokenMap = new SvXMLTokenMap(aFrameShapeElemTokenMap);
290 } // if(!mpFrameShapeElemTokenMap)
292 return *mpFrameShapeElemTokenMap;
295 const SvXMLTokenMap& XMLShapeImportHelper::Get3DSceneShapeElemTokenMap()
297 if(!mp3DSceneShapeElemTokenMap)
299 static const SvXMLTokenMapEntry a3DSceneShapeElemTokenMap[] =
301 { XML_NAMESPACE_DR3D, XML_SCENE, XML_TOK_3DSCENE_3DSCENE },
302 { XML_NAMESPACE_DR3D, XML_CUBE, XML_TOK_3DSCENE_3DCUBE },
303 { XML_NAMESPACE_DR3D, XML_SPHERE, XML_TOK_3DSCENE_3DSPHERE },
304 { XML_NAMESPACE_DR3D, XML_ROTATE, XML_TOK_3DSCENE_3DLATHE },
305 { XML_NAMESPACE_DR3D, XML_EXTRUDE, XML_TOK_3DSCENE_3DEXTRUDE },
306 XML_TOKEN_MAP_END
309 mp3DSceneShapeElemTokenMap = new SvXMLTokenMap(a3DSceneShapeElemTokenMap);
310 } // if(!mp3DSceneShapeElemTokenMap)
312 return *mp3DSceneShapeElemTokenMap;
315 const SvXMLTokenMap& XMLShapeImportHelper::Get3DObjectAttrTokenMap()
317 if(!mp3DObjectAttrTokenMap)
319 static const SvXMLTokenMapEntry a3DObjectAttrTokenMap[] =
321 { XML_NAMESPACE_DRAW, XML_STYLE_NAME, XML_TOK_3DOBJECT_DRAWSTYLE_NAME },
322 { XML_NAMESPACE_DR3D, XML_TRANSFORM, XML_TOK_3DOBJECT_TRANSFORM },
323 XML_TOKEN_MAP_END
326 mp3DObjectAttrTokenMap = new SvXMLTokenMap(a3DObjectAttrTokenMap);
327 } // if(!mp3DObjectAttrTokenMap)
329 return *mp3DObjectAttrTokenMap;
332 const SvXMLTokenMap& XMLShapeImportHelper::Get3DPolygonBasedAttrTokenMap()
334 if(!mp3DPolygonBasedAttrTokenMap)
336 static const SvXMLTokenMapEntry a3DPolygonBasedAttrTokenMap[] =
338 { XML_NAMESPACE_SVG, XML_VIEWBOX, XML_TOK_3DPOLYGONBASED_VIEWBOX },
339 { XML_NAMESPACE_SVG, XML_D, XML_TOK_3DPOLYGONBASED_D },
340 XML_TOKEN_MAP_END
343 mp3DPolygonBasedAttrTokenMap = new SvXMLTokenMap(a3DPolygonBasedAttrTokenMap);
344 } // if(!mp3DPolygonBasedAttrTokenMap)
346 return *mp3DPolygonBasedAttrTokenMap;
349 const SvXMLTokenMap& XMLShapeImportHelper::Get3DCubeObjectAttrTokenMap()
351 if(!mp3DCubeObjectAttrTokenMap)
353 static const SvXMLTokenMapEntry a3DCubeObjectAttrTokenMap[] =
355 { XML_NAMESPACE_DR3D, XML_MIN_EDGE, XML_TOK_3DCUBEOBJ_MINEDGE },
356 { XML_NAMESPACE_DR3D, XML_MAX_EDGE, XML_TOK_3DCUBEOBJ_MAXEDGE },
357 XML_TOKEN_MAP_END
360 mp3DCubeObjectAttrTokenMap = new SvXMLTokenMap(a3DCubeObjectAttrTokenMap);
361 } // if(!mp3DCubeObjectAttrTokenMap)
363 return *mp3DCubeObjectAttrTokenMap;
366 const SvXMLTokenMap& XMLShapeImportHelper::Get3DSphereObjectAttrTokenMap()
368 if(!mp3DSphereObjectAttrTokenMap)
370 static const SvXMLTokenMapEntry a3DSphereObjectAttrTokenMap[] =
372 { XML_NAMESPACE_DR3D, XML_CENTER, XML_TOK_3DSPHEREOBJ_CENTER },
373 { XML_NAMESPACE_DR3D, XML_SIZE, XML_TOK_3DSPHEREOBJ_SIZE },
374 XML_TOKEN_MAP_END
377 mp3DSphereObjectAttrTokenMap = new SvXMLTokenMap(a3DSphereObjectAttrTokenMap);
378 } // if(!mp3DSphereObjectAttrTokenMap)
380 return *mp3DSphereObjectAttrTokenMap;
383 const SvXMLTokenMap& XMLShapeImportHelper::Get3DLightAttrTokenMap()
385 if(!mp3DLightAttrTokenMap)
387 static const SvXMLTokenMapEntry a3DLightAttrTokenMap[] =
389 { XML_NAMESPACE_DR3D, XML_DIFFUSE_COLOR, XML_TOK_3DLIGHT_DIFFUSE_COLOR },
390 { XML_NAMESPACE_DR3D, XML_DIRECTION, XML_TOK_3DLIGHT_DIRECTION },
391 { XML_NAMESPACE_DR3D, XML_ENABLED, XML_TOK_3DLIGHT_ENABLED },
392 { XML_NAMESPACE_DR3D, XML_SPECULAR, XML_TOK_3DLIGHT_SPECULAR },
393 XML_TOKEN_MAP_END
396 mp3DLightAttrTokenMap = new SvXMLTokenMap(a3DLightAttrTokenMap);
397 } // if(!mp3DLightAttrTokenMap)
399 return *mp3DLightAttrTokenMap;
402 SvXMLShapeContext* XMLShapeImportHelper::Create3DSceneChildContext(
403 SvXMLImport& rImport,
404 sal_uInt16 p_nPrefix,
405 const OUString& rLocalName,
406 const uno::Reference< xml::sax::XAttributeList>& xAttrList,
407 uno::Reference< drawing::XShapes >& rShapes)
409 SdXMLShapeContext *pContext = 0L;
411 if(rShapes.is())
413 const SvXMLTokenMap& rTokenMap = Get3DSceneShapeElemTokenMap();
414 switch(rTokenMap.Get(p_nPrefix, rLocalName))
416 case XML_TOK_3DSCENE_3DSCENE:
418 // dr3d:3dscene inside dr3d:3dscene context
419 pContext = new SdXML3DSceneShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false);
420 break;
422 case XML_TOK_3DSCENE_3DCUBE:
424 // dr3d:3dcube inside dr3d:3dscene context
425 pContext = new SdXML3DCubeObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false);
426 break;
428 case XML_TOK_3DSCENE_3DSPHERE:
430 // dr3d:3dsphere inside dr3d:3dscene context
431 pContext = new SdXML3DSphereObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false);
432 break;
434 case XML_TOK_3DSCENE_3DLATHE:
436 // dr3d:3dlathe inside dr3d:3dscene context
437 pContext = new SdXML3DLatheObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false);
438 break;
440 case XML_TOK_3DSCENE_3DEXTRUDE:
442 // dr3d:3dextrude inside dr3d:3dscene context
443 pContext = new SdXML3DExtrudeObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false);
444 break;
449 // now parse the attribute list and call the child context for each unknown attribute
450 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
451 for(sal_Int16 a(0); a < nAttrCount; a++)
453 const OUString& rAttrName = xAttrList->getNameByIndex(a);
454 OUString aLocalName;
455 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(rAttrName, &aLocalName);
456 const OUString aValue( xAttrList->getValueByIndex(a) );
458 pContext->processAttribute( nPrefix, aLocalName, aValue );
461 return pContext;
464 void XMLShapeImportHelper::SetStylesContext(SvXMLStylesContext* pNew)
466 mpStylesContext = pNew;
467 if (mpStylesContext)
468 mpStylesContext->AddFirstRef();
471 void XMLShapeImportHelper::SetAutoStylesContext(SvXMLStylesContext* pNew)
473 mpAutoStylesContext = pNew;
474 if (mpAutoStylesContext)
475 mpAutoStylesContext->AddFirstRef();
478 SvXMLShapeContext* XMLShapeImportHelper::CreateGroupChildContext(
479 SvXMLImport& rImport,
480 sal_uInt16 p_nPrefix,
481 const OUString& rLocalName,
482 const uno::Reference< xml::sax::XAttributeList>& xAttrList,
483 uno::Reference< drawing::XShapes >& rShapes,
484 bool bTemporaryShape)
486 SdXMLShapeContext *pContext = 0L;
488 const SvXMLTokenMap& rTokenMap = GetGroupShapeElemTokenMap();
489 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
491 switch(rTokenMap.Get(p_nPrefix, rLocalName))
493 case XML_TOK_GROUP_GROUP:
495 // draw:g inside group context (RECURSIVE)
496 pContext = new SdXMLGroupShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape);
497 break;
499 case XML_TOK_GROUP_3DSCENE:
501 // dr3d:3dscene inside group context
502 pContext = new SdXML3DSceneShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape);
503 break;
505 case XML_TOK_GROUP_RECT:
507 // draw:rect inside group context
508 pContext = new SdXMLRectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
509 break;
511 case XML_TOK_GROUP_LINE:
513 // draw:line inside group context
514 pContext = new SdXMLLineShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
515 break;
517 case XML_TOK_GROUP_CIRCLE:
518 case XML_TOK_GROUP_ELLIPSE:
520 // draw:circle or draw:ellipse inside group context
521 pContext = new SdXMLEllipseShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
522 break;
524 case XML_TOK_GROUP_POLYGON:
525 case XML_TOK_GROUP_POLYLINE:
527 // draw:polygon or draw:polyline inside group context
528 pContext = new SdXMLPolygonShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes,
529 rTokenMap.Get(p_nPrefix, rLocalName) == XML_TOK_GROUP_POLYGON, bTemporaryShape );
530 break;
532 case XML_TOK_GROUP_PATH:
534 // draw:path inside group context
535 pContext = new SdXMLPathShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape);
536 break;
538 case XML_TOK_GROUP_FRAME:
540 // text:text-box inside group context
541 pContext = new SdXMLFrameShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
542 break;
544 case XML_TOK_GROUP_CONTROL:
546 // draw:control inside group context
547 pContext = new SdXMLControlShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
548 break;
550 case XML_TOK_GROUP_CONNECTOR:
552 // draw:connector inside group context
553 pContext = new SdXMLConnectorShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
554 break;
556 case XML_TOK_GROUP_MEASURE:
558 // draw:measure inside group context
559 pContext = new SdXMLMeasureShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
560 break;
562 case XML_TOK_GROUP_PAGE:
564 // draw:page inside group context
565 pContext = new SdXMLPageShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
566 break;
568 case XML_TOK_GROUP_CAPTION:
569 case XML_TOK_GROUP_ANNOTATION:
571 // draw:caption inside group context
572 pContext = new SdXMLCaptionShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
573 break;
575 case XML_TOK_GROUP_CHART:
577 // chart:chart inside group context
578 pContext = new SdXMLChartShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
579 break;
581 case XML_TOK_GROUP_CUSTOM_SHAPE:
583 // draw:customshape
584 pContext = new SdXMLCustomShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false );
585 break;
587 case XML_TOK_GROUP_A:
589 return new SdXMLShapeLinkContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
591 // add other shapes here...
592 default:
593 return new SvXMLShapeContext( rImport, p_nPrefix, rLocalName, bTemporaryShape );
596 // now parse the attribute list and call the child context for each unknown attribute
597 for(sal_Int16 a(0); a < nAttrCount; a++)
599 const OUString& rAttrName = xAttrList->getNameByIndex(a);
600 OUString aLocalName;
601 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(rAttrName, &aLocalName);
602 const OUString aValue( xAttrList->getValueByIndex(a) );
604 pContext->processAttribute( nPrefix, aLocalName, aValue );
607 return pContext;
610 // This method is called from SdXMLFrameShapeContext to create children of drawe:frame
611 SvXMLShapeContext* XMLShapeImportHelper::CreateFrameChildContext(
612 SvXMLImport& rImport,
613 sal_uInt16 p_nPrefix,
614 const OUString& rLocalName,
615 const uno::Reference< xml::sax::XAttributeList>& rAttrList,
616 uno::Reference< drawing::XShapes >& rShapes,
617 const uno::Reference< xml::sax::XAttributeList>& rFrameAttrList)
619 SdXMLShapeContext *pContext = 0L;
621 const SvXMLTokenMap& rTokenMap = GetFrameShapeElemTokenMap();
623 SvXMLAttributeList *pAttrList = new SvXMLAttributeList( rAttrList );
624 if( rFrameAttrList.is() )
625 pAttrList->AppendAttributeList( rFrameAttrList );
626 uno::Reference < xml::sax::XAttributeList > xAttrList = pAttrList;
628 switch(rTokenMap.Get(p_nPrefix, rLocalName))
630 case XML_TOK_FRAME_TEXT_BOX:
632 // text:text-box inside group context
633 pContext = new SdXMLTextBoxShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false );
634 break;
636 case XML_TOK_FRAME_IMAGE:
638 // office:image inside group context
639 pContext = new SdXMLGraphicObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false );
640 break;
642 case XML_TOK_FRAME_OBJECT:
643 case XML_TOK_FRAME_OBJECT_OLE:
645 // draw:object or draw:object_ole
646 pContext = new SdXMLObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false );
647 break;
649 case XML_TOK_FRAME_TABLE:
651 // draw:object or draw:object_ole
652 if( rImport.IsTableShapeSupported() )
653 pContext = new SdXMLTableShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
654 break;
657 case XML_TOK_FRAME_PLUGIN:
659 // draw:plugin
660 pContext = new SdXMLPluginShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false );
661 break;
663 case XML_TOK_FRAME_FLOATING_FRAME:
665 // draw:floating-frame
666 pContext = new SdXMLFloatingFrameShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false );
667 break;
669 case XML_TOK_FRAME_APPLET:
671 // draw:applet
672 pContext = new SdXMLAppletShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false );
673 break;
675 // add other shapes here...
676 default:
677 break;
680 if( pContext )
682 // now parse the attribute list and call the child context for each unknown attribute
683 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
684 for(sal_Int16 a(0); a < nAttrCount; a++)
686 const OUString& rAttrName = xAttrList->getNameByIndex(a);
687 OUString aLocalName;
688 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(rAttrName, &aLocalName);
689 const OUString aValue( xAttrList->getValueByIndex(a) );
691 pContext->processAttribute( nPrefix, aLocalName, aValue );
695 return pContext;
698 SvXMLImportContext *XMLShapeImportHelper::CreateFrameChildContext(
699 SvXMLImportContext *pThisContext,
700 sal_uInt16 nPrefix,
701 const OUString& rLocalName,
702 const uno::Reference< xml::sax::XAttributeList>& xAttrList )
704 SvXMLImportContext * pContext = NULL;
706 SdXMLFrameShapeContext *pFrameContext = PTR_CAST( SdXMLFrameShapeContext, pThisContext );
707 if( pFrameContext )
708 pContext = pFrameContext->CreateChildContext( nPrefix, rLocalName, xAttrList );
710 return pContext;
713 /** this function is called whenever the implementation classes like to add this new
714 shape to the given XShapes.
716 void XMLShapeImportHelper::addShape( uno::Reference< drawing::XShape >& rShape,
717 const uno::Reference< xml::sax::XAttributeList >&,
718 uno::Reference< drawing::XShapes >& rShapes)
720 if( rShape.is() && rShapes.is() )
722 // add new shape to parent
723 rShapes->add( rShape );
727 /** this function is called whenever the implementation classes have finished importing
728 a shape to the given XShapes. The shape is already inserted into its XShapes and
729 all properties and styles are set.
731 void XMLShapeImportHelper::finishShape(
732 com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& rShape,
733 const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >&,
734 com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >&)
736 /* Set property <PositionLayoutDir>
737 to <PositionInHoriL2R>, if it exists and the import states that
738 the shape positioning attributes are in horizontal left-to-right
739 layout. This is the case for the OpenOffice.org file format.
740 This setting is done for Writer documents, because the property
741 only exists at service com::sun::star::text::Shape - the Writer
742 UNO service for shapes.
743 The value indicates that the positioning attributes are given
744 in horizontal left-to-right layout. The property is evaluated
745 during the first positioning of the shape in order to convert
746 the shape position given in the OpenOffice.org file format to
747 the one for the OASIS Open Office file format. (#i28749#, #i36248#)
749 uno::Reference< beans::XPropertySet > xPropSet(rShape, uno::UNO_QUERY);
750 if ( xPropSet.is() )
752 if ( mrImporter.IsShapePositionInHoriL2R() &&
753 xPropSet->getPropertySetInfo()->hasPropertyByName(
754 OUString("PositionLayoutDir")) )
756 uno::Any aPosLayoutDir;
757 aPosLayoutDir <<= text::PositionLayoutDir::PositionInHoriL2R;
758 xPropSet->setPropertyValue(
759 OUString("PositionLayoutDir"),
760 aPosLayoutDir );
765 // helper functions for z-order sorting
766 struct ZOrderHint
768 sal_Int32 nIs;
769 sal_Int32 nShould;
771 bool operator<(const ZOrderHint& rComp) const { return nShould < rComp.nShould; }
774 class ShapeSortContext
776 public:
777 uno::Reference< drawing::XShapes > mxShapes;
778 list<ZOrderHint> maZOrderList;
779 list<ZOrderHint> maUnsortedList;
781 sal_Int32 mnCurrentZ;
782 ShapeSortContext* mpParentContext;
783 const OUString msZOrder;
785 ShapeSortContext( uno::Reference< drawing::XShapes >& rShapes, ShapeSortContext* pParentContext = NULL );
787 void moveShape( sal_Int32 nSourcePos, sal_Int32 nDestPos );
790 ShapeSortContext::ShapeSortContext( uno::Reference< drawing::XShapes >& rShapes, ShapeSortContext* pParentContext )
791 : mxShapes( rShapes ), mnCurrentZ( 0 ), mpParentContext( pParentContext ),
792 msZOrder("ZOrder")
796 void ShapeSortContext::moveShape( sal_Int32 nSourcePos, sal_Int32 nDestPos )
798 uno::Any aAny( mxShapes->getByIndex( nSourcePos ) );
799 uno::Reference< beans::XPropertySet > xPropSet;
800 aAny >>= xPropSet;
802 if( xPropSet.is() && xPropSet->getPropertySetInfo()->hasPropertyByName( msZOrder ) )
804 aAny <<= nDestPos;
805 xPropSet->setPropertyValue( msZOrder, aAny );
807 list<ZOrderHint>::iterator aIter = maZOrderList.begin();
808 list<ZOrderHint>::iterator aEnd = maZOrderList.end();
810 while( aIter != aEnd )
812 if( (*aIter).nIs < nSourcePos )
814 DBG_ASSERT( (*aIter).nIs >= nDestPos, "Shape sorting failed" );
815 (*aIter).nIs++;
817 ++aIter;
820 aIter = maUnsortedList.begin();
821 aEnd = maUnsortedList.end();
823 while( aIter != aEnd )
825 if( (*aIter).nIs < nSourcePos )
827 DBG_ASSERT( (*aIter).nIs >= nDestPos, "shape sorting failed" );
828 (*aIter).nIs++;
830 ++aIter;
835 void XMLShapeImportHelper::pushGroupForSorting( uno::Reference< drawing::XShapes >& rShapes )
837 mpImpl->mpSortContext = new ShapeSortContext( rShapes, mpImpl->mpSortContext );
840 void XMLShapeImportHelper::popGroupAndSort()
842 DBG_ASSERT( mpImpl->mpSortContext, "No context to sort!" );
843 if( mpImpl->mpSortContext == NULL )
844 return;
848 list<ZOrderHint>& rZList = mpImpl->mpSortContext->maZOrderList;
849 list<ZOrderHint>& rUnsortedList = mpImpl->mpSortContext->maUnsortedList;
851 // sort shapes
852 if( !rZList.empty() )
854 // only do something if we have shapes to sort
856 // check if there are more shapes than inserted with ::shapeWithZIndexAdded()
857 // This can happen if there where already shapes on the page before import
858 // Since the writer may delete some of this shapes during import, we need
859 // to do this here and not in our c'tor anymore
861 // check if we have more shapes than we know of
862 sal_Int32 nCount = mpImpl->mpSortContext->mxShapes->getCount();
864 nCount -= rZList.size();
865 nCount -= rUnsortedList.size();
867 if( nCount > 0 )
869 // first update offsets of added shapes
870 list<ZOrderHint>::iterator aIter( rZList.begin() );
871 while( aIter != rZList.end() )
872 (*aIter++).nIs += nCount;
874 aIter = rUnsortedList.begin();
875 while( aIter != rUnsortedList.end() )
876 (*aIter++).nIs += nCount;
878 // second add the already existing shapes in the unsorted list
879 ZOrderHint aNewHint;
883 nCount--;
885 aNewHint.nIs = nCount;
886 aNewHint.nShould = -1;
888 rUnsortedList.insert(rUnsortedList.begin(), aNewHint);
890 while( nCount );
893 // sort z ordered shapes
894 rZList.sort();
896 // this is the current index, all shapes before that
897 // index are finished
898 sal_Int32 nIndex = 0;
899 while( !rZList.empty() )
901 list<ZOrderHint>::iterator aIter( rZList.begin() );
903 while( nIndex < (*aIter).nShould && !rUnsortedList.empty() )
905 ZOrderHint aGapHint( *rUnsortedList.begin() );
906 rUnsortedList.pop_front();
908 mpImpl->mpSortContext->moveShape( aGapHint.nIs, nIndex++ );
911 if( (*aIter).nIs != nIndex )
912 mpImpl->mpSortContext->moveShape( (*aIter).nIs, nIndex );
914 rZList.pop_front();
915 nIndex++;
919 catch( uno::Exception& )
921 OSL_FAIL("exception while sorting shapes, sorting failed!");
924 // put parent on top and delete current context, were done
925 ShapeSortContext* pContext = mpImpl->mpSortContext;
926 mpImpl->mpSortContext = pContext->mpParentContext;
927 delete pContext;
930 void XMLShapeImportHelper::shapeWithZIndexAdded( com::sun::star::uno::Reference< com::sun::star::drawing::XShape >&, sal_Int32 nZIndex )
932 if( mpImpl->mpSortContext)
934 ZOrderHint aNewHint;
935 aNewHint.nIs = mpImpl->mpSortContext->mnCurrentZ++;
936 aNewHint.nShould = nZIndex;
938 if( nZIndex == -1 )
940 // don't care, so add to unsorted list
941 mpImpl->mpSortContext->maUnsortedList.push_back(aNewHint);
943 else
945 // insert into sort list
946 mpImpl->mpSortContext->maZOrderList.push_back(aNewHint);
951 void XMLShapeImportHelper::addShapeConnection( com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& rConnectorShape,
952 bool bStart,
953 const OUString& rDestShapeId,
954 sal_Int32 nDestGlueId )
956 ConnectionHint aHint;
957 aHint.mxConnector = rConnectorShape;
958 aHint.bStart = bStart;
959 aHint.aDestShapeId = rDestShapeId;
960 aHint.nDestGlueId = nDestGlueId;
962 mpImpl->maConnections.push_back( aHint );
965 void XMLShapeImportHelper::restoreConnections()
967 if( !mpImpl->maConnections.empty() )
969 uno::Any aAny;
971 const vector<ConnectionHint>::size_type nCount = mpImpl->maConnections.size();
972 for( vector<ConnectionHint>::size_type i = 0; i < nCount; i++ )
974 ConnectionHint& rHint = mpImpl->maConnections[i];
975 uno::Reference< beans::XPropertySet > xConnector( rHint.mxConnector, uno::UNO_QUERY );
976 if( xConnector.is() )
978 // #86637# remember line deltas
979 uno::Any aLine1Delta;
980 uno::Any aLine2Delta;
981 uno::Any aLine3Delta;
982 OUString aStr1("EdgeLine1Delta");
983 OUString aStr2("EdgeLine2Delta");
984 OUString aStr3("EdgeLine3Delta");
985 aLine1Delta = xConnector->getPropertyValue(aStr1);
986 aLine2Delta = xConnector->getPropertyValue(aStr2);
987 aLine3Delta = xConnector->getPropertyValue(aStr3);
989 // #86637# simply setting these values WILL force the connector to do
990 // an new layout promptly. So the line delta values have to be rescued
991 // and restored around connector changes.
992 uno::Reference< drawing::XShape > xShape(
993 mrImporter.getInterfaceToIdentifierMapper().getReference( rHint.aDestShapeId ), uno::UNO_QUERY );
994 if( xShape.is() )
996 aAny <<= xShape;
997 xConnector->setPropertyValue( rHint.bStart ? msStartShape : msEndShape, aAny );
999 sal_Int32 nGlueId = rHint.nDestGlueId < 4 ? rHint.nDestGlueId : getGluePointId( xShape, rHint.nDestGlueId );
1000 aAny <<= nGlueId;
1001 xConnector->setPropertyValue( rHint.bStart ? msStartGluePointIndex : msEndGluePointIndex, aAny );
1004 // #86637# restore line deltas
1005 xConnector->setPropertyValue(aStr1, aLine1Delta );
1006 xConnector->setPropertyValue(aStr2, aLine2Delta );
1007 xConnector->setPropertyValue(aStr3, aLine3Delta );
1010 mpImpl->maConnections.clear();
1014 SvXMLImportPropertyMapper* XMLShapeImportHelper::CreateShapePropMapper( const uno::Reference< frame::XModel>& rModel, SvXMLImport& rImport )
1016 rtl::Reference< XMLPropertyHandlerFactory > xFactory = new XMLSdPropHdlFactory( rModel, rImport );
1017 rtl::Reference < XMLPropertySetMapper > xMapper = new XMLShapePropertySetMapper( xFactory, false );
1018 SvXMLImportPropertyMapper* pResult = new SvXMLImportPropertyMapper( xMapper, rImport );
1020 // chain text attributes
1021 pResult->ChainImportMapper( XMLTextImportHelper::CreateParaExtPropMapper( rImport ) );
1022 return pResult;
1025 /** adds a mapping for a glue point identifier from an xml file to the identifier created after inserting
1026 the new glue point into the core. The saved mappings can be retrieved by getGluePointId() */
1027 void XMLShapeImportHelper::addGluePointMapping( com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape,
1028 sal_Int32 nSourceId, sal_Int32 nDestinnationId )
1030 if( mpPageContext )
1031 mpPageContext->maShapeGluePointsMap[xShape][nSourceId] = nDestinnationId;
1034 /** find mapping for given DestinationID. This allows to extract the original draw:id imported with a draw:glue-point */
1035 sal_Int32 XMLShapeImportHelper::findGluePointMapping(
1036 const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape,
1037 sal_Int32 nDestinnationId ) const
1039 if( mpPageContext )
1041 ShapeGluePointsMap::iterator aShapeIter( mpPageContext->maShapeGluePointsMap.find( xShape ) );
1043 if( aShapeIter != mpPageContext->maShapeGluePointsMap.end() )
1045 GluePointIdMap::iterator aShapeIdIter = (*aShapeIter).second.begin();
1046 GluePointIdMap::iterator aShapeIdEnd = (*aShapeIter).second.end();
1048 while ( aShapeIdIter != aShapeIdEnd )
1050 if ( (*aShapeIdIter).second == nDestinnationId )
1052 return (*aShapeIdIter).first;
1055 ++aShapeIdIter;
1060 return -1;
1063 /** moves all current DestinationId's by n */
1064 void XMLShapeImportHelper::moveGluePointMapping( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape, const sal_Int32 n )
1066 if( mpPageContext )
1068 ShapeGluePointsMap::iterator aShapeIter( mpPageContext->maShapeGluePointsMap.find( xShape ) );
1069 if( aShapeIter != mpPageContext->maShapeGluePointsMap.end() )
1071 GluePointIdMap::iterator aShapeIdIter = (*aShapeIter).second.begin();
1072 GluePointIdMap::iterator aShapeIdEnd = (*aShapeIter).second.end();
1073 while ( aShapeIdIter != aShapeIdEnd )
1075 if ( (*aShapeIdIter).second != -1 )
1076 (*aShapeIdIter).second += n;
1077 ++aShapeIdIter;
1083 /** retrieves a mapping for a glue point identifier from the current xml file to the identifier created after
1084 inserting the new glue point into the core. The mapping must be initialized first with addGluePointMapping() */
1085 sal_Int32 XMLShapeImportHelper::getGluePointId( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape, sal_Int32 nSourceId )
1087 if( mpPageContext )
1089 ShapeGluePointsMap::iterator aShapeIter( mpPageContext->maShapeGluePointsMap.find( xShape ) );
1090 if( aShapeIter != mpPageContext->maShapeGluePointsMap.end() )
1092 GluePointIdMap::iterator aIdIter = (*aShapeIter).second.find(nSourceId);
1093 if( aIdIter != (*aShapeIter).second.end() )
1094 return (*aIdIter).second;
1098 return -1;
1101 /** this method must be calling before the first shape is imported for the given page */
1102 void XMLShapeImportHelper::startPage( com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& rShapes )
1104 XMLShapeImportPageContextImpl* pOldContext = mpPageContext;
1105 mpPageContext = new XMLShapeImportPageContextImpl();
1106 mpPageContext->mpNext = pOldContext;
1107 mpPageContext->mxShapes = rShapes;
1110 /** this method must be calling after the last shape is imported for the given page */
1111 void XMLShapeImportHelper::endPage( com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >&
1112 #ifdef DBG_UTIL
1113 rShapes
1114 #endif
1117 DBG_ASSERT( mpPageContext && (mpPageContext->mxShapes == rShapes), "wrong call to endPage(), no startPage called or wrong page" );
1118 if( NULL == mpPageContext )
1119 return;
1121 restoreConnections();
1123 XMLShapeImportPageContextImpl* pNextContext = mpPageContext->mpNext;
1124 delete mpPageContext;
1125 mpPageContext = pNextContext;
1128 // #88546#
1129 /** defines if the import should increment the progress bar or not */
1130 void XMLShapeImportHelper::enableHandleProgressBar( bool bEnable )
1132 mpImpl->mbHandleProgressBar = bEnable;
1135 bool XMLShapeImportHelper::IsHandleProgressBarEnabled() const
1137 return mpImpl->mbHandleProgressBar;
1140 /** queries the capability of the current model to create presentation shapes */
1141 bool XMLShapeImportHelper::IsPresentationShapesSupported()
1143 return mpImpl->mbIsPresentationShapesSupported;
1146 const rtl::Reference< XMLTableImport >& XMLShapeImportHelper::GetShapeTableImport()
1148 if( !mxShapeTableImport.is() )
1150 rtl::Reference< XMLPropertyHandlerFactory > xFactory( new XMLSdPropHdlFactory( mrImporter.GetModel(), mrImporter ) );
1151 rtl::Reference< XMLPropertySetMapper > xPropertySetMapper( new XMLShapePropertySetMapper( xFactory.get(), false ) );
1152 mxShapeTableImport = new XMLTableImport( mrImporter, xPropertySetMapper, xFactory );
1155 return mxShapeTableImport;
1158 void SvXMLShapeContext::setHyperlink( const OUString& rHyperlink )
1160 msHyperlink = rHyperlink;
1163 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */