From 79eab8450b3a9db343a082e6d450764643340a3e Mon Sep 17 00:00:00 2001 From: Szymon Kłos Date: Tue, 15 Jun 2021 13:10:00 +0200 Subject: jsdialog: dump and activate popup windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4eb49a81d12ac37f50c6595eeec6d472fdbe6d82 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117251 Tested-by: Jenkins CollaboraOffice Reviewed-by: Szymon Kłos Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119581 Tested-by: Szymon Kłos --- include/vcl/toolkit/menubtn.hxx | 1 + vcl/inc/jsdialog/enabled.hxx | 1 + vcl/inc/jsdialog/jsdialogbuilder.hxx | 18 +++++++++-- vcl/jsdialog/enabled.cxx | 9 ++++++ vcl/jsdialog/executor.cxx | 20 ++++++++++++ vcl/jsdialog/jsdialogbuilder.cxx | 59 +++++++++++++++++++++++++++++++++++- vcl/source/control/menubtn.cxx | 18 +++++++++++ vcl/source/window/builder.cxx | 4 ++- 8 files changed, 126 insertions(+), 4 deletions(-) diff --git a/include/vcl/toolkit/menubtn.hxx b/include/vcl/toolkit/menubtn.hxx index db4f9f44f5d6..95d8a65d4769 100644 --- a/include/vcl/toolkit/menubtn.hxx +++ b/include/vcl/toolkit/menubtn.hxx @@ -92,6 +92,7 @@ public: void SetCurItemId(); + void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/jsdialog/enabled.hxx b/vcl/inc/jsdialog/enabled.hxx index 50586cf3bb13..0f37301d0c0d 100644 --- a/vcl/inc/jsdialog/enabled.hxx +++ b/vcl/inc/jsdialog/enabled.hxx @@ -14,6 +14,7 @@ namespace jsdialog { bool isBuilderEnabled(std::u16string_view rUIFile, bool bMobile); +bool isBuilderEnabledForPopup(std::u16string_view rUIFile); bool isBuilderEnabledForSidebar(std::u16string_view rUIFile); bool isInterimBuilderEnabledForNotebookbar(std::u16string_view rUIFile); } diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx index 78534ea8c29a..7c6ce7be45e1 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -195,6 +195,8 @@ class JSInstanceBuilder final : public SalInstanceBuilder, public JSDialogSender std::string m_sTypeOfJSON; bool m_bHasTopLevelDialog; bool m_bIsNotebookbar; + /// When LOKNotifier is set by jsdialogs code we need to release it + VclPtr m_aWindowToRelease; friend VCL_DLLPUBLIC bool jsdialog::ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rData); @@ -206,8 +208,9 @@ class JSInstanceBuilder final : public SalInstanceBuilder, public JSDialogSender void RememberWidget(const OString& id, weld::Widget* pWidget); static weld::Widget* FindWeldWidgetsMap(sal_uInt64 nWindowId, const OString& rWidget); - /// used for dialogs - JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile); + /// used for dialogs or popups + JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile, + bool bPopup = false); /// used for sidebar panels JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile, sal_uInt64 nLOKWindowId); @@ -231,6 +234,8 @@ public: static JSInstanceBuilder* CreateSidebarBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile, sal_uInt64 nLOKWindowId = 0); + static JSInstanceBuilder* CreatePopupBuilder(weld::Widget* pParent, const OUString& rUIRoot, + const OUString& rUIFile); virtual ~JSInstanceBuilder() override; virtual std::unique_ptr weld_message_dialog(const OString& id) override; @@ -255,6 +260,7 @@ public: virtual std::unique_ptr weld_radio_button(const OString& id) override; virtual std::unique_ptr weld_frame(const OString& id) override; virtual std::unique_ptr weld_menu_button(const OString& id) override; + virtual std::unique_ptr weld_popover(const OString& id) override; static weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, @@ -627,6 +633,14 @@ public: virtual void set_label(const OUString& rText) override; virtual void set_image(VirtualDevice* pDevice) override; virtual void set_image(const css::uno::Reference& rImage) override; + virtual void set_active(bool active) override; +}; + +class JSPopover : public JSWidget +{ +public: + JSPopover(JSDialogSender* pSender, DockingWindow* pPopover, SalInstanceBuilder* pBuilder, + bool bTakeOwnership); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx index 7160b8bcc38d..b0ef018c16c0 100644 --- a/vcl/jsdialog/enabled.cxx +++ b/vcl/jsdialog/enabled.cxx @@ -13,6 +13,7 @@ namespace jsdialog { bool isBuilderEnabled(std::u16string_view rUIFile, bool bMobile) { + // mobile only dialogs if (bMobile) { if (rUIFile == u"modules/swriter/ui/wordcount-mobile.ui" @@ -58,6 +59,14 @@ bool isBuilderEnabled(std::u16string_view rUIFile, bool bMobile) return false; } +bool isBuilderEnabledForPopup(std::u16string_view rUIFile) +{ + if (rUIFile == u"svx/ui/colorwindow.ui") + return true; + + return false; +} + bool isBuilderEnabledForSidebar(std::u16string_view rUIFile) { if (rUIFile == u"sfx/ui/panel.ui" || rUIFile == u"svx/ui/sidebartextpanel.ui" diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx index d35ae301be66..5675ec0b56f0 100644 --- a/vcl/jsdialog/executor.cxx +++ b/vcl/jsdialog/executor.cxx @@ -120,6 +120,26 @@ bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rDat } } } + else if (sControlType == "menubutton") + { + auto pButton = dynamic_cast(pWidget); + if (pButton) + { + if (sAction == "toggle") + { + if (pButton->get_active()) + pButton->set_active(false); + else + pButton->set_active(true); + + BaseJSWidget* pMenuButton = dynamic_cast(pButton); + if (pMenuButton) + pMenuButton->sendUpdate(true); + + return true; + } + } + } else if (sControlType == "checkbox") { auto pCheckButton = dynamic_cast(pWidget); diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx index 02e794808c78..a0b17f23bf08 100644 --- a/vcl/jsdialog/jsdialogbuilder.cxx +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -384,7 +384,7 @@ void JSDropTarget::fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEn // used for dialogs JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot, - const OUString& rUIFile) + const OUString& rUIFile, bool bPopup) : SalInstanceBuilder(extract_sal_widget(pParent), rUIRoot, rUIFile) , m_nWindowId(0) , m_aParentDialog(nullptr) @@ -392,7 +392,12 @@ JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIR , m_sTypeOfJSON("dialog") , m_bHasTopLevelDialog(false) , m_bIsNotebookbar(false) + , m_aWindowToRelease(nullptr) { + // when it is a popup we initialize sender in weld_popover + if (bPopup) + return; + vcl::Window* pRoot = m_xBuilder->get_widget_root(); if (pRoot && pRoot->GetParent()) @@ -416,6 +421,7 @@ JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIR , m_sTypeOfJSON("sidebar") , m_bHasTopLevelDialog(false) , m_bIsNotebookbar(false) + , m_aWindowToRelease(nullptr) { vcl::Window* pRoot = m_xBuilder->get_widget_root(); @@ -453,6 +459,7 @@ JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRo , m_sTypeOfJSON("notebookbar") , m_bHasTopLevelDialog(false) , m_bIsNotebookbar(false) + , m_aWindowToRelease(nullptr) { vcl::Window* pRoot = m_xBuilder->get_widget_root(); if (pRoot && pRoot->GetParent()) @@ -481,6 +488,7 @@ JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRo , m_sTypeOfJSON("autofilter") , m_bHasTopLevelDialog(false) , m_bIsNotebookbar(false) + , m_aWindowToRelease(nullptr) { vcl::Window* pRoot = m_xBuilder->get_widget_root(); m_aContentWindow = pParent; @@ -524,8 +532,21 @@ JSInstanceBuilder* JSInstanceBuilder::CreateSidebarBuilder(weld::Widget* pParent return new JSInstanceBuilder(pParent, rUIRoot, rUIFile, nLOKWindowId); } +JSInstanceBuilder* JSInstanceBuilder::CreatePopupBuilder(weld::Widget* pParent, + const OUString& rUIRoot, + const OUString& rUIFile) +{ + return new JSInstanceBuilder(pParent, rUIRoot, rUIFile, true); +} + JSInstanceBuilder::~JSInstanceBuilder() { + if (m_aWindowToRelease) + { + m_aWindowToRelease->ReleaseLOKNotifier(); + m_aWindowToRelease.clear(); + } + if (m_nWindowId && (m_bHasTopLevelDialog || m_bIsNotebookbar)) { GetLOKWeldWidgetsMap().erase(m_nWindowId); @@ -885,6 +906,30 @@ std::unique_ptr JSInstanceBuilder::weld_menu_button(const OStr return pWeldWidget; } +std::unique_ptr JSInstanceBuilder::weld_popover(const OString& id) +{ + DockingWindow* pDockingWindow = m_xBuilder->get(id); + std::unique_ptr pRet( + pDockingWindow ? new JSPopover(this, pDockingWindow, this, false) : nullptr); + if (pDockingWindow) + { + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pDockingWindow); + m_xBuilder->drop_ownership(pDockingWindow); + + if (VclPtr pWin = pDockingWindow->GetParentWithLOKNotifier()) + { + pDockingWindow->SetLOKNotifier(pWin->GetLOKNotifier()); + m_aParentDialog = pDockingWindow; + m_aWindowToRelease = pDockingWindow; + m_nWindowId = m_aParentDialog->GetLOKWindowId(); + InsertWindowToMap(m_nWindowId); + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); + } + } + return pRet; +} + weld::MessageDialog* JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, VclButtonsType eButtonType, @@ -1445,4 +1490,16 @@ void JSMenuButton::set_image(const css::uno::Reference& sendUpdate(); } +void JSMenuButton::set_active(bool active) +{ + SalInstanceMenuButton::set_active(active); + sendUpdate(); +} + +JSPopover::JSPopover(JSDialogSender* pSender, DockingWindow* pDockingWindow, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget(pSender, pDockingWindow, pBuilder, bTakeOwnership) +{ +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/source/control/menubtn.cxx b/vcl/source/control/menubtn.cxx index 33401186fc36..a46b6bab6789 100644 --- a/vcl/source/control/menubtn.cxx +++ b/vcl/source/control/menubtn.cxx @@ -28,6 +28,7 @@ #include #include #include +#include namespace { @@ -264,6 +265,23 @@ void MenuButton::SetCurItemId(){ msCurItemIdent = mpMenu->GetCurItemIdent(); } +void MenuButton::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) +{ + Button::DumpAsPropertyTree(rJsonWriter); + if (mpFloatingWindow) + { + auto aPopup = rJsonWriter.startNode("popup"); + if (InPopupMode()) + mpFloatingWindow->DumpAsPropertyTree(rJsonWriter); + else + rJsonWriter.put("action", "close"); + + VclPtr pParentWithNotifier = mpFloatingWindow->GetParentWithLOKNotifier(); + if (pParentWithNotifier) + rJsonWriter.put("id", pParentWithNotifier->GetLOKWindowId()); + } +} + //class MenuToggleButton ---------------------------------------------------- MenuToggleButton::MenuToggleButton( vcl::Window* pParent, WinBits nWinBits ) diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index 5b20c550eab9..2c34c47b1d95 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -184,7 +184,9 @@ weld::Builder* Application::CreateBuilder(weld::Widget* pParent, const OUString { if (jsdialog::isBuilderEnabledForSidebar(rUIFile)) return JSInstanceBuilder::CreateSidebarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, nLOKWindowId); - if (jsdialog::isBuilderEnabled(rUIFile, bMobile)) + else if (jsdialog::isBuilderEnabledForPopup(rUIFile)) + return JSInstanceBuilder::CreatePopupBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile); + else if (jsdialog::isBuilderEnabled(rUIFile, bMobile)) return JSInstanceBuilder::CreateDialogBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile); } -- cgit v1.2.3