use insert function instead of for loop
[LibreOffice.git] / oox / source / drawingml / diagram / diagramhelper.cxx
blob327524b655fabab227dd3014a09e3556337437ae
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 "diagramhelper.hxx"
21 #include "diagram.hxx"
23 #include <basegfx/matrix/b2dhommatrix.hxx>
24 #include <oox/shape/ShapeFilterBase.hxx>
25 #include <oox/ppt/pptimport.hxx>
26 #include <drawingml/fillproperties.hxx>
27 #include <svx/svdmodel.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <oox/drawingml/themefragmenthandler.hxx>
30 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
31 #include <utility>
33 using namespace ::com::sun::star;
35 namespace oox::drawingml {
37 bool AdvancedDiagramHelper::hasDiagramData() const
39 return mpDiagramPtr && mpDiagramPtr->getData();
42 AdvancedDiagramHelper::AdvancedDiagramHelper(
43 std::shared_ptr< Diagram > xDiagramPtr,
44 std::shared_ptr<::oox::drawingml::Theme> xTheme,
45 css::awt::Size aImportSize,
46 bool bSelfCreated)
47 : svx::diagram::IDiagramHelper(bSelfCreated)
48 , mpDiagramPtr(std::move(xDiagramPtr))
49 , mpThemePtr(std::move(xTheme))
50 , maImportSize(aImportSize)
54 AdvancedDiagramHelper::~AdvancedDiagramHelper()
58 void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget)
60 if(!mpDiagramPtr)
62 return;
65 // Rescue/remember geometric transformation of existing Diagram
66 basegfx::B2DHomMatrix aTransformation;
67 basegfx::B2DPolyPolygon aPolyPolygon;
68 rTarget.TRGetBaseGeometry(aTransformation, aPolyPolygon);
70 // create temporary oox::Shape as target. No longer needed is to keep/remember
71 // the original oox::Shape to do that. Use original Size and Pos from initial import
72 // to get the same layout(s)
73 oox::drawingml::ShapePtr pShapePtr = std::make_shared<Shape>( "com.sun.star.drawing.GroupShape" );
74 pShapePtr->setDiagramType();
75 pShapePtr->setSize(maImportSize);
77 // Re-create the oox::Shapes for the diagram content
78 mpDiagramPtr->addTo(pShapePtr, true);
80 // Delete all existing shapes in that group to prepare re-creation
81 rTarget.getChildrenOfSdrObject()->ClearSdrObjList();
83 // For re-creation we need to use ::addShape functionality from the
84 // oox import filter since currently Shape import is very tightly
85 // coupled to Shape creation. It converts a oox::Shape representation
86 // combined with an oox::Theme to incarnated XShapes representing the
87 // Diagram.
88 // To use that functionality, we have to create a temporary filter
89 // (based on ShapeFilterBase). Problems are that this needs to know
90 // the oox:Theme and a ComponentModel from TargetDocument.
91 // The DiagramHelper holds/delivers the oox::Theme to use, so
92 // it does not need to be re-imported from oox repeatedly.
93 // The ComponentModel can be derived from the existing XShape/GroupShape
94 // when knowing where to get it from, making it independent from app.
96 // NOTE: Using another (buffered) oox::Theme would allow to re-create
97 // using another theming in the future.
98 // NOTE: The incarnation of import filter (ShapeFilterBase) is only
99 // used for XShape creation, no xml snippets/data gets imported
100 // here. XShape creation may be isolated in the future.
101 SdrModel& rModel(rTarget.getSdrModelFromSdrObject());
102 uno::Reference< uno::XInterface > const & rUnoModel(rModel.getUnoModel());
103 const css::uno::Reference<css::uno::XComponentContext>& xContext(comphelper::getProcessComponentContext());
104 rtl::Reference<oox::shape::ShapeFilterBase> xFilter(new oox::shape::ShapeFilterBase(xContext));
106 // set oox::Theme at Filter. All LineStyle/FillStyle/Colors/Attributes
107 // will be taken from there
108 // also need to use theme when geometry gets self-created the first time
109 if(UseDiagramThemeData() || !isSelfCreated())
110 xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter));
112 css::uno::Reference< css::lang::XComponent > aComponentModel( rUnoModel, uno::UNO_QUERY );
113 xFilter->setTargetDocument(aComponentModel);
115 // set DiagramFontHeights
116 xFilter->setDiagramFontHeights(&mpDiagramPtr->getDiagramFontHeights());
118 // Prepare the target for the to-be-created XShapes
119 uno::Reference<drawing::XShapes> xShapes(rTarget.getUnoShape(), uno::UNO_QUERY_THROW);
121 for (auto const& child : pShapePtr->getChildren())
123 // Create all sub-shapes. This will recursively create needed geometry using
124 // filter-internal ::createShapes
125 child->addShape(
126 *xFilter,
127 xFilter->getCurrentTheme(),
128 xShapes,
129 aTransformation,
130 pShapePtr->getFillProperties());
133 // sync FontHeights
134 mpDiagramPtr->syncDiagramFontHeights();
136 if (isSelfCreated())
138 // already secured at import, re-apply secured data from ModelData
139 if(UseDiagramModelData())
140 mpDiagramPtr->getData()->restoreDataFromShapeToModelAfterDiagramImport(*pShapePtr);
142 else
144 // secure data from ModelData for the 1st time for shapes except BackgroundShape
145 if(UseDiagramModelData())
146 mpDiagramPtr->getData()->secureDataFromShapeToModelAfterDiagramImport(*pShapePtr);
148 // note that shapes are now self-created
149 setSelfCreated();
152 // Re-apply remembered geometry
153 rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon);
156 OUString AdvancedDiagramHelper::getString() const
158 if(hasDiagramData())
160 return mpDiagramPtr->getData()->getString();
163 return OUString();
166 std::vector<std::pair<OUString, OUString>> AdvancedDiagramHelper::getChildren(const OUString& rParentId) const
168 if(hasDiagramData())
170 return mpDiagramPtr->getData()->getChildren(rParentId);
173 return std::vector<std::pair<OUString, OUString>>();
176 OUString AdvancedDiagramHelper::addNode(const OUString& rText)
178 OUString aRetval;
180 if(hasDiagramData())
182 aRetval = mpDiagramPtr->getData()->addNode(rText);
184 // reset temporary buffered ModelData association lists & rebuild them
185 // and the Diagram DataModel
186 mpDiagramPtr->getData()->buildDiagramDataModel(true);
188 // also reset temporary buffered layout data - that might
189 // still refer to changed oox::Shape data
190 mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
193 return aRetval;
196 bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId)
198 bool bRetval(false);
200 if(hasDiagramData())
202 bRetval = mpDiagramPtr->getData()->removeNode(rNodeId);
204 // reset temporary buffered ModelData association lists & rebuild them
205 // and the Diagram DataModel
206 mpDiagramPtr->getData()->buildDiagramDataModel(true);
208 // also reset temporary buffered layout data - that might
209 // still refer to changed oox::Shape data
210 mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
213 return bRetval;
216 svx::diagram::DiagramDataStatePtr AdvancedDiagramHelper::extractDiagramDataState() const
218 if(!mpDiagramPtr)
220 return svx::diagram::DiagramDataStatePtr();
223 return mpDiagramPtr->getData()->extractDiagramDataState();
226 void AdvancedDiagramHelper::applyDiagramDataState(const svx::diagram::DiagramDataStatePtr& rState)
228 if(!mpDiagramPtr)
230 return;
233 mpDiagramPtr->getData()->applyDiagramDataState(rState);
236 void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Shape& rRootShape)
238 if(!mpDiagramPtr)
240 return;
243 mpDiagramPtr->syncDiagramFontHeights();
245 // After Diagram import, parts of the Diagram ModelData is at the
246 // oox::drawingml::Shape. Since these objects are temporary helpers,
247 // secure that data at the Diagram ModelData by copying.
248 mpDiagramPtr->getData()->secureDataFromShapeToModelAfterDiagramImport(rRootShape);
250 anchorToSdrObjGroup(rTarget);
253 const std::shared_ptr< ::oox::drawingml::Theme >& AdvancedDiagramHelper::getOrCreateThemePtr(
254 rtl::Reference< oox::shape::ShapeFilterBase >& rxFilter) const
256 // (Re-)Use already existing Theme if existing/imported if possible.
257 // If not, re-import Theme if data is available and thus possible
258 if(hasDiagramData() && (ForceThemePtrRecreation() || !mpThemePtr))
260 // get the originally imported dom::XDocument
261 const uno::Reference< css::xml::dom::XDocument >& xThemeDocument(mpDiagramPtr->getData()->getThemeDocument());
263 if(xThemeDocument)
265 // reset local Theme ModelData *always* to get rid of former data that would
266 // else be added additionally
267 const_cast<AdvancedDiagramHelper*>(this)->mpThemePtr = std::make_shared<oox::drawingml::Theme>();
268 auto pTheme = std::make_shared<model::Theme>();
269 mpThemePtr->setTheme(pTheme);
271 // import Theme ModelData
272 rxFilter->importFragment(
273 new ThemeFragmentHandler(*rxFilter, OUString(), *mpThemePtr, *pTheme),
274 uno::Reference< css::xml::sax::XFastSAXSerializable >(
275 xThemeDocument,
276 uno::UNO_QUERY_THROW));
280 return mpThemePtr;
285 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */