/src/libreoffice/svx/source/diagram/datamodel_svx.cxx
Line | Count | Source |
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 <unordered_set> |
21 | | #include <algorithm> |
22 | | #include <fstream> |
23 | | |
24 | | #include <svx/diagram/datamodel_svx.hxx> |
25 | | #include <svx/svdobj.hxx> |
26 | | #include <svx/svditer.hxx> |
27 | | #include <svx/svdogrp.hxx> |
28 | | #include <comphelper/xmltools.hxx> |
29 | | #include <sal/log.hxx> |
30 | | #include <utility> |
31 | | #include <sax/fastattribs.hxx> |
32 | | #include <com/sun/star/text/XText.hpp> |
33 | | #include <com/sun/star/drawing/XShapes.hpp> |
34 | | #include <xmloff/xmltoken.hxx> |
35 | | |
36 | | using namespace ::oox; |
37 | | using namespace ::com::sun::star; |
38 | | |
39 | | namespace svx::diagram { |
40 | | |
41 | | TypeConstant getTypeConstantForName(std::u16string_view aName) |
42 | 0 | { |
43 | 0 | if (u"Type" == aName) return TypeConstant::XML_type; |
44 | 0 | if (u"asst" == aName) return TypeConstant::XML_asst; |
45 | 0 | if (u"doc" == aName) return TypeConstant::XML_doc; |
46 | 0 | if (u"node" == aName) return TypeConstant::XML_node; |
47 | 0 | if (u"norm" == aName) return TypeConstant::XML_norm; |
48 | 0 | if (u"parOf" == aName) return TypeConstant::XML_parOf; |
49 | 0 | if (u"parTrans" == aName) return TypeConstant::XML_parTrans; |
50 | 0 | if (u"pres" == aName) return TypeConstant::XML_pres; |
51 | 0 | if (u"presOf" == aName) return TypeConstant::XML_presOf; |
52 | 0 | if (u"presParOf" == aName) return TypeConstant::XML_presParOf; |
53 | 0 | if (u"rel" == aName) return TypeConstant::XML_rel; |
54 | 0 | if (u"sibTrans" == aName) return TypeConstant::XML_sibTrans; |
55 | 0 | return TypeConstant::XML_none; |
56 | 0 | } |
57 | | |
58 | | std::u16string_view getNameForTypeConstant(TypeConstant aTypeConstant) |
59 | 0 | { |
60 | 0 | switch (aTypeConstant) |
61 | 0 | { |
62 | 0 | case TypeConstant::XML_type: return u"Type"; break; |
63 | 0 | case TypeConstant::XML_asst: return u"asst"; break; |
64 | 0 | case TypeConstant::XML_doc: return u"doc"; break; |
65 | 0 | case TypeConstant::XML_node: return u"node"; break; |
66 | 0 | case TypeConstant::XML_norm: return u"norm"; break; |
67 | 0 | case TypeConstant::XML_parOf: return u"parOf"; break; |
68 | 0 | case TypeConstant::XML_parTrans: return u"parTrans"; break; |
69 | 0 | case TypeConstant::XML_pres: return u"pres"; break; |
70 | 0 | case TypeConstant::XML_presOf: return u"presOf"; break; |
71 | 0 | case TypeConstant::XML_presParOf: return u"presParOf"; break; |
72 | 0 | case TypeConstant::XML_rel: return u"rel"; break; |
73 | 0 | case TypeConstant::XML_sibTrans: return u"sibTrans"; break; |
74 | 0 | case TypeConstant::XML_none: break; |
75 | 0 | } |
76 | | |
77 | 0 | return u""; |
78 | 0 | } |
79 | | |
80 | | void addTypeConstantToFastAttributeList(TypeConstant aTypeConstant, const rtl::Reference<sax_fastparser::FastAttributeList>& rAttributeList, bool bPoint) |
81 | 0 | { |
82 | 0 | if (TypeConstant::XML_none == aTypeConstant) |
83 | 0 | return; |
84 | 0 | if (TypeConstant::XML_node == aTypeConstant && bPoint) |
85 | 0 | return; |
86 | 0 | if (TypeConstant::XML_parOf == aTypeConstant && !bPoint) |
87 | 0 | return; |
88 | | |
89 | 0 | const std::u16string_view aName(getNameForTypeConstant(aTypeConstant)); |
90 | | // *CAUTION!* here '::XML_type' is *not* the same as 'XML_type' which would |
91 | | // namespace expand to oox::XML_type as in enum TypeConstant definitions (!) |
92 | 0 | if (!aName.empty()) |
93 | 0 | rAttributeList->add(::XML_type, aName); |
94 | 0 | } |
95 | | |
96 | | void addTypeConstantToDiagramModelData(TypeConstant aTypeConstant, boost::property_tree::ptree& rTarget, bool bPoint) |
97 | 0 | { |
98 | 0 | if (TypeConstant::XML_none == aTypeConstant) |
99 | 0 | return; |
100 | 0 | if (TypeConstant::XML_node == aTypeConstant && bPoint) |
101 | 0 | return; |
102 | 0 | if (TypeConstant::XML_parOf == aTypeConstant && !bPoint) |
103 | 0 | return; |
104 | | |
105 | 0 | const std::u16string_view aName(getNameForTypeConstant(aTypeConstant)); |
106 | 0 | if (!aName.empty()) |
107 | 0 | rTarget.put("XMLType", OUString(aName)); |
108 | 0 | } |
109 | | |
110 | | Connection::Connection() |
111 | 5.54k | : mnXMLType( XML_parOf ) |
112 | 5.54k | , msModelId() |
113 | 5.54k | , msSourceId() |
114 | 5.54k | , msDestId() |
115 | 5.54k | , msPresId() |
116 | 5.54k | , msSibTransId() |
117 | 5.54k | , msParTransId() |
118 | 5.54k | , mnSourceOrder( 0 ) |
119 | 5.54k | , mnDestOrder( 0 ) |
120 | 5.54k | { |
121 | 5.54k | } |
122 | | |
123 | | Connection::Connection(const boost::property_tree::ptree& rConnectionData) |
124 | 0 | : mnXMLType( XML_parOf ) |
125 | 0 | , msModelId(OUString::fromUtf8(rConnectionData.get("modelId", ""))) |
126 | 0 | , msSourceId(OUString::fromUtf8(rConnectionData.get("srcId", ""))) |
127 | 0 | , msDestId(OUString::fromUtf8(rConnectionData.get("destId", ""))) |
128 | 0 | , msPresId(OUString::fromUtf8(rConnectionData.get("presId", ""))) |
129 | 0 | , msSibTransId(OUString::fromUtf8(rConnectionData.get("sibTransId", ""))) |
130 | 0 | , msParTransId(OUString::fromUtf8(rConnectionData.get("parTransId", ""))) |
131 | 0 | , mnSourceOrder(rConnectionData.get("srcOrd", 0)) |
132 | 0 | , mnDestOrder(rConnectionData.get("destOrd", 0)) |
133 | 0 | { |
134 | 0 | const OUString aXMLType(OUString::fromUtf8(rConnectionData.get("XMLType", ""))); |
135 | 0 | if (!aXMLType.isEmpty()) |
136 | 0 | mnXMLType = getTypeConstantForName(aXMLType); |
137 | 0 | } |
138 | | |
139 | | void Connection::writeDiagramData(const sax_fastparser::FSHelperPtr& rTarget) |
140 | 0 | { |
141 | 0 | if (!rTarget) |
142 | 0 | return; |
143 | | |
144 | 0 | rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList(sax_fastparser::FastSerializerHelper::createAttrList()); |
145 | |
|
146 | 0 | if (!msModelId.isEmpty()) |
147 | 0 | pAttributeList->add(XML_modelId, msModelId); |
148 | 0 | addTypeConstantToFastAttributeList(mnXMLType, pAttributeList, false); |
149 | 0 | if (!msSourceId.isEmpty()) |
150 | 0 | pAttributeList->add(XML_srcId, msSourceId); |
151 | 0 | if (!msDestId.isEmpty()) |
152 | 0 | pAttributeList->add(XML_destId, msDestId); |
153 | 0 | pAttributeList->add(XML_srcOrd, OUString::number(mnSourceOrder)); |
154 | 0 | pAttributeList->add(XML_destOrd, OUString::number(mnDestOrder)); |
155 | 0 | if (!msPresId.isEmpty()) |
156 | 0 | pAttributeList->add(XML_presId, msPresId); |
157 | 0 | if (!msParTransId.isEmpty()) |
158 | 0 | pAttributeList->add(XML_parTransId, msParTransId); |
159 | 0 | if (!msSibTransId.isEmpty()) |
160 | 0 | pAttributeList->add(XML_sibTransId, msSibTransId); |
161 | |
|
162 | 0 | rTarget->singleElementNS(XML_dgm, XML_cxn, pAttributeList); |
163 | 0 | } |
164 | | |
165 | | void Connection::addDiagramModelData(boost::property_tree::ptree& rTarget) const |
166 | 0 | { |
167 | 0 | addTypeConstantToDiagramModelData(mnXMLType, rTarget, false); // XML_type |
168 | 0 | if (!msModelId.isEmpty()) rTarget.put("modelId", msModelId); // XML_modelId |
169 | 0 | if (!msSourceId.isEmpty()) rTarget.put("srcId", msSourceId); // XML_srcId |
170 | 0 | if (!msDestId.isEmpty()) rTarget.put("destId", msDestId); // XML_destId |
171 | 0 | if (!msPresId.isEmpty()) rTarget.put("presId", msPresId); // XML_presId |
172 | 0 | if (!msSibTransId.isEmpty()) rTarget.put("sibTransId", msSibTransId); // XML_sibTransId |
173 | 0 | if (!msParTransId.isEmpty()) rTarget.put("parTransId", msParTransId); // XML_parTransId |
174 | 0 | if (0 != mnSourceOrder) rTarget.put("srcOrd", mnSourceOrder); // XML_srcOrd |
175 | 0 | if (0 != mnDestOrder) rTarget.put("destOrd", mnDestOrder); // XML_destOrd |
176 | 0 | } |
177 | | |
178 | | Point::Point() |
179 | 6.42k | : mnXMLType(XML_node) |
180 | 6.42k | , mnMaxChildren(-1) |
181 | 6.42k | , mnPreferredChildren(-1) |
182 | 6.42k | , mnDirection(XML_norm) |
183 | 6.42k | , mnCustomAngle(-1) |
184 | 6.42k | , mnPercentageNeighbourWidth(-1) |
185 | 6.42k | , mnPercentageNeighbourHeight(-1) |
186 | 6.42k | , mnPercentageOwnWidth(-1) |
187 | 6.42k | , mnPercentageOwnHeight(-1) |
188 | 6.42k | , mnIncludeAngleScale(-1) |
189 | 6.42k | , mnRadiusScale(-1) |
190 | 6.42k | , mnWidthScale(-1) |
191 | 6.42k | , mnHeightScale(-1) |
192 | 6.42k | , mnWidthOverride(-1) |
193 | 6.42k | , mnHeightOverride(-1) |
194 | 6.42k | , mnLayoutStyleCount(-1) |
195 | 6.42k | , mnLayoutStyleIndex(-1) |
196 | 6.42k | , mbOrgChartEnabled(false) |
197 | 6.42k | , mbBulletEnabled(false) |
198 | 6.42k | , mbCoherent3DOffset(false) |
199 | 6.42k | , mbCustomHorizontalFlip(false) |
200 | 6.42k | , mbCustomVerticalFlip(false) |
201 | 6.42k | , mbCustomText(false) |
202 | 6.42k | , mbIsPlaceholder(false) |
203 | 6.42k | { |
204 | 6.42k | } |
205 | | |
206 | | Point::Point(const boost::property_tree::ptree& rPointData) |
207 | 0 | : msCnxId(OUString::fromUtf8(rPointData.get("cxnId", ""))) |
208 | 0 | , msModelId(OUString::fromUtf8(rPointData.get("modelId", ""))) |
209 | 0 | , msColorTransformCategoryId(OUString::fromUtf8(rPointData.get("csCatId", ""))) |
210 | 0 | , msColorTransformTypeId(OUString::fromUtf8(rPointData.get("csTypeId", ""))) |
211 | 0 | , msLayoutCategoryId(OUString::fromUtf8(rPointData.get("loCatId", ""))) |
212 | 0 | , msLayoutTypeId(OUString::fromUtf8(rPointData.get("loTypeId", ""))) |
213 | 0 | , msPlaceholderText(OUString::fromUtf8(rPointData.get("phldrT", ""))) |
214 | 0 | , msPresentationAssociationId(OUString::fromUtf8(rPointData.get("presAssocID", ""))) |
215 | 0 | , msPresentationLayoutName(OUString::fromUtf8(rPointData.get("presName", ""))) |
216 | 0 | , msPresentationLayoutStyleLabel(OUString::fromUtf8(rPointData.get("presStyleLbl", ""))) |
217 | 0 | , msQuickStyleCategoryId(OUString::fromUtf8(rPointData.get("qsCatId", ""))) |
218 | 0 | , msQuickStyleTypeId(OUString::fromUtf8(rPointData.get("qsTypeId", ""))) |
219 | 0 | , msResizeHandles(OUString::fromUtf8(rPointData.get("resizeHandles", ""))) |
220 | 0 | , mnXMLType(XML_node) |
221 | 0 | , mnMaxChildren(rPointData.get("chMax", -1)) |
222 | 0 | , mnPreferredChildren(rPointData.get("chPref", -1)) |
223 | 0 | , mnDirection(rPointData.get<int>("dir", XML_norm)) |
224 | 0 | , moHierarchyBranch() |
225 | 0 | , mnCustomAngle(rPointData.get("custAng", -1)) |
226 | 0 | , mnPercentageNeighbourWidth(rPointData.get("custLinFactNeighborX", -1)) |
227 | 0 | , mnPercentageNeighbourHeight(rPointData.get("custLinFactNeighborY", -1)) |
228 | 0 | , mnPercentageOwnWidth(rPointData.get("custLinFactX", -1)) |
229 | 0 | , mnPercentageOwnHeight(rPointData.get("custLinFactY", -1)) |
230 | 0 | , mnIncludeAngleScale(rPointData.get("custRadScaleInc", -1)) |
231 | 0 | , mnRadiusScale(rPointData.get("custRadScaleRad", -1)) |
232 | 0 | , mnWidthScale(rPointData.get("custScaleX", -1)) |
233 | 0 | , mnHeightScale(rPointData.get("custScaleY", -1)) |
234 | 0 | , mnWidthOverride(rPointData.get("custSzX", -1)) |
235 | 0 | , mnHeightOverride(rPointData.get("custSzY", -1)) |
236 | 0 | , mnLayoutStyleCount(rPointData.get("presStyleCnt", -1)) |
237 | 0 | , mnLayoutStyleIndex(rPointData.get("presStyleIdx", -1)) |
238 | 0 | , mbOrgChartEnabled(rPointData.get("orgChart", false)) |
239 | 0 | , mbBulletEnabled(rPointData.get("bulletEnabled", false)) |
240 | 0 | , mbCoherent3DOffset(rPointData.get("coherent3DOff", false)) |
241 | 0 | , mbCustomHorizontalFlip(rPointData.get("custFlipHor", false)) |
242 | 0 | , mbCustomVerticalFlip(rPointData.get("custFlipVert", false)) |
243 | 0 | , mbCustomText(rPointData.get("custT", false)) |
244 | 0 | , mbIsPlaceholder(rPointData.get("phldr", false)) |
245 | 0 | { |
246 | 0 | const OUString aXMLType(OUString::fromUtf8(rPointData.get("XMLType", ""))); |
247 | 0 | if (!aXMLType.isEmpty()) |
248 | 0 | mnXMLType = getTypeConstantForName(aXMLType); |
249 | |
|
250 | 0 | const boost::optional<sal_Int32> aBranch(rPointData.get_optional<int>("hierBranch")); |
251 | 0 | if (aBranch.has_value()) |
252 | 0 | moHierarchyBranch = aBranch.value(); |
253 | 0 | } |
254 | | |
255 | | void Point::writeDiagramData_data(const sax_fastparser::FSHelperPtr& rTarget) |
256 | 0 | { |
257 | 0 | rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList(sax_fastparser::FastSerializerHelper::createAttrList()); |
258 | |
|
259 | 0 | if (!msColorTransformCategoryId.isEmpty()) pAttributeList->add(XML_csCatId, msColorTransformCategoryId); |
260 | 0 | if (!msColorTransformTypeId.isEmpty()) pAttributeList->add(XML_csTypeId, msColorTransformTypeId); |
261 | 0 | if (!msLayoutCategoryId.isEmpty()) pAttributeList->add(XML_loCatId, msLayoutCategoryId); |
262 | 0 | if (!msLayoutTypeId.isEmpty()) pAttributeList->add(XML_loTypeId, msLayoutTypeId); |
263 | 0 | if (!msPlaceholderText.isEmpty()) pAttributeList->add(XML_phldrT, msPlaceholderText); |
264 | 0 | if (!msPresentationAssociationId.isEmpty()) pAttributeList->add(XML_presAssocID, msPresentationAssociationId); |
265 | 0 | if (!msPresentationLayoutName.isEmpty()) pAttributeList->add(XML_presName, msPresentationLayoutName); |
266 | 0 | if (!msPresentationLayoutStyleLabel.isEmpty()) pAttributeList->add(XML_presStyleLbl, msPresentationLayoutStyleLabel); |
267 | 0 | if (!msQuickStyleCategoryId.isEmpty()) pAttributeList->add(XML_qsCatId, msQuickStyleCategoryId); |
268 | 0 | if (!msQuickStyleTypeId.isEmpty()) pAttributeList->add(XML_qsTypeId, msQuickStyleTypeId); |
269 | |
|
270 | 0 | if (-1 != mnCustomAngle) pAttributeList->add(XML_custAng, OUString::number(mnCustomAngle)); |
271 | 0 | if (-1 != mnPercentageNeighbourWidth) pAttributeList->add(XML_custLinFactNeighborX, OUString::number(mnPercentageNeighbourWidth)); |
272 | 0 | if (-1 != mnPercentageNeighbourHeight) pAttributeList->add(XML_custLinFactNeighborY, OUString::number(mnPercentageNeighbourHeight)); |
273 | 0 | if (-1 != mnPercentageOwnWidth) pAttributeList->add(XML_custLinFactX, OUString::number(mnPercentageOwnWidth)); |
274 | 0 | if (-1 != mnPercentageOwnHeight) pAttributeList->add(XML_custLinFactY, OUString::number(mnPercentageOwnHeight)); |
275 | 0 | if (-1 != mnIncludeAngleScale) pAttributeList->add(XML_custRadScaleInc, OUString::number(mnIncludeAngleScale)); |
276 | 0 | if (-1 != mnRadiusScale) pAttributeList->add(XML_custRadScaleRad, OUString::number(mnRadiusScale)); |
277 | 0 | if (-1 != mnWidthScale) pAttributeList->add(XML_custScaleX, OUString::number(mnWidthScale)); |
278 | 0 | if (-1 != mnHeightScale) pAttributeList->add(XML_custScaleY, OUString::number(mnHeightScale)); |
279 | 0 | if (-1 != mnWidthOverride) pAttributeList->add(XML_custSzX, OUString::number(mnWidthOverride)); |
280 | 0 | if (-1 != mnHeightOverride) pAttributeList->add(XML_custSzY, OUString::number(mnHeightOverride)); |
281 | 0 | if (-1 != mnLayoutStyleCount) pAttributeList->add(XML_presStyleCnt, OUString::number(mnLayoutStyleCount)); |
282 | 0 | if (-1 != mnLayoutStyleIndex) pAttributeList->add(XML_presStyleIdx, OUString::number(mnLayoutStyleIndex)); |
283 | |
|
284 | 0 | static constexpr OUString aStrTrue = u"1"_ustr; // this uses "1", not "true" |
285 | 0 | if (mbCoherent3DOffset) pAttributeList->add(XML_coherent3DOff, aStrTrue); |
286 | 0 | if (mbCustomHorizontalFlip) pAttributeList->add(XML_custFlipHor, aStrTrue); |
287 | 0 | if (mbCustomVerticalFlip) pAttributeList->add(XML_custFlipVert, aStrTrue); |
288 | 0 | if (mbCustomText) pAttributeList->add(XML_custT, aStrTrue); |
289 | 0 | if (mbIsPlaceholder) pAttributeList->add(XML_phldr, aStrTrue); |
290 | |
|
291 | 0 | const bool bNeed_presLayoutVars(mbBulletEnabled |
292 | 0 | || -1 != mnMaxChildren |
293 | 0 | || -1 != mnPreferredChildren |
294 | 0 | || XML_norm != mnDirection |
295 | 0 | || moHierarchyBranch.has_value() |
296 | 0 | || mbOrgChartEnabled |
297 | 0 | || !msResizeHandles.isEmpty()); |
298 | |
|
299 | 0 | if (bNeed_presLayoutVars) |
300 | 0 | { |
301 | 0 | rTarget->startElementNS(XML_dgm, XML_prSet, pAttributeList); |
302 | 0 | rTarget->startElementNS(XML_dgm, XML_presLayoutVars); |
303 | |
|
304 | 0 | if (mbBulletEnabled) |
305 | 0 | rTarget->singleElementNS(XML_dgm, XML_bulletEnabled, XML_val, aStrTrue); |
306 | |
|
307 | 0 | if (-1 != mnMaxChildren) |
308 | 0 | rTarget->singleElementNS(XML_dgm, XML_chMax, XML_val, OUString::number(mnMaxChildren)); |
309 | |
|
310 | 0 | if (-1 != mnPreferredChildren) |
311 | 0 | rTarget->singleElementNS(XML_dgm, XML_chPref, XML_val, OUString::number(mnPreferredChildren)); |
312 | |
|
313 | 0 | if (XML_norm != mnDirection) |
314 | 0 | rTarget->singleElementNS(XML_dgm, XML_dir, XML_val, OString::number(mnDirection)); |
315 | |
|
316 | 0 | if (moHierarchyBranch.has_value()) |
317 | 0 | rTarget->singleElementNS(XML_dgm, XML_hierBranch, XML_val, OString::number(moHierarchyBranch.value())); |
318 | |
|
319 | 0 | if (mbOrgChartEnabled) |
320 | 0 | rTarget->singleElementNS(XML_dgm, XML_orgChart, XML_val, aStrTrue); |
321 | |
|
322 | 0 | if (!msResizeHandles.isEmpty()) |
323 | 0 | rTarget->singleElementNS(XML_dgm, XML_resizeHandles, XML_val, msResizeHandles); |
324 | |
|
325 | 0 | rTarget->endElementNS(XML_dgm, XML_presLayoutVars); |
326 | 0 | rTarget->endElementNS(XML_dgm, XML_prSet); |
327 | 0 | } |
328 | 0 | else |
329 | 0 | rTarget->singleElementNS(XML_dgm, XML_prSet, pAttributeList); |
330 | 0 | } |
331 | | |
332 | | void Point::addDiagramModelData(boost::property_tree::ptree& rTarget) const |
333 | 0 | { |
334 | 0 | if (!msCnxId.isEmpty()) rTarget.put("cxnId", msCnxId); // XML_cxnId |
335 | 0 | if (!msModelId.isEmpty()) rTarget.put("modelId", msModelId); // XML_modelId |
336 | 0 | if (!msColorTransformCategoryId.isEmpty()) rTarget.put("csCatId", msColorTransformCategoryId); // XML_csCatId |
337 | 0 | if (!msColorTransformTypeId.isEmpty()) rTarget.put("csTypeId", msColorTransformTypeId); // XML_csTypeId |
338 | 0 | if (!msLayoutCategoryId.isEmpty()) rTarget.put("loCatId", msLayoutCategoryId); // XML_loCatId |
339 | 0 | if (!msLayoutTypeId.isEmpty()) rTarget.put("loTypeId", msLayoutTypeId); // XML_loTypeId |
340 | 0 | if (!msPlaceholderText.isEmpty()) rTarget.put("phldrT", msPlaceholderText); // XML_phldrT |
341 | 0 | if (!msPresentationAssociationId.isEmpty()) rTarget.put("presAssocID", msPresentationAssociationId); // XML_presAssocID |
342 | 0 | if (!msPresentationLayoutName.isEmpty()) rTarget.put("presName", msPresentationLayoutName); // XML_presName |
343 | 0 | if (!msPresentationLayoutStyleLabel.isEmpty()) rTarget.put("presStyleLbl", msPresentationLayoutStyleLabel); // XML_presStyleLbl |
344 | 0 | if (!msQuickStyleCategoryId.isEmpty()) rTarget.put("qsCatId", msQuickStyleCategoryId); // XML_qsCatId |
345 | 0 | if (!msQuickStyleTypeId.isEmpty()) rTarget.put("qsTypeId", msQuickStyleTypeId); // XML_qsTypeId |
346 | 0 | if (!msResizeHandles.isEmpty()) rTarget.put("resizeHandles", msResizeHandles); // XML_resizeHandles |
347 | |
|
348 | 0 | addTypeConstantToDiagramModelData(mnXMLType, rTarget, true); // XML_type |
349 | 0 | if (-1 != mnMaxChildren) rTarget.put("chMax", mnMaxChildren); // XML_chMax |
350 | 0 | if (-1 != mnPreferredChildren) rTarget.put("chPref", mnPreferredChildren); // XML_chPref |
351 | 0 | if (XML_norm != mnDirection) rTarget.put("dir", mnDirection); // XML_dir |
352 | 0 | if (moHierarchyBranch.has_value()) rTarget.put("hierBranch", moHierarchyBranch.value()); // XML_hierBranch |
353 | |
|
354 | 0 | if (-1 != mnCustomAngle) rTarget.put("custAng", mnCustomAngle); // XML_custAng |
355 | 0 | if (-1 != mnPercentageNeighbourWidth) rTarget.put("custLinFactNeighborX", mnPercentageNeighbourWidth); // XML_custLinFactNeighborX |
356 | 0 | if (-1 != mnPercentageNeighbourHeight) rTarget.put("custLinFactNeighborY", mnPercentageNeighbourHeight); // XML_custLinFactNeighborY |
357 | 0 | if (-1 != mnPercentageOwnWidth) rTarget.put("custLinFactX", mnPercentageOwnWidth); // XML_custLinFactX |
358 | 0 | if (-1 != mnPercentageOwnHeight) rTarget.put("custLinFactY", mnPercentageOwnHeight); // XML_custLinFactY |
359 | 0 | if (-1 != mnIncludeAngleScale) rTarget.put("custRadScaleInc", mnIncludeAngleScale); // XML_custRadScaleInc |
360 | 0 | if (-1 != mnRadiusScale) rTarget.put("custRadScaleRad", mnRadiusScale); // XML_custRadScaleRad |
361 | 0 | if (-1 != mnWidthScale) rTarget.put("custScaleX", mnWidthScale); // XML_custScaleX |
362 | 0 | if (-1 != mnHeightScale) rTarget.put("custScaleY", mnHeightScale); // XML_custScaleY |
363 | 0 | if (-1 != mnWidthOverride) rTarget.put("custSzX", mnWidthOverride); // XML_custSzX |
364 | 0 | if (-1 != mnHeightOverride) rTarget.put("custSzY", mnHeightOverride); // XML_custSzY |
365 | 0 | if (-1 != mnLayoutStyleCount) rTarget.put("presStyleCnt", mnLayoutStyleCount); // XML_presStyleCnt |
366 | 0 | if (-1 != mnLayoutStyleIndex) rTarget.put("presStyleIdx", mnLayoutStyleIndex); // XML_presStyleIdx |
367 | |
|
368 | 0 | if (mbOrgChartEnabled) rTarget.put("orgChart", mbOrgChartEnabled); // XML_orgChart |
369 | 0 | if (mbBulletEnabled) rTarget.put("bulletEnabled", mbBulletEnabled); // XML_bulletEnabled |
370 | 0 | if (mbCoherent3DOffset) rTarget.put("coherent3DOff", mbCoherent3DOffset); // XML_coherent3DOff |
371 | 0 | if (mbCustomHorizontalFlip) rTarget.put("custFlipHor", mbCustomHorizontalFlip); // XML_custFlipHor |
372 | 0 | if (mbCustomVerticalFlip) rTarget.put("custFlipVert", mbCustomVerticalFlip); // XML_custFlipVert |
373 | 0 | if (mbCustomText) rTarget.put("custT", mbCustomText); // XML_custT |
374 | 0 | if (mbIsPlaceholder) rTarget.put("phldr", mbIsPlaceholder); // XML_phldr |
375 | 0 | } |
376 | | |
377 | | DiagramData_svx::DiagramData_svx() |
378 | 832 | : mxRootShape() |
379 | 832 | , maExtDrawings() |
380 | 832 | , maConnections() |
381 | 832 | , maPoints() |
382 | 832 | , mxThemeDocument() |
383 | 832 | , maPointsPresNameMap() |
384 | 832 | , maConnectionNameMap() |
385 | 832 | , maPresOfNameMap() |
386 | 832 | , msBackgroundShapeModelID() |
387 | 832 | { |
388 | 832 | } |
389 | | |
390 | | DiagramData_svx::DiagramData_svx(DiagramData_svx const& rSource) |
391 | 0 | : mxRootShape() |
392 | 0 | , maExtDrawings() |
393 | | // copy all Connections |
394 | 0 | , maConnections(rSource.maConnections) |
395 | | // copy all Points |
396 | 0 | , maPoints(rSource.maPoints) |
397 | 0 | , mxThemeDocument() |
398 | 0 | , maPointsPresNameMap() |
399 | 0 | , maConnectionNameMap() |
400 | 0 | , maPresOfNameMap() |
401 | | // copy BackgroundShapeModelID, the BGSgape will need to be identified on reLayout |
402 | 0 | , msBackgroundShapeModelID(rSource.msBackgroundShapeModelID) |
403 | 0 | { |
404 | 0 | } |
405 | | |
406 | | DiagramData_svx::DiagramData_svx(const boost::property_tree::ptree& rDiagramModel) |
407 | 0 | : mxRootShape() |
408 | 0 | , maExtDrawings() |
409 | 0 | , maConnections() |
410 | 0 | , maPoints() |
411 | 0 | , mxThemeDocument() |
412 | 0 | , maPointsPresNameMap() |
413 | 0 | , maConnectionNameMap() |
414 | 0 | , maPresOfNameMap() |
415 | 0 | , msBackgroundShapeModelID(OUString::fromUtf8(rDiagramModel.get("BGShapeModelID", ""))) |
416 | 0 | { |
417 | | // read all Point entries |
418 | 0 | auto aRangePt(rDiagramModel.equal_range("Pt")); |
419 | 0 | for (auto itPt = aRangePt.first; itPt != aRangePt.second; itPt++) |
420 | 0 | maPoints.emplace_back(itPt->second); |
421 | | |
422 | | // read all Connection entries |
423 | 0 | auto aRangeCn(rDiagramModel.equal_range("Cn")); |
424 | 0 | for (auto itCn = aRangeCn.first; itCn != aRangeCn.second; itCn++) |
425 | 0 | maConnections.emplace_back(itCn->second); |
426 | 0 | } |
427 | | |
428 | | DiagramData_svx::~DiagramData_svx() |
429 | 832 | { |
430 | 832 | } |
431 | | |
432 | | const Point* DiagramData_svx::getRootPoint() const |
433 | 107 | { |
434 | 107 | for (const auto & aCurrPoint : maPoints) |
435 | 84 | if (aCurrPoint.mnXMLType == TypeConstant::XML_doc) |
436 | 84 | return &aCurrPoint; |
437 | | |
438 | 23 | SAL_WARN("svx.diagram", "No root point"); |
439 | 23 | return nullptr; |
440 | 23 | } |
441 | | |
442 | | OUString DiagramData_svx::getDiagramString() const |
443 | 0 | { |
444 | 0 | OUStringBuffer aBuf; |
445 | 0 | const Point* pPoint = getRootPoint(); |
446 | 0 | getDiagramChildrenString(aBuf, pPoint, 0); |
447 | 0 | return aBuf.makeStringAndClear(); |
448 | 0 | } |
449 | | |
450 | | DomMapFlags DiagramData_svx::removeDiagramNode(const OUString& rNodeId) |
451 | 0 | { |
452 | 0 | DomMapFlags aRetval; |
453 | | |
454 | | // check if it doesn't have children |
455 | 0 | for (const auto& aCxn : maConnections) |
456 | 0 | if (aCxn.mnXMLType == TypeConstant::XML_parOf && aCxn.msSourceId == rNodeId) |
457 | 0 | { |
458 | 0 | SAL_WARN("svx.diagram", "Node has children - can't be removed"); |
459 | 0 | return aRetval; |
460 | 0 | } |
461 | | |
462 | 0 | Connection aParCxn; |
463 | 0 | for (const auto& aCxn : maConnections) |
464 | 0 | if (aCxn.mnXMLType == TypeConstant::XML_parOf && aCxn.msDestId == rNodeId) |
465 | 0 | aParCxn = aCxn; |
466 | |
|
467 | 0 | std::unordered_set<OUString> aIdsToRemove; |
468 | 0 | aIdsToRemove.insert(rNodeId); |
469 | 0 | if (!aParCxn.msParTransId.isEmpty()) |
470 | 0 | aIdsToRemove.insert(aParCxn.msParTransId); |
471 | 0 | if (!aParCxn.msSibTransId.isEmpty()) |
472 | 0 | aIdsToRemove.insert(aParCxn.msSibTransId); |
473 | |
|
474 | 0 | for (const Point& rPoint : maPoints) |
475 | 0 | if (aIdsToRemove.count(rPoint.msPresentationAssociationId)) |
476 | 0 | aIdsToRemove.insert(rPoint.msModelId); |
477 | | |
478 | | // insert also transition nodes |
479 | 0 | for (const auto& aCxn : maConnections) |
480 | 0 | if (aIdsToRemove.count(aCxn.msSourceId) || aIdsToRemove.count(aCxn.msDestId)) |
481 | 0 | if (!aCxn.msPresId.isEmpty()) |
482 | 0 | aIdsToRemove.insert(aCxn.msPresId); |
483 | | |
484 | | // remove connections |
485 | 0 | std::erase_if(maConnections, |
486 | 0 | [&aIdsToRemove](const Connection& rCxn) { |
487 | 0 | return aIdsToRemove.count(rCxn.msSourceId) || aIdsToRemove.count(rCxn.msDestId); |
488 | 0 | }); |
489 | | |
490 | | // remove data and presentation nodes |
491 | 0 | std::erase_if(maPoints, |
492 | 0 | [&aIdsToRemove](const Point& rPoint) { |
493 | 0 | return aIdsToRemove.count(rPoint.msModelId); |
494 | 0 | }); |
495 | | |
496 | | // TODO: fix source/dest order |
497 | | |
498 | | // prepare retval, OOXData and OOXLayout is changed |
499 | 0 | aRetval.push_back(DomMapFlag::OOXData); |
500 | 0 | aRetval.push_back(DomMapFlag::OOXDrawing); |
501 | 0 | aRetval.push_back(DomMapFlag::OOXDataImageRels); |
502 | 0 | aRetval.push_back(DomMapFlag::OOXDataHlinkRels); |
503 | 0 | aRetval.push_back(DomMapFlag::OOXDrawingImageRels); |
504 | 0 | aRetval.push_back(DomMapFlag::OOXDrawingHlinkRels); |
505 | |
|
506 | 0 | return aRetval; |
507 | 0 | } |
508 | | |
509 | | DiagramDataState::DiagramDataState(const Connections& aConnections, const Points& aPoints, const uno::Reference< drawing::XShape >& rRootShape, const OUString& rBackgroundShapeModelID) |
510 | 0 | : maConnections(aConnections) |
511 | 0 | , maPoints(aPoints) |
512 | 0 | , mxShapes() |
513 | 0 | , maTransformation() |
514 | 0 | , msBackgroundShapeModelID(rBackgroundShapeModelID) |
515 | 0 | { |
516 | 0 | SdrObjGroup* pSource(dynamic_cast<SdrObjGroup*>(SdrObject::getSdrObjectFromXShape(rRootShape))); |
517 | 0 | if (nullptr != pSource) |
518 | 0 | { |
519 | 0 | basegfx::B2DPolyPolygon aPolyPolygon; |
520 | 0 | pSource->TRGetBaseGeometry(maTransformation, aPolyPolygon); |
521 | |
|
522 | 0 | for(size_t a(0); a < pSource->GetObjCount(); a++) |
523 | 0 | { |
524 | 0 | SdrObject* pCandidate(pSource->GetObj(a)); |
525 | |
|
526 | 0 | if (nullptr != pCandidate) |
527 | 0 | { |
528 | 0 | uno::Reference<drawing::XShape> xCandidate(pCandidate->getUnoShape()); |
529 | 0 | mxShapes.push_back(xCandidate); |
530 | 0 | } |
531 | 0 | } |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | | DiagramDataStatePtr DiagramData_svx::extractDiagramDataState() const |
536 | 0 | { |
537 | | // Just copy all Connections && Points. The shared_ptr data in |
538 | | // Point-entries is no problem, it just continues exiting shared |
539 | 0 | return std::make_shared< DiagramDataState >(maConnections, maPoints, accessRootShape(), getBackgroundShapeModelID()); |
540 | 0 | } |
541 | | |
542 | | void DiagramData_svx::applyDiagramDataState(const DiagramDataStatePtr& rState) |
543 | 0 | { |
544 | 0 | if(rState) |
545 | 0 | { |
546 | 0 | maConnections = rState->getConnections(); |
547 | 0 | maPoints = rState->getPoints(); |
548 | |
|
549 | 0 | uno::Reference<drawing::XShapes> xRootShape(accessRootShape(), uno::UNO_QUERY); |
550 | 0 | if (xRootShape.is()) |
551 | 0 | { |
552 | 0 | SdrObjGroup* pTarget(dynamic_cast<SdrObjGroup*>(SdrObject::getSdrObjectFromXShape(xRootShape))); |
553 | |
|
554 | 0 | if (nullptr != pTarget) |
555 | 0 | { |
556 | | // Delete all existing shapes in that group |
557 | 0 | pTarget->getChildrenOfSdrObject()->ClearSdrObjList(); |
558 | 0 | } |
559 | |
|
560 | 0 | const std::vector<uno::Reference<drawing::XShape>>& rXShapes(rState->getXShapes()); |
561 | 0 | for (auto& rShape : rXShapes) |
562 | 0 | xRootShape->add(rShape); |
563 | |
|
564 | 0 | basegfx::B2DPolyPolygon aPolyPolygon; |
565 | 0 | pTarget->TRSetBaseGeometry(rState->getTransformation(), aPolyPolygon); |
566 | 0 | } |
567 | | |
568 | | // BackgroundShapeModelID is needed to identify the correct data |
569 | | // carrier in the following ::reLayout |
570 | 0 | setBackgroundShapeModelID(rState->getBackgroundShapeModelID()); |
571 | | |
572 | | // Reset temporary buffered ModelData association lists & rebuild them |
573 | | // and the Diagram DataModel. Do that here *immediately* to prevent |
574 | | // re-usage of potentially invalid Connection/Point objects |
575 | 0 | buildDiagramDataModel(true); |
576 | 0 | } |
577 | 0 | } |
578 | | |
579 | | void DiagramData_svx::getDiagramChildrenString( |
580 | | OUStringBuffer& rBuf, |
581 | | const svx::diagram::Point* pPoint, |
582 | | sal_Int32 nLevel) const |
583 | 0 | { |
584 | 0 | if (!pPoint) |
585 | 0 | return; |
586 | | |
587 | 0 | if (nLevel > 0) |
588 | 0 | { |
589 | 0 | for (sal_Int32 i = 0; i < nLevel-1; i++) |
590 | 0 | rBuf.append('\t'); |
591 | 0 | rBuf.append('+'); |
592 | 0 | rBuf.append(' '); |
593 | 0 | const OUString aText(getTextForPoint(*pPoint)); |
594 | 0 | rBuf.append(aText); |
595 | 0 | rBuf.append('\n'); |
596 | 0 | } |
597 | |
|
598 | 0 | std::vector< const svx::diagram::Point* > aChildren; |
599 | 0 | for (const auto& rCxn : maConnections) |
600 | 0 | if (rCxn.mnXMLType == TypeConstant::XML_parOf && rCxn.msSourceId == pPoint->msModelId) |
601 | 0 | { |
602 | 0 | if (rCxn.mnSourceOrder >= static_cast<sal_Int32>(aChildren.size())) |
603 | 0 | aChildren.resize(rCxn.mnSourceOrder + 1); |
604 | 0 | const Point* pChild(getPointByModelID(rCxn.msDestId)); |
605 | 0 | if (nullptr != pChild) |
606 | 0 | aChildren[rCxn.mnSourceOrder] = pChild; |
607 | 0 | } |
608 | |
|
609 | 0 | for (auto pChild : aChildren) |
610 | 0 | getDiagramChildrenString(rBuf, pChild, nLevel + 1); |
611 | 0 | } |
612 | | |
613 | | uno::Reference<drawing::XShape> DiagramData_svx::getXShapeByModelID(std::u16string_view rModelID) const |
614 | 0 | { |
615 | 0 | uno::Reference<drawing::XShape> xRetval; |
616 | 0 | if (rModelID.empty()) |
617 | 0 | return xRetval; |
618 | | |
619 | 0 | SdrObject* pCandidate(SdrObject::getSdrObjectFromXShape(accessRootShape())); |
620 | 0 | if (nullptr == pCandidate) |
621 | 0 | return xRetval; |
622 | | |
623 | 0 | SdrObjListIter aIterator(*pCandidate, SdrIterMode::DeepNoGroups); |
624 | 0 | while (aIterator.IsMore()) |
625 | 0 | { |
626 | 0 | pCandidate = aIterator.Next(); |
627 | 0 | if (nullptr != pCandidate && rModelID == pCandidate->getDiagramDataModelID()) |
628 | 0 | return pCandidate->getUnoShape(); |
629 | 0 | } |
630 | | |
631 | 0 | return xRetval; |
632 | 0 | } |
633 | | |
634 | | const Point* DiagramData_svx::getPointByModelID(std::u16string_view rModelID) const |
635 | 2.32k | { |
636 | 2.32k | for (const auto& rCandidate : getPoints()) |
637 | 30.8k | if (rModelID == rCandidate.msModelId) |
638 | 2.32k | return &rCandidate; |
639 | | |
640 | 0 | return nullptr; |
641 | 2.32k | } |
642 | | |
643 | | void DiagramData_svx::addDiagramModelData(boost::property_tree::ptree& rTarget) const |
644 | 0 | { |
645 | | // write BGShapeModelID to boost::property_tree |
646 | 0 | rTarget.put("BGShapeModelID", getBackgroundShapeModelID()); |
647 | | |
648 | | // write all points to boost::property_tree |
649 | 0 | const svx::diagram::Points& rPoints = getPoints(); |
650 | 0 | for (auto & point : rPoints) |
651 | 0 | { |
652 | 0 | boost::property_tree::ptree aPoints; |
653 | 0 | point.addDiagramModelData(aPoints); |
654 | | // const OUString aName(OUString::Concat("Pt") + OUString::number(count++)); |
655 | 0 | rTarget.push_back(std::make_pair("Pt", aPoints)); |
656 | 0 | } |
657 | | |
658 | | // write all connections to boost::property_tree |
659 | 0 | const svx::diagram::Connections& rConnections = getConnections(); |
660 | 0 | for (auto & connection : rConnections) |
661 | 0 | { |
662 | 0 | boost::property_tree::ptree aConnections; |
663 | 0 | connection.addDiagramModelData(aConnections); |
664 | | // const OUString aName(OUString::Concat("Cn") + OUString::number(count++)); |
665 | 0 | rTarget.push_back(std::make_pair("Cn", aConnections)); |
666 | 0 | } |
667 | 0 | } |
668 | | |
669 | | uno::Reference<drawing::XShape> DiagramData_svx::getMasterXShapeForPoint(const Point& rPoint) const |
670 | 1.95k | { |
671 | 1.95k | for (auto& rCandidate : getPoints()) |
672 | 55.4k | { |
673 | 55.4k | if (!rCandidate.msPresentationAssociationId.isEmpty() |
674 | 26.8k | && "textNode" == rCandidate.msPresentationLayoutName |
675 | 0 | && rCandidate.msPresentationAssociationId == rPoint.msModelId) |
676 | 0 | { |
677 | 0 | const uno::Reference<drawing::XShape> xMasterText = getXShapeByModelID(rCandidate.msModelId); |
678 | 0 | if (xMasterText) |
679 | 0 | return xMasterText; |
680 | 0 | } |
681 | 55.4k | } |
682 | | |
683 | 1.95k | return uno::Reference<drawing::XShape>(); |
684 | 1.95k | } |
685 | | |
686 | | OUString DiagramData_svx::getTextForPoint(const Point& rPoint) const |
687 | 1.95k | { |
688 | 1.95k | uno::Reference<drawing::XShape> xMasterText(getMasterXShapeForPoint(rPoint)); |
689 | 1.95k | uno::Reference<text::XText> xText(xMasterText, uno::UNO_QUERY); |
690 | | |
691 | 1.95k | if (xText) |
692 | 0 | return xText->getString(); |
693 | | |
694 | 1.95k | return OUString(); |
695 | 1.95k | } |
696 | | |
697 | | std::vector<std::pair<OUString, OUString>> DiagramData_svx::getDiagramChildren(const OUString& rParentId) const |
698 | 0 | { |
699 | 0 | const OUString sModelId = rParentId.isEmpty() ? getRootPoint()->msModelId : rParentId; |
700 | 0 | std::vector<std::pair<OUString, OUString>> aChildren; |
701 | 0 | for (const auto& rCxn : maConnections) |
702 | 0 | if (rCxn.mnXMLType == TypeConstant::XML_parOf && rCxn.msSourceId == sModelId) |
703 | 0 | { |
704 | 0 | if (rCxn.mnSourceOrder >= static_cast<sal_Int32>(aChildren.size())) |
705 | 0 | aChildren.resize(rCxn.mnSourceOrder + 1); |
706 | 0 | const Point* pChild(getPointByModelID(rCxn.msDestId)); |
707 | 0 | if (nullptr != pChild) |
708 | 0 | { |
709 | 0 | const OUString aText(getTextForPoint(*pChild)); |
710 | 0 | aChildren[rCxn.mnSourceOrder] = std::make_pair( |
711 | 0 | pChild->msModelId, |
712 | 0 | aText); |
713 | 0 | } |
714 | 0 | } |
715 | | |
716 | | // HACK: empty items shouldn't appear there |
717 | 0 | std::erase_if(aChildren, [](const std::pair<OUString, OUString>& aItem) { return aItem.first.isEmpty(); }); |
718 | |
|
719 | 0 | return aChildren; |
720 | 0 | } |
721 | | |
722 | | std::pair<OUString, DomMapFlags> DiagramData_svx::addDiagramNode() |
723 | 0 | { |
724 | 0 | DomMapFlags aRetval; |
725 | 0 | const svx::diagram::Point& rDataRoot = *getRootPoint(); |
726 | 0 | OUString sPresRoot; |
727 | 0 | for (const auto& aCxn : maConnections) |
728 | 0 | if (aCxn.mnXMLType == TypeConstant::XML_presOf && aCxn.msSourceId == rDataRoot.msModelId) |
729 | 0 | sPresRoot = aCxn.msDestId; |
730 | |
|
731 | 0 | if (sPresRoot.isEmpty()) |
732 | 0 | return std::make_pair(OUString(), aRetval); |
733 | | |
734 | 0 | OUString sNewNodeId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); |
735 | |
|
736 | 0 | svx::diagram::Point aDataPoint; |
737 | 0 | aDataPoint.mnXMLType = TypeConstant::XML_node; |
738 | 0 | aDataPoint.msModelId = sNewNodeId; |
739 | 0 | aDataPoint.msPlaceholderText = "[Text]"; |
740 | |
|
741 | 0 | OUString sDataSibling; |
742 | 0 | for (const auto& aCxn : maConnections) |
743 | 0 | if (aCxn.mnXMLType == TypeConstant::XML_parOf && aCxn.msSourceId == rDataRoot.msModelId) |
744 | 0 | sDataSibling = aCxn.msDestId; |
745 | |
|
746 | 0 | OUString sPresSibling; |
747 | 0 | for (const auto& aCxn : maConnections) |
748 | 0 | if (aCxn.mnXMLType == TypeConstant::XML_presOf && aCxn.msSourceId == sDataSibling) |
749 | 0 | sPresSibling = aCxn.msDestId; |
750 | |
|
751 | 0 | svx::diagram::Point aPresPoint; |
752 | 0 | aPresPoint.mnXMLType = TypeConstant::XML_pres; |
753 | 0 | aPresPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); |
754 | |
|
755 | 0 | aPresPoint.msPresentationAssociationId = aDataPoint.msModelId; |
756 | 0 | const svx::diagram::Point* pSiblingPoint = !sPresSibling.isEmpty() ? getPointByModelID(sPresSibling) : nullptr; |
757 | 0 | if (pSiblingPoint) |
758 | 0 | { |
759 | | // no idea where to get these values from, so copy from previous sibling |
760 | 0 | aPresPoint.msPresentationLayoutName = pSiblingPoint->msPresentationLayoutName; |
761 | 0 | aPresPoint.msPresentationLayoutStyleLabel = pSiblingPoint->msPresentationLayoutStyleLabel; |
762 | 0 | aPresPoint.mnLayoutStyleIndex = pSiblingPoint->mnLayoutStyleIndex; |
763 | 0 | aPresPoint.mnLayoutStyleCount = pSiblingPoint->mnLayoutStyleCount; |
764 | 0 | } |
765 | |
|
766 | 0 | addConnection(svx::diagram::TypeConstant::XML_parOf, rDataRoot.msModelId, aDataPoint.msModelId); |
767 | 0 | addConnection(svx::diagram::TypeConstant::XML_presParOf, sPresRoot, aPresPoint.msModelId); |
768 | 0 | addConnection(svx::diagram::TypeConstant::XML_presOf, aDataPoint.msModelId, aPresPoint.msModelId); |
769 | | |
770 | | // adding at the end, so that references are not invalidated in between |
771 | 0 | maPoints.push_back(std::move(aDataPoint)); |
772 | 0 | maPoints.push_back(std::move(aPresPoint)); |
773 | | |
774 | | // prepare retval, OOXData and OOXLayout is changed |
775 | 0 | aRetval.push_back(DomMapFlag::OOXData); |
776 | 0 | aRetval.push_back(DomMapFlag::OOXDrawing); |
777 | 0 | aRetval.push_back(DomMapFlag::OOXDataImageRels); |
778 | 0 | aRetval.push_back(DomMapFlag::OOXDataHlinkRels); |
779 | 0 | aRetval.push_back(DomMapFlag::OOXDrawingImageRels); |
780 | 0 | aRetval.push_back(DomMapFlag::OOXDrawingHlinkRels); |
781 | |
|
782 | 0 | return std::make_pair(sNewNodeId, aRetval); |
783 | 0 | } |
784 | | |
785 | | void DiagramData_svx::addConnection(svx::diagram::TypeConstant nType, const OUString& sSourceId, const OUString& sDestId) |
786 | 0 | { |
787 | 0 | sal_Int32 nMaxOrd = -1; |
788 | 0 | for (const auto& aCxn : maConnections) |
789 | 0 | if (aCxn.mnXMLType == nType && aCxn.msSourceId == sSourceId) |
790 | 0 | nMaxOrd = std::max(nMaxOrd, aCxn.mnSourceOrder); |
791 | |
|
792 | 0 | svx::diagram::Connection& rCxn = maConnections.emplace_back(); |
793 | 0 | rCxn.mnXMLType = nType; |
794 | 0 | rCxn.msSourceId = sSourceId; |
795 | 0 | rCxn.msDestId = sDestId; |
796 | 0 | rCxn.mnSourceOrder = nMaxOrd + 1; |
797 | 0 | } |
798 | | |
799 | | // #define DEBUG_OOX_DIAGRAM |
800 | | #ifdef DEBUG_OOX_DIAGRAM |
801 | | OString normalizeDotName( const OUString& rStr ) |
802 | | { |
803 | | OUStringBuffer aBuf; |
804 | | aBuf.append('N'); |
805 | | |
806 | | const sal_Int32 nLen(rStr.getLength()); |
807 | | sal_Int32 nCurrIndex(0); |
808 | | while( nCurrIndex < nLen ) |
809 | | { |
810 | | const sal_Int32 aChar=rStr.iterateCodePoints(&nCurrIndex); |
811 | | if( aChar != '-' && aChar != '{' && aChar != '}' ) |
812 | | aBuf.append((sal_Unicode)aChar); |
813 | | } |
814 | | |
815 | | return OUStringToOString(aBuf.makeStringAndClear(), |
816 | | RTL_TEXTENCODING_UTF8); |
817 | | } |
818 | | #endif |
819 | | |
820 | | static sal_Int32 calcDepth( std::u16string_view rNodeName, |
821 | | const svx::diagram::Connections& rCnx ) |
822 | 1.10k | { |
823 | | // find length of longest path in 'isChild' graph, ending with rNodeName |
824 | 1.10k | for (auto const& elem : rCnx) |
825 | 20.6k | { |
826 | 20.6k | if( !elem.msParTransId.isEmpty() && |
827 | 4.03k | !elem.msSibTransId.isEmpty() && |
828 | 4.03k | !elem.msSourceId.isEmpty() && |
829 | 4.03k | !elem.msDestId.isEmpty() && |
830 | 4.03k | elem.mnXMLType == TypeConstant::XML_parOf && |
831 | 4.03k | rNodeName == elem.msDestId ) |
832 | 426 | { |
833 | 426 | return calcDepth(elem.msSourceId, rCnx) + 1; |
834 | 426 | } |
835 | 20.6k | } |
836 | | |
837 | 677 | return 0; |
838 | 1.10k | } |
839 | | |
840 | | void DiagramData_svx::buildDiagramDataModel(bool /*bClearOoxShapes*/) |
841 | 107 | { |
842 | | // build name-object maps |
843 | 107 | maPointsPresNameMap.clear(); |
844 | 107 | maConnectionNameMap.clear(); |
845 | 107 | maPresOfNameMap.clear(); |
846 | | |
847 | | #ifdef DEBUG_OOX_DIAGRAM |
848 | | std::ofstream output("tree.dot"); |
849 | | |
850 | | output << "digraph datatree {" << std::endl; |
851 | | #endif |
852 | 107 | svx::diagram::Points& rPoints = getPoints(); |
853 | 107 | for (auto & point : rPoints) |
854 | 1.95k | { |
855 | | #ifdef DEBUG_OOX_DIAGRAM |
856 | | output << "\t" |
857 | | << normalizeDotName(point.msModelId).getStr() |
858 | | << "["; |
859 | | |
860 | | if( !point.msPresentationLayoutName.isEmpty() ) |
861 | | output << "label=\"" |
862 | | << OUStringToOString( |
863 | | point.msPresentationLayoutName, |
864 | | RTL_TEXTENCODING_UTF8).getStr() << "\", "; |
865 | | else |
866 | | output << "label=\"" |
867 | | << OUStringToOString( |
868 | | point.msModelId, |
869 | | RTL_TEXTENCODING_UTF8).getStr() << "\", "; |
870 | | |
871 | | switch( point.mnXMLType ) |
872 | | { |
873 | | case TypeConstant::XML_doc: output << "style=filled, color=red"; break; |
874 | | case TypeConstant::XML_asst: output << "style=filled, color=green"; break; |
875 | | default: |
876 | | case TypeConstant::XML_node: output << "style=filled, color=blue"; break; |
877 | | case TypeConstant::XML_pres: output << "style=filled, color=yellow"; break; |
878 | | case TypeConstant::XML_parTrans: output << "color=grey"; break; |
879 | | case TypeConstant::XML_sibTrans: output << " "; break; |
880 | | } |
881 | | |
882 | | output << "];" << std::endl; |
883 | | #endif |
884 | | |
885 | | // does currpoint have any text set? |
886 | 1.95k | const OUString aTextAtPoint(getTextForPoint(point)); |
887 | 1.95k | if(!aTextAtPoint.isEmpty()) |
888 | 0 | { |
889 | | #ifdef DEBUG_OOX_DIAGRAM |
890 | | static sal_Int32 nCount=0; |
891 | | output << "\t" |
892 | | << "textNode" << nCount |
893 | | << " [" |
894 | | << "label=\"" |
895 | | << OUStringToOString( |
896 | | aTextAtPoint, |
897 | | RTL_TEXTENCODING_UTF8).getStr() |
898 | | << "\"" << "];" << std::endl; |
899 | | output << "\t" |
900 | | << normalizeDotName(point.msModelId).getStr() |
901 | | << " -> " |
902 | | << "textNode" << nCount++ |
903 | | << ";" << std::endl; |
904 | | #endif |
905 | 0 | } |
906 | | |
907 | 1.95k | const bool bInserted1(nullptr != getPointByModelID(point.msModelId)); |
908 | 1.95k | SAL_WARN_IF(!bInserted1, "oox.drawingml", "DiagramData_svx::build(): non-unique point model id"); |
909 | | |
910 | 1.95k | if( !point.msPresentationLayoutName.isEmpty() ) |
911 | 887 | { |
912 | 887 | DiagramData_svx::PointsNameMap::value_type::second_type& rVec= |
913 | 887 | getPointsPresNameMap()[point.msPresentationLayoutName]; |
914 | 887 | rVec.push_back(&point); |
915 | 887 | } |
916 | 1.95k | } |
917 | | |
918 | 107 | const svx::diagram::Connections& rConnections = getConnections(); |
919 | 107 | for (auto const& connection : rConnections) |
920 | 1.80k | { |
921 | | #ifdef DEBUG_OOX_DIAGRAM |
922 | | if( !connection.msParTransId.isEmpty() || |
923 | | !connection.msSibTransId.isEmpty() ) |
924 | | { |
925 | | if( !connection.msSourceId.isEmpty() || |
926 | | !connection.msDestId.isEmpty() ) |
927 | | { |
928 | | output << "\t" |
929 | | << normalizeDotName(connection.msSourceId).getStr() |
930 | | << " -> " |
931 | | << normalizeDotName(connection.msParTransId).getStr() |
932 | | << " -> " |
933 | | << normalizeDotName(connection.msSibTransId).getStr() |
934 | | << " -> " |
935 | | << normalizeDotName(connection.msDestId).getStr() |
936 | | << " [style=dotted," |
937 | | << ((connection.mnXMLType == TypeConstant::XML_presOf) ? " color=red, " : ((connection.mnXMLType == TypeConstant::XML_presParOf) ? " color=green, " : " ")) |
938 | | << "label=\"" |
939 | | << OUStringToOString(connection.msModelId, |
940 | | RTL_TEXTENCODING_UTF8 ).getStr() |
941 | | << "\"];" << std::endl; |
942 | | } |
943 | | else |
944 | | { |
945 | | output << "\t" |
946 | | << normalizeDotName(connection.msParTransId).getStr() |
947 | | << " -> " |
948 | | << normalizeDotName(connection.msSibTransId).getStr() |
949 | | << " [" |
950 | | << ((connection.mnXMLType == TypeConstant::XML_presOf) ? " color=red, " : ((connection.mnXMLType == TypeConstant::XML_presParOf) ? " color=green, " : " ")) |
951 | | << "label=\"" |
952 | | << OUStringToOString(connection.msModelId, |
953 | | RTL_TEXTENCODING_UTF8 ).getStr() |
954 | | << "\"];" << std::endl; |
955 | | } |
956 | | } |
957 | | else if( !connection.msSourceId.isEmpty() || |
958 | | !connection.msDestId.isEmpty() ) |
959 | | output << "\t" |
960 | | << normalizeDotName(connection.msSourceId).getStr() |
961 | | << " -> " |
962 | | << normalizeDotName(connection.msDestId).getStr() |
963 | | << " [label=\"" |
964 | | << OUStringToOString(connection.msModelId, |
965 | | RTL_TEXTENCODING_UTF8 ).getStr() |
966 | | << ((connection.mnXMLType == TypeConstant::XML_presOf) ? "\", color=red]" : ((connection.mnXMLType == TypeConstant::XML_presParOf) ? "\", color=green]" : "\"]")) |
967 | | << ";" << std::endl; |
968 | | #endif |
969 | | |
970 | 1.80k | const bool bInserted1 = maConnectionNameMap.insert( |
971 | 1.80k | std::make_pair(connection.msModelId,&connection)).second; |
972 | | |
973 | 1.80k | SAL_WARN_IF(!bInserted1, "oox.drawingml", "DiagramData_svx::build(): non-unique connection model id"); |
974 | | |
975 | 1.80k | if( connection.mnXMLType == TypeConstant::XML_presOf ) |
976 | 677 | { |
977 | 677 | DiagramData_svx::StringMap::value_type::second_type& rVec = getPresOfNameMap()[connection.msDestId]; |
978 | 677 | rVec[connection.mnDestOrder] = { connection.msSourceId, sal_Int32(0) }; |
979 | 677 | } |
980 | 1.80k | } |
981 | | |
982 | | // assign outline levels |
983 | 107 | DiagramData_svx::StringMap& rStringMap = getPresOfNameMap(); |
984 | 107 | for (auto & elemPresOf : rStringMap) |
985 | 677 | { |
986 | 677 | for (auto & elem : elemPresOf.second) |
987 | 677 | { |
988 | 677 | const sal_Int32 nDepth = calcDepth(elem.second.msSourceId, getConnections()); |
989 | 677 | elem.second.mnDepth = nDepth != 0 ? nDepth : -1; |
990 | 677 | } |
991 | 677 | } |
992 | | #ifdef DEBUG_OOX_DIAGRAM |
993 | | output << "}" << std::endl; |
994 | | #endif |
995 | 107 | } |
996 | | |
997 | | } |
998 | | |
999 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |