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