devtools: on demand create the content of tab pages

Until now all the tree views in each tab page were populated at
once when the object was inspected.
With this change, the tree views are filled on demand when the
user enters a tab page, and is cleaned when the user leaves a
tab page.

Change-Id: I7f2ff89ab4c09412563b71e6524d4529318dee85
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111533
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx b/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx
index 97b0c8e..f5c2149 100644
--- a/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx
+++ b/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx
@@ -37,6 +37,7 @@ private:
    std::unique_ptr<weld::TreeView> mpDocumentModelTreeView;
    std::unique_ptr<weld::ToggleButton> mpSelectionToggle;
    std::unique_ptr<weld::Toolbar> mpObjectInspectorToolbar;
    std::unique_ptr<weld::Notebook> mpObjectInspectorNotebook;

    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 c61da73..65a16be 100644
--- a/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx
+++ b/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx
@@ -30,6 +30,7 @@ private:
    std::unique_ptr<weld::TreeView>& mpMethodsTreeView;
    std::unique_ptr<weld::Label>& mpClassNameLabel;
    std::unique_ptr<weld::Toolbar>& mpObjectInspectorToolbar;
    std::unique_ptr<weld::Notebook>& mpObjectInspectorNotebook;

    std::deque<css::uno::Any> maInspectionStack;

@@ -58,7 +59,8 @@ public:
                               std::unique_ptr<weld::TreeView>& pPropertiesTreeView,
                               std::unique_ptr<weld::TreeView>& pMethodsTreeView,
                               std::unique_ptr<weld::Label>& pClassNameLabel,
                               std::unique_ptr<weld::Toolbar>& pObjectInspectorToolbar);
                               std::unique_ptr<weld::Toolbar>& pObjectInspectorToolbar,
                               std::unique_ptr<weld::Notebook>& pObjectInspectorNotebook);

    DECL_LINK(ExpandingHandlerInterfaces, const weld::TreeIter&, bool);
    DECL_LINK(ExpandingHandlerServices, const weld::TreeIter&, bool);
@@ -68,6 +70,8 @@ public:

    DECL_LINK(PopupMenuHandler, const CommandEvent&, bool);
    DECL_LINK(ToolbarButtonClicked, const OString&, void);
    DECL_LINK(NotebookEnterPage, const OString&, void);
    DECL_LINK(NotebookLeavePage, const OString&, bool);

    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 d7d0219..a6b3409 100644
--- a/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx
+++ b/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx
@@ -35,11 +35,13 @@ DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBi
    , 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"))
    , mpObjectInspectorNotebook(m_xBuilder->weld_notebook("object_inspector_notebookbar"))
    , maDocumentModelTreeHandler(
          mpDocumentModelTreeView,
          pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel())
    , maObjectInspectorTreeHandler(mpInterfacesTreeView, mpServicesTreeView, mpPropertiesTreeView,
                                   mpMethodsTreeView, mpClassNameLabel, mpObjectInspectorToolbar)
                                   mpMethodsTreeView, mpClassNameLabel, mpObjectInspectorToolbar,
                                   mpObjectInspectorNotebook)
{
    mpDocumentModelTreeView->connect_changed(
        LINK(this, DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler));
diff --git a/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx b/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx
index c100ed5f..c00ddc6 100644
--- a/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx
+++ b/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx
@@ -629,13 +629,15 @@ ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
    std::unique_ptr<weld::TreeView>& pPropertiesTreeView,
    std::unique_ptr<weld::TreeView>& pMethodsTreeView,
    std::unique_ptr<weld::Label>& pClassNameLabel,
    std::unique_ptr<weld::Toolbar>& pObjectInspectorToolbar)
    std::unique_ptr<weld::Toolbar>& pObjectInspectorToolbar,
    std::unique_ptr<weld::Notebook>& pObjectInspectorNotebook)
    : mpInterfacesTreeView(pInterfacesTreeView)
    , mpServicesTreeView(pServicesTreeView)
    , mpPropertiesTreeView(pPropertiesTreeView)
    , mpMethodsTreeView(pMethodsTreeView)
    , mpClassNameLabel(pClassNameLabel)
    , mpObjectInspectorToolbar(pObjectInspectorToolbar)
    , mpObjectInspectorNotebook(pObjectInspectorNotebook)
{
    mpInterfacesTreeView->connect_expanding(
        LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerInterfaces));
@@ -658,6 +660,11 @@ ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
        LINK(this, ObjectInspectorTreeHandler, ToolbarButtonClicked));
    mpObjectInspectorToolbar->set_item_sensitive("inspect", false);
    mpObjectInspectorToolbar->set_item_sensitive("back", false);

    mpObjectInspectorNotebook->connect_leave_page(
        LINK(this, ObjectInspectorTreeHandler, NotebookLeavePage));
    mpObjectInspectorNotebook->connect_enter_page(
        LINK(this, ObjectInspectorTreeHandler, NotebookEnterPage));
}

void ObjectInspectorTreeHandler::handleExpanding(std::unique_ptr<weld::TreeView>& pTreeView,
@@ -764,6 +771,72 @@ IMPL_LINK(ObjectInspectorTreeHandler, ToolbarButtonClicked, const OString&, rSel
    }
}

IMPL_LINK(ObjectInspectorTreeHandler, NotebookEnterPage, const OString&, rPageId, void)
{
    uno::Any aAny = maInspectionStack.back();
    if (aAny.hasValue())
    {
        uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
        if (rPageId == "object_inspector_interfaces_tab")
        {
            mpInterfacesTreeView->freeze();
            clearAll(mpInterfacesTreeView);
            appendInterfaces(xInterface);
            mpInterfacesTreeView->thaw();
        }
        else if (rPageId == "object_inspector_services_tab")
        {
            mpServicesTreeView->freeze();
            clearAll(mpServicesTreeView);
            appendServices(xInterface);
            mpServicesTreeView->thaw();
        }
        else if (rPageId == "object_inspector_properties_tab")
        {
            mpPropertiesTreeView->freeze();
            clearAll(mpPropertiesTreeView);
            appendProperties(xInterface);
            mpPropertiesTreeView->thaw();
        }
        else if (rPageId == "object_inspector_methods_tab")
        {
            mpMethodsTreeView->freeze();
            clearAll(mpMethodsTreeView);
            appendMethods(xInterface);
            mpMethodsTreeView->thaw();
        }
    }
}

IMPL_LINK(ObjectInspectorTreeHandler, NotebookLeavePage, const OString&, rPageId, bool)
{
    if (rPageId == "object_inspector_interfaces_tab")
    {
        mpInterfacesTreeView->freeze();
        clearAll(mpInterfacesTreeView);
        mpInterfacesTreeView->thaw();
    }
    else if (rPageId == "object_inspector_services_tab")
    {
        mpServicesTreeView->freeze();
        clearAll(mpServicesTreeView);
        mpServicesTreeView->thaw();
    }
    else if (rPageId == "object_inspector_properties_tab")
    {
        mpPropertiesTreeView->freeze();
        clearAll(mpPropertiesTreeView);
        mpPropertiesTreeView->thaw();
    }
    else if (rPageId == "object_inspector_methods_tab")
    {
        mpMethodsTreeView->freeze();
        clearAll(mpMethodsTreeView);
        mpMethodsTreeView->thaw();
    }
    return true;
}

void ObjectInspectorTreeHandler::clearObjectInspectorChildren(
    std::unique_ptr<weld::TreeView>& pTreeView, weld::TreeIter const& rParent)
{
@@ -891,26 +964,8 @@ void ObjectInspectorTreeHandler::inspectObject(uno::Reference<uno::XInterface> c
    OUString aImplementationName = xServiceInfo->getImplementationName();
    mpClassNameLabel->set_label(aImplementationName);

    // fill object inspector
    mpInterfacesTreeView->freeze();
    clearAll(mpInterfacesTreeView);
    appendInterfaces(xInterface);
    mpInterfacesTreeView->thaw();

    mpServicesTreeView->freeze();
    clearAll(mpServicesTreeView);
    appendServices(xInterface);
    mpServicesTreeView->thaw();

    mpPropertiesTreeView->freeze();
    clearAll(mpPropertiesTreeView);
    appendProperties(xInterface);
    mpPropertiesTreeView->thaw();

    mpMethodsTreeView->freeze();
    clearAll(mpMethodsTreeView);
    appendMethods(xInterface);
    mpMethodsTreeView->thaw();
    auto rPageId = mpObjectInspectorNotebook->get_current_page_ident();
    NotebookEnterPage(rPageId);
}

void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface)
diff --git a/sfx2/uiconfig/ui/developmenttool.ui b/sfx2/uiconfig/ui/developmenttool.ui
index a234169..b915d1f 100644
--- a/sfx2/uiconfig/ui/developmenttool.ui
+++ b/sfx2/uiconfig/ui/developmenttool.ui
@@ -145,7 +145,7 @@
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <child>
              <object class="GtkNotebook">
              <object class="GtkNotebook" id="object_inspector_notebookbar">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="hexpand">True</property>
@@ -188,7 +188,7 @@
                  </object>
                </child>
                <child type="tab">
                  <object class="GtkLabel">
                  <object class="GtkLabel" id="object_inspector_interfaces_tab">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <property name="label" translatable="yes" context="developmenttool|interfaces">Interfaces</property>
@@ -237,7 +237,7 @@
                  </packing>
                </child>
                <child type="tab">
                  <object class="GtkLabel">
                  <object class="GtkLabel" id="object_inspector_services_tab">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <property name="label" translatable="yes" context="developmenttool|services">Services</property>
@@ -311,7 +311,7 @@
                  </packing>
                </child>
                <child type="tab">
                  <object class="GtkLabel">
                  <object class="GtkLabel" id="object_inspector_properties_tab">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <property name="label" translatable="yes" context="developmenttool|properties">Properties</property>
@@ -397,7 +397,7 @@
                  </packing>
                </child>
                <child type="tab">
                  <object class="GtkLabel">
                  <object class="GtkLabel" id="object_inspector_methods_tab">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <property name="label" translatable="yes" context="developmenttool|methods">Methods</property>