[Libreoffice-commits] core.git: include/vcl vcl/inc vcl/jsdialog vcl/source

Szymon KÅ‚os (via logerrit) logerrit at kemper.freedesktop.org
Thu Jul 29 09:05:04 UTC 2021


 include/vcl/toolkit/menubtn.hxx      |    3 
 vcl/inc/jsdialog/jsdialogbuilder.hxx |   35 ++++++++-
 vcl/inc/salvtables.hxx               |    4 -
 vcl/jsdialog/enabled.cxx             |    2 
 vcl/jsdialog/jsdialogbuilder.cxx     |  132 ++++++++++++++++++++++++++++++++---
 vcl/source/control/menubtn.cxx       |   17 ----
 vcl/source/window/toolbox2.cxx       |    8 +-
 7 files changed, 166 insertions(+), 35 deletions(-)

New commits:
commit cf9baa91a3c15fb798639c96f2fee6a5bd4975ff
Author:     Szymon Kłos <szymon.klos at collabora.com>
AuthorDate: Thu Jun 24 14:31:45 2021 +0200
Commit:     Szymon Kłos <szymon.klos at collabora.com>
CommitDate: Thu Jul 29 11:04:29 2021 +0200

    jsdialog: toolbox popups
    
    unify menubutton popups and toolbox dropdowns
    
    Change-Id: I61c0c33a17d96f03d6513507bda6d5c8edbc55dd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117786
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119608
    Tested-by: Szymon Kłos <szymon.klos at collabora.com>

diff --git a/include/vcl/toolkit/menubtn.hxx b/include/vcl/toolkit/menubtn.hxx
index 95d8a65d4769..ca77a48c9fec 100644
--- a/include/vcl/toolkit/menubtn.hxx
+++ b/include/vcl/toolkit/menubtn.hxx
@@ -82,6 +82,7 @@ public:
     PopupMenu*      GetPopupMenu() const { return mpMenu; }
 
     void            SetPopover(Window* pWindow);
+    Window*         GetPopover() { return mpFloatingWindow.get(); }
 
     OString const & GetCurItemIdent() const { return msCurItemIdent; }
 
@@ -91,8 +92,6 @@ public:
     virtual FactoryFunction GetUITestFactory() const override;
 
     void SetCurItemId();
-
-    void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx
index 7c6ce7be45e1..92acff3fc594 100644
--- a/vcl/inc/jsdialog/jsdialogbuilder.hxx
+++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx
@@ -9,9 +9,10 @@
 
 #pragma once
 
+#include <comphelper/string.hxx>
+#include <osl/mutex.hxx>
 #include <vcl/weld.hxx>
 #include <vcl/jsdialog/executor.hxx>
-#include <comphelper/string.hxx>
 #include <vcl/sysdata.hxx>
 #include <vcl/virdev.hxx>
 #include <vcl/builder.hxx>
@@ -29,6 +30,9 @@
 #include <unordered_map>
 
 #define ACTION_TYPE "action_type"
+#define PARENT_ID "parent_id"
+#define WINDOW_ID "id"
+#define CLOSE_ID "close_id"
 
 class ToolBox;
 class ComboBox;
@@ -46,7 +50,8 @@ enum MessageType
     FullUpdate,
     WidgetUpdate,
     Close,
-    Action
+    Action,
+    Popup
 };
 }
 
@@ -102,6 +107,7 @@ class JSDialogNotifyIdle final : public Idle
     bool m_bForce;
 
     std::deque<JSDialogMessageInfo> m_aMessageQueue;
+    osl::Mutex m_aQueueMutex;
 
 public:
     JSDialogNotifyIdle(VclPtr<vcl::Window> aNotifierWindow, VclPtr<vcl::Window> aContentWindow,
@@ -121,6 +127,9 @@ private:
     std::unique_ptr<tools::JsonWriter> generateCloseMessage() const;
     std::unique_ptr<tools::JsonWriter>
     generateActionMessage(VclPtr<vcl::Window> pWindow, std::unique_ptr<ActionDataMap> pData) const;
+    std::unique_ptr<tools::JsonWriter>
+    generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId) const;
+    std::unique_ptr<tools::JsonWriter> generateClosePopupMessage(OUString sWindowId) const;
 };
 
 class JSDialogSender
@@ -141,6 +150,8 @@ public:
     void sendClose();
     void sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce = false);
     virtual void sendAction(VclPtr<vcl::Window> pWindow, std::unique_ptr<ActionDataMap> pData);
+    virtual void sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId);
+    virtual void sendClosePopup(vcl::LOKWindowId nWindowId);
     void flush() { mpIdleNotify->Invoke(); }
 
 protected:
@@ -288,6 +299,10 @@ public:
     virtual void sendFullUpdate(bool bForce = false) = 0;
 
     virtual void sendAction(std::unique_ptr<ActionDataMap> pData) = 0;
+
+    virtual void sendPopup(vcl::Window* pPopup, OUString sParentId, OUString sCloseId) = 0;
+
+    virtual void sendClosePopup(vcl::LOKWindowId nWindowId) = 0;
 };
 
 template <class BaseInstanceClass, class VclClass>
@@ -395,6 +410,18 @@ public:
         if (!m_bIsFreezed && m_pSender && pData)
             m_pSender->sendAction(BaseInstanceClass::m_xWidget, std::move(pData));
     }
+
+    virtual void sendPopup(vcl::Window* pPopup, OUString sParentId, OUString sCloseId) override
+    {
+        if (!m_bIsFreezed && m_pSender)
+            m_pSender->sendPopup(pPopup, sParentId, sCloseId);
+    }
+
+    virtual void sendClosePopup(vcl::LOKWindowId nWindowId) override
+    {
+        if (!m_bIsFreezed && m_pSender)
+            m_pSender->sendClosePopup(nWindowId);
+    }
 };
 
 class JSDialog final : public JSWidget<SalInstanceDialog, ::Dialog>
