LibreOffice Module oox (master) 1
diagramhelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include "diagramhelper.hxx"
21#include "diagram.hxx"
22
25#include <oox/ppt/pptimport.hxx>
27#include <svx/svdmodel.hxx>
30#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
31#include <utility>
32
33using namespace ::com::sun::star;
34
35namespace oox::drawingml {
36
38{
39 return mpDiagramPtr && mpDiagramPtr->getData();
40}
41
43 std::shared_ptr< Diagram > xDiagramPtr,
44 std::shared_ptr<::oox::drawingml::Theme> xTheme,
45 css::awt::Size aImportSize)
46: svx::diagram::IDiagramHelper()
47, mpDiagramPtr(std::move(xDiagramPtr))
48, mpThemePtr(std::move(xTheme))
49, maImportSize(aImportSize)
50{
51}
52
54{
55}
56
58{
59 if(!mpDiagramPtr)
60 {
61 return;
62 }
63
64 // Rescue/remember geometric transformation of existing Diagram
65 basegfx::B2DHomMatrix aTransformation;
66 basegfx::B2DPolyPolygon aPolyPolygon;
67 rTarget.TRGetBaseGeometry(aTransformation, aPolyPolygon);
68
69 // create temporary oox::Shape as target. No longer needed is to keep/remember
70 // the original oox::Shape to do that. Use original Size and Pos from initial import
71 // to get the same layout(s)
72 oox::drawingml::ShapePtr pShapePtr = std::make_shared<Shape>( "com.sun.star.drawing.GroupShape" );
73 pShapePtr->setDiagramType();
74 pShapePtr->setSize(maImportSize);
75
76 // Re-create the oox::Shapes for the diagram content
77 mpDiagramPtr->addTo(pShapePtr);
78
79 // Delete all existing shapes in that group to prepare re-creation
80 rTarget.getChildrenOfSdrObject()->ClearSdrObjList();
81
82 // For re-creation we need to use ::addShape functionality from the
83 // oox import filter since currently Shape import is very tightly
84 // coupled to Shape creation. It converts a oox::Shape representation
85 // combined with an oox::Theme to incarnated XShapes representing the
86 // Diagram.
87 // To use that functionality, we have to create a temporary filter
88 // (based on ShapeFilterBase). Problems are that this needs to know
89 // the oox:Theme and a ComponentModel from TargetDocument.
90 // The DiagramHelper holds/delivers the oox::Theme to use, so
91 // it does not need to be re-imported from oox repeatedly.
92 // The ComponentModel can be derived from the existing XShape/GroupShape
93 // when knowing where to get it from, making it independent from app.
94 //
95 // NOTE: Using another (buffered) oox::Theme would allow to re-create
96 // using another theming in the future.
97 // NOTE: The incarnation of import filter (ShapeFilterBase) is only
98 // used for XShape creation, no xml snippets/data gets imported
99 // here. XShape creation may be isolated in the future.
100 SdrModel& rModel(rTarget.getSdrModelFromSdrObject());
101 uno::Reference< uno::XInterface > const & rUnoModel(rModel.getUnoModel());
102 css::uno::Reference<css::uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
104
105 // set oox::Theme at Filter. All LineStyle/FillStyle/Colors/Attributes
106 // will be taken from there
108 xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter));
109
110 css::uno::Reference< css::lang::XComponent > aComponentModel( rUnoModel, uno::UNO_QUERY );
111 xFilter->setTargetDocument(aComponentModel);
112
113 // set DiagramFontHeights
114 xFilter->setDiagramFontHeights(&mpDiagramPtr->getDiagramFontHeights());
115
116 // Prepare the target for the to-be-created XShapes
117 uno::Reference<drawing::XShapes> xShapes(rTarget.getUnoShape(), uno::UNO_QUERY_THROW);
118
119 for (auto const& child : pShapePtr->getChildren())
120 {
121 // Create all sub-shapes. This will recursively create needed geometry using
122 // filter-internal ::createShapes
123 child->addShape(
124 *xFilter,
125 xFilter->getCurrentTheme(),
126 xShapes,
127 aTransformation,
128 pShapePtr->getFillProperties());
129 }
130
131 // sync FontHeights
132 mpDiagramPtr->syncDiagramFontHeights();
133
134 // re-apply secured data from ModelData
136 mpDiagramPtr->getData()->restoreDataFromShapeToModelAfterDiagramImport(*pShapePtr);
137
138 // Re-apply remembered geometry
139 rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon);
140}
141
143{
144 if(hasDiagramData())
145 {
146 return mpDiagramPtr->getData()->getString();
147 }
148
149 return OUString();
150}
151
152std::vector<std::pair<OUString, OUString>> AdvancedDiagramHelper::getChildren(const OUString& rParentId) const
153{
154 if(hasDiagramData())
155 {
156 return mpDiagramPtr->getData()->getChildren(rParentId);
157 }
158
159 return std::vector<std::pair<OUString, OUString>>();
160}
161
162OUString AdvancedDiagramHelper::addNode(const OUString& rText)
163{
164 OUString aRetval;
165
166 if(hasDiagramData())
167 {
168 aRetval = mpDiagramPtr->getData()->addNode(rText);
169
170 // reset temporary buffered ModelData association lists & rebuild them
171 // and the Diagram DataModel
172 mpDiagramPtr->getData()->buildDiagramDataModel(true);
173
174 // also reset temporary buffered layout data - that might
175 // still refer to changed oox::Shape data
176 mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
177 }
178
179 return aRetval;
180}
181
182bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId)
183{
184 bool bRetval(false);
185
186 if(hasDiagramData())
187 {
188 bRetval = mpDiagramPtr->getData()->removeNode(rNodeId);
189
190 // reset temporary buffered ModelData association lists & rebuild them
191 // and the Diagram DataModel
192 mpDiagramPtr->getData()->buildDiagramDataModel(true);
193
194 // also reset temporary buffered layout data - that might
195 // still refer to changed oox::Shape data
196 mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
197 }
198
199 return bRetval;
200}
201
203{
204 if(!mpDiagramPtr)
205 {
207 }
208
209 return mpDiagramPtr->getData()->extractDiagramDataState();
210}
211
213{
214 if(!mpDiagramPtr)
215 {
216 return;
217 }
218
219 mpDiagramPtr->getData()->applyDiagramDataState(rState);
220}
221
223{
224 if(!mpDiagramPtr)
225 {
226 return;
227 }
228
229 mpDiagramPtr->syncDiagramFontHeights();
230
231 // After Diagram import, parts of the Diagram ModelData is at the
232 // oox::drawingml::Shape. Since these objects are temporary helpers,
233 // secure that data at the Diagram ModelData by copying.
234 mpDiagramPtr->getData()->secureDataFromShapeToModelAfterDiagramImport(rRootShape);
235
237}
238
239const std::shared_ptr< ::oox::drawingml::Theme >& AdvancedDiagramHelper::getOrCreateThemePtr(
241{
242 // (Re-)Use already existing Theme if existing/imported if possible.
243 // If not, re-import Theme if data is available and thus possible
245 {
246 // get the originally imported dom::XDocument
247 const uno::Reference< css::xml::dom::XDocument >& xThemeDocument(mpDiagramPtr->getData()->getThemeDocument());
248
249 if(xThemeDocument)
250 {
251 // reset local Theme ModelData *always* to get rid of former data that would
252 // else be added additionally
253 const_cast<AdvancedDiagramHelper*>(this)->mpThemePtr = std::make_shared<oox::drawingml::Theme>();
254 auto pTheme = std::make_shared<model::Theme>();
255 mpThemePtr->setTheme(pTheme);
256
257 // import Theme ModelData
258 rxFilter->importFragment(
259 new ThemeFragmentHandler(*rxFilter, OUString(), *mpThemePtr, *pTheme),
260 uno::Reference< css::xml::sax::XFastSAXSerializable >(
261 xThemeDocument,
262 uno::UNO_QUERY_THROW));
263 }
264 }
265
266 return mpThemePtr;
267}
268
269}
270
271/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::uno::XInterface > const & getUnoModel()
virtual bool removeNode(const OUString &rNodeId) override
void doAnchor(SdrObjGroup &rTarget, ::oox::drawingml::Shape &rRootShape)
std::shared_ptr<::oox::drawingml::Theme > mpThemePtr
const std::shared_ptr< Diagram > mpDiagramPtr
virtual std::shared_ptr< svx::diagram::DiagramDataState > extractDiagramDataState() const override
const std::shared_ptr< ::oox::drawingml::Theme > & getOrCreateThemePtr(rtl::Reference< oox::shape::ShapeFilterBase > &rxFilter) const
AdvancedDiagramHelper(std::shared_ptr< Diagram > xDiagramPtr, std::shared_ptr<::oox::drawingml::Theme > xTheme, css::awt::Size aImportSize)
virtual OUString addNode(const OUString &rText) override
virtual void reLayout(SdrObjGroup &rTarget) override
virtual void applyDiagramDataState(const std::shared_ptr< svx::diagram::DiagramDataState > &rState) override
virtual OUString getString() const override
virtual std::vector< std::pair< OUString, OUString > > getChildren(const OUString &rParentId) const override
bool ForceThemePtrRecreation() const
void anchorToSdrObjGroup(SdrObjGroup &rTarget)
FilterGroup & rTarget
Reference< XComponentContext > getProcessComponentContext()
std::shared_ptr< Shape > ShapePtr
std::shared_ptr< DiagramDataState > DiagramDataStatePtr