compilerplugins/clang/badstatics.cxx  |    7 -
 vcl/Library_vcl.mk                    |    1 
 vcl/inc/jsdialog/jsdialogbuilder.hxx  |   24 +---
 vcl/inc/jsdialog/jsdialogregister.hxx |   52 ++++++++
 vcl/jsdialog/executor.cxx             |   14 +-
 vcl/jsdialog/jsdialogbuilder.cxx      |  197 +++-------------------------------
 vcl/jsdialog/jsdialogregister.cxx     |   74 ++++++++++++
 7 files changed, 174 insertions(+), 195 deletions(-)

New commits:
commit 969f242f2e63deef3609809dbc2d70eeb40d81f4
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Tue Dec 3 13:25:04 2024 +0100
Commit:     Szymon Kłos <szymon.k...@collabora.com>
CommitDate: Tue Dec 10 12:15:42 2024 +0100

    jsdialog: share code for widget registry
    
    - move all helpers for widgets registration into
      separate file
    - share code for Widgets, Menu and Popup register
    
    Change-Id: I3449721d7e436ff4459edb7990c1af860b78054f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177738
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178205
    Tested-by: Jenkins
    Reviewed-by: Szymon Kłos <szymon.k...@collabora.com>

diff --git a/compilerplugins/clang/badstatics.cxx 
b/compilerplugins/clang/badstatics.cxx
index 3a69f78caef8..bb4663f71e35 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -208,8 +208,11 @@ public:
                 || (loplugin::DeclCheck(pVarDecl).Var("maThreadSpecific")
                     .Class("ScDocument").GlobalNamespace()) // not owning
                 || name == "s_aLOKWindowsMap" // LOK only, guarded by assert, 
and LOK never tries to perform a VCL cleanup
-                || name == "s_aLOKWeldBuildersMap" // LOK only, similar case 
as above
-                || name == "s_aLOKPopupsMap" // LOK only, similar case as above
+                    // vcl/inc/jsdialog/jsdialogbuilder.hxx
+                || name == "m_aWidgets" // LOK only, similar case as above
+                || name == "m_aPopups" // LOK only, similar case as above
+                || name == "m_aMenus" // LOK only, similar case as above
+                    //
                 || name == "gNotebookBarManager" // LOK only case, when 
notebookbar is closed - VclPtr instance is removed
                 || name == "gStaticManager" // vcl/source/graphic/Manager.cxx 
- stores non-owning pointers
                 || name == "aThreadedInterpreterPool"    // 
ScInterpreterContext(Pool), not owning
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index c410b94fddd5..8c8f5fb88199 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -540,6 +540,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/backendtest/GraphicsRenderTests \
     vcl/jsdialog/enabled \
     vcl/jsdialog/jsdialogbuilder \
+    vcl/jsdialog/jsdialogregister \
     vcl/jsdialog/executor \
 ))
 
diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx 
b/vcl/inc/jsdialog/jsdialogbuilder.hxx
index 420722c9997b..41f261924288 100644
--- a/vcl/inc/jsdialog/jsdialogbuilder.hxx
+++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx
@@ -9,6 +9,7 @@
 
 #pragma once
 
+#include <jsdialog/jsdialogregister.hxx>
 #include <utility>
 #include <vcl/weld.hxx>
 #include <vcl/jsdialog/executor.hxx>
@@ -44,8 +45,6 @@ namespace vcl
 class ILibreOfficeKitNotifier;
 }
 
-typedef std::map<OUString, weld::Widget*> WidgetMap;
-
 namespace jsdialog
 {
 enum MessageType
@@ -59,6 +58,8 @@ enum MessageType
 };
 }
 
