summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSzymon Kłos <szymon.klos@collabora.com>2021-06-24 14:31:45 +0200
committerSzymon Kłos <szymon.klos@collabora.com>2021-07-29 11:04:29 +0200
commitcf9baa91a3c15fb798639c96f2fee6a5bd4975ff (patch)
tree698ea280f7e49c32064e870f1ba6d3a13b18cbc9
parentAvoid some division by zero (diff)
downloadcore-cf9baa91a3c15fb798639c96f2fee6a5bd4975ff.tar.gz
core-cf9baa91a3c15fb798639c96f2fee6a5bd4975ff.zip
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@gmail.com> Reviewed-by: Szymon Kłos <szymon.klos@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119608 Tested-by: Szymon Kłos <szymon.klos@collabora.com>
-rw-r--r--include/vcl/toolkit/menubtn.hxx3
-rw-r--r--vcl/inc/jsdialog/jsdialogbuilder.hxx35
-rw-r--r--vcl/inc/salvtables.hxx4
-rw-r--r--vcl/jsdialog/enabled.cxx2
-rw-r--r--vcl/jsdialog/jsdialogbuilder.cxx132
-rw-r--r--vcl/source/control/menubtn.cxx17
-rw-r--r--vcl/source/window/toolbox2.cxx8
7 files changed, 166 insertions, 35 deletions
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);
}
}
}