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: */