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