+typedef jsdialog::WidgetRegister<weld::Widget*> WidgetMap;
+
 /// Class with the message description for storing in the queue
 class JSDialogMessageInfo
 {
@@ -211,6 +212,10 @@ public:
 
 class JSInstanceBuilder final : public SalInstanceBuilder, public 
JSDialogSender
 {
+    static jsdialog::WidgetRegister<std::shared_ptr<WidgetMap>> m_aWidgets;
+    static jsdialog::WidgetRegister<VclPtr<vcl::Window>> m_aPopups;
+    static jsdialog::WidgetRegister<weld::Menu*> m_aMenus;
+
     sal_uInt64 m_nWindowId;
     /// used in case of tab pages where dialog is not a direct top level
     VclPtr<vcl::Window> m_aParentDialog;
@@ -238,12 +243,10 @@ class JSInstanceBuilder final : public 
SalInstanceBuilder, public JSDialogSender
                                                    const OUString& rWidget,
                                                    
std::unique_ptr<jsdialog::ActionDataMap> pData);
 
-    static std::map<OUString, WidgetMap>& GetLOKWeldWidgetsMap();
     static void InsertWindowToMap(const OUString& nWindowId);
     void RememberWidget(OUString id, weld::Widget* pWidget);
     static void RememberWidget(const OUString& nWindowId, const OUString& id,
                                weld::Widget* pWidget);
-    static weld::Widget* FindWeldWidgetsMap(const OUString& nWindowId, const 
OUString& rWidget);
 
     OUString getMapIdFromWindowId() const;
 
@@ -322,19 +325,14 @@ public:
                         VclButtonsType eButtonType, const OUString& 
rPrimaryMessage,
                         const vcl::ILibreOfficeKitNotifier* pNotifier = 
nullptr);
 
-    static void AddChildWidget(const OUString& nWindowId, const OUString& id,
-                               weld::Widget* pWidget);
-    static void RemoveWindowWidget(const OUString& nWindowId);
+    // regular widgets
+    static jsdialog::WidgetRegister<std::shared_ptr<WidgetMap>>& Widgets() { 
return m_aWidgets; };
 
     // we need to remember original popup window to close it properly (its 
handled by vcl)
-    static void RememberPopup(const OUString& nWindowId, const 
VclPtr<vcl::Window>& pWidget);
-    static void ForgetPopup(const OUString& nWindowId);
-    static vcl::Window* FindPopup(const OUString& nWindowId);
+    static jsdialog::WidgetRegister<VclPtr<vcl::Window>>& Popups() { return 
m_aPopups; }
 
     // menus in separate container as they don't share base class with 
weld::Widget
-    static void RememberMenu(const OUString& nWindowId, weld::Menu* pMenu);
-    static void ForgetMenu(const OUString& nWindowId);
-    static weld::Menu* FindMenu(const OUString& nWindowId);
+    static jsdialog::WidgetRegister<weld::Menu*>& Menus() { return m_aMenus; }
 
 private:
     const OUString& GetTypeOfJSON() const;
diff --git a/vcl/inc/jsdialog/jsdialogregister.hxx 
b/vcl/inc/jsdialog/jsdialogregister.hxx
new file mode 100644
index 000000000000..85a772679a55
--- /dev/null
+++ b/vcl/inc/jsdialog/jsdialogregister.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <map>
+#include <rtl/ustring.hxx>
+
+namespace jsdialog
+{
+template <class T> class WidgetRegister
+{
+    // Map to remember the LOKWindowId <-> widget binding.
+    std::map<OUString, T> m_aWidgetMap;
+    std::map<OUString, T>& Map() { return m_aWidgetMap; }
+
+public:
+    void Remember(const OUString& rId, T pWidget);
+    void Forget(const OUString& rId);
+    T Find(const OUString& rId);
+};
+
+template <class T> void WidgetRegister<T>::Remember(const OUString& nWindowId, 
T pMenu)
+{
+    Map()[nWindowId] = pMenu;
+}
+
+template <class T> void WidgetRegister<T>::Forget(const OUString& nWindowId)
+{
+    auto it = Map().find(nWindowId);
+    if (it != Map().end())
+        Map().erase(it);
+}
+
+template <class T> T WidgetRegister<T>::Find(const OUString& nWindowId)
+{
+    const auto it = Map().find(nWindowId);
+
+    if (it != Map().end())
+        return it->second;
+
+    return nullptr;
+}
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx
index bb000d3daa97..10bdad905db5 100644
--- a/vcl/jsdialog/executor.cxx
+++ b/vcl/jsdialog/executor.cxx
@@ -37,7 +37,8 @@ StringMap jsonToStringMap(const char* pJSON)
 
 void SendFullUpdate(const OUString& nWindowId, const OUString& rWidget)
 {
-    weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, 
rWidget);
+    auto aWidgetMap = JSInstanceBuilder::Widgets().Find(nWindowId);
+    weld::Widget* pWidget = aWidgetMap ? aWidgetMap->Find(rWidget) : nullptr;
     if (auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget))
         pJSWidget->sendFullUpdate();
 }
