Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */