oox/source/drawingml/diagram/diagram.cxx | 6 oox/source/drawingml/diagram/diagramfragmenthandler.cxx | 10 oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 247 ++++++---------- oox/source/drawingml/diagram/diagramlayoutatoms.hxx | 24 + oox/source/drawingml/diagram/layoutatomvisitors.cxx | 148 +++++++-- oox/source/drawingml/diagram/layoutatomvisitors.hxx | 35 +- oox/source/drawingml/diagram/layoutnodecontext.cxx | 32 -- 7 files changed, 286 insertions(+), 216 deletions(-)
New commits: commit 558ded72d2a39fd0eac1f3f375b446c72b7141e5 Author: Grzegorz Araminowicz <g.araminow...@gmail.com> Date: Wed Jul 19 22:08:38 2017 +0200 SmartArt: shape styling Change-Id: I7e9ab4c2286fd803cd518dd01ab8ebd5ac2d8428 diff --git a/oox/source/drawingml/diagram/diagramfragmenthandler.cxx b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx index a85fe611dd18..1ad24270477e 100644 --- a/oox/source/drawingml/diagram/diagramfragmenthandler.cxx +++ b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx @@ -122,7 +122,7 @@ DiagramQStylesFragmentHandler::DiagramQStylesFragmentHandler( XmlFilterBase& rFi const AttributeList& rAttribs ) { // state-table like way of navigating the color fragment. we - // currently ignore everything except styleLbl in the colorsDef + // currently ignore everything except styleLbl in the styleDef // element switch( getCurrentElement() ) { @@ -136,16 +136,16 @@ DiagramQStylesFragmentHandler::DiagramQStylesFragmentHandler( XmlFilterBase& rFi { switch( nElement ) { - case DGM_TOKEN(lnRef) : // CT_StyleMatrixReference + case A_TOKEN(lnRef): // CT_StyleMatrixReference return createStyleMatrixContext(nElement,rAttribs, maStyleEntry.maLineStyle); - case DGM_TOKEN(fillRef) : // CT_StyleMatrixReference + case A_TOKEN(fillRef): // CT_StyleMatrixReference return createStyleMatrixContext(nElement,rAttribs, maStyleEntry.maFillStyle); - case DGM_TOKEN(effectRef) : // CT_StyleMatrixReference + case A_TOKEN(effectRef): // CT_StyleMatrixReference return createStyleMatrixContext(nElement,rAttribs, maStyleEntry.maEffectStyle); - case DGM_TOKEN(fontRef) : // CT_FontRe ference + case A_TOKEN(fontRef): // CT_FontReference return createStyleMatrixContext(nElement,rAttribs, maStyleEntry.maTextStyle); } diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 1bad1f0f4ece..fef4ad22e44a 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -320,15 +320,16 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const Diagram& rDgm, sal_uI if( aDataNode != rDgm.getData()->getPointsPresNameMap().end() && aDataNode->second.size() > nIdx ) { + const dgm::Point* aPresNode = aDataNode->second.at(nIdx); SAL_INFO( "oox.drawingml", "Filling content from " << nIdx << "th layout node named \"" << msName << "\", modelId \"" - << aDataNode->second.at(nIdx)->msModelId << "\""); + << aPresNode->msModelId << "\""); // got the presentation node - now, need the actual data node: const DiagramData::StringMap::const_iterator aNodeName=rDgm.getData()->getPresOfNameMap().find( - aDataNode->second.at(nIdx)->msModelId); + aPresNode->msModelId); if( aNodeName != rDgm.getData()->getPresOfNameMap().end() ) { DiagramData::StringMap::value_type::second_type::const_iterator aVecIter=aNodeName->second.begin(); @@ -404,22 +405,30 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const Diagram& rDgm, sal_uI << " for layout node named \"" << msName << "\""); } - // TODO(Q1): apply styling & coloring - taking - // layout node's styleLbl for both style & color - // now, but docs are a bit unclear on this - if( !msStyleLabel.isEmpty() ) + // TODO(Q1): apply styling & coloring - take presentation + // point's presStyleLbl for both style & color + // if not found use layout node's styleLbl + // however, docs are a bit unclear on this + OUString aStyleLabel = aPresNode->msPresentationLayoutStyleLabel; + if (aStyleLabel.isEmpty()) + aStyleLabel = msStyleLabel; + if( !aStyleLabel.isEmpty() ) { - const DiagramQStyleMap::const_iterator aStyle=rDgm.getStyles().find(msStyleLabel); + const DiagramQStyleMap::const_iterator aStyle = rDgm.getStyles().find(aStyleLabel); if( aStyle != rDgm.getStyles().end() ) { - rShape->getShapeStyleRefs()[XML_fillRef] = aStyle->second.maFillStyle; - rShape->getShapeStyleRefs()[XML_lnRef] = aStyle->second.maLineStyle; - rShape->getShapeStyleRefs()[XML_effectRef] = aStyle->second.maEffectStyle; - rShape->getShapeStyleRefs()[XML_fontRef] = aStyle->second.maTextStyle; - Color aColor=aStyle->second.maTextStyle.maPhClr; + const DiagramStyle& rStyle = aStyle->second; + rShape->getShapeStyleRefs()[XML_fillRef] = rStyle.maFillStyle; + rShape->getShapeStyleRefs()[XML_lnRef] = rStyle.maLineStyle; + rShape->getShapeStyleRefs()[XML_effectRef] = rStyle.maEffectStyle; + rShape->getShapeStyleRefs()[XML_fontRef] = rStyle.maTextStyle; + } + else + { + SAL_WARN("oox.drawingml", "Style " << aStyleLabel << " not found"); } - const DiagramColorMap::const_iterator aColor=rDgm.getColors().find(msStyleLabel); + const DiagramColorMap::const_iterator aColor = rDgm.getColors().find(aStyleLabel); if( aColor != rDgm.getColors().end() ) { const DiagramColor& rColor=aColor->second; @@ -433,12 +442,6 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const Diagram& rDgm, sal_uI rShape->getShapeStyleRefs()[XML_fontRef].maPhClr = rColor.maTextFillColor; } } - else - { - // if no style label apply at least some fill color - rShape->getShapeStyleRefs()[XML_fillRef].maPhClr.setScrgbClr(0, 0, 0); - rShape->getShapeStyleRefs()[XML_fillRef].mnThemedIdx = 2; - } // even if no data node found, successful anyway. it's // contained at the layoutnode commit 47e52b47845265ba126c30eba149e90689538b93 Author: Grzegorz Araminowicz <g.araminow...@gmail.com> Date: Thu Jul 13 18:39:42 2017 +0200 SmartArt: more layout work * basic layout algorithms implementation * change layouting order to "from top" Change-Id: I8ef397fa0e39bb6d8cda2d1387b663980f134a59 diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 533156bbfb86..175df73e9420 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -328,7 +328,11 @@ void Diagram::addTo( const ShapePtr & pParentShape ) // create Shape hierarchy ShapeCreationVisitor aCreationVisitor(pParentShape, *this); mpLayout->getNode()->setExistingShape(pParentShape); - mpLayout->getNode()->accept( aCreationVisitor ); + mpLayout->getNode()->accept(aCreationVisitor); + + // layout shapes - now all shapes are created + ShapeLayoutingVisitor aLayoutingVisitor; + mpLayout->getNode()->accept(aLayoutingVisitor); } pParentShape->setDiagramDoms( getDomsAsPropertyValues() ); } diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index daf0edf52c5a..1bad1f0f4ece 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -149,59 +149,13 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, { case XML_composite: { - if( rShape->getChildren().empty() ) - { - rShape->setSize(awt::Size(50,50)); - break; - } - - // just put stuff below each other - const sal_Int32 nIncX=0; - const sal_Int32 nIncY=1; - - std::vector<ShapePtr>::const_iterator aCurrShape=rShape->getChildren().begin(); - const std::vector<ShapePtr>::const_iterator aLastShape=rShape->getChildren().end(); - - // find biggest shape - awt::Size aMaxSize; - while( aCurrShape != aLastShape ) - { - const awt::Size& sz=(*aCurrShape)->getSize(); - - aMaxSize.Width = std::max( - aMaxSize.Width, - sz.Width); - aMaxSize.Height = std::max( - aMaxSize.Height, - sz.Height); + // all shapes fill parent - ++aCurrShape; - } - - aCurrShape=rShape->getChildren().begin(); - const awt::Point aStartPos=(*aCurrShape)->getPosition(); - awt::Point aCurrPos=aStartPos; - awt::Size aTotalSize; - aTotalSize.Width = aMaxSize.Width; - while( aCurrShape != aLastShape ) + for (auto & aCurrShape : rShape->getChildren()) { - const awt::Size& sz=(*aCurrShape)->getSize(); - (*aCurrShape)->setPosition(aCurrPos); - (*aCurrShape)->setSize( - awt::Size(aMaxSize.Width, - sz.Height)); - - aTotalSize.Height = std::max( - aTotalSize.Height, - aCurrPos.Y + sz.Height); - - aCurrPos.X += nIncX*sz.Width; - aCurrPos.Y += nIncY*sz.Height; - - ++aCurrShape; + aCurrShape->setSize(rShape->getSize()); + aCurrShape->setChildSize(rShape->getSize()); } - - rShape->setSize(aTotalSize); break; } @@ -210,11 +164,8 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, case XML_cycle: { - if( rShape->getChildren().empty() ) - { - rShape->setSize(awt::Size(50,50)); + if (rShape->getChildren().empty()) break; - } const sal_Int32 nStartAngle=maMap.count(XML_stAng) ? maMap.find(XML_stAng)->second : 0; const sal_Int32 nSpanAngle=maMap.count(XML_spanAng) ? maMap.find(XML_spanAng)->second : 360; @@ -241,27 +192,15 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, // layout shapes const sal_Int32 nMaxDim=std::max(aMaxSize.Width,aMaxSize.Height); - awt::Size aTotalSize; aCurrShape=rShape->getChildren().begin(); for( sal_Int32 i=0; i<nShapes; ++i, ++aCurrShape ) { - const awt::Size& sz=(*aCurrShape)->getSize(); - const double r=nShapes*nMaxDim/F_2PI * 360.0/nSpanAngle; const awt::Point aCurrPos( r + r*sin( (double(i)*nSpanAngle/nShapes + nStartAngle)*F_PI180 ), r - r*cos( (double(i)*nSpanAngle/nShapes + nStartAngle)*F_PI180 ) ); (*aCurrShape)->setPosition(aCurrPos); - - aTotalSize.Width = std::max( - aTotalSize.Width, - aCurrPos.X + sz.Width); - aTotalSize.Height = std::max( - aTotalSize.Height, - aCurrPos.Y + sz.Height); } - - rShape->setSize(aTotalSize); break; } @@ -270,97 +209,103 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, break; case XML_lin: - case XML_snake: { - if( rShape->getChildren().empty() ) - { - rShape->setSize(awt::Size(50,50)); + // spread childres evenly across one axis, strech across second + + if (rShape->getChildren().empty() || rShape->getSize().Width == 0 || rShape->getSize().Height == 0) break; - } - const sal_Int32 nDir=maMap.count(XML_linDir) ? maMap.find(XML_linDir)->second : XML_fromL; - const sal_Int32 nIncX=nDir==XML_fromL ? 1 : (nDir==XML_fromR ? -1 : 0); - const sal_Int32 nIncY=nDir==XML_fromT ? 1 : (nDir==XML_fromB ? -1 : 0); + const sal_Int32 nDir = maMap.count(XML_linDir) ? maMap.find(XML_linDir)->second : XML_fromL; + const sal_Int32 nIncX = nDir==XML_fromL ? 1 : (nDir==XML_fromR ? -1 : 0); + const sal_Int32 nIncY = nDir==XML_fromT ? 1 : (nDir==XML_fromB ? -1 : 0); - std::vector<ShapePtr>::const_iterator aCurrShape=rShape->getChildren().begin(); - const std::vector<ShapePtr>::const_iterator aLastShape=rShape->getChildren().end(); - const awt::Point aStartPos=(*aCurrShape)->getPosition(); - awt::Point aCurrPos=aStartPos; - awt::Size aTotalSize; - while( aCurrShape != aLastShape ) - { - const awt::Size& sz=(*aCurrShape)->getSize(); - (*aCurrShape)->setPosition(aCurrPos); + // TODO: get values from constraints + sal_Int32 nCount = rShape->getChildren().size(); + double fSpace = 0.3; - aTotalSize.Width = std::max( - aTotalSize.Width, - aCurrPos.X + sz.Width); - aTotalSize.Height = std::max( - aTotalSize.Height, - aCurrPos.Y + sz.Height); + awt::Size aChildSize = rShape->getSize(); + if (nIncX) + aChildSize.Width /= (nCount + (nCount-1)*fSpace); + if (nIncY) + aChildSize.Height /= (nCount + (nCount-1)*fSpace); - // HACK: the spacing is arbitrary - aCurrPos.X += nIncX*(sz.Width+5); - aCurrPos.Y += nIncY*(sz.Height+5); - - ++aCurrShape; + awt::Point aCurrPos = rShape->getChildren().front()->getPosition(); + for (auto & aCurrShape : rShape->getChildren()) + { + aCurrShape->setPosition(aCurrPos); + aCurrShape->setSize(aChildSize); + aCurrShape->setChildSize(aChildSize); + aCurrPos.X += nIncX * (aChildSize.Width + fSpace*aChildSize.Width); + aCurrPos.Y += nIncY * (aChildSize.Height + fSpace*aChildSize.Height); } - - rShape->setSize(aTotalSize); break; } case XML_pyra: break; - case XML_sp: - // HACK. Handled one level higher. Or rather, planned to - break; - - case XML_tx: + case XML_snake: { - TextBodyPtr pTextBody=rShape->getTextBody(); - if( !pTextBody || - pTextBody->getParagraphs().empty() || - pTextBody->getParagraphs().front()->getRuns().empty() ) - { - rShape->setSize(awt::Size(5,5)); + // find optimal grid to layout children that have fixed aspect ratio + + if (rShape->getChildren().empty() || rShape->getSize().Width == 0 || rShape->getSize().Height == 0) break; - } - // HACK - count chars & paragraphs to come up with *some* - // notion of necessary size - const sal_Int32 nHackyFontHeight=50; - const sal_Int32 nHackyFontWidth=20; - awt::Size aTotalSize; - for( size_t nPara=0; nPara<pTextBody->getParagraphs().size(); ++nPara ) + // TODO: get values from constraints + sal_Int32 nCount = rShape->getChildren().size(); + double fSpace = 0.3; + double fAspectRatio = 0.6; + + sal_Int32 nCol = 1; + sal_Int32 nRow = 1; + for ( ; nCol<nCount; nCol++) { - aTotalSize.Height += nHackyFontHeight; + nRow = (nCount+nCol-1) / nCol; + if ((rShape->getSize().Height / nRow) / (rShape->getSize().Width / nCol) >= fAspectRatio) + break; + } + SAL_INFO("oox.drawingml", "Snake layout grid: " << nCol << "x" << nRow); - sal_Int32 nLocalWidth=0; - for( size_t nRun=0; nRun<pTextBody->getParagraphs().at(nPara)->getRuns().size(); ++nRun ) - nLocalWidth += - pTextBody->getParagraphs().at(nPara)->getRuns().at(nRun)->getText().getLength() - * nHackyFontWidth; + sal_Int32 nWidth = rShape->getSize().Width / (nCol + (nCol-1)*fSpace); + const awt::Size aChildSize(nWidth, nWidth * fAspectRatio); - aTotalSize.Width = std::max( - aTotalSize.Width, - nLocalWidth); - } + awt::Point aStartPos = rShape->getChildren().front()->getPosition(); + awt::Point aCurrPos = aStartPos; + sal_Int32 nColIdx = 0; - rShape->setSize(aTotalSize); + for (auto & aCurrShape : rShape->getChildren()) + { + aCurrShape->setPosition(aCurrPos); + aCurrShape->setSize(aChildSize); + aCurrShape->setChildSize(aChildSize); + aCurrPos.X += aChildSize.Width + fSpace*aChildSize.Width; + if (++nColIdx == nCol) + { + aStartPos.Y += aChildSize.Height + fSpace*aChildSize.Height; + aCurrPos = aStartPos; + nColIdx = 0; + } + } break; } + case XML_sp: + // HACK. Handled one level higher. Or rather, planned to + break; + + case XML_tx: + // TODO: adjust text size to fit shape + break; + default: break; } SAL_INFO( "oox.drawingml", - "Layouting shape " << rName << ": (" << rShape->getPosition().X << "," - << rShape->getPosition().Y << "," << rShape->getSize().Width << "," - << rShape->getSize().Height << ")"); + "Layouting shape " << rName << ", alg type: " << mnType << ", (" + << rShape->getPosition().X << "," << rShape->getPosition().Y << "," + << rShape->getSize().Width << "," << rShape->getSize().Height << ")"); } void LayoutNode::accept( LayoutAtomVisitor& rVisitor ) diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx index 7a168528c0ec..a6123ccbd62c 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx @@ -242,6 +242,8 @@ public: { mpExistingShape = pShape; } const ShapePtr& getExistingShape() const { return mpExistingShape; } + std::vector<ShapePtr> & getNodeShapes() + { return mpNodeShapes; } bool setupShape( const ShapePtr& rShape, const Diagram& rDgm, @@ -252,6 +254,7 @@ private: OUString msMoveWith; OUString msStyleLabel; ShapePtr mpExistingShape; + std::vector<ShapePtr> mpNodeShapes; sal_Int32 mnChildOrder; }; diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx index ade7e4ccfec9..a580da73ff32 100755 --- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx @@ -97,7 +97,9 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom) if (rAtom.getExistingShape()) { - rAtom.setupShape(rAtom.getExistingShape(), mrDgm, mnCurrIdx); + // reuse existing shape + if (rAtom.setupShape(rAtom.getExistingShape(), mrDgm, mnCurrIdx)) + rAtom.getNodeShapes().push_back(rAtom.getExistingShape()); } else { @@ -117,6 +119,7 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom) { pCurrParent->addChild(pShape); pCurrParent = pShape; + rAtom.getNodeShapes().push_back(pShape); } } else @@ -135,10 +138,11 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom) // restore parent mpParentShape=pPreviousParent; - // layout shapes - now all child shapes are created - ShapeLayoutingVisitor aLayoutingVisitor(pCurrParent, - rAtom.getName()); - aLayoutingVisitor.defaultVisit(rAtom); + // remove unneeded empty group shapes + pCurrParent->getChildren().erase( + std::remove_if(pCurrParent->getChildren().begin(), pCurrParent->getChildren().end(), + [] (const ShapePtr & aChild) { return aChild->getServiceName() == "com.sun.star.drawing.GroupShape" && aChild->getChildren().empty(); }), + pCurrParent->getChildren().end()); } void ShapeCreationVisitor::visit(ShapeAtom& /*rAtom*/) @@ -212,12 +216,16 @@ void ShapeLayoutingVisitor::visit(ConstraintAtom& /*rAtom*/) void ShapeLayoutingVisitor::visit(AlgAtom& rAtom) { - rAtom.layoutShape(mpParentShape, maName); + if (mbLookForAlg && mpCurrentLayoutNode) + { + for (const auto& pShape : mpCurrentLayoutNode->getNodeShapes()) + rAtom.layoutShape(pShape, mpCurrentLayoutNode->getName()); + } } -void ShapeLayoutingVisitor::visit(ForEachAtom& /*rAtom*/) +void ShapeLayoutingVisitor::visit(ForEachAtom& rAtom) { - // stop processing + defaultVisit(rAtom); } void ShapeLayoutingVisitor::visit(ConditionAtom& rAtom) @@ -230,9 +238,21 @@ void ShapeLayoutingVisitor::visit(ChooseAtom& rAtom) defaultVisit(rAtom); } -void ShapeLayoutingVisitor::visit(LayoutNode& /*rAtom*/) +void ShapeLayoutingVisitor::visit(LayoutNode& rAtom) { - // stop processing - only traverse Condition/Choose atoms + if (mbLookForAlg) + return; + + LayoutNode* pPreviousLayoutNode = mpCurrentLayoutNode; + mpCurrentLayoutNode = &rAtom; + + // process alg atoms first, nested layout nodes afterwards + mbLookForAlg = true; + defaultVisit(rAtom); + mbLookForAlg = false; + defaultVisit(rAtom); + + mpCurrentLayoutNode = pPreviousLayoutNode; } void ShapeLayoutingVisitor::visit(ShapeAtom& /*rAtom*/) diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.hxx b/oox/source/drawingml/diagram/layoutatomvisitors.hxx index 28558f69bb24..3ffef36d8954 100755 --- a/oox/source/drawingml/diagram/layoutatomvisitors.hxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.hxx @@ -72,9 +72,10 @@ public: class ShapeLayoutingVisitor : public LayoutAtomVisitor { - ShapePtr mpParentShape; - OUString maName; + LayoutNode* mpCurrentLayoutNode; + bool mbLookForAlg; + void defaultVisit(LayoutAtom& rAtom); virtual void visit(ConstraintAtom& rAtom) override; virtual void visit(AlgAtom& rAtom) override; virtual void visit(ForEachAtom& rAtom) override; @@ -84,13 +85,10 @@ class ShapeLayoutingVisitor : public LayoutAtomVisitor virtual void visit(ShapeAtom& rAtom) override; public: - ShapeLayoutingVisitor(const ShapePtr& rParentShape, - const OUString& rName) : - mpParentShape(rParentShape), - maName(rName) + ShapeLayoutingVisitor() : + mpCurrentLayoutNode(nullptr), + mbLookForAlg(false) {} - - void defaultVisit(LayoutAtom& rAtom); }; class ShallowPresNameVisitor : public LayoutAtomVisitor commit 21f28f94744b4378ba45b1361870592dd7cfabb2 Author: Grzegorz Araminowicz <g.araminow...@gmail.com> Date: Sat Jul 1 14:10:53 2017 +0200 SmartArt: add ShapeAtom to store shape template instead of LayoutNode it allows to load shapes inside choose/if Change-Id: I8040967d1f769796f6ad6b2d0c7b5ce698f89ee3 diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index d32e2f963b59..daf0edf52c5a 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -511,6 +511,11 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const Diagram& rDgm, sal_uI return false; } +void ShapeAtom::accept( LayoutAtomVisitor& rVisitor ) +{ + rVisitor.visit(*this); +} + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx index d5b9fcdf9e29..7a168528c0ec 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx @@ -238,12 +238,8 @@ public: { msStyleLabel = sLabel; } void setChildOrder( sal_Int32 nOrder ) { mnChildOrder = nOrder; } - void setShapeTemplate( const ShapePtr& pShape ) - { mpShapeTemplate = pShape; } void setExistingShape( const ShapePtr& pShape ) { mpExistingShape = pShape; } - const ShapePtr& getShapeTemplate() const - { return mpShapeTemplate; } const ShapePtr& getExistingShape() const { return mpExistingShape; } @@ -255,13 +251,27 @@ private: VarMap mVariables; OUString msMoveWith; OUString msStyleLabel; - ShapePtr mpShapeTemplate; ShapePtr mpExistingShape; sal_Int32 mnChildOrder; }; typedef std::shared_ptr< LayoutNode > LayoutNodePtr; +class ShapeAtom + : public LayoutAtom +{ +public: + ShapeAtom(const ShapePtr& pShape) : mpShapeTemplate(pShape) {} + virtual void accept( LayoutAtomVisitor& ) override; + const ShapePtr& getShapeTemplate() const + { return mpShapeTemplate; } + +private: + ShapePtr mpShapeTemplate; +}; + +typedef std::shared_ptr< ShapeAtom > ShapeAtomPtr; + struct LayoutAtomVisitor { virtual ~LayoutAtomVisitor() {} @@ -271,6 +281,7 @@ struct LayoutAtomVisitor virtual void visit(ConditionAtom& rAtom) = 0; virtual void visit(ChooseAtom& rAtom) = 0; virtual void visit(LayoutNode& rAtom) = 0; + virtual void visit(ShapeAtom& rAtom) = 0; }; } } diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx index fd6e9d7b7e1b..ade7e4ccfec9 100755 --- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx @@ -94,34 +94,35 @@ void ShapeCreationVisitor::visit(ChooseAtom& rAtom) void ShapeCreationVisitor::visit(LayoutNode& rAtom) { ShapePtr pCurrParent(mpParentShape); - ShapePtr pCurrShape(rAtom.getShapeTemplate()); if (rAtom.getExistingShape()) { rAtom.setupShape(rAtom.getExistingShape(), mrDgm, mnCurrIdx); } - else if( pCurrShape ) + else { - SAL_INFO( - "oox.drawingml", - "processing shape type " - << (pCurrShape->getCustomShapeProperties() - ->getShapePresetType())); - - // TODO(F3): cloned shape shares all properties by reference, - // don't change them! - ShapePtr pClonedShape( - new Shape( pCurrShape )); - - if( rAtom.setupShape(pClonedShape, mrDgm, mnCurrIdx) ) + ShapeTemplateVisitor aTemplateVisitor; + aTemplateVisitor.defaultVisit(rAtom); + ShapePtr pShape = aTemplateVisitor.getShapeCopy(); + + if (pShape) { - pCurrParent->addChild(pClonedShape); - pCurrParent = pClonedShape; + SAL_INFO( + "oox.drawingml", + "processing shape type " + << (pShape->getCustomShapeProperties() + ->getShapePresetType())); + + if (rAtom.setupShape(pShape, mrDgm, mnCurrIdx)) + { + pCurrParent->addChild(pShape); + pCurrParent = pShape; + } + } + else + { + SAL_WARN("oox.drawingml", "ShapeCreationVisitor::visit: no shape set while processing layoutnode named " << rAtom.getName()); } - } - else - { - SAL_WARN("oox.drawingml", "ShapeCreationVisitor::visit: no shape set while processing layoutnode named " << rAtom.getName() ); } // set new parent for children @@ -140,6 +141,63 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom) aLayoutingVisitor.defaultVisit(rAtom); } +void ShapeCreationVisitor::visit(ShapeAtom& /*rAtom*/) +{ + // stop processing +} + +void ShapeTemplateVisitor::defaultVisit(LayoutAtom& rAtom) +{ + // visit all children, one of them needs to be the layout algorithm + for (const auto& pAtom : rAtom.getChildren()) + pAtom->accept(*this); +} + +void ShapeTemplateVisitor::visit(ConstraintAtom& /*rAtom*/) +{ + // stop processing +} + +void ShapeTemplateVisitor::visit(AlgAtom& /*rAtom*/) +{ + // stop processing +} + +void ShapeTemplateVisitor::visit(ForEachAtom& /*rAtom*/) +{ + // stop processing +} + +void ShapeTemplateVisitor::visit(ConditionAtom& rAtom) +{ + defaultVisit(rAtom); +} + +void ShapeTemplateVisitor::visit(ChooseAtom& rAtom) +{ + defaultVisit(rAtom); +} + +void ShapeTemplateVisitor::visit(LayoutNode& /*rAtom*/) +{ + // stop processing - only traverse Condition/Choose atoms +} + +void ShapeTemplateVisitor::visit(ShapeAtom& rAtom) +{ + if (mpShape) + { + SAL_WARN("oox.drawingml", "multiple shapes encountered inside LayoutNode"); + return; + } + + ShapePtr pCurrShape(rAtom.getShapeTemplate()); + + // TODO(F3): cloned shape shares all properties by reference, + // don't change them! + mpShape.reset(new Shape(pCurrShape)); +} + void ShapeLayoutingVisitor::defaultVisit(LayoutAtom& rAtom) { // visit all children, one of them needs to be the layout algorithm @@ -177,6 +235,11 @@ void ShapeLayoutingVisitor::visit(LayoutNode& /*rAtom*/) // stop processing - only traverse Condition/Choose atoms } +void ShapeLayoutingVisitor::visit(ShapeAtom& /*rAtom*/) +{ + // stop processing +} + void ShallowPresNameVisitor::defaultVisit(LayoutAtom& rAtom) { // visit all children, at least one of them needs to have proper @@ -219,6 +282,11 @@ void ShallowPresNameVisitor::visit(LayoutNode& rAtom) aDataNode->second.size()); } +void ShallowPresNameVisitor::visit(ShapeAtom& /*rAtom*/) +{ + // stop processing +} + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.hxx b/oox/source/drawingml/diagram/layoutatomvisitors.hxx index 9353f4ba0a4b..28558f69bb24 100755 --- a/oox/source/drawingml/diagram/layoutatomvisitors.hxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.hxx @@ -41,6 +41,7 @@ class ShapeCreationVisitor : public LayoutAtomVisitor virtual void visit(ConditionAtom& rAtom) override; virtual void visit(ChooseAtom& rAtom) override; virtual void visit(LayoutNode& rAtom) override; + virtual void visit(ShapeAtom& rAtom) override; public: ShapeCreationVisitor(const ShapePtr& rParentShape, @@ -51,6 +52,24 @@ public: {} }; +class ShapeTemplateVisitor : public LayoutAtomVisitor +{ + ShapePtr mpShape; + + virtual void visit(ConstraintAtom& rAtom) override; + virtual void visit(AlgAtom& rAtom) override; + virtual void visit(ForEachAtom& rAtom) override; + virtual void visit(ConditionAtom& rAtom) override; + virtual void visit(ChooseAtom& rAtom) override; + virtual void visit(LayoutNode& rAtom) override; + virtual void visit(ShapeAtom& rAtom) override; + +public: + void defaultVisit(LayoutAtom& rAtom); + ShapePtr getShapeCopy() const + { return mpShape; } +}; + class ShapeLayoutingVisitor : public LayoutAtomVisitor { ShapePtr mpParentShape; @@ -62,6 +81,7 @@ class ShapeLayoutingVisitor : public LayoutAtomVisitor virtual void visit(ConditionAtom& rAtom) override; virtual void visit(ChooseAtom& rAtom) override; virtual void visit(LayoutNode& rAtom) override; + virtual void visit(ShapeAtom& rAtom) override; public: ShapeLayoutingVisitor(const ShapePtr& rParentShape, @@ -85,6 +105,7 @@ class ShallowPresNameVisitor : public LayoutAtomVisitor virtual void visit(ConditionAtom& rAtom) override; virtual void visit(ChooseAtom& rAtom) override; virtual void visit(LayoutNode& rAtom) override; + virtual void visit(ShapeAtom& rAtom) override; public: explicit ShallowPresNameVisitor(const Diagram& rDgm) : diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx index 5d66de142c96..715e94d72eab 100644 --- a/oox/source/drawingml/diagram/layoutnodecontext.cxx +++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx @@ -246,31 +246,23 @@ LayoutNodeContext::onCreateContext( ::sal_Int32 aElement, } case DGM_TOKEN( shape ): { - LayoutNodePtr pNode(std::dynamic_pointer_cast<LayoutNode>(mpNode)); - if( pNode ) - { - ShapePtr pShape; - - if( rAttribs.hasAttribute( XML_type ) ) - { - pShape.reset( new Shape("com.sun.star.drawing.CustomShape") ); - const sal_Int32 nType(rAttribs.getToken( XML_type, XML_obj )); - pShape->setSubType( nType ); - pShape->getCustomShapeProperties()->setShapePresetType( nType ); - } - else - { - pShape.reset( new Shape("com.sun.star.drawing.GroupShape") ); - } + ShapePtr pShape; - pNode->setShapeTemplate( pShape ); - return new ShapeContext( *this, ShapePtr(), pShape ); + if( rAttribs.hasAttribute( XML_type ) ) + { + pShape.reset( new Shape("com.sun.star.drawing.CustomShape") ); + const sal_Int32 nType(rAttribs.getToken( XML_type, XML_obj )); + pShape->setSubType( nType ); + pShape->getCustomShapeProperties()->setShapePresetType( nType ); } else { - SAL_WARN("oox", "OOX: encountered a shape in a non layoutNode context" ); + pShape.reset( new Shape("com.sun.star.drawing.GroupShape") ); } - break; + + ShapeAtomPtr pAtom( new ShapeAtom(pShape) ); + mpNode->addChild( pAtom ); + return new ShapeContext( *this, ShapePtr(), pShape ); } case DGM_TOKEN( extLst ): return nullptr; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits