From 6eb7dd4a2683fb4c28506a464317d7ee54cfe1de Mon Sep 17 00:00:00 2001 From: Grzegorz Araminowicz Date: Fri, 30 Aug 2019 10:20:38 +0200 Subject: SmartArt edit UI: add new node First approach to adding new node. Currently it's possible only to add top-level node to the end of diagram. Change-Id: Icd9530ab2fb8987a1690ffc96c244cc845b72eba Reviewed-on: https://gerrit.libreoffice.org/78286 Tested-by: Jenkins Reviewed-by: Grzegorz Araminowicz --- cui/source/dialogs/DiagramDialog.cxx | 20 +++++++++ cui/source/inc/DiagramDialog.hxx | 4 ++ cui/uiconfig/ui/diagramdialog.ui | 39 +++++++++++++++- include/svx/DiagramDataInterface.hxx | 3 ++ oox/source/drawingml/diagram/diagram.cxx | 76 ++++++++++++++++++++++++++++++++ oox/source/drawingml/diagram/diagram.hxx | 2 + 6 files changed, 142 insertions(+), 2 deletions(-) diff --git a/cui/source/dialogs/DiagramDialog.cxx b/cui/source/dialogs/DiagramDialog.cxx index c48e8f58089d..f3b84c0fcc4e 100644 --- a/cui/source/dialogs/DiagramDialog.cxx +++ b/cui/source/dialogs/DiagramDialog.cxx @@ -9,7 +9,9 @@ #include +#include #include +#include DiagramDialog::DiagramDialog(weld::Window* pWindow, std::shared_ptr pDiagramData) @@ -17,8 +19,12 @@ DiagramDialog::DiagramDialog(weld::Window* pWindow, , mpDiagramData(pDiagramData) , mpBtnOk(m_xBuilder->weld_button("btnOk")) , mpBtnCancel(m_xBuilder->weld_button("btnCancel")) + , mpBtnAdd(m_xBuilder->weld_button("btnAdd")) , mpTreeDiagram(m_xBuilder->weld_tree_view("treeDiagram")) + , mpTextAdd(m_xBuilder->weld_text_view("textAdd")) { + mpBtnAdd->connect_clicked(LINK(this, DiagramDialog, OnAddClick)); + populateTree(nullptr, OUString()); // expand all items @@ -29,6 +35,20 @@ DiagramDialog::DiagramDialog(weld::Window* pWindow, }); } +IMPL_LINK_NOARG(DiagramDialog, OnAddClick, weld::Button&, void) +{ + OUString sText = mpTextAdd->get_text(); + if (!sText.isEmpty()) + { + std::unique_ptr pEntry(mpTreeDiagram->make_iterator()); + mpTreeDiagram->insert(nullptr, -1, &sText, nullptr, nullptr, nullptr, nullptr, false, + pEntry.get()); + mpTreeDiagram->select(*pEntry); + mpDiagramData->addNode(sText); + comphelper::dispatchCommand(".uno:RegenerateDiagram", {}); + } +} + void DiagramDialog::populateTree(weld::TreeIter* pParent, const OUString& rParentId) { auto aItems = mpDiagramData->getChildren(rParentId); diff --git a/cui/source/inc/DiagramDialog.hxx b/cui/source/inc/DiagramDialog.hxx index ec47de6414bd..c1ce3316427e 100644 --- a/cui/source/inc/DiagramDialog.hxx +++ b/cui/source/inc/DiagramDialog.hxx @@ -26,7 +26,11 @@ private: std::shared_ptr mpDiagramData; std::unique_ptr mpBtnOk; std::unique_ptr mpBtnCancel; + std::unique_ptr mpBtnAdd; std::unique_ptr mpTreeDiagram; + std::unique_ptr mpTextAdd; + + DECL_LINK(OnAddClick, weld::Button&, void); void populateTree(weld::TreeIter* pParent, const OUString& rParentId); }; diff --git a/cui/uiconfig/ui/diagramdialog.ui b/cui/uiconfig/ui/diagramdialog.ui index 000f340f028a..c52376f0b3a3 100644 --- a/cui/uiconfig/ui/diagramdialog.ui +++ b/cui/uiconfig/ui/diagramdialog.ui @@ -49,7 +49,7 @@ False False - 1 + 2 @@ -57,7 +57,6 @@ True True False - True @@ -68,6 +67,42 @@ 0 + + + True + False + + + True + True + + + True + True + 0 + + + + + gtk-add + True + True + True + True + + + False + True + 1 + + + + + False + True + 1 + + diff --git a/include/svx/DiagramDataInterface.hxx b/include/svx/DiagramDataInterface.hxx index 9174a2b2fefe..aaa3a46968b3 100644 --- a/include/svx/DiagramDataInterface.hxx +++ b/include/svx/DiagramDataInterface.hxx @@ -38,6 +38,9 @@ public: virtual std::vector> getChildren(const OUString& rParentId) const = 0; + // add new top-level node to data model + virtual void addNode(const OUString& rText) = 0; + protected: ~DiagramDataInterface() throw() {} }; diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 4fcfbe760699..a6e8ee28acf5 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -40,6 +40,7 @@ #include #include #include +#include #include "diagramlayoutatoms.hxx" #include "layoutatomvisitors.hxx" @@ -156,6 +157,76 @@ std::vector> DiagramData::getChildren(const OUStri return aChildren; } +void DiagramData::addConnection(sal_Int32 nType, const OUString& sSourceId, const OUString& sDestId) +{ + sal_Int32 nMaxOrd = -1; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == nType && aCxn.msSourceId == sSourceId) + nMaxOrd = std::max(nMaxOrd, aCxn.mnSourceOrder); + + dgm::Connection& rCxn = maConnections.emplace_back(); + rCxn.mnType = nType; + rCxn.msSourceId = sSourceId; + rCxn.msDestId = sDestId; + rCxn.mnSourceOrder = nMaxOrd + 1; +} + +void DiagramData::addNode(const OUString& rText) +{ + const dgm::Point& rDataRoot = *getRootPoint(); + OUString sPresRoot; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_presOf && aCxn.msSourceId == rDataRoot.msModelId) + sPresRoot = aCxn.msDestId; + + if (sPresRoot.isEmpty()) + return; + + dgm::Point aDataPoint; + aDataPoint.mnType = XML_node; + aDataPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); + aDataPoint.mpShape.reset(new Shape()); + aDataPoint.mpShape->setTextBody(std::make_shared()); + TextRunPtr pTextRun(new TextRun()); + pTextRun->getText() = rText; + aDataPoint.mpShape->getTextBody()->addParagraph().addRun(pTextRun); + + OUString sDataSibling; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_parOf && aCxn.msSourceId == rDataRoot.msModelId) + sDataSibling = aCxn.msDestId; + + OUString sPresSibling; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_presOf && aCxn.msSourceId == sDataSibling) + sPresSibling = aCxn.msDestId; + + dgm::Point aPresPoint; + aPresPoint.mnType = XML_pres; + aPresPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); + aPresPoint.mpShape.reset(new Shape()); + aPresPoint.msPresentationAssociationId = aDataPoint.msModelId; + if (!sPresSibling.isEmpty()) + { + // no idea where to get these values from, so copy from previous sibling + const dgm::Point* pSiblingPoint = maPointNameMap[sPresSibling]; + aPresPoint.msPresentationLayoutName = pSiblingPoint->msPresentationLayoutName; + aPresPoint.msPresentationLayoutStyleLabel = pSiblingPoint->msPresentationLayoutStyleLabel; + aPresPoint.mnLayoutStyleIndex = pSiblingPoint->mnLayoutStyleIndex; + aPresPoint.mnLayoutStyleCount = pSiblingPoint->mnLayoutStyleCount; + } + + addConnection(XML_parOf, rDataRoot.msModelId, aDataPoint.msModelId); + addConnection(XML_presParOf, sPresRoot, aPresPoint.msModelId); + addConnection(XML_presOf, aDataPoint.msModelId, aPresPoint.msModelId); + + // adding at the end, so that references are not invalidated inbetween + maPoints.push_back(aDataPoint); + maPoints.push_back(aPresPoint); + + build(); +} + #ifdef DEBUG_OOX_DIAGRAM OString normalizeDotName( const OUString& rStr ) { @@ -239,6 +310,11 @@ static void sortChildrenByZOrder(const ShapePtr& pShape) void DiagramData::build() { // build name-object maps + maPointNameMap.clear(); + maPointsPresNameMap.clear(); + maConnectionNameMap.clear(); + maPresOfNameMap.clear(); + #ifdef DEBUG_OOX_DIAGRAM std::ofstream output("tree.dot"); diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index 66b57b145c3b..84526a55425c 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -194,9 +194,11 @@ public: void dump() const; OUString getString() const override; std::vector> getChildren(const OUString& rParentId) const override; + void addNode(const OUString& rText) override; private: void getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const; + void addConnection(sal_Int32 nType, const OUString& sSourceId, const OUString& sDestId); ::std::vector maExtDrawings; FillPropertiesPtr mpFillProperties; -- cgit