summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorGrzegorz Araminowicz <grzegorz.araminowicz@collabora.com>2019-06-26 10:42:28 +0200
committerGrzegorz Araminowicz <grzegorz.araminowicz@collabora.com>2019-07-11 08:33:52 +0200
commit100b6232b4a0cea8aea852d55dfc850b510bdf1f (patch)
treee00905a442f9d0205dbb0cf737ea64faabaa2233 /oox
parent583a3140c01e6140022b846e6b067c2846812e56 (diff)
SmartArt: all visitors follow data presentation nodes
* visitors now are keeping track of current presentation node instead of looking it up by name * extracted visitor base class that follows if/else and for-each nodes * moved condition logic from ConditionAtom to visitor, as it depends on visitor state Change-Id: Iede86cd74a6098f2398a77b6cb3e9c6272dbfe4b Reviewed-on: https://gerrit.libreoffice.org/74732 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/75390 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Grzegorz Araminowicz <grzegorz.araminowicz@collabora.com>
Diffstat (limited to 'oox')
-rw-r--r--oox/Library_oox.mk1
-rw-r--r--oox/source/drawingml/diagram/diagram.cxx7
-rw-r--r--oox/source/drawingml/diagram/diagram.hxx4
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.cxx130
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.hxx26
-rw-r--r--oox/source/drawingml/diagram/layoutatomvisitorbase.cxx173
-rw-r--r--oox/source/drawingml/diagram/layoutatomvisitorbase.hxx99
-rw-r--r--oox/source/drawingml/diagram/layoutatomvisitors.cxx197
-rw-r--r--oox/source/drawingml/diagram/layoutatomvisitors.hxx93
9 files changed, 403 insertions, 327 deletions
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index f924d27543ba..34976d7ac35b 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -144,6 +144,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
oox/source/drawingml/diagram/diagramdefinitioncontext \
oox/source/drawingml/diagram/diagramfragmenthandler \
oox/source/drawingml/diagram/diagramlayoutatoms \
+ oox/source/drawingml/diagram/layoutatomvisitorbase \
oox/source/drawingml/diagram/layoutatomvisitors \
oox/source/drawingml/diagram/layoutnodecontext \
oox/source/drawingml/drawingmltypes \
diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx
index be49c85d40aa..c53b983526a9 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -347,15 +347,16 @@ void Diagram::addTo( const ShapePtr & pParentShape )
pParentShape->setChildSize(pParentShape->getSize());
- if( mpLayout->getNode() )
+ const dgm::Point* pRootPoint = mpData->getRootPoint();
+ if (mpLayout->getNode() && pRootPoint)
{
// create Shape hierarchy
- ShapeCreationVisitor aCreationVisitor(pParentShape, *this);
+ ShapeCreationVisitor aCreationVisitor(*this, pRootPoint, pParentShape);
mpLayout->getNode()->setExistingShape(pParentShape);
mpLayout->getNode()->accept(aCreationVisitor);
// layout shapes - now all shapes are created
- ShapeLayoutingVisitor aLayoutingVisitor;
+ ShapeLayoutingVisitor aLayoutingVisitor(*this, pRootPoint);
mpLayout->getNode()->accept(aLayoutingVisitor);
sortChildrenByZOrder(pParentShape);
diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx
index c5b8ec10eaf6..2e4ceae304c8 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -208,6 +208,7 @@ private:
typedef std::shared_ptr< DiagramData > DiagramDataPtr;
typedef std::map<OUString, LayoutAtomPtr> LayoutAtomMap;
+typedef std::map<const dgm::Point*, ShapePtr> PresPointShapeMap;
class DiagramLayout
{
@@ -239,6 +240,8 @@ public:
{ return mpStyleData; }
LayoutAtomMap & getLayoutAtomMap()
{ return maLayoutAtomMap; }
+ PresPointShapeMap & getPresPointShapeMap()
+ { return maPresPointShapeMap; }
private:
const Diagram& mrDgm;
@@ -256,6 +259,7 @@ private:
// clrData
LayoutAtomMap maLayoutAtomMap;
+ PresPointShapeMap maPresPointShapeMap;
};
typedef std::shared_ptr< DiagramLayout > DiagramLayoutPtr;
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 909efaebf751..b5c7a23738f7 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -19,6 +19,8 @@
#include "diagramlayoutatoms.hxx"
+#include "layoutatomvisitorbase.hxx"
+
#include <basegfx/numeric/ftools.hxx>
#include <sal/log.hxx>
@@ -300,17 +302,6 @@ void ChooseAtom::accept( LayoutAtomVisitor& rVisitor )
rVisitor.visit(*this);
}
-const std::vector<LayoutAtomPtr>& ChooseAtom::getChildren() const
-{
- for (const auto& pChild : mpChildNodes)
- {
- const ConditionAtomPtr pCond = std::dynamic_pointer_cast<ConditionAtom>(pChild);
- if (pCond && pCond->getDecision())
- return pCond->getChildren();
- }
- return maEmptyChildren;
-}
-
ConditionAtom::ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const Reference< XFastAttributeList >& xAttributes) :
LayoutAtom(rLayoutNode),
mIsElse(isElse)
@@ -335,18 +326,6 @@ bool ConditionAtom::compareResult(sal_Int32 nOperator, sal_Int32 nFirst, sal_Int
}
}
-const dgm::Point* ConditionAtom::getPresNode() const
-{
- const DiagramData::PointsNameMap& rPoints = mrLayoutNode.getDiagram().getData()->getPointsPresNameMap();
- DiagramData::PointsNameMap::const_iterator aDataNode = rPoints.find(mrLayoutNode.getName());
- if (aDataNode != rPoints.end())
- {
- SAL_WARN_IF(aDataNode->second.size() > 1, "oox.drawingml", "multiple nodes found; taking first one");
- return aDataNode->second.front();
- }
- return nullptr;
-}
-
namespace
{
/**
@@ -377,71 +356,63 @@ OUString navigate(const LayoutNode& rLayoutNode, sal_Int32 nType, const OUString
}
}
-sal_Int32 ConditionAtom::getNodeCount() const
+sal_Int32 ConditionAtom::getNodeCount(const dgm::Point* pPresPoint) const
{
sal_Int32 nCount = 0;
- const dgm::Point* pPoint = getPresNode();
- if (pPoint)
- {
- OUString sNodeId = "";
+ OUString sNodeId = navigate(mrLayoutNode, XML_presOf, pPresPoint->msModelId, /*bSourceToDestination*/ false);
- sNodeId
- = navigate(mrLayoutNode, XML_presOf, pPoint->msModelId, /*bSourceToDestination*/ false);
-
- if (sNodeId.isEmpty())
- {
- // The current layout node is not a presentation of anything. Look
- // up the first presentation child of the layout node.
- OUString sFirstPresChildId = navigate(mrLayoutNode, XML_presParOf, pPoint->msModelId,
- /*bSourceToDestination*/ true);
- if (!sFirstPresChildId.isEmpty())
- // It has a presentation child: is that a presentation of a
- // model node?
- sNodeId = navigate(mrLayoutNode, XML_presOf, sFirstPresChildId,
- /*bSourceToDestination*/ false);
- }
+ if (sNodeId.isEmpty())
+ {
+ // The current layout node is not a presentation of anything. Look
+ // up the first presentation child of the layout node.
+ OUString sFirstPresChildId = navigate(mrLayoutNode, XML_presParOf, pPresPoint->msModelId,
+ /*bSourceToDestination*/ true);
+ if (!sFirstPresChildId.isEmpty())
+ // It has a presentation child: is that a presentation of a
+ // model node?
+ sNodeId = navigate(mrLayoutNode, XML_presOf, sFirstPresChildId,
+ /*bSourceToDestination*/ false);
+ }
- if (!sNodeId.isEmpty())
- {
- for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections())
- if (aCxn.mnType == XML_parOf && aCxn.msSourceId == sNodeId)
- nCount++;
- }
- else
- {
- // No presentation child is a presentation of a model node: just
- // count presentation children.
- for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections())
- if (aCxn.mnType == XML_presParOf && aCxn.msSourceId == pPoint->msModelId)
- nCount++;
- }
+ if (!sNodeId.isEmpty())
+ {
+ for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections())
+ if (aCxn.mnType == XML_parOf && aCxn.msSourceId == sNodeId)
+ nCount++;
+ }
+ else
+ {
+ // No presentation child is a presentation of a model node: just
+ // count presentation children.
+ for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections())
+ if (aCxn.mnType == XML_presParOf && aCxn.msSourceId == pPresPoint->msModelId)
+ nCount++;
}
+
return nCount;
}
-bool ConditionAtom::getDecision() const
+bool ConditionAtom::getDecision(const dgm::Point* pPresPoint) const
{
if (mIsElse)
return true;
+ if (!pPresPoint)
+ return false;
switch (maCond.mnFunc)
{
case XML_var:
{
- const dgm::Point* pPoint = getPresNode();
- if (!pPoint)
- break;
-
if (maCond.mnArg == XML_dir)
- return compareResult(maCond.mnOp, pPoint->mnDirection, maCond.mnVal);
+ return compareResult(maCond.mnOp, pPresPoint->mnDirection, maCond.mnVal);
else if (maCond.mnArg == XML_hierBranch)
{
- sal_Int32 nHierarchyBranch = pPoint->moHierarchyBranch.get(XML_std);
- if (!pPoint->moHierarchyBranch.has())
+ sal_Int32 nHierarchyBranch = pPresPoint->moHierarchyBranch.get(XML_std);
+ if (!pPresPoint->moHierarchyBranch.has())
{
// If <dgm:hierBranch> is missing in the current presentation
// point, ask the parent.
- OUString aParent = navigate(mrLayoutNode, XML_presParOf, pPoint->msModelId,
+ OUString aParent = navigate(mrLayoutNode, XML_presParOf, pPresPoint->msModelId,
/*bSourceToDestination*/ false);
DiagramData::PointNameMap& rPointNameMap
= mrLayoutNode.getDiagram().getData()->getPointNameMap();
@@ -459,11 +430,18 @@ bool ConditionAtom::getDecision() const
}
case XML_cnt:
- return compareResult(maCond.mnOp, getNodeCount(), maCond.msVal.toInt32());
+ return compareResult(maCond.mnOp, getNodeCount(pPresPoint), maCond.msVal.toInt32());
case XML_maxDepth:
+ // TODO: probably depth from current point - docs are unclear
return compareResult(maCond.mnOp, mrLayoutNode.getDiagram().getData()->getMaxDepth(), maCond.msVal.toInt32());
+ case XML_depth:
+ case XML_pos:
+ case XML_revPos:
+ case XML_posEven:
+ case XML_posOdd:
+ // TODO
default:
SAL_WARN("oox.drawingml", "unknown function " << maCond.mnFunc);
break;
@@ -723,7 +701,12 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
// hierRoot is the manager -> employees vertical linear path,
// hierChild is the first employee -> last employee horizontal
// linear path.
- const sal_Int32 nDir = mnType == XML_hierRoot ? XML_fromT : XML_fromL;
+ sal_Int32 nDir = XML_fromL;
+ if (mnType == XML_hierRoot)
+ nDir = XML_fromT;
+ else if (maMap.count(XML_linDir))
+ nDir = maMap.find(XML_linDir)->second;
+
if (rShape->getChildren().empty() || rShape->getSize().Width == 0
|| rShape->getSize().Height == 0)
break;
@@ -773,18 +756,25 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
aChildSize.Width /= nCount;
aChildSize.Height *= fHeightScale;
aChildSize.Width *= fWidthScale;
+ awt::Size aConnectorSize = aChildSize;
+ aConnectorSize.Width = 1;
awt::Point aChildPos(nXOffset, 0);
for (auto& pChild : rShape->getChildren())
{
pChild->setPosition(aChildPos);
- pChild->setSize(aChildSize);
- pChild->setChildSize(aChildSize);
if (mnType == XML_hierChild && pChild->getSubType() == XML_conn)
+ {
// Connectors should not influence the position of
// non-connect shapes.
+ pChild->setSize(aConnectorSize);
+ pChild->setChildSize(aConnectorSize);
continue;
+ }
+
+ pChild->setSize(aChildSize);
+ pChild->setChildSize(aChildSize);
if (nDir == XML_fromT)
aChildPos.Y += aChildSize.Height + aChildSize.Height * fSpace;
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index 4dcee899a4c0..b4255927185b 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -112,7 +112,7 @@ private:
void setParent(const LayoutAtomPtr& pParent) { mpParent = pParent; }
public:
- virtual const std::vector<LayoutAtomPtr>& getChildren() const
+ const std::vector<LayoutAtomPtr>& getChildren() const
{ return mpChildNodes; }
LayoutAtomPtr getParent() const { return mpParent.lock(); }
@@ -211,11 +211,11 @@ class ConditionAtom
public:
explicit ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes);
virtual void accept( LayoutAtomVisitor& ) override;
- bool getDecision() const;
+ bool getDecision(const dgm::Point* pPresPoint) const;
+
private:
static bool compareResult(sal_Int32 nOperator, sal_Int32 nFirst, sal_Int32 nSecond);
- const dgm::Point* getPresNode() const;
- sal_Int32 getNodeCount() const;
+ sal_Int32 getNodeCount(const dgm::Point* pPresPoint) const;
bool const mIsElse;
IteratorAttr maIter;
@@ -231,14 +231,8 @@ class ChooseAtom
public:
ChooseAtom(LayoutNode& rLayoutNode)
: LayoutAtom(rLayoutNode)
-#if defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8
- , maEmptyChildren()
-#endif
{}
virtual void accept( LayoutAtomVisitor& ) override;
- virtual const std::vector<LayoutAtomPtr>& getChildren() const override;
-private:
- const std::vector<LayoutAtomPtr> maEmptyChildren;
};
class LayoutNode
@@ -301,18 +295,6 @@ private:
typedef std::shared_ptr< ShapeAtom > ShapeAtomPtr;
-struct LayoutAtomVisitor
-{
- virtual ~LayoutAtomVisitor() {}
- virtual void visit(ConstraintAtom& rAtom) = 0;
- virtual void visit(AlgAtom& rAtom) = 0;
- virtual void visit(ForEachAtom& rAtom) = 0;
- virtual void visit(ConditionAtom& rAtom) = 0;
- virtual void visit(ChooseAtom& rAtom) = 0;
- virtual void visit(LayoutNode& rAtom) = 0;
- virtual void visit(ShapeAtom& rAtom) = 0;
-};
-
} }
#endif
diff --git a/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx b/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx
new file mode 100644
index 000000000000..49b1d801bee9
--- /dev/null
+++ b/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "layoutatomvisitorbase.hxx"
+
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace oox { namespace drawingml {
+
+void LayoutAtomVisitorBase::defaultVisit(LayoutAtom const& rAtom)
+{
+ for (const auto& pAtom : rAtom.getChildren())
+ pAtom->accept(*this);
+}
+
+void LayoutAtomVisitorBase::visit(ChooseAtom& rAtom)
+{
+ for (const auto& pChild : rAtom.getChildren())
+ {
+ const ConditionAtomPtr pCond = std::dynamic_pointer_cast<ConditionAtom>(pChild);
+ if (pCond && pCond->getDecision(mpCurrentNode))
+ {
+ SAL_INFO("oox.drawingml", "Entering if node: " << pCond->getName());
+ pCond->accept(*this);
+ break;
+ }
+ }
+}
+
+void LayoutAtomVisitorBase::visit(ConditionAtom& rAtom)
+{
+ defaultVisit(rAtom);
+}
+
+void LayoutAtomVisitorBase::visit(ForEachAtom& rAtom)
+{
+ if (!rAtom.getRef().isEmpty())
+ {
+ if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
+ pRefAtom->accept(*this);
+ return;
+ }
+
+ if (rAtom.iterator().mbHideLastTrans && rAtom.iterator().mnAxis == XML_followSib)
+ {
+ // If last transition is hidden and the axis is the follow sibling,
+ // then the last atom should not be visited.
+ if (mnCurrIdx + mnCurrStep >= mnCurrCnt)
+ return;
+ }
+
+ sal_Int32 nChildren = 1;
+ // Approximate the non-assistant type with the node type.
+ if (rAtom.iterator().mnPtType == XML_node || rAtom.iterator().mnPtType == XML_nonAsst)
+ {
+ // count child data nodes - check all child Atoms for "name"
+ // attribute that is contained in diagram's
+ // getPointsPresNameMap()
+ ShallowPresNameVisitor aVisitor(mrDgm, mpCurrentNode);
+ for (const auto& pAtom : rAtom.getChildren())
+ pAtom->accept(aVisitor);
+ nChildren = aVisitor.getCount();
+ }
+
+ const sal_Int32 nCnt = std::min(
+ nChildren,
+ rAtom.iterator().mnCnt==-1 ? nChildren : rAtom.iterator().mnCnt);
+
+ const sal_Int32 nOldIdx = mnCurrIdx;
+ const sal_Int32 nOldStep = mnCurrStep;
+ const sal_Int32 nOldCnt = mnCurrCnt;
+ const sal_Int32 nStep = rAtom.iterator().mnStep;
+ mnCurrStep = nStep;
+ mnCurrCnt = nCnt;
+ for( mnCurrIdx=0; mnCurrIdx<nCnt && nStep>0; mnCurrIdx+=nStep )
+ {
+ // TODO there is likely some conditions
+ for (const auto& pAtom : rAtom.getChildren())
+ pAtom->accept(*this);
+ }
+
+ // and restore idx
+ mnCurrIdx = nOldIdx;
+ mnCurrStep = nOldStep;
+ mnCurrCnt = nOldCnt;
+}
+
+void LayoutAtomVisitorBase::visit(LayoutNode& rAtom)
+{
+ // TODO: deduplicate code in descendants
+
+ // stop processing if it's not a child of previous LayoutNode
+
+ const DiagramData::PointsNameMap::const_iterator aDataNode
+ = mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
+ if (aDataNode == mrDgm.getData()->getPointsPresNameMap().end()
+ || mnCurrIdx >= static_cast<sal_Int32>(aDataNode->second.size()))
+ return;
+
+ const dgm::Point* pNewNode = aDataNode->second.at(mnCurrIdx);
+ if (!mpCurrentNode || !pNewNode)
+ return;
+
+ bool bIsChild = false;
+ for (const auto& aConnection : mrDgm.getData()->getConnections())
+ if (aConnection.msSourceId == mpCurrentNode->msModelId
+ && aConnection.msDestId == pNewNode->msModelId)
+ bIsChild = true;
+
+ if (!bIsChild)
+ return;
+
+ const dgm::Point* pPreviousNode = mpCurrentNode;
+ mpCurrentNode = pNewNode;
+ mnCurrLevel++;
+
+ defaultVisit(rAtom);
+
+ mnCurrLevel--;
+ mpCurrentNode = pPreviousNode;
+}
+
+void ShallowPresNameVisitor::visit(ConstraintAtom& /*rAtom*/)
+{
+ // stop processing
+}
+
+void ShallowPresNameVisitor::visit(AlgAtom& /*rAtom*/)
+{
+ // stop processing
+}
+
+void ShallowPresNameVisitor::visit(ForEachAtom& rAtom)
+{
+ defaultVisit(rAtom);
+}
+
+void ShallowPresNameVisitor::visit(LayoutNode& rAtom)
+{
+ DiagramData::PointsNameMap::const_iterator aDataNode =
+ mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
+ if( aDataNode != mrDgm.getData()->getPointsPresNameMap().end() )
+ mnCnt = std::max(mnCnt,
+ aDataNode->second.size());
+}
+
+void ShallowPresNameVisitor::visit(ShapeAtom& /*rAtom*/)
+{
+ // stop processing
+}
+
+} }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx b/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx
new file mode 100644
index 000000000000..25f2b4dea54b
--- /dev/null
+++ b/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_LAYOUTATOMVISITORBASE_HXX
+#define INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_LAYOUTATOMVISITORBASE_HXX
+
+#include <memory>
+
+#include <oox/drawingml/shape.hxx>
+#include "diagram.hxx"
+#include "diagramlayoutatoms.hxx"
+
+namespace oox { namespace drawingml {
+
+struct LayoutAtomVisitor
+{
+ virtual ~LayoutAtomVisitor() {}
+ virtual void visit(ConstraintAtom& rAtom) = 0;
+ virtual void visit(AlgAtom& rAtom) = 0;
+ virtual void visit(ForEachAtom& rAtom) = 0;
+ virtual void visit(ConditionAtom& rAtom) = 0;
+ virtual void visit(ChooseAtom& rAtom) = 0;
+ virtual void visit(LayoutNode& rAtom) = 0;
+ virtual void visit(ShapeAtom& rAtom) = 0;
+};
+
+// basic visitor implementation that follows if/else and for-each nodes
+// and keeps track of current position in data tree
+class LayoutAtomVisitorBase : public LayoutAtomVisitor
+{
+public:
+ LayoutAtomVisitorBase(const Diagram& rDgm, const dgm::Point* pRootPoint) :
+ mrDgm(rDgm),
+ mpCurrentNode(pRootPoint),
+ mnCurrIdx(0),
+ mnCurrStep(0),
+ mnCurrCnt(0),
+ mnCurrLevel(0)
+ {}
+
+ void defaultVisit(LayoutAtom const& rAtom);
+
+ using LayoutAtomVisitor::visit;
+ virtual void visit(ForEachAtom& rAtom) override;
+ virtual void visit(ConditionAtom& rAtom) override;
+ virtual void visit(ChooseAtom& rAtom) override;
+ virtual void visit(LayoutNode& rAtom) override;
+
+protected:
+ const Diagram& mrDgm;
+ const dgm::Point* mpCurrentNode;
+ sal_Int32 mnCurrIdx;
+ sal_Int32 mnCurrStep;
+ sal_Int32 mnCurrCnt;
+ sal_Int32 mnCurrLevel;
+};
+
+class ShallowPresNameVisitor : public LayoutAtomVisitorBase
+{
+public:
+ explicit ShallowPresNameVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint) :
+ LayoutAtomVisitorBase(rDgm, pRootPoint),
+ mnCnt(0)
+ {}
+
+ using LayoutAtomVisitorBase::visit;
+ virtual void visit(ConstraintAtom& rAtom) override;
+ virtual void visit(AlgAtom& rAtom) override;
+ virtual void visit(ForEachAtom& rAtom) override;
+ virtual void visit(LayoutNode& rAtom) override;
+ virtual void visit(ShapeAtom& rAtom) override;
+
+ size_t getCount() const { return mnCnt; }
+
+private:
+ size_t mnCnt;
+};
+
+} }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
index aa1d21b179f1..b72133033470 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
@@ -30,12 +30,6 @@ using namespace ::oox::core;
namespace oox { namespace drawingml {
-void ShapeCreationVisitor::defaultVisit(LayoutAtom const & rAtom)
-{
- for (const auto& pAtom : rAtom.getChildren())
- pAtom->accept(*this);
-}
-
void ShapeCreationVisitor::visit(ConstraintAtom& /*rAtom*/)
{
// stop processing
@@ -46,71 +40,6 @@ void ShapeCreationVisitor::visit(AlgAtom& rAtom)
mpParentShape->setAspectRatio(rAtom.getAspectRatio());
}
-void ShapeCreationVisitor::visit(ForEachAtom& rAtom)
-{
- if (!rAtom.getRef().isEmpty())
- {
- if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
- pRefAtom->accept(*this);
- return;
- }
-
- if (rAtom.iterator().mbHideLastTrans && rAtom.iterator().mnAxis == XML_followSib)
- {
- // If last transition is hidden and the axis is the follow sibling,
- // then the last atom should not be visited.
- if (mnCurrIdx + mnCurrStep >= mnCurrCnt)
- return;
- }
-
- const std::vector<LayoutAtomPtr>& rChildren=rAtom.getChildren();
-
- sal_Int32 nChildren=1;
- // Approximate the non-assistant type with the node type.
- if (rAtom.iterator().mnPtType == XML_node || rAtom.iterator().mnPtType == XML_nonAsst)
- {
- // count child data nodes - check all child Atoms for "name"
- // attribute that is contained in diagram's
- // getPointsPresNameMap()
- ShallowPresNameVisitor aVisitor(mrDgm);
- for (const auto& pAtom : rChildren)
- pAtom->accept(aVisitor);
- nChildren = aVisitor.getCount();
- }
-
- const sal_Int32 nCnt = std::min(
- nChildren,
- rAtom.iterator().mnCnt==-1 ? nChildren : rAtom.iterator().mnCnt);
-
- const sal_Int32 nOldIdx=mnCurrIdx;
- const sal_Int32 nOldStep = mnCurrStep;
- const sal_Int32 nOldCnt = mnCurrCnt;
- const sal_Int32 nStep=rAtom.iterator().mnStep;
- mnCurrStep = nStep;
- mnCurrCnt = nCnt;
- for( mnCurrIdx=0; mnCurrIdx<nCnt && nStep>0; mnCurrIdx+=nStep )
- {
- // TODO there is likely some conditions
- for (const auto& pAtom : rChildren)
- pAtom->accept(*this);
- }
-
- // and restore idx
- mnCurrIdx = nOldIdx;
- mnCurrStep = nOldStep;
- mnCurrCnt = nOldCnt;
-}
-
-void ShapeCreationVisitor::visit(ConditionAtom& rAtom)
-{
- defaultVisit(rAtom);
-}
-
-void ShapeCreationVisitor::visit(ChooseAtom& rAtom)
-{
- defaultVisit(rAtom);
-}
-
void ShapeCreationVisitor::visit(LayoutNode& rAtom)
{
// stop processing if it's not a child of previous LayoutNode
@@ -141,11 +70,12 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
{
pShape->setInternalName(rAtom.getName());
rAtom.addNodeShape(pShape, mnCurrLevel);
+ mrDgm.getLayout()->getPresPointShapeMap()[pNewNode] = pShape;
}
}
else
{
- ShapeTemplateVisitor aTemplateVisitor;
+ ShapeTemplateVisitor aTemplateVisitor(mrDgm, pNewNode);
aTemplateVisitor.defaultVisit(rAtom);
ShapePtr pShape = aTemplateVisitor.getShapeCopy();
@@ -162,6 +92,7 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
pCurrParent->addChild(pShape);
pCurrParent = pShape;
rAtom.addNodeShape(pShape, mnCurrLevel);
+ mrDgm.getLayout()->getPresPointShapeMap()[pNewNode] = pShape;
}
}
else
@@ -198,13 +129,6 @@ void ShapeCreationVisitor::visit(ShapeAtom& /*rAtom*/)
// stop processing
}
-void ShapeTemplateVisitor::defaultVisit(LayoutAtom const & 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
@@ -220,16 +144,6 @@ 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
@@ -253,13 +167,6 @@ void ShapeTemplateVisitor::visit(ShapeAtom& rAtom)
mpShape->cloneFillProperties();
}
-void ShapeLayoutingVisitor::defaultVisit(LayoutAtom const & rAtom)
-{
- // visit all children, one of them needs to be the layout algorithm
- for (const auto& pAtom : rAtom.getChildren())
- pAtom->accept(*this);
-}
-
void ShapeLayoutingVisitor::visit(ConstraintAtom& rAtom)
{
if (meLookFor == CONSTRAINT)
@@ -270,46 +177,44 @@ void ShapeLayoutingVisitor::visit(AlgAtom& rAtom)
{
if (meLookFor == ALGORITHM)
{
- auto pShapes = rAtom.getLayoutNode().getNodeShapes().find(mnCurrLevel);
- if (pShapes != rAtom.getLayoutNode().getNodeShapes().end())
- for (const auto& pShape : pShapes->second)
- rAtom.layoutShape(pShape, maConstraints, mnCurrLevel);
+ const PresPointShapeMap aMap = rAtom.getLayoutNode().getDiagram().getLayout()->getPresPointShapeMap();
+ auto pShape = aMap.find(mpCurrentNode);
+ if (pShape != aMap.end())
+ rAtom.layoutShape(pShape->second, maConstraints, mnCurrLevel);
}
}
-void ShapeLayoutingVisitor::visit(ForEachAtom& rAtom)
+void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
{
- if (!rAtom.getRef().isEmpty())
- {
- if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
- pRefAtom->accept(*this);
+ if (meLookFor != LAYOUT_NODE)
return;
- }
-
- defaultVisit(rAtom);
-}
-void ShapeLayoutingVisitor::visit(ConditionAtom& rAtom)
-{
- defaultVisit(rAtom);
-}
+ // stop processing if it's not a child of previous LayoutNode
-void ShapeLayoutingVisitor::visit(ChooseAtom& rAtom)
-{
- defaultVisit(rAtom);
-}
+ const DiagramData::PointsNameMap::const_iterator aDataNode
+ = mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
+ if (aDataNode == mrDgm.getData()->getPointsPresNameMap().end()
+ || mnCurrIdx >= static_cast<sal_Int32>(aDataNode->second.size()))
+ return;
-void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
-{
- if (meLookFor != LAYOUT_NODE)
+ const dgm::Point* pNewNode = aDataNode->second.at(mnCurrIdx);
+ if (!mpCurrentNode || !pNewNode)
return;
- // stop processing if there is no more shapes on this level
- if (rAtom.getNodeShapes().empty() || mnCurrLevel > rAtom.getNodeShapes().rbegin()->first)
+ bool bIsChild = false;
+ for (const auto& aConnection : mrDgm.getData()->getConnections())
+ if (aConnection.msSourceId == mpCurrentNode->msModelId
+ && aConnection.msDestId == pNewNode->msModelId)
+ bIsChild = true;
+
+ if (!bIsChild)
return;
size_t nParentConstraintsNumber = maConstraints.size();
+ const dgm::Point* pPreviousNode = mpCurrentNode;
+ mpCurrentNode = pNewNode;
+
// process alg atoms first, nested layout nodes afterwards
meLookFor = CONSTRAINT;
defaultVisit(rAtom);
@@ -320,6 +225,7 @@ void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
meLookFor = LAYOUT_NODE;
defaultVisit(rAtom);
mnCurrLevel--;
+ mpCurrentNode = pPreviousNode;
// delete added constraints, keep parent constraints
maConstraints.erase(maConstraints.begin() + nParentConstraintsNumber, maConstraints.end());
@@ -330,53 +236,6 @@ void ShapeLayoutingVisitor::visit(ShapeAtom& /*rAtom*/)
// stop processing
}
-void ShallowPresNameVisitor::defaultVisit(LayoutAtom const & rAtom)
-{
- // visit all children, at least one of them needs to have proper
- // name set
- for (const auto& pAtom : rAtom.getChildren())
- pAtom->accept(*this);
-}
-
-void ShallowPresNameVisitor::visit(ConstraintAtom& /*rAtom*/)
-{
- // stop processing
-}
-
-void ShallowPresNameVisitor::visit(AlgAtom& /*rAtom*/)
-{
- // stop processing
-}
-
-void ShallowPresNameVisitor::visit(ForEachAtom& rAtom)
-{
- defaultVisit(rAtom);
-}
-
-void ShallowPresNameVisitor::visit(ConditionAtom& rAtom)
-{
- defaultVisit(rAtom);
-}
-
-void ShallowPresNameVisitor::visit(ChooseAtom& rAtom)
-{
- defaultVisit(rAtom);
-}
-
-void ShallowPresNameVisitor::visit(LayoutNode& rAtom)
-{
- DiagramData::PointsNameMap::const_iterator aDataNode=
- mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
- if( aDataNode != mrDgm.getData()->getPointsPresNameMap().end() )
- mnCnt = std::max(mnCnt,
- 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 4a61a75eb0f5..2950fb01a17c 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.hxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.hxx
@@ -25,101 +25,68 @@
#include <oox/drawingml/shape.hxx>
#include "diagram.hxx"
#include "diagramlayoutatoms.hxx"
+#include "layoutatomvisitorbase.hxx"
namespace oox { namespace drawingml {
-class ShapeCreationVisitor : public LayoutAtomVisitor
+class ShapeCreationVisitor : public LayoutAtomVisitorBase
{
- ShapePtr mpParentShape;
- const Diagram& mrDgm;
- sal_Int32 mnCurrIdx;
- sal_Int32 mnCurrStep = 0;
- sal_Int32 mnCurrCnt = 0;
- sal_Int32 mnCurrLevel;
- const dgm::Point* mpCurrentNode;
-
- void defaultVisit(LayoutAtom const & rAtom);
+public:
+ ShapeCreationVisitor(const Diagram& rDgm,
+ const dgm::Point* pRootPoint,
+ const ShapePtr& rParentShape) :
+ LayoutAtomVisitorBase(rDgm, pRootPoint),
+ mpParentShape(rParentShape)
+ {}
+
+ using LayoutAtomVisitorBase::visit;
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:
- ShapeCreationVisitor(const ShapePtr& rParentShape,
- const Diagram& rDgm) :
- mpParentShape(rParentShape),
- mrDgm(rDgm),
- mnCurrIdx(0),
- mnCurrLevel(0),
- mpCurrentNode(rDgm.getData()->getRootPoint())
- {}
+private:
+ ShapePtr mpParentShape;
};
-class ShapeTemplateVisitor : public LayoutAtomVisitor
+class ShapeTemplateVisitor : public LayoutAtomVisitorBase
{
- ShapePtr mpShape;
+public:
+ ShapeTemplateVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint)
+ : LayoutAtomVisitorBase(rDgm, pRootPoint)
+ {}
+ using LayoutAtomVisitorBase::visit;
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 const & rAtom);
ShapePtr const & getShapeCopy() const
{ return mpShape; }
+
+private:
+ ShapePtr mpShape;
};
-class ShapeLayoutingVisitor : public LayoutAtomVisitor
+class ShapeLayoutingVisitor : public LayoutAtomVisitorBase
{
- std::vector<Constraint> maConstraints;
- enum {LAYOUT_NODE, CONSTRAINT, ALGORITHM} meLookFor;
- sal_Int32 mnCurrLevel;
-
- void defaultVisit(LayoutAtom const & rAtom);
- 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:
- ShapeLayoutingVisitor() :
- meLookFor(LAYOUT_NODE),
- mnCurrLevel(0)
+ ShapeLayoutingVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint) :
+ LayoutAtomVisitorBase(rDgm, pRootPoint),
+ meLookFor(LAYOUT_NODE)
{}
-};
-class ShallowPresNameVisitor : public LayoutAtomVisitor
-{
- const Diagram& mrDgm;
- size_t mnCnt;
-
- void defaultVisit(LayoutAtom const & rAtom);
+ using LayoutAtomVisitorBase::visit;
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:
- explicit ShallowPresNameVisitor(const Diagram& rDgm) :
- mrDgm(rDgm),
- mnCnt(0)
- {}
-
- size_t getCount() const
- { return mnCnt; }
+private:
+ std::vector<Constraint> maConstraints;
+ enum {LAYOUT_NODE, CONSTRAINT, ALGORITHM} meLookFor;
};
} }