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 "layoutnodecontext.hxx"
21
22 #include <oox/helper/attributelist.hxx>
23 #include <oox/drawingml/shapecontext.hxx>
24 #include <drawingml/customshapeproperties.hxx>
25 #include "constraintlistcontext.hxx"
26 #include "rulelistcontext.hxx"
27 #include <oox/token/namespaces.hxx>
28 #include <oox/token/tokens.hxx>
29 #include <sal/log.hxx>
30
31 using namespace ::oox::core;
32 using namespace ::com::sun::star::uno;
33 using namespace ::com::sun::star::xml::sax;
34
35 namespace oox::drawingml {
36
37 namespace {
38
39 class IfContext
40 : public LayoutNodeContext
41 {
42 public:
IfContext(ContextHandler2Helper const & rParent,const AttributeList & rAttribs,const ConditionAtomPtr & pAtom)43 IfContext( ContextHandler2Helper const & rParent,
44 const AttributeList& rAttribs,
45 const ConditionAtomPtr& pAtom )
46 : LayoutNodeContext( rParent, rAttribs, pAtom )
47 {}
48 };
49
50 class AlgorithmContext
51 : public ContextHandler2
52 {
53 public:
AlgorithmContext(ContextHandler2Helper const & rParent,const AttributeList & rAttribs,const AlgAtomPtr & pNode)54 AlgorithmContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, const AlgAtomPtr & pNode )
55 : ContextHandler2( rParent )
56 , mnRevision( 0 )
57 , mpNode( pNode )
58 {
59 mnRevision = rAttribs.getInteger( XML_rev, 0 );
60 pNode->setType(rAttribs.getToken(XML_type, 0));
61 }
62
63 virtual ContextHandlerRef
onCreateContext(::sal_Int32 aElement,const AttributeList & rAttribs)64 onCreateContext( ::sal_Int32 aElement,
65 const AttributeList& rAttribs ) override
66 {
67 switch( aElement )
68 {
69 case DGM_TOKEN( param ):
70 {
71 sal_Int32 nType = rAttribs.getToken(XML_type, 0);
72 switch (nType)
73 {
74 case XML_ar:
75 mpNode->setAspectRatio(rAttribs.getDouble(XML_val, 0));
76 break;
77 default:
78 const sal_Int32 nValTok = rAttribs.getToken(XML_val, 0);
79 mpNode->addParam(nType, nValTok > 0 ? nValTok
80 : rAttribs.getInteger(XML_val, 0));
81 break;
82 }
83 break;
84 }
85 default:
86 break;
87 }
88
89 return this;
90 }
91
92 private:
93 sal_Int32 mnRevision;
94 AlgAtomPtr mpNode;
95 };
96
97 class ChooseContext
98 : public ContextHandler2
99 {
100 public:
ChooseContext(ContextHandler2Helper const & rParent,const AttributeList & rAttribs,const LayoutAtomPtr & pNode)101 ChooseContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, const LayoutAtomPtr & pNode )
102 : ContextHandler2( rParent )
103 , mpNode( pNode )
104 {
105 msName = rAttribs.getString( XML_name ).get();
106 }
107
108 virtual ContextHandlerRef
onCreateContext(::sal_Int32 aElement,const AttributeList & rAttribs)109 onCreateContext( ::sal_Int32 aElement,
110 const AttributeList& rAttribs ) override
111 {
112 switch( aElement )
113 {
114 case DGM_TOKEN( if ):
115 {
116 // CT_When
117 ConditionAtomPtr pNode = std::make_shared<ConditionAtom>(mpNode->getLayoutNode(), false, rAttribs.getFastAttributeList());
118 LayoutAtom::connect(mpNode, pNode);
119 return new IfContext( *this, rAttribs, pNode );
120 }
121 case DGM_TOKEN( else ):
122 {
123 // CT_Otherwise
124 ConditionAtomPtr pNode = std::make_shared<ConditionAtom>(mpNode->getLayoutNode(), true, rAttribs.getFastAttributeList());
125 LayoutAtom::connect(mpNode, pNode);
126 return new IfContext( *this, rAttribs, pNode );
127 }
128 default:
129 break;
130 }
131
132 return this;
133 }
134 private:
135 OUString msName;
136 LayoutAtomPtr mpNode;
137 };
138
139 class ForEachContext
140 : public LayoutNodeContext
141 {
142 public:
ForEachContext(ContextHandler2Helper const & rParent,const AttributeList & rAttribs,const ForEachAtomPtr & pAtom)143 ForEachContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, const ForEachAtomPtr& pAtom )
144 : LayoutNodeContext( rParent, rAttribs, pAtom )
145 {
146 pAtom->setRef(rAttribs.getString(XML_ref).get());
147 pAtom->iterator().loadFromXAttr( rAttribs.getFastAttributeList() );
148
149 LayoutAtomMap& rLayoutAtomMap = pAtom->getLayoutNode().getDiagram().getLayout()->getLayoutAtomMap();
150 rLayoutAtomMap[pAtom->getName()] = pAtom;
151 }
152 };
153
154 // CT_LayoutVariablePropertySet
155 class LayoutVariablePropertySetContext
156 : public ContextHandler2
157 {
158 public:
LayoutVariablePropertySetContext(ContextHandler2Helper const & rParent,LayoutNode::VarMap & aVar)159 LayoutVariablePropertySetContext( ContextHandler2Helper const & rParent, LayoutNode::VarMap & aVar )
160 : ContextHandler2( rParent )
161 , mVariables( aVar )
162 {
163 }
164
onCreateContext(::sal_Int32 aElement,const AttributeList & rAttribs)165 virtual ContextHandlerRef onCreateContext( ::sal_Int32 aElement, const AttributeList& rAttribs ) override
166 {
167 mVariables[ getBaseToken(aElement) ] = rAttribs.getString( XML_val ).get();
168 return this;
169 }
170 private:
171 LayoutNode::VarMap & mVariables;
172 };
173
174 }
175
176 // CT_LayoutNode
LayoutNodeContext(ContextHandler2Helper const & rParent,const AttributeList & rAttribs,const LayoutAtomPtr & pAtom)177 LayoutNodeContext::LayoutNodeContext( ContextHandler2Helper const & rParent,
178 const AttributeList& rAttribs,
179 const LayoutAtomPtr& pAtom )
180 : ContextHandler2( rParent )
181 , mpNode( pAtom )
182 {
183 assert( pAtom && "Node must NOT be NULL" );
184 mpNode->setName( rAttribs.getString( XML_name ).get() );
185 }
186
~LayoutNodeContext()187 LayoutNodeContext::~LayoutNodeContext()
188 {
189 }
190
191 ContextHandlerRef
onCreateContext(::sal_Int32 aElement,const AttributeList & rAttribs)192 LayoutNodeContext::onCreateContext( ::sal_Int32 aElement,
193 const AttributeList& rAttribs )
194 {
195 switch( aElement )
196 {
197 case DGM_TOKEN( layoutNode ):
198 {
199 LayoutNodePtr pNode = std::make_shared<LayoutNode>(mpNode->getLayoutNode().getDiagram());
200 LayoutAtom::connect(mpNode, pNode);
201
202 if (rAttribs.hasAttribute(XML_chOrder))
203 {
204 pNode->setChildOrder(rAttribs.getToken(XML_chOrder, XML_b));
205 }
206 else
207 {
208 for (LayoutAtomPtr pAtom = mpNode; pAtom; pAtom = pAtom->getParent())
209 {
210 auto pLayoutNode = dynamic_cast<LayoutNode*>(pAtom.get());
211 if (pLayoutNode)
212 {
213 pNode->setChildOrder(pLayoutNode->getChildOrder());
214 break;
215 }
216 }
217 }
218
219 pNode->setMoveWith( rAttribs.getString( XML_moveWith ).get() );
220 pNode->setStyleLabel( rAttribs.getString( XML_styleLbl ).get() );
221 return new LayoutNodeContext( *this, rAttribs, pNode );
222 }
223 case DGM_TOKEN( shape ):
224 {
225 ShapePtr pShape;
226
227 if( rAttribs.hasAttribute( XML_type ) )
228 {
229 pShape = std::make_shared<Shape>("com.sun.star.drawing.CustomShape");
230 if (!rAttribs.getBool(XML_hideGeom, false))
231 {
232 const sal_Int32 nType(rAttribs.getToken( XML_type, XML_obj ));
233 pShape->setSubType( nType );
234 pShape->getCustomShapeProperties()->setShapePresetType( nType );
235 }
236 }
237 else
238 {
239 pShape = std::make_shared<Shape>("com.sun.star.drawing.GroupShape");
240 }
241
242 pShape->setDiagramRotation(rAttribs.getInteger(XML_rot, 0) * PER_DEGREE);
243
244 pShape->setZOrderOff(rAttribs.getInteger(XML_zOrderOff, 0));
245
246 ShapeAtomPtr pAtom = std::make_shared<ShapeAtom>(mpNode->getLayoutNode(), pShape);
247 LayoutAtom::connect(mpNode, pAtom);
248 return new ShapeContext( *this, ShapePtr(), pShape );
249 }
250 case DGM_TOKEN( extLst ):
251 return nullptr;
252 case DGM_TOKEN( alg ):
253 {
254 // CT_Algorithm
255 AlgAtomPtr pAtom = std::make_shared<AlgAtom>(mpNode->getLayoutNode());
256 LayoutAtom::connect(mpNode, pAtom);
257 return new AlgorithmContext( *this, rAttribs, pAtom );
258 }
259 case DGM_TOKEN( choose ):
260 {
261 // CT_Choose
262 LayoutAtomPtr pAtom = std::make_shared<ChooseAtom>(mpNode->getLayoutNode());
263 LayoutAtom::connect(mpNode, pAtom);
264 return new ChooseContext( *this, rAttribs, pAtom );
265 }
266 case DGM_TOKEN( forEach ):
267 {
268 // CT_ForEach
269 ForEachAtomPtr pAtom = std::make_shared<ForEachAtom>(mpNode->getLayoutNode(), rAttribs.getFastAttributeList());
270 LayoutAtom::connect(mpNode, pAtom);
271 return new ForEachContext( *this, rAttribs, pAtom );
272 }
273 case DGM_TOKEN( constrLst ):
274 // CT_Constraints
275 return new ConstraintListContext( *this, mpNode );
276 case DGM_TOKEN( presOf ):
277 {
278 // CT_PresentationOf
279 // TODO
280 IteratorAttr aIterator;
281 aIterator.loadFromXAttr(rAttribs.getFastAttributeList());
282 break;
283 }
284 case DGM_TOKEN( ruleLst ):
285 // CT_Rules
286 return new RuleListContext( *this, mpNode );
287 case DGM_TOKEN( varLst ):
288 {
289 LayoutNodePtr pNode(std::dynamic_pointer_cast<LayoutNode>(mpNode));
290 if( pNode )
291 {
292 return new LayoutVariablePropertySetContext( *this, pNode->variables() );
293 }
294 else
295 {
296 SAL_WARN("oox", "OOX: encountered a varLst in a non layoutNode context" );
297 }
298 break;
299 }
300 default:
301 break;
302 }
303
304 return this;
305 }
306
307 }
308
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
310