1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "layoutatomvisitors.hxx"
22 #include <drawingml/customshapeproperties.hxx>
24 #include <sal/log.hxx>
26 using namespace ::com::sun::star
;
27 using namespace ::com::sun::star::xml::sax
;
29 namespace oox::drawingml
31 void ShapeCreationVisitor::visit(ConstraintAtom
& /*rAtom*/)
36 void ShapeCreationVisitor::visit(RuleAtom
& /*rAtom*/)
41 void ShapeCreationVisitor::visit(AlgAtom
& rAtom
)
43 if (meLookFor
== ALGORITHM
)
45 mpParentShape
->setAspectRatio(rAtom
.getAspectRatio());
46 mpParentShape
->setVerticalShapesCount(rAtom
.getVerticalShapesCount(mpParentShape
));
50 void ShapeCreationVisitor::visit(LayoutNode
& rAtom
)
52 if (meLookFor
!= LAYOUT_NODE
)
55 // stop processing if it's not a child of previous LayoutNode
57 const DiagramData::PointsNameMap::const_iterator aDataNode
58 = mrDgm
.getData()->getPointsPresNameMap().find(rAtom
.getName());
59 if (aDataNode
== mrDgm
.getData()->getPointsPresNameMap().end()
60 || mnCurrIdx
>= static_cast<sal_Int32
>(aDataNode
->second
.size()))
63 const svx::diagram::Point
* pNewNode
= aDataNode
->second
.at(mnCurrIdx
);
64 if (!mpCurrentNode
|| !pNewNode
)
67 bool bIsChild
= false;
68 for (const auto& aConnection
: mrDgm
.getData()->getConnections())
69 if (aConnection
.msSourceId
== mpCurrentNode
->msModelId
70 && aConnection
.msDestId
== pNewNode
->msModelId
)
76 ShapePtr
xCurrParent(mpParentShape
);
78 if (rAtom
.getExistingShape())
80 // reuse existing shape
81 ShapePtr pShape
= rAtom
.getExistingShape();
82 if (rAtom
.setupShape(pShape
, pNewNode
, mnCurrIdx
))
84 pShape
->setInternalName(rAtom
.getName());
85 rAtom
.addNodeShape(pShape
);
86 mrDgm
.getLayout()->getPresPointShapeMap()[pNewNode
] = std::move(pShape
);
91 ShapeTemplateVisitor
aTemplateVisitor(mrDgm
, pNewNode
);
92 aTemplateVisitor
.defaultVisit(rAtom
);
93 ShapePtr pShape
= aTemplateVisitor
.getShapeCopy();
97 SAL_INFO("oox.drawingml",
98 "processing shape type "
99 << (pShape
->getCustomShapeProperties()->getShapePresetType()));
101 if (rAtom
.setupShape(pShape
, pNewNode
, mnCurrIdx
))
103 pShape
->setInternalName(rAtom
.getName());
104 xCurrParent
->addChild(pShape
);
105 xCurrParent
= pShape
;
106 rAtom
.addNodeShape(pShape
);
107 mrDgm
.getLayout()->getPresPointShapeMap()[pNewNode
] = std::move(pShape
);
112 SAL_WARN("oox.drawingml",
113 "ShapeCreationVisitor::visit: no shape set while processing layoutnode named "
118 const svx::diagram::Point
* pPreviousNode
= mpCurrentNode
;
119 mpCurrentNode
= pNewNode
;
121 // set new parent for children
122 ShapePtr
xPreviousParent(mpParentShape
);
123 mpParentShape
= std::move(xCurrParent
);
126 meLookFor
= LAYOUT_NODE
;
129 meLookFor
= ALGORITHM
;
131 meLookFor
= LAYOUT_NODE
;
134 mpParentShape
= std::move(xPreviousParent
);
135 mpCurrentNode
= pPreviousNode
;
138 void ShapeCreationVisitor::visit(ShapeAtom
& /*rAtom*/)
143 void ShapeTemplateVisitor::visit(ConstraintAtom
& /*rAtom*/)
148 void ShapeTemplateVisitor::visit(RuleAtom
& /*rAtom*/)
153 void ShapeTemplateVisitor::visit(AlgAtom
& /*rAtom*/)
158 void ShapeTemplateVisitor::visit(ForEachAtom
& /*rAtom*/)
163 void ShapeTemplateVisitor::visit(LayoutNode
& /*rAtom*/)
165 // stop processing - only traverse Condition/Choose atoms
168 void ShapeTemplateVisitor::visit(ShapeAtom
& rAtom
)
172 SAL_WARN("oox.drawingml", "multiple shapes encountered inside LayoutNode");
176 const ShapePtr
& pCurrShape(rAtom
.getShapeTemplate());
178 // TODO(F3): cloned shape shares all properties by reference,
179 // don't change them!
180 mpShape
= std::make_shared
<Shape
>(pCurrShape
);
181 // Fill properties have to be changed as sometimes only the presentation node contains the blip
182 // fill, unshare those.
183 mpShape
->cloneFillProperties();
185 // add/set ModelID from current node to allow later association
187 mpShape
->setDiagramDataModelID(mpCurrentNode
->msModelId
);
190 void ShapeLayoutingVisitor::visit(ConstraintAtom
& rAtom
)
192 if (meLookFor
== CONSTRAINT
)
193 rAtom
.parseConstraint(maConstraints
, /*bRequireForName=*/true);
196 void ShapeLayoutingVisitor::visit(RuleAtom
& rAtom
)
198 if (meLookFor
== RULE
)
199 rAtom
.parseRule(maRules
);
202 void ShapeLayoutingVisitor::visit(AlgAtom
& rAtom
)
204 if (meLookFor
== ALGORITHM
)
206 const PresPointShapeMap aMap
207 = rAtom
.getLayoutNode().getDiagram().getLayout()->getPresPointShapeMap();
208 auto pShape
= aMap
.find(mpCurrentNode
);
209 if (pShape
!= aMap
.end())
210 rAtom
.layoutShape(pShape
->second
, maConstraints
, maRules
);
214 void ShapeLayoutingVisitor::visit(LayoutNode
& rAtom
)
216 if (meLookFor
!= LAYOUT_NODE
)
219 // stop processing if it's not a child of previous LayoutNode
221 const DiagramData::PointsNameMap::const_iterator aDataNode
222 = mrDgm
.getData()->getPointsPresNameMap().find(rAtom
.getName());
223 if (aDataNode
== mrDgm
.getData()->getPointsPresNameMap().end()
224 || mnCurrIdx
>= static_cast<sal_Int32
>(aDataNode
->second
.size()))
227 const svx::diagram::Point
* pNewNode
= aDataNode
->second
.at(mnCurrIdx
);
228 if (!mpCurrentNode
|| !pNewNode
)
231 bool bIsChild
= false;
232 for (const auto& aConnection
: mrDgm
.getData()->getConnections())
233 if (aConnection
.msSourceId
== mpCurrentNode
->msModelId
234 && aConnection
.msDestId
== pNewNode
->msModelId
)
240 size_t nParentConstraintsNumber
= maConstraints
.size();
242 const svx::diagram::Point
* pPreviousNode
= mpCurrentNode
;
243 mpCurrentNode
= pNewNode
;
245 // process alg atoms first, nested layout nodes afterwards
246 meLookFor
= CONSTRAINT
;
250 meLookFor
= ALGORITHM
;
252 meLookFor
= LAYOUT_NODE
;
255 mpCurrentNode
= pPreviousNode
;
257 // delete added constraints, keep parent constraints
258 maConstraints
.erase(maConstraints
.begin() + nParentConstraintsNumber
, maConstraints
.end());
261 void ShapeLayoutingVisitor::visit(ShapeAtom
& /*rAtom*/)
267 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */