Line data Source code
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 "diagramlayoutatoms.hxx"
21 :
22 : #include <functional>
23 : #include <boost/bind.hpp>
24 :
25 : #include <osl/diagnose.h>
26 : #include <basegfx/numeric/ftools.hxx>
27 :
28 : #include "oox/helper/attributelist.hxx"
29 : #include "oox/drawingml/fillproperties.hxx"
30 : #include "oox/drawingml/lineproperties.hxx"
31 : #include "drawingml/textbody.hxx"
32 : #include "drawingml/textparagraph.hxx"
33 : #include "drawingml/textrun.hxx"
34 : #include "drawingml/customshapeproperties.hxx"
35 : #include "layoutnodecontext.hxx"
36 :
37 : using namespace ::com::sun::star;
38 : using namespace ::com::sun::star::uno;
39 : using namespace ::com::sun::star::xml::sax;
40 : using namespace ::oox::core;
41 :
42 : namespace oox { namespace drawingml {
43 :
44 39 : IteratorAttr::IteratorAttr( )
45 : : mnAxis( 0 )
46 : , mnCnt( -1 )
47 : , mbHideLastTrans( false )
48 : , mnPtType( 0 )
49 : , mnSt( 0 )
50 39 : , mnStep( 1 )
51 : {
52 39 : }
53 :
54 59 : void IteratorAttr::loadFromXAttr( const Reference< XFastAttributeList >& xAttr )
55 : {
56 59 : AttributeList attr( xAttr );
57 59 : mnAxis = xAttr->getOptionalValueToken( XML_axis, 0 );
58 59 : mnCnt = attr.getInteger( XML_cnt, -1 );
59 59 : mbHideLastTrans = attr.getBool( XML_hideLastTrans, false );
60 59 : mnPtType = xAttr->getOptionalValueToken( XML_ptType, 0 );
61 59 : mnSt = attr.getInteger( XML_st, 0 );
62 59 : mnStep = attr.getInteger( XML_step, 1 );
63 59 : }
64 :
65 19 : ConditionAttr::ConditionAttr()
66 : : mnFunc( 0 )
67 : , mnArg( 0 )
68 19 : , mnOp( 0 )
69 : {
70 :
71 19 : }
72 :
73 19 : void ConditionAttr::loadFromXAttr( const Reference< XFastAttributeList >& xAttr )
74 : {
75 19 : mnFunc = xAttr->getOptionalValueToken( XML_func, 0 );
76 : // mnArg will be -1 for "none" or any other unknown value
77 19 : mnArg = LayoutNodeContext::tagToVarIdx( xAttr->getOptionalValueToken( XML_arg, XML_none ) );
78 19 : mnOp = xAttr->getOptionalValueToken( XML_op, 0 );
79 19 : msVal = xAttr->getOptionalValue( XML_val );
80 19 : }
81 :
82 292 : void LayoutAtom::dump(int level)
83 : {
84 : OSL_TRACE( "level = %d - %s of type %s", level,
85 : OUSTRING_TO_CSTR( msName ),
86 : typeid(*this).name() );
87 292 : const std::vector<LayoutAtomPtr>& pChildren=getChildren();
88 : std::for_each( pChildren.begin(), pChildren.end(),
89 292 : boost::bind( &LayoutAtom::dump, _1, level + 1 ) );
90 292 : }
91 :
92 20 : ForEachAtom::ForEachAtom(const Reference< XFastAttributeList >& xAttributes)
93 : {
94 20 : maIter.loadFromXAttr(xAttributes);
95 20 : }
96 :
97 83 : void ForEachAtom::accept( LayoutAtomVisitor& rVisitor )
98 : {
99 83 : rVisitor.visit(*this);
100 83 : }
101 :
102 53 : void ChooseAtom::accept( LayoutAtomVisitor& rVisitor )
103 : {
104 53 : rVisitor.visit(*this);
105 53 : }
106 :
107 19 : ConditionAtom::ConditionAtom(const Reference< XFastAttributeList >& xAttributes) :
108 19 : mbElse( false )
109 : {
110 19 : maIter.loadFromXAttr( xAttributes );
111 19 : maCond.loadFromXAttr( xAttributes );
112 19 : }
113 :
114 72 : const std::vector<LayoutAtomPtr>& ConditionAtom::getChildren() const
115 : {
116 72 : bool bDecisionVar=true;
117 : // HACK
118 72 : if( maCond.mnFunc == XML_var && maCond.mnArg == XML_dir && maCond.mnOp == XML_equ && maCond.msVal != "norm" )
119 0 : bDecisionVar=false;
120 :
121 72 : if( bDecisionVar )
122 72 : return mpChildNodes;
123 : else
124 0 : return mpElseChildNodes;
125 : }
126 :
127 53 : void ConditionAtom::accept( LayoutAtomVisitor& rVisitor )
128 : {
129 53 : rVisitor.visit(*this);
130 53 : }
131 :
132 74 : void ConditionAtom::addChild( const LayoutAtomPtr & pNode )
133 : {
134 74 : if( mbElse )
135 37 : mpElseChildNodes.push_back( pNode );
136 : else
137 37 : mpChildNodes.push_back( pNode );
138 74 : }
139 :
140 902 : void ConstraintAtom::accept( LayoutAtomVisitor& rVisitor )
141 : {
142 902 : rVisitor.visit(*this);
143 902 : }
144 :
145 352 : void AlgAtom::accept( LayoutAtomVisitor& rVisitor )
146 : {
147 352 : rVisitor.visit(*this);
148 352 : }
149 :
150 176 : void AlgAtom::layoutShape( const ShapePtr& rShape,
151 : const Diagram& /*rDgm*/,
152 : const OUString& rName ) const
153 : {
154 176 : switch(mnType)
155 : {
156 : case XML_composite:
157 : {
158 21 : if( rShape->getChildren().empty() )
159 : {
160 0 : rShape->setSize(awt::Size(50,50));
161 0 : break;
162 : }
163 :
164 : // just put stuff below each other
165 21 : const sal_Int32 nIncX=0;
166 21 : const sal_Int32 nIncY=1;
167 :
168 21 : std::vector<ShapePtr>::const_iterator aCurrShape=rShape->getChildren().begin();
169 21 : const std::vector<ShapePtr>::const_iterator aLastShape=rShape->getChildren().end();
170 :
171 : // find biggest shape
172 21 : awt::Size aMaxSize;
173 132 : while( aCurrShape != aLastShape )
174 : {
175 90 : const awt::Size& sz=(*aCurrShape)->getSize();
176 :
177 : aMaxSize.Width = std::max(
178 : aMaxSize.Width,
179 90 : sz.Width);
180 : aMaxSize.Height = std::max(
181 : aMaxSize.Height,
182 90 : sz.Height);
183 :
184 90 : ++aCurrShape;
185 : }
186 :
187 21 : aCurrShape=rShape->getChildren().begin();
188 21 : const awt::Point aStartPos=(*aCurrShape)->getPosition();
189 21 : awt::Point aCurrPos=aStartPos;
190 21 : awt::Size aTotalSize;
191 21 : aTotalSize.Width = aMaxSize.Width;
192 132 : while( aCurrShape != aLastShape )
193 : {
194 90 : const awt::Size& sz=(*aCurrShape)->getSize();
195 90 : (*aCurrShape)->setPosition(aCurrPos);
196 90 : (*aCurrShape)->setSize(
197 : awt::Size(aMaxSize.Width,
198 180 : sz.Height));
199 :
200 : aTotalSize.Height = std::max(
201 : aTotalSize.Height,
202 90 : aCurrPos.Y + sz.Height);
203 :
204 90 : aCurrPos.X += nIncX*sz.Width;
205 90 : aCurrPos.Y += nIncY*sz.Height;
206 :
207 90 : ++aCurrShape;
208 : }
209 :
210 21 : rShape->setSize(aTotalSize);
211 21 : break;
212 : }
213 :
214 : case XML_conn:
215 0 : break;
216 :
217 : case XML_cycle:
218 : {
219 0 : if( rShape->getChildren().empty() )
220 : {
221 0 : rShape->setSize(awt::Size(50,50));
222 0 : break;
223 : }
224 :
225 0 : const sal_Int32 nStartAngle=maMap.count(XML_stAng) ? maMap.find(XML_stAng)->second : 0;
226 0 : const sal_Int32 nSpanAngle=maMap.count(XML_spanAng) ? maMap.find(XML_spanAng)->second : 360;
227 :
228 0 : std::vector<ShapePtr>::const_iterator aCurrShape=rShape->getChildren().begin();
229 0 : const std::vector<ShapePtr>::const_iterator aLastShape=rShape->getChildren().end();
230 0 : const sal_Int32 nShapes=aLastShape-aCurrShape;
231 :
232 : // find biggest shape
233 0 : awt::Size aMaxSize;
234 0 : while( aCurrShape != aLastShape )
235 : {
236 0 : const awt::Size& sz=(*aCurrShape)->getSize();
237 :
238 : aMaxSize.Width = std::max(
239 : aMaxSize.Width,
240 0 : sz.Width);
241 : aMaxSize.Height = std::max(
242 : aMaxSize.Height,
243 0 : sz.Height);
244 :
245 0 : ++aCurrShape;
246 : }
247 :
248 : // layout shapes
249 0 : const sal_Int32 nMaxDim=std::max(aMaxSize.Width,aMaxSize.Height);
250 0 : awt::Size aTotalSize;
251 0 : aCurrShape=rShape->getChildren().begin();
252 0 : for( sal_Int32 i=0; i<nShapes; ++i, ++aCurrShape )
253 : {
254 0 : const awt::Size& sz=(*aCurrShape)->getSize();
255 :
256 0 : const double r=nShapes*nMaxDim/F_2PI * 360.0/nSpanAngle;
257 : const awt::Point aCurrPos(
258 0 : r + r*sin( (double(i)*nSpanAngle/nShapes + nStartAngle)*F_PI180 ),
259 0 : r - r*cos( (double(i)*nSpanAngle/nShapes + nStartAngle)*F_PI180 ) );
260 0 : (*aCurrShape)->setPosition(aCurrPos);
261 :
262 : aTotalSize.Width = std::max(
263 : aTotalSize.Width,
264 0 : aCurrPos.X + sz.Width);
265 : aTotalSize.Height = std::max(
266 : aTotalSize.Height,
267 0 : aCurrPos.Y + sz.Height);
268 : }
269 :
270 0 : rShape->setSize(aTotalSize);
271 0 : break;
272 : }
273 :
274 : case XML_hierChild:
275 : case XML_hierRoot:
276 0 : break;
277 :
278 : case XML_lin:
279 : {
280 3 : if( rShape->getChildren().empty() )
281 : {
282 0 : rShape->setSize(awt::Size(50,50));
283 0 : break;
284 : }
285 :
286 3 : const sal_Int32 nDir=maMap.count(XML_linDir) ? maMap.find(XML_linDir)->second : XML_fromL;
287 3 : const sal_Int32 nIncX=nDir==XML_fromL ? 1 : (nDir==XML_fromR ? -1 : 0);
288 3 : const sal_Int32 nIncY=nDir==XML_fromT ? 1 : (nDir==XML_fromB ? -1 : 0);
289 :
290 3 : std::vector<ShapePtr>::const_iterator aCurrShape=rShape->getChildren().begin();
291 3 : const std::vector<ShapePtr>::const_iterator aLastShape=rShape->getChildren().end();
292 3 : const awt::Point aStartPos=(*aCurrShape)->getPosition();
293 3 : awt::Point aCurrPos=aStartPos;
294 3 : awt::Size aTotalSize;
295 36 : while( aCurrShape != aLastShape )
296 : {
297 30 : const awt::Size& sz=(*aCurrShape)->getSize();
298 30 : (*aCurrShape)->setPosition(aCurrPos);
299 :
300 : aTotalSize.Width = std::max(
301 : aTotalSize.Width,
302 30 : aCurrPos.X + sz.Width);
303 : aTotalSize.Height = std::max(
304 : aTotalSize.Height,
305 30 : aCurrPos.Y + sz.Height);
306 :
307 : // HACK: the spacing is arbitrary
308 30 : aCurrPos.X += nIncX*(sz.Width+5);
309 30 : aCurrPos.Y += nIncY*(sz.Height+5);
310 :
311 30 : ++aCurrShape;
312 : }
313 :
314 3 : rShape->setSize(aTotalSize);
315 3 : break;
316 : }
317 :
318 : case XML_pyra:
319 : case XML_snake:
320 7 : break;
321 :
322 : case XML_sp:
323 : // HACK. Handled one level higher. Or rather, planned to
324 92 : break;
325 :
326 : case XML_tx:
327 : {
328 53 : TextBodyPtr pTextBody=rShape->getTextBody();
329 118 : if( !pTextBody ||
330 65 : pTextBody->getParagraphs().empty() ||
331 12 : pTextBody->getParagraphs().front()->getRuns().empty() )
332 : {
333 41 : rShape->setSize(awt::Size(5,5));
334 41 : break;
335 : }
336 :
337 : // HACK - count chars & paragraphs to come up with *some*
338 : // notion of necessary size
339 12 : const sal_Int32 nHackyFontHeight=50;
340 12 : const sal_Int32 nHackyFontWidth=20;
341 12 : awt::Size aTotalSize;
342 24 : for( size_t nPara=0; nPara<pTextBody->getParagraphs().size(); ++nPara )
343 : {
344 12 : aTotalSize.Height += nHackyFontHeight;
345 :
346 12 : sal_Int32 nLocalWidth=0;
347 24 : for( size_t nRun=0; nRun<pTextBody->getParagraphs().at(nPara)->getRuns().size(); ++nRun )
348 : nLocalWidth +=
349 12 : pTextBody->getParagraphs().at(nPara)->getRuns().at(nRun)->getText().getLength()
350 12 : * nHackyFontWidth;
351 :
352 : aTotalSize.Width = std::max(
353 : aTotalSize.Width,
354 12 : nLocalWidth);
355 : }
356 :
357 12 : rShape->setSize(aTotalSize);
358 : }
359 :
360 : default:
361 12 : break;
362 : }
363 :
364 : SAL_INFO(
365 : "oox.drawingml",
366 : "Layouting shape " << rName << ": (" << rShape->getPosition().X << ","
367 : << rShape->getPosition().Y << "," << rShape->getSize().Width << ","
368 : << rShape->getSize().Height << ")");
369 176 : }
370 :
371 256 : void LayoutNode::accept( LayoutAtomVisitor& rVisitor )
372 : {
373 256 : rVisitor.visit(*this);
374 256 : }
375 :
376 173 : bool LayoutNode::setupShape( const ShapePtr& rShape, const Diagram& rDgm, sal_uInt32 nIdx ) const
377 : {
378 : // find the data node to grab text from
379 173 : DiagramData::PointsNameMap::const_iterator aDataNode=rDgm.getData()->getPointsPresNameMap().find(msName);
380 346 : if( aDataNode != rDgm.getData()->getPointsPresNameMap().end() &&
381 173 : aDataNode->second.size() > nIdx )
382 : {
383 : SAL_INFO(
384 : "oox.drawingml",
385 : "Filling content from " << nIdx << "th layout node named \""
386 : << msName << "\", modelId \""
387 : << aDataNode->second.at(nIdx)->msModelId << "\"");
388 :
389 : // got the presentation node - now, need the actual data node:
390 298 : const DiagramData::StringMap::const_iterator aNodeName=rDgm.getData()->getPresOfNameMap().find(
391 298 : aDataNode->second.at(nIdx)->msModelId);
392 149 : if( aNodeName != rDgm.getData()->getPresOfNameMap().end() )
393 : {
394 57 : DiagramData::StringMap::value_type::second_type::const_iterator aVecIter=aNodeName->second.begin();
395 57 : const DiagramData::StringMap::value_type::second_type::const_iterator aVecEnd=aNodeName->second.end();
396 171 : while( aVecIter != aVecEnd )
397 : {
398 57 : DiagramData::PointNameMap& rMap = rDgm.getData()->getPointNameMap();
399 57 : DiagramData::PointNameMap::const_iterator aDataNode2 = rMap.find(aVecIter->first);
400 57 : if (aDataNode2 == rMap.end())
401 : {
402 : //busted, skip it
403 1 : ++aVecIter;
404 1 : continue;
405 : }
406 :
407 56 : if( aVecIter->second == 0 )
408 : {
409 : // grab shape attr from topmost element(s)
410 0 : rShape->getShapeProperties() = aDataNode2->second->mpShape->getShapeProperties();
411 0 : rShape->getLineProperties() = aDataNode2->second->mpShape->getLineProperties();
412 0 : rShape->getFillProperties() = aDataNode2->second->mpShape->getFillProperties();
413 0 : rShape->getCustomShapeProperties() = aDataNode2->second->mpShape->getCustomShapeProperties();
414 0 : rShape->setMasterTextListStyle( aDataNode2->second->mpShape->getMasterTextListStyle() );
415 :
416 : SAL_INFO(
417 : "oox.drawingml",
418 : "Custom shape with preset type "
419 : << (rShape->getCustomShapeProperties()
420 : ->getShapePresetType())
421 : << " added for layout node named \"" << msName
422 : << "\"");
423 : }
424 :
425 : // append text with right outline level
426 274 : if( aDataNode2->second->mpShape->getTextBody() &&
427 383 : !aDataNode2->second->mpShape->getTextBody()->getParagraphs().empty() &&
428 162 : !aDataNode2->second->mpShape->getTextBody()->getParagraphs().front()->getRuns().empty() )
429 : {
430 12 : TextBodyPtr pTextBody=rShape->getTextBody();
431 12 : if( !pTextBody )
432 : {
433 12 : pTextBody.reset( new TextBody() );
434 :
435 : // also copy text attrs
436 12 : pTextBody->getTextListStyle() =
437 24 : aDataNode2->second->mpShape->getTextBody()->getTextListStyle();
438 12 : pTextBody->getTextProperties() =
439 24 : aDataNode2->second->mpShape->getTextBody()->getTextProperties();
440 :
441 12 : rShape->setTextBody(pTextBody);
442 : }
443 :
444 12 : TextParagraph& rPara=pTextBody->addParagraph();
445 12 : if( aVecIter->second != -1 )
446 12 : rPara.getProperties().setLevel(aVecIter->second);
447 :
448 : rPara.addRun(
449 12 : aDataNode2->second->mpShape->getTextBody()->getParagraphs().front()->getRuns().front());
450 12 : rPara.getProperties().apply(
451 24 : aDataNode2->second->mpShape->getTextBody()->getParagraphs().front()->getProperties());
452 : }
453 :
454 56 : ++aVecIter;
455 : }
456 : }
457 : else
458 : {
459 : SAL_INFO(
460 : "oox.drawingml",
461 : "ShapeCreationVisitor::visit: no data node name found while"
462 : " processing shape type "
463 : << rShape->getCustomShapeProperties()->getShapePresetType()
464 : << " for layout node named \"" << msName << "\"");
465 : }
466 :
467 : // TODO(Q1): apply styling & coloring - taking
468 : // layout node's styleLbl for both style & color
469 : // now, but docs are a bit unclear on this
470 149 : if( !msStyleLabel.isEmpty() )
471 : {
472 : SAL_INFO(
473 : "oox.drawingml", "setting style with label " << msStyleLabel);
474 :
475 12 : const DiagramQStyleMap::const_iterator aStyle=rDgm.getStyles().find(msStyleLabel);
476 12 : if( aStyle != rDgm.getStyles().end() )
477 : {
478 12 : rShape->getShapeStyleRefs()[XML_fillRef] = aStyle->second.maFillStyle;
479 : SAL_INFO(
480 : "oox.drawingml",
481 : "added fill style with id "
482 : << aStyle->second.maFillStyle.mnThemedIdx);
483 12 : rShape->getShapeStyleRefs()[XML_lnRef] = aStyle->second.maLineStyle;
484 : SAL_INFO(
485 : "oox.drawingml",
486 : "added line style with id "
487 : << aStyle->second.maLineStyle.mnThemedIdx);
488 12 : rShape->getShapeStyleRefs()[XML_effectRef] = aStyle->second.maEffectStyle;
489 : SAL_INFO(
490 : "oox.drawingml",
491 : "added effect style with id "
492 : << aStyle->second.maEffectStyle.mnThemedIdx);
493 12 : rShape->getShapeStyleRefs()[XML_fontRef] = aStyle->second.maTextStyle;
494 : SAL_INFO(
495 : "oox.drawingml",
496 : "added fontref style with id "
497 : << aStyle->second.maTextStyle.mnThemedIdx);
498 12 : Color aColor=aStyle->second.maTextStyle.maPhClr;
499 12 : OSL_TRACE("added fontref color with alpha %d", aColor.getTransparency() );
500 : }
501 :
502 12 : const DiagramColorMap::const_iterator aColor=rDgm.getColors().find(msStyleLabel);
503 12 : if( aColor != rDgm.getColors().end() )
504 : {
505 12 : const DiagramColor& rColor=aColor->second;
506 12 : if( rColor.maFillColor.isUsed() )
507 12 : rShape->getShapeStyleRefs()[XML_fillRef].maPhClr = rColor.maFillColor;
508 12 : if( rColor.maLineColor.isUsed() )
509 12 : rShape->getShapeStyleRefs()[XML_lnRef].maPhClr = rColor.maLineColor;
510 12 : if( rColor.maEffectColor.isUsed() )
511 0 : rShape->getShapeStyleRefs()[XML_effectRef].maPhClr = rColor.maEffectColor;
512 12 : if( rColor.maTextFillColor.isUsed() )
513 12 : rShape->getShapeStyleRefs()[XML_fontRef].maPhClr = rColor.maTextFillColor;
514 : }
515 : }
516 :
517 : // even if no data node found, successful anyway. it's
518 : // contained at the layoutnode
519 149 : return true;
520 : }
521 : else
522 : {
523 : SAL_INFO(
524 : "oox.drawingml",
525 : "no text found while processing shape type "
526 : << rShape->getCustomShapeProperties()->getShapePresetType()
527 : << " for layout node named \"" << msName << "\"");
528 : }
529 :
530 24 : return false;
531 : }
532 :
533 : // Visitation
534 :
535 176 : class ShapeLayoutingVisitor : public LayoutAtomVisitor
536 : {
537 : ShapePtr mpParentShape;
538 : const Diagram& mrDgm;
539 : OUString maName;
540 :
541 : virtual void visit(ConstraintAtom& rAtom) SAL_OVERRIDE;
542 : virtual void visit(AlgAtom& rAtom) SAL_OVERRIDE;
543 : virtual void visit(ForEachAtom& rAtom) SAL_OVERRIDE;
544 : virtual void visit(ConditionAtom& rAtom) SAL_OVERRIDE;
545 : virtual void visit(ChooseAtom& rAtom) SAL_OVERRIDE;
546 : virtual void visit(LayoutNode& rAtom) SAL_OVERRIDE;
547 :
548 : public:
549 176 : ShapeLayoutingVisitor(const ShapePtr& rParentShape,
550 : const Diagram& rDgm,
551 : const OUString& rName) :
552 : mpParentShape(rParentShape),
553 : mrDgm(rDgm),
554 176 : maName(rName)
555 176 : {}
556 :
557 : void defaultVisit(LayoutAtom& rAtom);
558 : };
559 :
560 10 : class ShallowPresNameVisitor : public LayoutAtomVisitor
561 : {
562 : const Diagram& mrDgm;
563 : size_t mnCnt;
564 :
565 : void defaultVisit(LayoutAtom& rAtom);
566 : virtual void visit(ConstraintAtom& rAtom) SAL_OVERRIDE;
567 : virtual void visit(AlgAtom& rAtom) SAL_OVERRIDE;
568 : virtual void visit(ForEachAtom& rAtom) SAL_OVERRIDE;
569 : virtual void visit(ConditionAtom& rAtom) SAL_OVERRIDE;
570 : virtual void visit(ChooseAtom& rAtom) SAL_OVERRIDE;
571 : virtual void visit(LayoutNode& rAtom) SAL_OVERRIDE;
572 :
573 : public:
574 10 : explicit ShallowPresNameVisitor(const Diagram& rDgm) :
575 : mrDgm(rDgm),
576 10 : mnCnt(0)
577 10 : {}
578 :
579 10 : size_t getCount() const
580 10 : { return mnCnt; }
581 : };
582 :
583 420 : void ShapeCreationVisitor::defaultVisit(LayoutAtom& rAtom)
584 : {
585 420 : const std::vector<LayoutAtomPtr>& pChildren=rAtom.getChildren();
586 : std::for_each( pChildren.begin(), pChildren.end(),
587 : boost::bind( &LayoutAtom::accept,
588 : _1,
589 420 : boost::ref(*this)) );
590 420 : }
591 :
592 451 : void ShapeCreationVisitor::visit(ConstraintAtom& /*rAtom*/)
593 : {
594 : // TODO: eval the constraints
595 451 : }
596 :
597 176 : void ShapeCreationVisitor::visit(AlgAtom& rAtom)
598 : {
599 176 : defaultVisit(rAtom);
600 176 : }
601 :
602 63 : void ShapeCreationVisitor::visit(ForEachAtom& rAtom)
603 : {
604 63 : const std::vector<LayoutAtomPtr>& pChildren=rAtom.getChildren();
605 :
606 63 : sal_Int32 nChildren=1;
607 63 : if( rAtom.iterator().mnPtType == XML_node )
608 : {
609 : // cound child data nodes - check all child Atoms for "name"
610 : // attribute that is contained in diagram's
611 : // getPointsPresNameMap()
612 10 : ShallowPresNameVisitor aVisitor(mrDgm);
613 : std::for_each( pChildren.begin(), pChildren.end(),
614 : boost::bind( &LayoutAtom::accept,
615 : _1,
616 10 : boost::ref(aVisitor)) );
617 10 : nChildren = aVisitor.getCount();
618 : }
619 :
620 : const sal_Int32 nCnt = std::min(
621 : nChildren,
622 63 : rAtom.iterator().mnCnt==-1 ? nChildren : rAtom.iterator().mnCnt);
623 :
624 63 : const sal_Int32 nOldIdx=mnCurrIdx;
625 63 : const sal_Int32 nStep=rAtom.iterator().mnStep;
626 169 : for( mnCurrIdx=0; mnCurrIdx<nCnt && nStep>0; mnCurrIdx+=nStep )
627 : {
628 : // TODO there is likely some conditions
629 : std::for_each( pChildren.begin(), pChildren.end(),
630 : boost::bind( &LayoutAtom::accept,
631 : _1,
632 106 : boost::ref(*this)) );
633 : }
634 :
635 : // and restore idx
636 63 : mnCurrIdx = nOldIdx;
637 63 : }
638 :
639 34 : void ShapeCreationVisitor::visit(ConditionAtom& rAtom)
640 : {
641 34 : defaultVisit(rAtom);
642 34 : }
643 :
644 34 : void ShapeCreationVisitor::visit(ChooseAtom& rAtom)
645 : {
646 34 : defaultVisit(rAtom);
647 34 : }
648 :
649 176 : void ShapeCreationVisitor::visit(LayoutNode& rAtom)
650 : {
651 176 : ShapePtr pCurrParent(mpParentShape);
652 352 : ShapePtr pCurrShape(rAtom.getShape());
653 176 : if( pCurrShape )
654 : {
655 : SAL_INFO(
656 : "oox.drawingml",
657 : "processing shape type "
658 : << (pCurrShape->getCustomShapeProperties()
659 : ->getShapePresetType()));
660 :
661 : // TODO(F3): cloned shape shares all properties by reference,
662 : // don't change them!
663 : ShapePtr pClonedShape(
664 173 : new Shape( pCurrShape ));
665 :
666 173 : if( rAtom.setupShape(pClonedShape, mrDgm, mnCurrIdx) )
667 : {
668 149 : pCurrParent->addChild(pClonedShape);
669 149 : pCurrParent = pClonedShape;
670 173 : }
671 : }
672 : else
673 : {
674 : OSL_TRACE("ShapeCreationVisitor::visit: no shape set while processing layoutnode named %s",
675 : OUSTRING_TO_CSTR( rAtom.getName() ) );
676 : }
677 :
678 : // set new parent for children
679 352 : ShapePtr pPreviousParent(mpParentShape);
680 176 : mpParentShape=pCurrParent;
681 :
682 : // process children
683 176 : defaultVisit(rAtom);
684 :
685 : // restore parent
686 176 : mpParentShape=pPreviousParent;
687 :
688 : // layout shapes - now all child shapes are created
689 : ShapeLayoutingVisitor aLayoutingVisitor(pCurrParent,
690 : mrDgm,
691 352 : rAtom.getName());
692 352 : aLayoutingVisitor.defaultVisit(rAtom);
693 176 : }
694 :
695 208 : void ShapeLayoutingVisitor::defaultVisit(LayoutAtom& rAtom)
696 : {
697 : // visit all children, one of them needs to be the layout algorithm
698 208 : const std::vector<LayoutAtomPtr>& pChildren=rAtom.getChildren();
699 : std::for_each( pChildren.begin(), pChildren.end(),
700 : boost::bind( &LayoutAtom::accept,
701 : _1,
702 208 : boost::ref(*this)) );
703 208 : }
704 :
705 451 : void ShapeLayoutingVisitor::visit(ConstraintAtom& /*rAtom*/)
706 : {
707 : // stop processing
708 451 : }
709 :
710 176 : void ShapeLayoutingVisitor::visit(AlgAtom& rAtom)
711 : {
712 176 : rAtom.layoutShape(mpParentShape,mrDgm,maName);
713 176 : }
714 :
715 10 : void ShapeLayoutingVisitor::visit(ForEachAtom& /*rAtom*/)
716 : {
717 : // stop processing
718 10 : }
719 :
720 16 : void ShapeLayoutingVisitor::visit(ConditionAtom& rAtom)
721 : {
722 16 : defaultVisit(rAtom);
723 16 : }
724 :
725 16 : void ShapeLayoutingVisitor::visit(ChooseAtom& rAtom)
726 : {
727 16 : defaultVisit(rAtom);
728 16 : }
729 :
730 60 : void ShapeLayoutingVisitor::visit(LayoutNode& /*rAtom*/)
731 : {
732 : // stop processing - only traverse Condition/Choose atoms
733 60 : }
734 :
735 16 : void ShallowPresNameVisitor::defaultVisit(LayoutAtom& rAtom)
736 : {
737 : // visit all children, at least one of them needs to have proper
738 : // name set
739 16 : const std::vector<LayoutAtomPtr>& pChildren=rAtom.getChildren();
740 : std::for_each( pChildren.begin(), pChildren.end(),
741 : boost::bind( &LayoutAtom::accept,
742 : _1,
743 16 : boost::ref(*this)) );
744 16 : }
745 :
746 0 : void ShallowPresNameVisitor::visit(ConstraintAtom& /*rAtom*/)
747 : {
748 : // stop processing
749 0 : }
750 :
751 0 : void ShallowPresNameVisitor::visit(AlgAtom& /*rAtom*/)
752 : {
753 : // stop processing
754 0 : }
755 :
756 10 : void ShallowPresNameVisitor::visit(ForEachAtom& rAtom)
757 : {
758 10 : defaultVisit(rAtom);
759 10 : }
760 :
761 3 : void ShallowPresNameVisitor::visit(ConditionAtom& rAtom)
762 : {
763 3 : defaultVisit(rAtom);
764 3 : }
765 :
766 3 : void ShallowPresNameVisitor::visit(ChooseAtom& rAtom)
767 : {
768 3 : defaultVisit(rAtom);
769 3 : }
770 :
771 20 : void ShallowPresNameVisitor::visit(LayoutNode& rAtom)
772 : {
773 : DiagramData::PointsNameMap::const_iterator aDataNode=
774 20 : mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
775 20 : if( aDataNode != mrDgm.getData()->getPointsPresNameMap().end() )
776 : mnCnt = std::max(mnCnt,
777 20 : aDataNode->second.size());
778 20 : }
779 :
780 246 : } }
781 :
782 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|