@@ -45,14 +46,16 @@ void SendFullUpdate(const OUString& nWindowId, const 
OUString& rWidget)
 void SendAction(const OUString& nWindowId, const OUString& rWidget,
                 std::unique_ptr<ActionDataMap> pData)
 {
-    weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, 
rWidget);
+    auto aWidgetMap = JSInstanceBuilder::Widgets().Find(nWindowId);
+    weld::Widget* pWidget = aWidgetMap ? aWidgetMap->Find(rWidget) : nullptr;
     if (auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget))
         pJSWidget->sendAction(std::move(pData));
 }
 
 bool ExecuteAction(const OUString& nWindowId, const OUString& rWidget, 
StringMap& rData)
 {
-    weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, 
rWidget);
+    auto aWidgetMap = JSInstanceBuilder::Widgets().Find(nWindowId);
+    weld::Widget* pWidget = aWidgetMap ? aWidgetMap->Find(rWidget) : nullptr;
 
     OUString sControlType = rData[u"type"_ustr];
     OUString sAction = rData[u"cmd"_ustr];
@@ -63,7 +66,8 @@ bool ExecuteAction(const OUString& nWindowId, const OUString& 
rWidget, StringMap
         if (pWidget == nullptr || (pButton && 
!pButton->is_custom_handler_set()))
         {
             // welded wrapper not found - use response code instead
-            pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, 
u"__DIALOG__"_ustr);
+            auto aWindowMap = JSInstanceBuilder::Widgets().Find(nWindowId);
+            pWidget = aWindowMap ? aWindowMap->Find(u"__DIALOG__"_ustr) : 
nullptr;
             sControlType = "dialog";
             sAction = "response";
         }
@@ -79,7 +83,7 @@ bool ExecuteAction(const OUString& nWindowId, const OUString& 
rWidget, StringMap
         // weld::Menu doesn't have base of weld::Widget
         if (sControlType == "menu")
         {
-            weld::Menu* pMenu = JSInstanceBuilder::FindMenu(nWindowId);
+            weld::Menu* pMenu = JSInstanceBuilder::Menus().Find(nWindowId);
             if (pMenu && sAction == "activated")
             {
                 LOKTrigger::trigger_activated(*pMenu, rData["data"]);
diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx
index 5c1e82397f9f..290710471baa 100644
--- a/vcl/jsdialog/jsdialogbuilder.cxx
+++ b/vcl/jsdialog/jsdialogbuilder.cxx
@@ -32,22 +32,6 @@
 #include <vcl/cvtgrf.hxx>
 #include <wizdlg.hxx>
 
-static std::map<OUString, vcl::Window*>& GetLOKPopupsMap()
-{
-    // Map to remember the LOKWindowId <-> vcl popup binding.
-    static std::map<OUString, vcl::Window*> s_aLOKPopupsMap;
-
-    return s_aLOKPopupsMap;
-}
-
-static std::map<OUString, weld::Menu*>& GetLOKMenusMap()
-{
-    // Map to remember the LOKWindowId <-> weld menu binding.
-    static std::map<OUString, weld::Menu*> s_aLOKMenusMap;
-
-    return s_aLOKMenusMap;
-}
-
 namespace
 {
 void response_help(vcl::Window* pWindow)
@@ -495,15 +479,6 @@ void JSDropTarget::fire_dragEnter(const 
css::datatransfer::dnd::DropTargetDragEn
     }
 }
 
-OUString JSInstanceBuilder::getMapIdFromWindowId() const
-{
-    if (m_sTypeOfJSON == "sidebar" || m_sTypeOfJSON == "notebookbar"
-        || m_sTypeOfJSON == "formulabar")
-        return OUString::number(m_nWindowId) + m_sTypeOfJSON;
-    else
-        return OUString::number(m_nWindowId);
-}
-
 // used for dialogs
 JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const 
std::u16string_view sUIRoot,
                                      const OUString& rUIFile, bool bPopup)
@@ -693,153 +668,19 @@ JSInstanceBuilder::~JSInstanceBuilder()
 
     if (m_nWindowId && (m_bHasTopLevelDialog || m_bIsNotebookbar))
     {
-        GetLOKWeldWidgetsMap().erase(getMapIdFromWindowId());
+        JSInstanceBuilder::Widgets().Forget(getMapIdFromWindowId());
     }
     else
     {
-        auto it = GetLOKWeldWidgetsMap().find(getMapIdFromWindowId());
-        if (it != GetLOKWeldWidgetsMap().end())
+        auto aWindowMap = 
JSInstanceBuilder::Widgets().Find(getMapIdFromWindowId());
+        if (aWindowMap)
         {
             std::for_each(m_aRememberedWidgets.begin(), 
m_aRememberedWidgets.end(),
-                          [it](const OUString& sId) { it->second.erase(sId); 
});
-        }
-    }
-
-    GetLOKPopupsMap().erase(OUString::number(m_nWindowId));
-}
-
-std::map<OUString, WidgetMap>& JSInstanceBuilder::GetLOKWeldWidgetsMap()
-{
-    // Map to remember the LOKWindowId <-> weld widgets binding.
-    static std::map<OUString, WidgetMap> s_aLOKWeldBuildersMap;
-
-    return s_aLOKWeldBuildersMap;
-}
-
-weld::Widget* JSInstanceBuilder::FindWeldWidgetsMap(const OUString& nWindowId,
-                                                    const OUString& rWidget)
-{
-    const auto it = GetLOKWeldWidgetsMap().find(nWindowId);
-
-    if (it != GetLOKWeldWidgetsMap().end())
-    {
-        auto widgetIt = it->second.find(rWidget);
-        if (widgetIt != it->second.end())
-            return widgetIt->second;
-    }
-
-    return nullptr;
-}
-
-void JSInstanceBuilder::InsertWindowToMap(const OUString& nWindowId)
-{
-    WidgetMap map;
-    auto it = GetLOKWeldWidgetsMap().find(nWindowId);
-    if (it == GetLOKWeldWidgetsMap().end())
-        GetLOKWeldWidgetsMap().insert({ nWindowId, map });
-}
-
-void JSInstanceBuilder::RememberWidget(OUString sId, weld::Widget* pWidget)
-{
-    // do not use the same id for two widgets inside one builder
-    // exception is sidebar where we base our full invalidation on that 
"Panel" id sharing
-    if (m_sTypeOfJSON != "sidebar")
-    {
-        static std::atomic<unsigned long long int> nNotRepeatIndex = 0;
-        auto aWindowIt = GetLOKWeldWidgetsMap().find(getMapIdFromWindowId());
-        if (aWindowIt != GetLOKWeldWidgetsMap().end())
-        {
-            auto aWidgetIt = aWindowIt->second.find(sId);
-            if (aWidgetIt != aWindowIt->second.end())
-            {
-                unsigned long long int nIndex = nNotRepeatIndex++;
-                // found duplicated it -> add some number to the id and apply 
to the widget
-                sId = sId + OUString::number(nIndex);
-                SalInstanceWidget* pSalWidget = 
dynamic_cast<SalInstanceWidget*>(pWidget);
-                assert(pSalWidget && "can only be a SalInstanceWidget");
-                vcl::Window* pVclWidget = pSalWidget->getWidget();
-                pVclWidget->set_id(pVclWidget->get_id() + 
OUString::number(nIndex));
-            }
+                          [&aWindowMap](const OUString& sId) { 
aWindowMap->Forget(sId); });
         }
     }
 
-    RememberWidget(getMapIdFromWindowId(), sId, pWidget);
-    m_aRememberedWidgets.push_back(sId);
-}
-
-void JSInstanceBuilder::RememberWidget(const OUString& nWindowId, const 
OUString& id,
-                                       weld::Widget* pWidget)
-{
-    auto it = GetLOKWeldWidgetsMap().find(nWindowId);
-    if (it != GetLOKWeldWidgetsMap().end())
-    {
-        it->second.erase(id);
-        it->second.insert(WidgetMap::value_type(id, pWidget));
-    }
-}
-
-void JSInstanceBuilder::AddChildWidget(const OUString& nWindowId, const 
OUString& id,
-                                       weld::Widget* pWidget)
-{
-    auto it = GetLOKWeldWidgetsMap().find(nWindowId);
-    if (it != GetLOKWeldWidgetsMap().end())
-    {
-        it->second.erase(id);
-        it->second.insert(WidgetMap::value_type(id, pWidget));
-    }
-}
-
-void JSInstanceBuilder::RemoveWindowWidget(const OUString& nWindowId)
-{
-    auto it = JSInstanceBuilder::GetLOKWeldWidgetsMap().find(nWindowId);
-    if (it != JSInstanceBuilder::GetLOKWeldWidgetsMap().end())
-    {
-        JSInstanceBuilder::GetLOKWeldWidgetsMap().erase(it);
-    }
-}
-
-void JSInstanceBuilder::RememberPopup(const OUString& nWindowId, const 
VclPtr<vcl::Window>& pWidget)
-{
-    GetLOKPopupsMap()[nWindowId] = pWidget;
-}
-
-void JSInstanceBuilder::ForgetPopup(const OUString& nWindowId)
-{
-    auto it = GetLOKPopupsMap().find(nWindowId);
-    if (it != GetLOKPopupsMap().end())
-        GetLOKPopupsMap().erase(it);
-}
-
-void JSInstanceBuilder::RememberMenu(const OUString& nWindowId, weld::Menu* 
pMenu)
-{
-    GetLOKMenusMap()[nWindowId] = pMenu;
-}
-
-void JSInstanceBuilder::ForgetMenu(const OUString& nWindowId)
-{
-    auto it = GetLOKMenusMap().find(nWindowId);
-    if (it != GetLOKMenusMap().end())
-        GetLOKMenusMap().erase(it);
-}
-
-weld::Menu* JSInstanceBuilder::FindMenu(const OUString& nWindowId)
-{
-    const auto it = GetLOKMenusMap().find(nWindowId);
-
-    if (it != GetLOKMenusMap().end())
-        return it->second;
-
-    return nullptr;
-}
-
-vcl::Window* JSInstanceBuilder::FindPopup(const OUString& nWindowId)
-{
-    const auto it = GetLOKPopupsMap().find(nWindowId);
-
-    if (it != GetLOKPopupsMap().end())
-        return it->second;
-
-    return nullptr;
+    JSInstanceBuilder::Popups().Forget(OUString::number(m_nWindowId));
 }
 
 const OUString& JSInstanceBuilder::GetTypeOfJSON() const { return 
m_sTypeOfJSON; }
@@ -961,8 +802,13 @@ std::unique_ptr<weld::Container> 
JSInstanceBuilder::weld_container(const OUStrin
         // use parent builder to send update - avoid multiple calls from many 
builders
         vcl::Window* pParent = pContainer->GetParent();
         OUString sId = OUString::number(m_nWindowId);
-        while (pParent && !FindWeldWidgetsMap(sId, pParent->get_id()))
+        while (pParent)
+        {
+            auto aWidgetMap = Widgets().Find(sId);
+            if (!aWidgetMap || !aWidgetMap->Find(pParent->get_id()))
+                break;
             pParent = pParent->GetParent();
+        }
 
         if (pParent)
             jsdialog::SendFullUpdate(sId, pParent->get_id());
@@ -1244,7 +1090,7 @@ std::unique_ptr<weld::Menu> 
JSInstanceBuilder::weld_menu(const OUString& id)
     std::unique_ptr<weld::Menu> pWeldWidget(pMenu);
 
     if (pWeldWidget)
-        RememberMenu(getMapIdFromWindowId(), pWeldWidget.get());
+        JSInstanceBuilder::Menus().Remember(getMapIdFromWindowId(), 
pWeldWidget.get());
 
     return pWeldWidget;
 }
