summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Araminowicz <grzegorz.araminowicz@collabora.com>2019-06-11 08:31:18 +0200
committerGrzegorz Araminowicz <grzegorz.araminowicz@collabora.com>2019-06-19 14:31:53 +0200
commita95d04250f6921730c6164fbd207ed1222c4315f (patch)
treea6e9af9b98b86c6f71da41ff43d68cc3548b08c8
parente9fbb0a06b4318233e8cc4eec1273f7fde1beca1 (diff)
SmartArt: support ForEach references
ForEach 'ref' parameter causes specified ForEach node to be used instead. Used to create recursive structures like organisation charts. Change-Id: Iee61b2e103759355b59beb8d3f33eb3cce47c590 Reviewed-on: https://gerrit.libreoffice.org/74271 Tested-by: Jenkins Reviewed-by: Grzegorz Araminowicz <grzegorz.araminowicz@collabora.com> (cherry picked from commit 76478f9938a5f6d96ac65b3b633280024b60baed) Reviewed-on: https://gerrit.libreoffice.org/74337
-rw-r--r--oox/source/drawingml/diagram/diagram.hxx10
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.cxx14
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.hxx6
-rw-r--r--oox/source/drawingml/diagram/layoutatomvisitors.cxx14
-rw-r--r--oox/source/drawingml/diagram/layoutnodecontext.cxx5
-rw-r--r--sd/qa/unit/data/pptx/smartart-recursion.pptxbin0 -> 52943 bytes
-rw-r--r--sd/qa/unit/import-tests-smartart.cxx42
7 files changed, 90 insertions, 1 deletions
diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx
index 91cb0f39fd2c..cf12dce576a7 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -149,6 +149,8 @@ typedef std::vector< Point > Points;
class Diagram;
class LayoutNode;
typedef std::shared_ptr< LayoutNode > LayoutNodePtr;
+class LayoutAtom;
+typedef std::shared_ptr<LayoutAtom> LayoutAtomPtr;
typedef std::map< OUString, css::uno::Reference<css::xml::dom::XDocument> > DiagramDomMap;
@@ -205,6 +207,8 @@ private:
typedef std::shared_ptr< DiagramData > DiagramDataPtr;
+typedef std::map<OUString, LayoutAtomPtr> LayoutAtomMap;
+
class DiagramLayout
{
public:
@@ -233,6 +237,8 @@ public:
{ return mpStyleData; }
const DiagramDataPtr & getStyleData() const
{ return mpStyleData; }
+ LayoutAtomMap & getLayoutAtomMap()
+ { return maLayoutAtomMap; }
private:
const Diagram& mrDgm;
@@ -248,6 +254,8 @@ private:
// TODO
// catLst
// clrData
+
+ LayoutAtomMap maLayoutAtomMap;
};
typedef std::shared_ptr< DiagramLayout > DiagramLayoutPtr;
@@ -283,6 +291,8 @@ public:
{ return mpData; }
void setLayout( const DiagramLayoutPtr & pLayout )
{ mpLayout = pLayout; }
+ const DiagramLayoutPtr& getLayout() const
+ { return mpLayout; }
DiagramQStyleMap& getStyles() { return maStyles; }
const DiagramQStyleMap& getStyles() const { return maStyles; }
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index f9c443c5d626..6497e3ba22cf 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -229,6 +229,20 @@ void ForEachAtom::accept( LayoutAtomVisitor& rVisitor )
rVisitor.visit(*this);
}
+LayoutAtomPtr ForEachAtom::getRefAtom()
+{
+ if (!msRef.isEmpty())
+ {
+ const LayoutAtomMap& rLayoutAtomMap = getLayoutNode().getDiagram().getLayout()->getLayoutAtomMap();
+ LayoutAtomMap::const_iterator pRefAtom = rLayoutAtomMap.find(msRef);
+ if (pRefAtom != rLayoutAtomMap.end())
+ return pRefAtom->second;
+ else
+ SAL_WARN("oox.drawingml", "ForEach reference \"" << msRef << "\" not found");
+ }
+ return LayoutAtomPtr();
+}
+
void ChooseAtom::accept( LayoutAtomVisitor& rVisitor )
{
rVisitor.visit(*this);
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index 8a11ed5cbac8..9fff33686dd6 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -188,10 +188,16 @@ public:
IteratorAttr & iterator()
{ return maIter; }
+ void setRef(const OUString& rsRef)
+ { msRef = rsRef; }
+ const OUString& getRef() const
+ { return msRef; }
virtual void accept( LayoutAtomVisitor& ) override;
+ LayoutAtomPtr getRefAtom();
private:
IteratorAttr maIter;
+ OUString msRef;
};
typedef std::shared_ptr< ForEachAtom > ForEachAtomPtr;
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
index cd7b82aa9efd..5d6f0065241d 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
@@ -48,6 +48,13 @@ void ShapeCreationVisitor::visit(AlgAtom& rAtom)
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,
@@ -276,6 +283,13 @@ void ShapeLayoutingVisitor::visit(AlgAtom& rAtom)
void ShapeLayoutingVisitor::visit(ForEachAtom& rAtom)
{
+ if (!rAtom.getRef().isEmpty())
+ {
+ if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
+ pRefAtom->accept(*this);
+ return;
+ }
+
defaultVisit(rAtom);
}
diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx
index e984862c44b4..8e3e3c2f6eb4 100644
--- a/oox/source/drawingml/diagram/layoutnodecontext.cxx
+++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx
@@ -141,8 +141,11 @@ public:
ForEachContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, const ForEachAtomPtr& pAtom )
: LayoutNodeContext( rParent, rAttribs, pAtom )
{
- rAttribs.getString( XML_ref );
+ pAtom->setRef(rAttribs.getString(XML_ref).get());
pAtom->iterator().loadFromXAttr( rAttribs.getFastAttributeList() );
+
+ LayoutAtomMap& rLayoutAtomMap = pAtom->getLayoutNode().getDiagram().getLayout()->getLayoutAtomMap();
+ rLayoutAtomMap[pAtom->getName()] = pAtom;
}
};
diff --git a/sd/qa/unit/data/pptx/smartart-recursion.pptx b/sd/qa/unit/data/pptx/smartart-recursion.pptx
new file mode 100644
index 000000000000..205db6b703de
--- /dev/null
+++ b/sd/qa/unit/data/pptx/smartart-recursion.pptx
Binary files differ
diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx
index 775411c57bba..944e583df040 100644
--- a/sd/qa/unit/import-tests-smartart.cxx
+++ b/sd/qa/unit/import-tests-smartart.cxx
@@ -79,6 +79,7 @@ public:
void testFontSize();
void testVerticalBlockList();
void testBulletList();
+ void testRecursion();
CPPUNIT_TEST_SUITE(SdImportTestSmartArt);
@@ -119,6 +120,7 @@ public:
CPPUNIT_TEST(testFontSize);
CPPUNIT_TEST(testVerticalBlockList);
CPPUNIT_TEST(testBulletList);
+ CPPUNIT_TEST(testRecursion);
CPPUNIT_TEST_SUITE_END();
};
@@ -1273,6 +1275,46 @@ void SdImportTestSmartArt::testBulletList()
xDocShRef->DoClose();
}
+void SdImportTestSmartArt::testRecursion()
+{
+ sd::DrawDocShellRef xDocShRef = loadURL(
+ m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/smartart-recursion.pptx"), PPTX);
+
+ uno::Reference<drawing::XShapes> xGroup(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY);
+ uno::Reference<drawing::XShapes> xGroup1(xGroup->getByIndex(1), uno::UNO_QUERY);
+
+ uno::Reference<drawing::XShapes> xGroupA(xGroup1->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XText> xTextA(xGroupA->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("A"), xTextA->getString());
+
+ uno::Reference<drawing::XShapes> xGroupB(xGroup1->getByIndex(1), uno::UNO_QUERY);
+ // 5 connectors, B1 with children, B2 with children
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(7), xGroupB->getCount());
+
+ uno::Reference<drawing::XShapes> xGroupB1(xGroupB->getByIndex(1), uno::UNO_QUERY);
+
+ uno::Reference<drawing::XShapes> xGroupB1a(xGroupB1->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XText> xTextB1(xGroupB1a->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("B1"), xTextB1->getString());
+
+ uno::Reference<drawing::XShape> xGroupC12(xGroupB1->getByIndex(1), uno::UNO_QUERY);
+ uno::Reference<text::XText> xTextC1(getChildShape(getChildShape(getChildShape(xGroupC12, 0), 0), 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("C1"), xTextC1->getString());
+ uno::Reference<text::XText> xTextC2(getChildShape(getChildShape(getChildShape(xGroupC12, 1), 0), 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("C2"), xTextC2->getString());
+
+ uno::Reference<drawing::XShapes> xGroupB2(xGroupB->getByIndex(5), uno::UNO_QUERY);
+
+ uno::Reference<drawing::XShapes> xGroupB2a(xGroupB2->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XText> xTextB2(xGroupB2a->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("B2"), xTextB2->getString());
+
+ uno::Reference<drawing::XShape> xGroupC3(xGroupB2->getByIndex(1), uno::UNO_QUERY);
+ uno::Reference<text::XText> xTextC3(getChildShape(getChildShape(getChildShape(xGroupC3, 0), 0), 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("C3"), xTextC3->getString());
+
+ xDocShRef->DoClose();
+}
CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt);