diff options
author | Grzegorz Araminowicz <grzegorz.araminowicz@collabora.com> | 2019-09-20 12:53:45 +0200 |
---|---|---|
committer | Grzegorz Araminowicz <grzegorz.araminowicz@collabora.com> | 2019-09-25 09:31:08 +0200 |
commit | 711c0b6331958da4fd53eb6c4f9ecd5a422bb186 (patch) | |
tree | e17b463e3f813cc4a4d849d91397adc610f121db | |
parent | b13421011d9377676e1adc282634991d5064a866 (diff) |
SmartArt Edit UI: remove node
Removes data node from data model including associated presentation nodes,
transition nodes and all connections between them (child-parent and
presentation-of).
It still doesn't update order of remaining connections after removal, so
empty entries can happen. Additional step is needed or using better data
structures.
Change-Id: I96e0752b6ec5a19ae8e972dbd421314e6c442b53
Reviewed-on: https://gerrit.libreoffice.org/79279
Tested-by: Jenkins
Reviewed-by: Grzegorz Araminowicz <grzegorz.araminowicz@collabora.com>
-rw-r--r-- | cui/source/dialogs/DiagramDialog.cxx | 19 | ||||
-rw-r--r-- | cui/source/inc/DiagramDialog.hxx | 2 | ||||
-rw-r--r-- | cui/uiconfig/ui/diagramdialog.ui | 14 | ||||
-rw-r--r-- | include/svx/DiagramDataInterface.hxx | 6 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/datamodel.cxx | 68 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/datamodel.hxx | 3 |
6 files changed, 104 insertions, 8 deletions
diff --git a/cui/source/dialogs/DiagramDialog.cxx b/cui/source/dialogs/DiagramDialog.cxx index 4891ef93daee..f3a4a069a19c 100644 --- a/cui/source/dialogs/DiagramDialog.cxx +++ b/cui/source/dialogs/DiagramDialog.cxx @@ -20,10 +20,12 @@ DiagramDialog::DiagramDialog(weld::Window* pWindow, , mpBtnOk(m_xBuilder->weld_button("btnOk")) , mpBtnCancel(m_xBuilder->weld_button("btnCancel")) , mpBtnAdd(m_xBuilder->weld_button("btnAdd")) + , mpBtnRemove(m_xBuilder->weld_button("btnRemove")) , mpTreeDiagram(m_xBuilder->weld_tree_view("treeDiagram")) , mpTextAdd(m_xBuilder->weld_text_view("textAdd")) { mpBtnAdd->connect_clicked(LINK(this, DiagramDialog, OnAddClick)); + mpBtnRemove->connect_clicked(LINK(this, DiagramDialog, OnRemoveClick)); populateTree(nullptr, OUString()); @@ -40,15 +42,28 @@ IMPL_LINK_NOARG(DiagramDialog, OnAddClick, weld::Button&, void) OUString sText = mpTextAdd->get_text(); if (!sText.isEmpty()) { + OUString sNodeId = mpDiagramData->addNode(sText); std::unique_ptr<weld::TreeIter> pEntry(mpTreeDiagram->make_iterator()); - mpTreeDiagram->insert(nullptr, -1, &sText, nullptr, nullptr, nullptr, nullptr, false, + mpTreeDiagram->insert(nullptr, -1, &sText, &sNodeId, nullptr, nullptr, nullptr, false, pEntry.get()); mpTreeDiagram->select(*pEntry); - mpDiagramData->addNode(sText); comphelper::dispatchCommand(".uno:RegenerateDiagram", {}); } } +IMPL_LINK_NOARG(DiagramDialog, OnRemoveClick, weld::Button&, void) +{ + std::unique_ptr<weld::TreeIter> pEntry(mpTreeDiagram->make_iterator()); + if (mpTreeDiagram->get_selected(pEntry.get())) + { + if (mpDiagramData->removeNode(mpTreeDiagram->get_id(*pEntry))) + { + mpTreeDiagram->remove(*pEntry); + comphelper::dispatchCommand(".uno:RegenerateDiagram", {}); + } + } +} + void DiagramDialog::populateTree(const 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 461ffee9a7e6..e97144050a0e 100644 --- a/cui/source/inc/DiagramDialog.hxx +++ b/cui/source/inc/DiagramDialog.hxx @@ -27,10 +27,12 @@ private: std::unique_ptr<weld::Button> mpBtnOk; std::unique_ptr<weld::Button> mpBtnCancel; std::unique_ptr<weld::Button> mpBtnAdd; + std::unique_ptr<weld::Button> mpBtnRemove; std::unique_ptr<weld::TreeView> mpTreeDiagram; std::unique_ptr<weld::TextView> mpTextAdd; DECL_LINK(OnAddClick, weld::Button&, void); + DECL_LINK(OnRemoveClick, weld::Button&, void); void populateTree(const weld::TreeIter* pParent, const OUString& rParentId); }; diff --git a/cui/uiconfig/ui/diagramdialog.ui b/cui/uiconfig/ui/diagramdialog.ui index 98a67717209a..c05031f19bc4 100644 --- a/cui/uiconfig/ui/diagramdialog.ui +++ b/cui/uiconfig/ui/diagramdialog.ui @@ -129,6 +129,20 @@ <property name="position">1</property> </packing> </child> + <child> + <object class="GtkButton" id="btnRemove"> + <property name="label">gtk-remove</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> </object> <packing> <property name="expand">False</property> diff --git a/include/svx/DiagramDataInterface.hxx b/include/svx/DiagramDataInterface.hxx index aaa3a46968b3..f64dc3a09316 100644 --- a/include/svx/DiagramDataInterface.hxx +++ b/include/svx/DiagramDataInterface.hxx @@ -38,8 +38,10 @@ public: virtual std::vector<std::pair<OUString, OUString>> getChildren(const OUString& rParentId) const = 0; - // add new top-level node to data model - virtual void addNode(const OUString& rText) = 0; + // add new top-level node to data model, returns its id + virtual OUString addNode(const OUString& rText) = 0; + + virtual bool removeNode(const OUString& rNodeId) = 0; protected: ~DiagramDataInterface() throw() {} diff --git a/oox/source/drawingml/diagram/datamodel.cxx b/oox/source/drawingml/diagram/datamodel.cxx index 1f1794b31854..6b7d05ebe58d 100644 --- a/oox/source/drawingml/diagram/datamodel.cxx +++ b/oox/source/drawingml/diagram/datamodel.cxx @@ -29,6 +29,7 @@ #include <svx/DiagramDataInterface.hxx> #include <comphelper/xmltools.hxx> +#include <unordered_set> #include <iostream> #include <fstream> @@ -137,6 +138,12 @@ std::vector<std::pair<OUString, OUString>> DiagramData::getChildren(const OUStri pChild->second->msModelId, pChild->second->mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText()); } + + // HACK: empty items shouldn't appear there + aChildren.erase(std::remove_if(aChildren.begin(), aChildren.end(), + [](const std::pair<OUString, OUString>& aItem) { return aItem.first.isEmpty(); }), + aChildren.end()); + return aChildren; } @@ -154,7 +161,7 @@ void DiagramData::addConnection(sal_Int32 nType, const OUString& sSourceId, cons rCxn.mnSourceOrder = nMaxOrd + 1; } -void DiagramData::addNode(const OUString& rText) +OUString DiagramData::addNode(const OUString& rText) { const dgm::Point& rDataRoot = *getRootPoint(); OUString sPresRoot; @@ -163,11 +170,13 @@ void DiagramData::addNode(const OUString& rText) sPresRoot = aCxn.msDestId; if (sPresRoot.isEmpty()) - return; + return OUString(); + + OUString sNewNodeId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); dgm::Point aDataPoint; aDataPoint.mnType = XML_node; - aDataPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); + aDataPoint.msModelId = sNewNodeId; aDataPoint.mpShape.reset(new Shape()); aDataPoint.mpShape->setTextBody(std::make_shared<TextBody>()); TextRunPtr pTextRun(new TextRun()); @@ -208,6 +217,59 @@ void DiagramData::addNode(const OUString& rText) maPoints.push_back(aPresPoint); build(); + return sNewNodeId; +} + +bool DiagramData::removeNode(const OUString& rNodeId) +{ + // check if it doesn't have children + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_parOf && aCxn.msSourceId == rNodeId) + { + SAL_WARN("oox.drawingml", "Node has children - can't be removed"); + return false; + } + + dgm::Connection aParCxn; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_parOf && aCxn.msDestId == rNodeId) + aParCxn = aCxn; + + std::unordered_set<OUString> aIdsToRemove; + aIdsToRemove.insert(rNodeId); + if (!aParCxn.msParTransId.isEmpty()) + aIdsToRemove.insert(aParCxn.msParTransId); + if (!aParCxn.msSibTransId.isEmpty()) + aIdsToRemove.insert(aParCxn.msSibTransId); + + for (const dgm::Point& rPoint : maPoints) + if (aIdsToRemove.count(rPoint.msPresentationAssociationId)) + aIdsToRemove.insert(rPoint.msModelId); + + // instert also transition nodes + for (const auto& aCxn : maConnections) + if (aIdsToRemove.count(aCxn.msSourceId) || aIdsToRemove.count(aCxn.msDestId)) + if (!aCxn.msPresId.isEmpty()) + aIdsToRemove.insert(aCxn.msPresId); + + // remove connections + maConnections.erase(std::remove_if(maConnections.begin(), maConnections.end(), + [aIdsToRemove](const dgm::Connection& rCxn) { + return aIdsToRemove.count(rCxn.msSourceId) || aIdsToRemove.count(rCxn.msDestId); + }), + maConnections.end()); + + // remove data and presentation nodes + maPoints.erase(std::remove_if(maPoints.begin(), maPoints.end(), + [aIdsToRemove](const dgm::Point& rPoint) { + return aIdsToRemove.count(rPoint.msModelId); + }), + maPoints.end()); + + // TODO: fix source/dest order + + build(); + return true; } #ifdef DEBUG_OOX_DIAGRAM diff --git a/oox/source/drawingml/diagram/datamodel.hxx b/oox/source/drawingml/diagram/datamodel.hxx index b4c7ce7f82f7..7f7f0f4910c5 100644 --- a/oox/source/drawingml/diagram/datamodel.hxx +++ b/oox/source/drawingml/diagram/datamodel.hxx @@ -182,7 +182,8 @@ public: void dump() const; OUString getString() const override; std::vector<std::pair<OUString, OUString>> getChildren(const OUString& rParentId) const override; - void addNode(const OUString& rText) override; + OUString addNode(const OUString& rText) override; + bool removeNode(const OUString& rNodeId) override; private: void getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const; |