@@ -1270,7 +1116,7 @@ std::unique_ptr<weld::Popover> 
JSInstanceBuilder::weld_popover(const OUString& i
             m_nWindowId = m_aParentDialog->GetLOKWindowId();
 
             pPopover->set_window_id(m_nWindowId);
-            JSInstanceBuilder::RememberPopup(OUString::number(m_nWindowId), 
pDockingWindow);
+            
JSInstanceBuilder::Popups().Remember(OUString::number(m_nWindowId), 
pDockingWindow);
 
             InsertWindowToMap(getMapIdFromWindowId());
             initializeSender(GetNotifierWindow(), GetContentWindow(), 
GetTypeOfJSON());
@@ -1869,7 +1715,7 @@ JSMessageDialog::JSMessageDialog(::MessageDialog* 
pDialog, SalInstanceBuilder* p
         = 
dynamic_cast<::OKButton*>(m_xMessageDialog->get_widget_for_response(RET_OK)))
     {
         m_pOK.reset(new JSButton(m_pSender, pOKBtn, nullptr, false));
-        JSInstanceBuilder::AddChildWidget(m_sWindowId, pOKBtn->get_id(), 
m_pOK.get());
+        JSInstanceBuilder::RememberWidget(m_sWindowId, pOKBtn->get_id(), 
m_pOK.get());
         m_pOK->connect_clicked(LINK(this, JSMessageDialog, OKHdl));
     }
 
@@ -1877,7 +1723,7 @@ JSMessageDialog::JSMessageDialog(::MessageDialog* 
pDialog, SalInstanceBuilder* p
         = 
dynamic_cast<::CancelButton*>(m_xMessageDialog->get_widget_for_response(RET_CANCEL)))
     {
         m_pCancel.reset(new JSButton(m_pSender, pCancelBtn, nullptr, false));
-        JSInstanceBuilder::AddChildWidget(m_sWindowId, pCancelBtn->get_id(), 
m_pCancel.get());
+        JSInstanceBuilder::RememberWidget(m_sWindowId, pCancelBtn->get_id(), 
m_pCancel.get());
         m_pCancel->connect_clicked(LINK(this, JSMessageDialog, CancelHdl));
     }
 }