@@ -531,9 +558,13 @@ public:
 
 class JSToolbar final : public JSWidget<SalInstanceToolbar, ::ToolBox>
 {
+    std::map<sal_uInt16, weld::Widget*> m_pPopovers;
+
 public:
     JSToolbar(JSDialogSender* pSender, ::ToolBox* pToolbox, SalInstanceBuilder* pBuilder,
               bool bTakeOwnership);
+
+    virtual void set_menu_item_active(const OString& rIdent, bool bActive) override;
 };
 
 class JSTextView final : public JSWidget<SalInstanceTextView, ::VclMultiLineEdit>
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index 3d5dc97a3a31..1cca6afd071b 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -1189,7 +1189,7 @@ public:
 
 class SalInstanceToolbar : public SalInstanceWidget, public virtual weld::Toolbar
 {
-private:
+protected:
     VclPtr<ToolBox> m_xToolBox;
     std::map<ToolBoxItemId, VclPtr<vcl::Window>> m_aFloats;
     std::map<ToolBoxItemId, VclPtr<PopupMenu>> m_aMenus;
@@ -1841,7 +1841,7 @@ public:
 
 class SalInstanceMenuButton : public SalInstanceButton, public virtual weld::MenuButton
 {
-private:
+protected:
     VclPtr<::MenuButton> m_xMenuButton;
     sal_uInt16 m_nLastId;
 
diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx
index b0ef018c16c0..67a7cb90c1f0 100644
--- a/vcl/jsdialog/enabled.cxx
+++ b/vcl/jsdialog/enabled.cxx
@@ -61,7 +61,7 @@ bool isBuilderEnabled(std::u16string_view rUIFile, bool bMobile)
 
 bool isBuilderEnabledForPopup(std::u16string_view rUIFile)
 {
-    if (rUIFile == u"svx/ui/colorwindow.ui")
+    if (rUIFile == u"svx/ui/colorwindow.ui" || rUIFile == u"modules/scalc/ui/floatinglinestyle.ui")
         return true;
 
     return false;
diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx
index 65414c46ed5f..9526b9e020fa 100644
--- a/vcl/jsdialog/jsdialogbuilder.cxx
+++ b/vcl/jsdialog/jsdialogbuilder.cxx
@@ -101,6 +101,8 @@ OUString extractActionType(const ActionDataMap& rData)
 void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow,
                                      std::unique_ptr<ActionDataMap> pData)
 {
+    m_aQueueMutex.acquire();
+
     // we want only the latest update of same type
     // TODO: also if we met full update - previous updates are not valid
     auto it = m_aMessageQueue.begin();
@@ -123,6 +125,8 @@ void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Wi
 
     JSDialogMessageInfo aMessage(eType, pWindow, std::move(pData));
     m_aMessageQueue.push_back(aMessage);
+
+    m_aQueueMutex.release();
 }
 
 std::unique_ptr<tools::JsonWriter> JSDialogNotifyIdle::generateFullUpdate() const
@@ -210,9 +214,56 @@ JSDialogNotifyIdle::generateActionMessage(VclPtr<vcl::Window> pWindow,
     return aJsonWriter;
 }
 
+std::unique_ptr<tools::JsonWriter>
+JSDialogNotifyIdle::generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId,
+                                         OUString sCloseId) const
+{
+    std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
+
+    if (!pWindow || !m_aNotifierWindow)
+        return aJsonWriter;
+
+    pWindow->DumpAsPropertyTree(*aJsonWriter);
+
+    aJsonWriter->put("jsontype", "dialog");
+    aJsonWriter->put("type", "modalpopup");
+    aJsonWriter->put("cancellable", true);
+    aJsonWriter->put("popupParent", sParentId);
+    aJsonWriter->put("clickToClose", sCloseId);
+    aJsonWriter->put("id", pWindow->GetLOKWindowId());
+
+    return aJsonWriter;
+}
+
+std::unique_ptr<tools::JsonWriter>
+JSDialogNotifyIdle::generateClosePopupMessage(OUString sWindowId) const
+{
+    std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
+
+    if (!m_aNotifierWindow)
+        return aJsonWriter;
+
+    aJsonWriter->put("jsontype", "dialog");
+    aJsonWriter->put("action", "close");
+    aJsonWriter->put("id", sWindowId);
+
+    return aJsonWriter;
+}
+
 void JSDialogNotifyIdle::Invoke()
 {
-    for (auto& rMessage : m_aMessageQueue)
+    bool bAcquired = m_aQueueMutex.acquire();
+
+    if (!bAcquired)
+        SAL_WARN("vcl", "JSDialogNotifyIdle::Invoke : mutex cannot be acquired");
+
+    std::deque<JSDialogMessageInfo> aMessageQueue(std::move(m_aMessageQueue));
+    m_aMessageQueue = std::deque<JSDialogMessageInfo>();
+    clearQueue();
+
+    m_aQueueMutex.release();
+
+    for (auto& rMessage : aMessageQueue)
     {
         jsdialog::MessageType eType = rMessage.m_eType;
 
@@ -233,10 +284,21 @@ void JSDialogNotifyIdle::Invoke()
             case jsdialog::MessageType::Action:
                 send(*generateActionMessage(rMessage.m_pWindow, std::move(rMessage.m_pData)));
                 break;
+
+            case jsdialog::MessageType::Popup:
+            {
+                OUString sParentId = (*rMessage.m_pData)[PARENT_ID];
+                OUString sWindowId = (*rMessage.m_pData)[WINDOW_ID];
+                OUString sCloseId = (*rMessage.m_pData)[CLOSE_ID];
+
+                if (!sParentId.isEmpty())
+                    send(*generatePopupMessage(rMessage.m_pWindow, sParentId, sCloseId));
+                else if (!sWindowId.isEmpty())
+                    send(*generateClosePopupMessage(sWindowId));
+                break;
+            }
         }
     }
-
-    clearQueue();
 }
 
 void JSDialogNotifyIdle::clearQueue() { m_aMessageQueue.clear(); }
@@ -278,6 +340,23 @@ void JSDialogSender::sendAction(VclPtr<vcl::Window> pWindow, std::unique_ptr<Act
     mpIdleNotify->Start();
 }
 
