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