@@ -1889,7 +1735,7 @@ JSMessageDialog::~JSMessageDialog()
         // For Message Dialogs created from Application::CreateMessageDialog
         // (where there is no builder to take care of this for us) explicitly
         // remove this window id on tear down
-        JSInstanceBuilder::RemoveWindowWidget(m_sWindowId);
+        JSInstanceBuilder::Widgets().Forget(m_sWindowId);
     }
 }
 
@@ -1897,7 +1743,8 @@ void JSMessageDialog::RememberMessageDialog()
 {
     static constexpr OUString sWidgetName = u"__DIALOG__"_ustr;
     OUString sWindowId = OUString::number(m_xMessageDialog->GetLOKWindowId());
-    if (JSInstanceBuilder::FindWeldWidgetsMap(sWindowId, sWidgetName) != 
nullptr)
+    auto aWidgetMap = JSInstanceBuilder::Widgets().Find(sWindowId);
+    if (!aWidgetMap || !aWidgetMap->Find(sWidgetName))
         return;
 
     JSInstanceBuilder::InsertWindowToMap(sWindowId);
@@ -2028,13 +1875,13 @@ void JSToolbar::set_menu_item_active(const OUString& 
rIdent, bool bActive)
     {
         if (bActive)
         {
-            
JSInstanceBuilder::RememberPopup(OUString::number(pPopupRoot->GetLOKWindowId()),
-                                             pFloat);
+            
JSInstanceBuilder::Popups().Remember(OUString::number(pPopupRoot->GetLOKWindowId()),
+                                                 pFloat);
             sendPopup(pPopupRoot, m_xToolBox->get_id(), rIdent);
         }
         else if (bWasActive)
         {
-            
JSInstanceBuilder::ForgetPopup(OUString::number(pPopupRoot->GetLOKWindowId()));
+            
JSInstanceBuilder::Popups().Forget(OUString::number(pPopupRoot->GetLOKWindowId()));
             sendClosePopup(pPopupRoot->GetLOKWindowId());
         }
     }
@@ -2428,7 +2275,7 @@ void JSPopover::popup_at_rect(weld::Widget* pParent, 
const tools::Rectangle& rRe
 
 void JSPopover::popdown()
 {
-    vcl::Window* pPopup = 
JSInstanceBuilder::FindPopup(OUString::number(mnWindowId));
+    VclPtr<vcl::Window> pPopup = 
JSInstanceBuilder::Popups().Find(OUString::number(mnWindowId));
 
     if (pPopup)
     {
diff --git a/vcl/jsdialog/jsdialogregister.cxx 
b/vcl/jsdialog/jsdialogregister.cxx
new file mode 100644
index 000000000000..66f4d21fa349
--- /dev/null
+++ b/vcl/jsdialog/jsdialogregister.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <jsdialog/jsdialogregister.hxx>
+#include <jsdialog/jsdialogbuilder.hxx>
+
+jsdialog::WidgetRegister<std::shared_ptr<WidgetMap>> 
JSInstanceBuilder::m_aWidgets;
+jsdialog::WidgetRegister<VclPtr<vcl::Window>> JSInstanceBuilder::m_aPopups;
+jsdialog::WidgetRegister<weld::Menu*> JSInstanceBuilder::m_aMenus;
+
+OUString JSInstanceBuilder::getMapIdFromWindowId() const
+{
+    if (m_sTypeOfJSON == "sidebar" || m_sTypeOfJSON == "notebookbar"
+        || m_sTypeOfJSON == "formulabar" || m_sTypeOfJSON == 
"addressinputfield")
+    {
+        return OUString::number(m_nWindowId) + m_sTypeOfJSON;
+    }
+    else
+        return OUString::number(m_nWindowId);
+}
+
+void JSInstanceBuilder::InsertWindowToMap(const OUString& nWindowId)
+{
+    auto aWidgetMap = JSInstanceBuilder::Widgets().Find(nWindowId);
+    if (!aWidgetMap)
+        JSInstanceBuilder::Widgets().Remember(nWindowId, 
std::make_shared<WidgetMap>());
+}
+
+void JSInstanceBuilder::RememberWidget(OUString sId, weld::Widget* pWidget)
+{
+    // do not use the same id for two widgets inside one builder
+    // exception is sidebar where we base our full invalidation on that 
"Panel" id sharing
+    if (m_sTypeOfJSON != "sidebar")
+    {
+        static std::atomic<unsigned long long int> nNotRepeatIndex = 0;
+        auto aWindowIt = 
JSInstanceBuilder::Widgets().Find(getMapIdFromWindowId());
+        if (aWindowIt)
+        {
+            auto aWidgetIt = aWindowIt->Find(sId);
+            if (aWidgetIt)
+            {
+                unsigned long long int nIndex = nNotRepeatIndex++;
+                // found duplicated it -> add some number to the id and apply 
to the widget
+                sId = sId + OUString::number(nIndex);
+                SalInstanceWidget* pSalWidget = 
dynamic_cast<SalInstanceWidget*>(pWidget);
+                assert(pSalWidget && "can only be a SalInstanceWidget");
+                vcl::Window* pVclWidget = pSalWidget->getWidget();
+                pVclWidget->set_id(pVclWidget->get_id() + 
OUString::number(nIndex));
+            }
+        }
+    }
+
+    JSInstanceBuilder::RememberWidget(getMapIdFromWindowId(), sId, pWidget);
+    m_aRememberedWidgets.push_back(sId);
+}
+
+void JSInstanceBuilder::RememberWidget(const OUString& nWindowId, const 
OUString& id,
+                                       weld::Widget* pWidget)
+{
+    auto aWindowMap = JSInstanceBuilder::Widgets().Find(nWindowId);
+    if (aWindowMap)
+    {
+        aWindowMap->Forget(id);
+        aWindowMap->Remember(id, pWidget);
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */

Reply via email to