include/sfx2/devtools/DevelopmentToolDockingWindow.hxx | 1 include/sfx2/devtools/ObjectInspectorTreeHandler.hxx | 21 ++ sfx2/source/devtools/DevelopmentToolDockingWindow.cxx | 4 sfx2/source/devtools/ObjectInspectorTreeHandler.cxx | 152 ++++++++++++++--- sfx2/uiconfig/ui/developmenttool.ui | 123 +++++++++---- 5 files changed, 238 insertions(+), 63 deletions(-)
New commits: commit eb3789bd35e9dc62e92008467bfaa0650cd8d6be Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Thu Feb 25 20:58:42 2021 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sun Feb 28 01:13:30 2021 +0100 devtools: object inspector toolbar and object stack This change adds a toolbar to the object inspector with buttons for inspect (which just links to the same action added to the context menu) and back. Back uses the newly added object stack to return to the previously inspected object. Only the objects which we used the "inspect" command in the object inspector tree are added to the object stack. Change-Id: Icb5b6e841200d6e0e41e260092a195fc84729d0f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111532 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx b/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx index f3633189c9b6..97b0c8e06e68 100644 --- a/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx +++ b/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx @@ -36,6 +36,7 @@ private: std::unique_ptr<weld::TreeView> mpMethodsTreeView; std::unique_ptr<weld::TreeView> mpDocumentModelTreeView; std::unique_ptr<weld::ToggleButton> mpSelectionToggle; + std::unique_ptr<weld::Toolbar> mpObjectInspectorToolbar; css::uno::Reference<css::uno::XInterface> mxRoot; css::uno::Reference<css::uno::XInterface> mxCurrentSelection; diff --git a/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx b/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx index 7008a398df5a..c61da73aa6e4 100644 --- a/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx +++ b/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx @@ -18,6 +18,9 @@ #include <com/sun/star/uno/XInterface.hpp> #include <com/sun/star/uno/Reference.hxx> +#include <memory> +#include <deque> + class ObjectInspectorTreeHandler { private: @@ -25,8 +28,10 @@ private: std::unique_ptr<weld::TreeView>& mpServicesTreeView; std::unique_ptr<weld::TreeView>& mpPropertiesTreeView; std::unique_ptr<weld::TreeView>& mpMethodsTreeView; - std::unique_ptr<weld::Label>& mpClassNameLabel; + std::unique_ptr<weld::Toolbar>& mpObjectInspectorToolbar; + + std::deque<css::uno::Any> maInspectionStack; static void clearObjectInspectorChildren(std::unique_ptr<weld::TreeView>& pTreeView, weld::TreeIter const& rParent); @@ -39,18 +44,30 @@ private: void appendProperties(css::uno::Reference<css::uno::XInterface> const& xInterface); void appendMethods(css::uno::Reference<css::uno::XInterface> const& xInterface); + void inspectObject(css::uno::Reference<css::uno::XInterface> const& xInterface); + + void clearStack(); + void addToStack(css::uno::Any const& rAny); + css::uno::Any popFromStack(); + + void updateBackButtonState(); + public: ObjectInspectorTreeHandler(std::unique_ptr<weld::TreeView>& pInterfacesTreeView, std::unique_ptr<weld::TreeView>& pServicesTreeView, std::unique_ptr<weld::TreeView>& pPropertiesTreeView, std::unique_ptr<weld::TreeView>& pMethodsTreeView, - std::unique_ptr<weld::Label>& pClassNameLabel); + std::unique_ptr<weld::Label>& pClassNameLabel, + std::unique_ptr<weld::Toolbar>& pObjectInspectorToolbar); DECL_LINK(ExpandingHandlerInterfaces, const weld::TreeIter&, bool); DECL_LINK(ExpandingHandlerServices, const weld::TreeIter&, bool); DECL_LINK(ExpandingHandlerProperties, const weld::TreeIter&, bool); DECL_LINK(ExpandingHandlerMethods, const weld::TreeIter&, bool); + DECL_LINK(SelectionChanged, weld::TreeView&, void); + DECL_LINK(PopupMenuHandler, const CommandEvent&, bool); + DECL_LINK(ToolbarButtonClicked, const OString&, void); void introspect(css::uno::Reference<css::uno::XInterface> const& xInterface); diff --git a/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx b/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx index 6bd92f17256d..d7d02198d331 100644 --- a/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx +++ b/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx @@ -34,11 +34,12 @@ DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBi , mpMethodsTreeView(m_xBuilder->weld_tree_view("methods_treeview_id")) , mpDocumentModelTreeView(m_xBuilder->weld_tree_view("leftside_treeview_id")) , mpSelectionToggle(m_xBuilder->weld_toggle_button("selection_toggle")) + , mpObjectInspectorToolbar(m_xBuilder->weld_toolbar("object_inspector_toolbar")) , maDocumentModelTreeHandler( mpDocumentModelTreeView, pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel()) , maObjectInspectorTreeHandler(mpInterfacesTreeView, mpServicesTreeView, mpPropertiesTreeView, - mpMethodsTreeView, mpClassNameLabel) + mpMethodsTreeView, mpClassNameLabel, mpObjectInspectorToolbar) { mpDocumentModelTreeView->connect_changed( LINK(this, DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler)); @@ -116,6 +117,7 @@ void DevelopmentToolDockingWindow::dispose() mpMethodsTreeView.reset(); mpSelectionToggle.reset(); mpDocumentModelTreeView.reset(); + mpObjectInspectorToolbar.reset(); SfxDockingWindow::dispose(); } diff --git a/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx b/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx index 54cebc87c2a4..c100ed5fff31 100644 --- a/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx +++ b/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx @@ -593,6 +593,34 @@ ObjectInspectorNodeInterface* BasicValueNode::createNodeObjectForAny(OUString co return new BasicValueNode(rName, rAny, mxContext); } +ObjectInspectorNodeInterface* getSelectedNode(weld::TreeView const& rTreeView) +{ + OUString sID = rTreeView.get_selected_id(); + if (sID.isEmpty()) + return nullptr; + + if (auto* pNode = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64())) + return pNode; + + return nullptr; +} + +uno::Reference<uno::XInterface> getSelectedXInterface(weld::TreeView const& rTreeView) +{ + uno::Reference<uno::XInterface> xInterface; + + if (auto* pNode = getSelectedNode(rTreeView)) + { + if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode)) + { + uno::Any aAny = pBasicValueNode->getAny(); + xInterface.set(aAny, uno::UNO_QUERY); + } + } + + return xInterface; +} + } // end anonymous namespace ObjectInspectorTreeHandler::ObjectInspectorTreeHandler( @@ -600,12 +628,14 @@ ObjectInspectorTreeHandler::ObjectInspectorTreeHandler( std::unique_ptr<weld::TreeView>& pServicesTreeView, std::unique_ptr<weld::TreeView>& pPropertiesTreeView, std::unique_ptr<weld::TreeView>& pMethodsTreeView, - std::unique_ptr<weld::Label>& pClassNameLabel) + std::unique_ptr<weld::Label>& pClassNameLabel, + std::unique_ptr<weld::Toolbar>& pObjectInspectorToolbar) : mpInterfacesTreeView(pInterfacesTreeView) , mpServicesTreeView(pServicesTreeView) , mpPropertiesTreeView(pPropertiesTreeView) , mpMethodsTreeView(pMethodsTreeView) , mpClassNameLabel(pClassNameLabel) + , mpObjectInspectorToolbar(pObjectInspectorToolbar) { mpInterfacesTreeView->connect_expanding( LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerInterfaces)); @@ -618,6 +648,16 @@ ObjectInspectorTreeHandler::ObjectInspectorTreeHandler( mpPropertiesTreeView->connect_popup_menu( LINK(this, ObjectInspectorTreeHandler, PopupMenuHandler)); + + mpInterfacesTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged)); + mpServicesTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged)); + mpPropertiesTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged)); + mpMethodsTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged)); + + mpObjectInspectorToolbar->connect_clicked( + LINK(this, ObjectInspectorTreeHandler, ToolbarButtonClicked)); + mpObjectInspectorToolbar->set_item_sensitive("inspect", false); + mpObjectInspectorToolbar->set_item_sensitive("back", false); } void ObjectInspectorTreeHandler::handleExpanding(std::unique_ptr<weld::TreeView>& pTreeView, @@ -659,41 +699,69 @@ IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerMethods, weld::TreeIter co return true; } +IMPL_LINK(ObjectInspectorTreeHandler, SelectionChanged, weld::TreeView&, rTreeView, void) +{ + bool bHaveNodeWithObject = false; + + if (mpPropertiesTreeView.get() == &rTreeView) + { + auto* pNode = getSelectedNode(rTreeView); + if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode)) + { + uno::Any aAny = pBasicValueNode->getAny(); + uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY); + bHaveNodeWithObject = xInterface.is(); + } + } + + mpObjectInspectorToolbar->set_item_sensitive("inspect", bHaveNodeWithObject); +} + IMPL_LINK(ObjectInspectorTreeHandler, PopupMenuHandler, const CommandEvent&, rCommandEvent, bool) { if (rCommandEvent.GetCommand() != CommandEventId::ContextMenu) return false; - uno::Any aAny; - OUString sID = mpPropertiesTreeView->get_selected_id(); - if (sID.isEmpty()) - return false; + auto xInterface = getSelectedXInterface(*mpPropertiesTreeView); + if (xInterface.is()) + { + std::unique_ptr<weld::Builder> xBuilder( + Application::CreateBuilder(mpPropertiesTreeView.get(), "sfx/ui/devtoolsmenu.ui")); + std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("inspect_menu")); - auto* pNode = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64()); - if (pNode) + OString sCommand( + xMenu->popup_at_rect(mpPropertiesTreeView.get(), + tools::Rectangle(rCommandEvent.GetMousePosPixel(), Size(1, 1)))); + + if (sCommand == "inspect") + { + addToStack(uno::Any(xInterface)); + inspectObject(xInterface); + } + } + return true; +} + +IMPL_LINK(ObjectInspectorTreeHandler, ToolbarButtonClicked, const OString&, rSelectionId, void) +{ + if (rSelectionId == "inspect") { - auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode); - if (pBasicValueNode) + auto xInterface = getSelectedXInterface(*mpPropertiesTreeView); + if (xInterface.is()) + { + addToStack(uno::Any(xInterface)); + inspectObject(xInterface); + } + } + else if (rSelectionId == "back") + { + uno::Any aAny = popFromStack(); + if (aAny.hasValue()) { - aAny = pBasicValueNode->getAny(); uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY); - if (xInterface.is()) - { - std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder( - mpPropertiesTreeView.get(), "sfx/ui/devtoolsmenu.ui")); - std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("inspect_menu")); - - OString sCommand(xMenu->popup_at_rect( - mpPropertiesTreeView.get(), - tools::Rectangle(rCommandEvent.GetMousePosPixel(), Size(1, 1)))); - if (sCommand == "inspect") - { - introspect(xInterface); - } - } + inspectObject(xInterface); } } - return true; } void ObjectInspectorTreeHandler::clearObjectInspectorChildren( @@ -784,7 +852,32 @@ void ObjectInspectorTreeHandler::appendMethods(uno::Reference<uno::XInterface> c } } -void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface) +void ObjectInspectorTreeHandler::updateBackButtonState() +{ + mpObjectInspectorToolbar->set_item_sensitive("back", maInspectionStack.size() > 1); +} + +void ObjectInspectorTreeHandler::clearStack() +{ + maInspectionStack.clear(); + updateBackButtonState(); +} + +void ObjectInspectorTreeHandler::addToStack(css::uno::Any const& rAny) +{ + maInspectionStack.push_back(rAny); + updateBackButtonState(); +} + +css::uno::Any ObjectInspectorTreeHandler::popFromStack() +{ + maInspectionStack.pop_back(); + uno::Any aAny = maInspectionStack.back(); + updateBackButtonState(); + return aAny; +} + +void ObjectInspectorTreeHandler::inspectObject(uno::Reference<uno::XInterface> const& xInterface) { if (!xInterface.is()) return; @@ -820,6 +913,13 @@ void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> cons mpMethodsTreeView->thaw(); } +void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface) +{ + clearStack(); + addToStack(uno::Any(xInterface)); + inspectObject(xInterface); +} + void ObjectInspectorTreeHandler::dispose() { clearAll(mpInterfacesTreeView); diff --git a/sfx2/uiconfig/ui/developmenttool.ui b/sfx2/uiconfig/ui/developmenttool.ui index 3eeb94859885..a234169405e8 100644 --- a/sfx2/uiconfig/ui/developmenttool.ui +++ b/sfx2/uiconfig/ui/developmenttool.ui @@ -134,7 +134,7 @@ </packing> </child> <child> - <!-- n-columns=2 n-rows=2 --> + <!-- n-columns=1 n-rows=2 --> <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -144,38 +144,6 @@ <property name="margin-bottom">6</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <child> - <object class="GtkLabel" id="class_name_label"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="hexpand">False</property> - <property name="vexpand">False</property> - <property name="label" translatable="yes" context="developmenttool|classname">Class name:</property> - <accessibility> - <relation type="label-for" target="class_name_value_id"/> - </accessibility> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="class_name_value_id"> - <property name="name">class_name_id</property> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="hexpand">True</property> - <property name="selectable">True</property> - <accessibility> - <relation type="labelled-by" target="class_name_label"/> - </accessibility> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">0</property> - </packing> - </child> <child> <object class="GtkNotebook"> <property name="visible">True</property> @@ -443,7 +411,94 @@ <packing> <property name="left-attach">0</property> <property name="top-attach">1</property> - <property name="width">2</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkToolbar" id="object_inspector_toolbar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="toolbar-style">icons</property> + <child> + <object class="GtkToolButton" id="back"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes" context="developmenttool|back">Back</property> + <property name="label" translatable="yes" context="developmenttool|back">Back</property> + <property name="use-underline">True</property> + <property name="icon-name">cmd/lc_prevrecord.png</property> + </object> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <object class="GtkToolButton" id="inspect"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes" context="developmenttool|inspect">Inspect</property> + <property name="label" translatable="yes" context="developmenttool|inspect">Inspect</property> + <property name="use-underline">True</property> + <property name="icon-name">cmd/lc_recsearch.png</property> + </object> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="class_name_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="xpad">6</property> + <property name="ypad">6</property> + <property name="label" translatable="yes" context="developmenttool|classname">Class name:</property> + <accessibility> + <relation type="label-for" target="class_name_value_id"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="class_name_value_id"> + <property name="name">class_name_id</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <accessibility> + <relation type="labelled-by" target="class_name_label"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> </packing> </child> </object> _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits