[Libreoffice-commits] core.git: include/svx svx/source
Tomaž Vajngerl (via logerrit)
logerrit at kemper.freedesktop.org
Wed Feb 10 13:17:00 UTC 2021
include/svx/devtools/DevelopmentToolDockingWindow.hxx | 4
svx/source/devtools/DevelopmentToolDockingWindow.cxx | 471 ++++++++++++------
2 files changed, 322 insertions(+), 153 deletions(-)
New commits:
commit 570df33b75298b7c7c3e7afd233d36d0cdf7e0a3
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Feb 3 21:33:29 2021 +0900
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Wed Feb 10 14:16:20 2021 +0100
devtools: handle object inspector with attached objects
This changes the object inspector tree view to create child nodes
on demand (when expanded) and attach specialized node objects to
the node, which are responsible to get the specific introspection
information for the current inspected UNO object.
Change-Id: Ib8431cc2a2c6d6d3ac7fd9db5bc61c9071d5e8f8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110462
Tested-by: Tomaž Vajngerl <quikee at gmail.com>
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/include/svx/devtools/DevelopmentToolDockingWindow.hxx b/include/svx/devtools/DevelopmentToolDockingWindow.hxx
index 8e24c2d0cd8d..1f10c0c2a672 100644
--- a/include/svx/devtools/DevelopmentToolDockingWindow.hxx
+++ b/include/svx/devtools/DevelopmentToolDockingWindow.hxx
@@ -40,9 +40,13 @@ private:
DECL_LINK(LeftSideSelected, weld::TreeView&, void);
DECL_LINK(SelectionToggled, weld::ToggleButton&, void);
+ DECL_LINK(ObjectInspectorExpandingHandler, const weld::TreeIter&, bool);
+
void inspectDocument();
void updateSelection();
+ void clearObjectInspectorChildren(weld::TreeIter const& rParent);
+
public:
DevelopmentToolDockingWindow(SfxBindings* pBindings, SfxChildWindow* pChildWindow,
vcl::Window* pParent);
diff --git a/svx/source/devtools/DevelopmentToolDockingWindow.cxx b/svx/source/devtools/DevelopmentToolDockingWindow.cxx
index da3b8d5896b5..8c519e807125 100644
--- a/svx/source/devtools/DevelopmentToolDockingWindow.cxx
+++ b/svx/source/devtools/DevelopmentToolDockingWindow.cxx
@@ -100,105 +100,6 @@ private:
SelectionChangeHandler& operator=(const SelectionChangeHandler&) = delete;
};
-} // end anonymous namespace
-
-DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBindings,
- SfxChildWindow* pChildWindow,
- vcl::Window* pParent)
- : SfxDockingWindow(pInputBindings, pChildWindow, pParent, "DevelopmentTool",
- "svx/ui/developmenttool.ui")
- , mpClassNameLabel(m_xBuilder->weld_label("class_name_value_id"))
- , mpClassListBox(m_xBuilder->weld_tree_view("class_listbox_id"))
- , mpLeftSideTreeView(m_xBuilder->weld_tree_view("leftside_treeview_id"))
- , mpSelectionToggle(m_xBuilder->weld_toggle_button("selection_toggle"))
- , maDocumentModelTreeHandler(
- mpLeftSideTreeView,
- pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel())
-{
- mpLeftSideTreeView->connect_changed(LINK(this, DevelopmentToolDockingWindow, LeftSideSelected));
- mpSelectionToggle->connect_toggled(LINK(this, DevelopmentToolDockingWindow, SelectionToggled));
-
- auto* pViewFrame = pInputBindings->GetDispatcher()->GetFrame();
-
- uno::Reference<frame::XController> xController = pViewFrame->GetFrame().GetController();
-
- mxRoot = pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel();
-
- introspect(mxRoot);
- maDocumentModelTreeHandler.inspectDocument();
- mxSelectionListener.set(new SelectionChangeHandler(xController, this));
-}
-
-IMPL_LINK(DevelopmentToolDockingWindow, LeftSideSelected, weld::TreeView&, rView, void)
-{
- if (mpSelectionToggle->get_state() == TRISTATE_TRUE)
- return;
-
- OUString sID = rView.get_selected_id();
- auto xObject = DocumentModelTreeHandler::getObjectByID(sID);
- if (xObject.is())
- introspect(xObject);
-}
-
-IMPL_LINK_NOARG(DevelopmentToolDockingWindow, SelectionToggled, weld::ToggleButton&, void)
-{
- updateSelection();
-}
-
-DevelopmentToolDockingWindow::~DevelopmentToolDockingWindow() { disposeOnce(); }
-
-void DevelopmentToolDockingWindow::dispose()
-{
- auto* pSelectionChangeHandler
- = dynamic_cast<SelectionChangeHandler*>(mxSelectionListener.get());
- if (pSelectionChangeHandler)
- pSelectionChangeHandler->disconnect();
-
- mxSelectionListener = uno::Reference<view::XSelectionChangeListener>();
- maDocumentModelTreeHandler.dispose();
-
- mpClassNameLabel.reset();
- mpClassListBox.reset();
- mpSelectionToggle.reset();
- mpLeftSideTreeView.reset();
-
- SfxDockingWindow::dispose();
-}
-
-void DevelopmentToolDockingWindow::updateSelection()
-{
- TriState eTriState = mpSelectionToggle->get_state();
- if (eTriState == TRISTATE_TRUE)
- {
- introspect(mxCurrentSelection);
- mpLeftSideTreeView->set_sensitive(false);
- }
- else
- {
- mpLeftSideTreeView->set_sensitive(true);
- LeftSideSelected(*mpLeftSideTreeView);
- }
-}
-
-void DevelopmentToolDockingWindow::ToggleFloatingMode()
-{
- SfxDockingWindow::ToggleFloatingMode();
-
- if (GetFloatingWindow())
- GetFloatingWindow()->SetMinOutputSizePixel(Size(300, 300));
-
- Invalidate();
-}
-
-void DevelopmentToolDockingWindow::selectionChanged(
- uno::Reference<uno::XInterface> const& xInterface)
-{
- mxCurrentSelection = xInterface;
- updateSelection();
-}
-
-namespace
-{
uno::Reference<reflection::XIdlClass>
TypeToIdlClass(const uno::Type& rType, const uno::Reference<uno::XComponentContext>& xContext)
{
@@ -345,60 +246,133 @@ OUString AnyToString(const uno::Any& aValue, const uno::Reference<uno::XComponen
}
return aRetStr;
}
-}
-void DevelopmentToolDockingWindow::introspect(uno::Reference<uno::XInterface> const& xInterface)
+// Object inspector nodes
+
+class ObjectInspectorNode
{
- if (!xInterface.is())
- return;
+public:
+ css::uno::Reference<css::uno::XInterface> mxObject;
- uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
- if (!xContext.is())
- return;
+ ObjectInspectorNode() = default;
- auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
- OUString aImplementationName = xServiceInfo->getImplementationName();
+ ObjectInspectorNode(css::uno::Reference<css::uno::XInterface> const& xObject)
+ : mxObject(xObject)
+ {
+ }
- mpClassNameLabel->set_label(aImplementationName);
+ virtual ~ObjectInspectorNode() {}
- mpClassListBox->freeze();
- mpClassListBox->clear();
+ virtual OUString getObjectName() = 0;
+
+ virtual void fillChildren(std::unique_ptr<weld::TreeView>& rTree, weld::TreeIter const& rParent)
+ = 0;
+};
- std::unique_ptr<weld::TreeIter> pParent = mpClassListBox->make_iterator();
- OUString aServicesString("Services");
- mpClassListBox->insert(nullptr, -1, &aServicesString, nullptr, nullptr, nullptr, false,
- pParent.get());
- mpClassListBox->set_text_emphasis(*pParent, true, 0);
+OUString lclAppendNode(std::unique_ptr<weld::TreeView>& pTree, ObjectInspectorNode* pEntry,
+ bool bChildrenOnDemand = false)
+{
+ OUString sName = pEntry->getObjectName();
+ OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
+ std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
+ pTree->insert(nullptr, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, pCurrent.get());
+ pTree->set_text_emphasis(*pCurrent, true, 0);
+ return sId;
+}
- std::unique_ptr<weld::TreeIter> pResult = mpClassListBox->make_iterator();
- const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames());
- for (auto const& aServiceName : aServiceNames)
+OUString lclAppendNodeToParent(std::unique_ptr<weld::TreeView>& pTree,
+ weld::TreeIter const& rParent, ObjectInspectorNode* pEntry,
+ bool bChildrenOnDemand = false)
+{
+ OUString sName = pEntry->getObjectName();
+ OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
+ std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
+ pTree->insert(&rParent, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, nullptr);
+ pTree->set_text_emphasis(*pCurrent, true, 0);
+ return sId;
+}
+
+OUString lclAppendNodeWithIterToParent(std::unique_ptr<weld::TreeView>& pTree,
+ weld::TreeIter const& rParent, weld::TreeIter& rCurrent,
+ ObjectInspectorNode* pEntry, bool bChildrenOnDemand = false)
+{
+ OUString sName = pEntry->getObjectName();
+ OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
+ pTree->insert(&rParent, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, &rCurrent);
+ pTree->set_text_emphasis(rCurrent, true, 0);
+ return sId;
+}
+
+class ObjectInspectorNamedNode : public ObjectInspectorNode
+{
+public:
+ OUString msName;
+
+ ObjectInspectorNamedNode(OUString const& rName,
+ css::uno::Reference<css::uno::XInterface> const& xObject)
+ : ObjectInspectorNode(xObject)
+ , msName(rName)
{
- mpClassListBox->insert(pParent.get(), -1, &aServiceName, nullptr, nullptr, nullptr, false,
- pResult.get());
- mpClassListBox->set_text_emphasis(*pResult, false, 0);
}
- uno::Reference<beans::XIntrospection> xIntrospection;
- xIntrospection = beans::theIntrospection::get(xContext);
+ OUString getObjectName() override { return msName; }
- uno::Reference<beans::XIntrospectionAccess> xIntrospectionAccess;
- xIntrospectionAccess = xIntrospection->inspect(uno::makeAny(xInterface));
+ void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
+ weld::TreeIter const& /*rParent*/) override
{
- OUString aPropertiesString("Properties");
+ }
+};
- mpClassListBox->insert(nullptr, -1, &aPropertiesString, nullptr, nullptr, nullptr, false,
- pParent.get());
- mpClassListBox->set_text_emphasis(*pParent, true, 0);
+class ServicesNode : public ObjectInspectorNamedNode
+{
+public:
+ ServicesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
+ : ObjectInspectorNamedNode("Services", xObject)
+ {
+ }
+
+ void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+ weld::TreeIter const& rParent) override
+ {
+ auto xServiceInfo = uno::Reference<lang::XServiceInfo>(mxObject, uno::UNO_QUERY);
+ const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames());
+ for (auto const& aServiceName : aServiceNames)
+ {
+ lclAppendNodeToParent(pTree, rParent,
+ new ObjectInspectorNamedNode(aServiceName, mxObject));
+ }
+ }
+};
- uno::Reference<beans::XPropertySet> xPropertySet(xInterface, uno::UNO_QUERY);
+class PropertiesNode : public ObjectInspectorNamedNode
+{
+public:
+ uno::Reference<uno::XComponentContext> mxContext;
+
+ PropertiesNode(css::uno::Reference<css::uno::XInterface> const& xObject,
+ uno::Reference<uno::XComponentContext> const& xContext)
+ : ObjectInspectorNamedNode("Properties", xObject)
+ , mxContext(xContext)
+ {
+ }
+
+ void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+ weld::TreeIter const& rParent) override
+ {
+ uno::Reference<beans::XIntrospection> xIntrospection
+ = beans::theIntrospection::get(mxContext);
+ auto xIntrospectionAccess = xIntrospection->inspect(uno::makeAny(mxObject));
const auto xProperties = xIntrospectionAccess->getProperties(
beans::PropertyConcept::ALL - beans::PropertyConcept::DANGEROUS);
+
+ uno::Reference<beans::XPropertySet> xPropertySet(mxObject, uno::UNO_QUERY);
+
for (auto const& xProperty : xProperties)
{
- mpClassListBox->insert(pParent.get(), -1, &xProperty.Name, nullptr, nullptr, nullptr,
- false, pResult.get());
+ std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
+ lclAppendNodeWithIterToParent(pTree, rParent, *pCurrent,
+ new ObjectInspectorNamedNode(xProperty.Name, mxObject));
if (xPropertySet.is())
{
@@ -406,50 +380,241 @@ void DevelopmentToolDockingWindow::introspect(uno::Reference<uno::XInterface> co
try
{
uno::Any aAny = xPropertySet->getPropertyValue(xProperty.Name);
- aValue = AnyToString(aAny, xContext);
+ aValue = AnyToString(aAny, mxContext);
}
catch (const beans::UnknownPropertyException&)
{
aValue = "UnknownPropertyException";
}
- mpClassListBox->set_text(*pResult, aValue, 1);
+ pTree->set_text(*pCurrent, aValue, 1);
}
}
}
+};
+
+class InterfacesNode : public ObjectInspectorNamedNode
+{
+public:
+ InterfacesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
+ : ObjectInspectorNamedNode("Interfaces", xObject)
+ {
+ }
+ void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+ weld::TreeIter const& rParent) override
{
- uno::Reference<lang::XTypeProvider> xTypeProvider(xInterface, uno::UNO_QUERY);
+ uno::Reference<lang::XTypeProvider> xTypeProvider(mxObject, uno::UNO_QUERY);
if (xTypeProvider.is())
{
- OUString aTypesString("Interfaces");
- mpClassListBox->insert(nullptr, -1, &aTypesString, nullptr, nullptr, nullptr, false,
- pParent.get());
- mpClassListBox->set_text_emphasis(*pParent, true, 0);
-
const auto xSequenceTypes = xTypeProvider->getTypes();
for (auto const& xType : xSequenceTypes)
{
OUString aName = xType.getTypeName();
- mpClassListBox->insert(pParent.get(), -1, &aName, nullptr, nullptr, nullptr, false,
- pResult.get());
+ lclAppendNodeToParent(pTree, rParent,
+ new ObjectInspectorNamedNode(aName, mxObject));
}
}
}
+};
+
+class MethodsNode : public ObjectInspectorNamedNode
+{
+public:
+ uno::Reference<uno::XComponentContext> mxContext;
+
+ MethodsNode(css::uno::Reference<css::uno::XInterface> const& xObject,
+ uno::Reference<uno::XComponentContext> const& xContext)
+ : ObjectInspectorNamedNode("Methods", xObject)
+ , mxContext(xContext)
+ {
+ }
+
+ void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+ weld::TreeIter const& rParent) override
+ {
+ uno::Reference<beans::XIntrospection> xIntrospection
+ = beans::theIntrospection::get(mxContext);
+ auto xIntrospectionAccess = xIntrospection->inspect(uno::makeAny(mxObject));
+
+ const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
+ for (auto const& xMethod : xMethods)
+ {
+ OUString aMethodName = xMethod->getName();
+
+ lclAppendNodeToParent(pTree, rParent,
+ new ObjectInspectorNamedNode(aMethodName, mxObject));
+ }
+ }
+};
+
+} // end anonymous namespace
+
+DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBindings,
+ SfxChildWindow* pChildWindow,
+ vcl::Window* pParent)
+ : SfxDockingWindow(pInputBindings, pChildWindow, pParent, "DevelopmentTool",
+ "svx/ui/developmenttool.ui")
+ , mpClassNameLabel(m_xBuilder->weld_label("class_name_value_id"))
+ , mpClassListBox(m_xBuilder->weld_tree_view("class_listbox_id"))
+ , mpLeftSideTreeView(m_xBuilder->weld_tree_view("leftside_treeview_id"))
+ , mpSelectionToggle(m_xBuilder->weld_toggle_button("selection_toggle"))
+ , maDocumentModelTreeHandler(
+ mpLeftSideTreeView,
+ pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel())
+{
+ mpLeftSideTreeView->connect_changed(LINK(this, DevelopmentToolDockingWindow, LeftSideSelected));
+ mpSelectionToggle->connect_toggled(LINK(this, DevelopmentToolDockingWindow, SelectionToggled));
+ mpClassListBox->connect_expanding(
+ LINK(this, DevelopmentToolDockingWindow, ObjectInspectorExpandingHandler));
+
+ auto* pViewFrame = pInputBindings->GetDispatcher()->GetFrame();
+
+ uno::Reference<frame::XController> xController = pViewFrame->GetFrame().GetController();
+
+ mxRoot = pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel();
+
+ introspect(mxRoot);
+ maDocumentModelTreeHandler.inspectDocument();
+ mxSelectionListener.set(new SelectionChangeHandler(xController, this));
+}
+
+IMPL_LINK(DevelopmentToolDockingWindow, LeftSideSelected, weld::TreeView&, rView, void)
+{
+ if (mpSelectionToggle->get_state() == TRISTATE_TRUE)
+ return;
+
+ OUString sID = rView.get_selected_id();
+ auto xObject = DocumentModelTreeHandler::getObjectByID(sID);
+ if (xObject.is())
+ introspect(xObject);
+}
+
+IMPL_LINK_NOARG(DevelopmentToolDockingWindow, SelectionToggled, weld::ToggleButton&, void)
+{
+ updateSelection();
+}
+
+void DevelopmentToolDockingWindow::clearObjectInspectorChildren(weld::TreeIter const& rParent)
+{
+ bool bChild = false;
+ do
+ {
+ bChild = mpClassListBox->iter_has_child(rParent);
+ if (bChild)
+ {
+ std::unique_ptr<weld::TreeIter> pChild = mpClassListBox->make_iterator(&rParent);
+ bChild = mpClassListBox->iter_children(*pChild);
+ if (bChild)
+ {
+ clearObjectInspectorChildren(*pChild);
+ OUString sID = mpClassListBox->get_id(*pChild);
+ auto* pEntry = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
+ delete pEntry;
+ mpClassListBox->remove(*pChild);
+ }
+ }
+ } while (bChild);
+}
- OUString aMethodsString("Methods");
- mpClassListBox->insert(nullptr, -1, &aMethodsString, nullptr, nullptr, nullptr, false,
- pParent.get());
- mpClassListBox->set_text_emphasis(*pParent, true, 0);
+DevelopmentToolDockingWindow::~DevelopmentToolDockingWindow() { disposeOnce(); }
+
+void DevelopmentToolDockingWindow::dispose()
+{
+ auto* pSelectionChangeHandler
+ = dynamic_cast<SelectionChangeHandler*>(mxSelectionListener.get());
+ if (pSelectionChangeHandler)
+ pSelectionChangeHandler->disconnect();
+
+ mxSelectionListener = uno::Reference<view::XSelectionChangeListener>();
+ maDocumentModelTreeHandler.dispose();
+
+ // destroy all ObjectInspectorNodes from the tree
+ mpClassListBox->all_foreach([this](weld::TreeIter& rEntry) {
+ OUString sID = mpClassListBox->get_id(rEntry);
+ auto* pEntry = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
+ delete pEntry;
+ return false;
+ });
+
+ // dispose welded objects
+ mpClassNameLabel.reset();
+ mpClassListBox.reset();
+ mpSelectionToggle.reset();
+ mpLeftSideTreeView.reset();
- const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
- for (auto const& xMethod : xMethods)
+ SfxDockingWindow::dispose();
+}
+
+void DevelopmentToolDockingWindow::updateSelection()
+{
+ TriState eTriState = mpSelectionToggle->get_state();
+ if (eTriState == TRISTATE_TRUE)
+ {
+ introspect(mxCurrentSelection);
+ mpLeftSideTreeView->set_sensitive(false);
+ }
+ else
{
- OUString aMethodName = xMethod->getName();
- mpClassListBox->insert(pParent.get(), -1, &aMethodName, nullptr, nullptr, nullptr, false,
- pResult.get());
- mpClassListBox->set_text_emphasis(*pResult, false, 0);
+ mpLeftSideTreeView->set_sensitive(true);
+ LeftSideSelected(*mpLeftSideTreeView);
}
+}
+
+void DevelopmentToolDockingWindow::ToggleFloatingMode()
+{
+ SfxDockingWindow::ToggleFloatingMode();
+
+ if (GetFloatingWindow())
+ GetFloatingWindow()->SetMinOutputSizePixel(Size(300, 300));
+
+ Invalidate();
+}
+
+IMPL_LINK(DevelopmentToolDockingWindow, ObjectInspectorExpandingHandler, weld::TreeIter const&,
+ rParent, bool)
+{
+ OUString sID = mpClassListBox->get_id(rParent);
+ if (sID.isEmpty())
+ return true;
+
+ clearObjectInspectorChildren(rParent);
+ auto* pNode = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
+ pNode->fillChildren(mpClassListBox, rParent);
+
+ return true;
+}
+
+void DevelopmentToolDockingWindow::selectionChanged(
+ uno::Reference<uno::XInterface> const& xInterface)
+{
+ mxCurrentSelection = xInterface;
+ updateSelection();
+}
+
+void DevelopmentToolDockingWindow::introspect(uno::Reference<uno::XInterface> const& xInterface)
+{
+ if (!xInterface.is())
+ return;
+
+ uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
+ if (!xContext.is())
+ return;
+
+ // Set implementation name
+ auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
+ OUString aImplementationName = xServiceInfo->getImplementationName();
+ mpClassNameLabel->set_label(aImplementationName);
+
+ // fill object inspector
+
+ mpClassListBox->freeze();
+ mpClassListBox->clear();
+
+ lclAppendNode(mpClassListBox, new ServicesNode(xInterface), true);
+ lclAppendNode(mpClassListBox, new InterfacesNode(xInterface), true);
+ lclAppendNode(mpClassListBox, new PropertiesNode(xInterface, xContext), true);
+ lclAppendNode(mpClassListBox, new MethodsNode(xInterface, xContext), true);
mpClassListBox->thaw();
}
More information about the Libreoffice-commits
mailing list