+void JSDialogSender::sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId)
+{
+    std::unique_ptr<ActionDataMap> pData = std::make_unique<ActionDataMap>();
+    (*pData)[PARENT_ID] = sParentId;
+    (*pData)[CLOSE_ID] = sCloseId;
+    mpIdleNotify->sendMessage(jsdialog::MessageType::Popup, pWindow, std::move(pData));
+    mpIdleNotify->Start();
+}
+
+void JSDialogSender::sendClosePopup(vcl::LOKWindowId nWindowId)
+{
+    std::unique_ptr<ActionDataMap> pData = std::make_unique<ActionDataMap>();
+    (*pData)[WINDOW_ID] = OUString::number(nWindowId);
+    mpIdleNotify->sendMessage(jsdialog::MessageType::Popup, nullptr, std::move(pData));
+    mpIdleNotify->Start();
+}
+
 namespace
 {
 vcl::Window* extract_sal_widget(weld::Widget* pParent)
@@ -919,9 +998,10 @@ std::unique_ptr<weld::Popover> JSInstanceBuilder::weld_popover(const OString& id
 
         if (VclPtr<vcl::Window> pWin = pDockingWindow->GetParentWithLOKNotifier())
         {
-            pDockingWindow->SetLOKNotifier(pWin->GetLOKNotifier());
-            m_aParentDialog = pDockingWindow;
-            m_aWindowToRelease = pDockingWindow;
+            vcl::Window* pPopupRoot = pDockingWindow->GetChild(0);
+            pPopupRoot->SetLOKNotifier(pWin->GetLOKNotifier());
+            m_aParentDialog = pPopupRoot;
+            m_aWindowToRelease = pPopupRoot;
             m_nWindowId = m_aParentDialog->GetLOKWindowId();
             InsertWindowToMap(m_nWindowId);
             initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
@@ -1251,6 +1331,32 @@ JSToolbar::JSToolbar(JSDialogSender* pSender, ::ToolBox* pToolbox, SalInstanceBu
 {
 }
 
+void JSToolbar::set_menu_item_active(const OString& rIdent, bool bActive)
+{
+    SalInstanceToolbar::set_menu_item_active(rIdent, bActive);
+
+    ToolBoxItemId nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
+    VclPtr<vcl::Window> pFloat = m_aFloats[nItemId];
+
+    if (pFloat)
+    {
+        // See WeldToolbarPopup : include/svtools/toolbarmenu.hxx
+        // TopLevel (Popover) -> Container -> main container of the popup
+        vcl::Window* pPopupRoot = pFloat->GetChild(0);
+        if (pPopupRoot)
+            pPopupRoot = pPopupRoot->GetChild(0);
+
+        if (pPopupRoot)
+        {
+            if (bActive)
+                sendPopup(pPopupRoot, m_xToolBox->get_id(),
+                          OStringToOUString(rIdent, RTL_TEXTENCODING_ASCII_US));
+            else
+                sendClosePopup(pPopupRoot->GetLOKWindowId());
+        }
+    }
+}
+
 JSTextView::JSTextView(JSDialogSender* pSender, ::VclMultiLineEdit* pTextView,
                        SalInstanceBuilder* pBuilder, bool bTakeOwnership)
     : JSWidget<SalInstanceTextView, ::VclMultiLineEdit>(pSender, pTextView, pBuilder,
@@ -1494,10 +1600,18 @@ void JSMenuButton::set_image(const css::uno::Reference<css::graphic::XGraphic>&
     sendUpdate();
 }
 
-void JSMenuButton::set_active(bool active)
+void JSMenuButton::set_active(bool bActive)
 {
-    SalInstanceMenuButton::set_active(active);
-    sendUpdate();
+    SalInstanceMenuButton::set_active(bActive);
+
+    VclPtr<vcl::Window> pPopup = m_xMenuButton->GetPopover();
+    if (pPopup)
+    {
+        if (bActive)
+            sendPopup(pPopup->GetChild(0), m_xMenuButton->get_id(), m_xMenuButton->get_id());
+        else
+            sendClosePopup(pPopup->GetChild(0)->GetLOKWindowId());
+    }
 }
 
 JSPopover::JSPopover(JSDialogSender* pSender, DockingWindow* pDockingWindow,
diff --git a/vcl/source/control/menubtn.cxx b/vcl/source/control/menubtn.cxx
index a46b6bab6789..cd9b2095985e 100644
--- a/vcl/source/control/menubtn.cxx
+++ b/vcl/source/control/menubtn.cxx
@@ -265,23 +265,6 @@ 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<vcl::Window> 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/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
index 52af143f293d..47bc4d1ff743 100644
--- a/vcl/source/window/toolbox2.cxx
+++ b/vcl/source/window/toolbox2.cxx
@@ -1749,11 +1749,15 @@ void ToolBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
             }
             else
             {
-                if (!IsItemVisible(nId))
-                    continue;
                 rJsonWriter.put("type", "toolitem");
                 rJsonWriter.put("text", GetItemText(nId));
                 rJsonWriter.put("command", GetItemCommand(nId));
+                if (!IsItemVisible(nId))
+                    rJsonWriter.put("visible", false);
+                if (GetItemBits(nId) & ToolBoxItemBits::DROPDOWN)
+                    rJsonWriter.put("dropdown", true);
+                if (!IsItemEnabled(nId))
+                    rJsonWriter.put("enabled", false);
             }
         }
     }


More information about the Libreoffice-commits mailing list