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