include/vcl/menu.hxx | 3 + sfx2/source/dialog/StyleList.cxx | 12 +++-- sfx2/source/inc/StyleList.hxx | 1 vcl/inc/jsdialog/enabled.hxx | 1 vcl/inc/jsdialog/jsdialogbuilder.hxx | 3 + vcl/inc/jsdialog/jsdialogmessages.hxx | 28 +++++++++--- vcl/inc/jsdialog/jsdialogsender.hxx | 12 +++-- vcl/jsdialog/enabled.cxx | 9 ++++ vcl/jsdialog/executor.cxx | 19 +++++--- vcl/jsdialog/jsdialogbuilder.cxx | 13 +++-- vcl/jsdialog/jsdialogsender.cxx | 76 +++++++++++++++++++++++++++------- vcl/source/window/builder.cxx | 2 vcl/source/window/menu.cxx | 21 +++++++++ 13 files changed, 158 insertions(+), 42 deletions(-)
New commits: commit c6a0ccf1dc3b4a217de4915402f9d61df49bb41d Author: Szymon Kłos <[email protected]> AuthorDate: Tue Dec 10 12:38:04 2024 +0100 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Wed Dec 11 13:22:39 2024 +0100 jsdialog: add const Change-Id: If689daf52ca01904bc22c8f2e72f65247be2a3f5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178223 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/vcl/inc/jsdialog/jsdialogmessages.hxx b/vcl/inc/jsdialog/jsdialogmessages.hxx index fba40e151d82..7a9ebe904836 100644 --- a/vcl/inc/jsdialog/jsdialogmessages.hxx +++ b/vcl/inc/jsdialog/jsdialogmessages.hxx @@ -105,19 +105,19 @@ public: void clearQueue(); void forceUpdate(); template <class VclType> - void sendMessage(jsdialog::MessageType eType, VclPtr<VclType> pWindow, + void sendMessage(const jsdialog::MessageType eType, const VclPtr<VclType>& pWindow, std::unique_ptr<jsdialog::ActionDataMap> pData = nullptr); private: void send(const OString& sMsg); OString generateFullUpdate() const; - OString generateWidgetUpdate(VclPtr<vcl::Window> pWindow) const; + OString generateWidgetUpdate(const VclPtr<vcl::Window>& pWindow) const; OString generateCloseMessage() const; - OString generateActionMessage(VclPtr<vcl::Window> pWindow, + OString generateActionMessage(const VclPtr<vcl::Window>& pWindow, std::unique_ptr<jsdialog::ActionDataMap> pData) const; - OString generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId, - OUString sCloseId) const; - OString generateClosePopupMessage(OUString sWindowId) const; + OString generatePopupMessage(const VclPtr<vcl::Window>& pWindow, const OUString& sParentId, + const OUString& sCloseId) const; + OString generateClosePopupMessage(const OUString& sWindowId) const; OString generateMenuMessage(const VclPtr<PopupMenu>& pMenu) const; }; diff --git a/vcl/inc/jsdialog/jsdialogsender.hxx b/vcl/inc/jsdialog/jsdialogsender.hxx index 85066e10f37d..44324fb07844 100644 --- a/vcl/inc/jsdialog/jsdialogsender.hxx +++ b/vcl/inc/jsdialog/jsdialogsender.hxx @@ -48,8 +48,8 @@ public: : m_bCanClose(true) { } - JSDialogSender(VclPtr<vcl::Window> aNotifierWindow, VclPtr<vcl::Window> aContentWindow, - const OUString& sTypeOfJSON) + JSDialogSender(const VclPtr<vcl::Window>& aNotifierWindow, + const VclPtr<vcl::Window>& aContentWindow, const OUString& sTypeOfJSON) : m_bCanClose(true) { initializeSender(aNotifierWindow, aContentWindow, sTypeOfJSON); @@ -59,10 +59,11 @@ public: virtual void sendFullUpdate(bool bForce = false); void sendClose(); - void sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce = false); - virtual void sendAction(VclPtr<vcl::Window> pWindow, + void sendUpdate(const VclPtr<vcl::Window>& pWindow, bool bForce = false); + virtual void sendAction(const VclPtr<vcl::Window>& pWindow, std::unique_ptr<jsdialog::ActionDataMap> pData); - virtual void sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId); + virtual void sendPopup(const VclPtr<vcl::Window>& pWindow, const OUString& sParentId, + const OUString& sCloseId); virtual void sendMenu(const VclPtr<PopupMenu>& pMenu); virtual void sendClosePopup(vcl::LOKWindowId nWindowId); void flush() { mpIdleNotify->Invoke(); } diff --git a/vcl/jsdialog/jsdialogsender.cxx b/vcl/jsdialog/jsdialogsender.cxx index b166ed76cc6e..fac9cf229013 100644 --- a/vcl/jsdialog/jsdialogsender.cxx +++ b/vcl/jsdialog/jsdialogsender.cxx @@ -46,7 +46,8 @@ void JSDialogNotifyIdle::send(const OString& sMsg) } template <class VclType> -void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<VclType> pTarget, +void JSDialogNotifyIdle::sendMessage(const jsdialog::MessageType eType, + const VclPtr<VclType>& pTarget, std::unique_ptr<jsdialog::ActionDataMap> pData) { std::scoped_lock aGuard(m_aQueueMutex); @@ -94,7 +95,7 @@ OString JSDialogNotifyIdle::generateFullUpdate() const return aJsonWriter.finishAndGetAsOString(); } -OString JSDialogNotifyIdle::generateWidgetUpdate(VclPtr<vcl::Window> pWindow) const +OString JSDialogNotifyIdle::generateWidgetUpdate(const VclPtr<vcl::Window>& pWindow) const { if (!pWindow || !m_aNotifierWindow) return OString(); @@ -125,7 +126,7 @@ OString JSDialogNotifyIdle::generateCloseMessage() const } OString -JSDialogNotifyIdle::generateActionMessage(VclPtr<vcl::Window> pWindow, +JSDialogNotifyIdle::generateActionMessage(const VclPtr<vcl::Window>& pWindow, std::unique_ptr<jsdialog::ActionDataMap> pData) const { tools::JsonWriter aJsonWriter; @@ -146,8 +147,9 @@ JSDialogNotifyIdle::generateActionMessage(VclPtr<vcl::Window> pWindow, return aJsonWriter.finishAndGetAsOString(); } -OString JSDialogNotifyIdle::generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId, - OUString sCloseId) const +OString JSDialogNotifyIdle::generatePopupMessage(const VclPtr<vcl::Window>& pWindow, + const OUString& sParentId, + const OUString& sCloseId) const { if (!pWindow || !m_aNotifierWindow) return OString(); @@ -195,7 +197,7 @@ OString JSDialogNotifyIdle::generatePopupMessage(VclPtr<vcl::Window> pWindow, OU return aJsonWriter.finishAndGetAsOString(); } -OString JSDialogNotifyIdle::generateClosePopupMessage(OUString sWindowId) const +OString JSDialogNotifyIdle::generateClosePopupMessage(const OUString& sWindowId) const { if (!m_aNotifierWindow) return OString(); @@ -322,7 +324,7 @@ void JSDialogSender::sendClose() flush(); } -void JSDialogSender::sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce) +void JSDialogSender::sendUpdate(const VclPtr<vcl::Window>& pWindow, bool bForce) { if (!mpIdleNotify) return; @@ -334,7 +336,7 @@ void JSDialogSender::sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce) mpIdleNotify->Start(); } -void JSDialogSender::sendAction(VclPtr<vcl::Window> pWindow, +void JSDialogSender::sendAction(const VclPtr<vcl::Window>& pWindow, std::unique_ptr<jsdialog::ActionDataMap> pData) { if (!mpIdleNotify) @@ -344,7 +346,8 @@ void JSDialogSender::sendAction(VclPtr<vcl::Window> pWindow, mpIdleNotify->Start(); } -void JSDialogSender::sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId) +void JSDialogSender::sendPopup(const VclPtr<vcl::Window>& pWindow, const OUString& sParentId, + const OUString& sCloseId) { if (!mpIdleNotify) return; commit b79031d14cc39bb9f4ac87f1f57865ba00fd9b5a Author: Szymon Kłos <[email protected]> AuthorDate: Wed Dec 4 10:41:22 2024 +0100 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Wed Dec 11 13:22:31 2024 +0100 jsdialog: send message for weld::Menu - we need to setup correct notifier - enable context menu in the style sidebar in Writer - handle menu actions - base of vcl::Window and PopupMenu is VclReferenceBase - prepare template function sendMessage to handle both Change-Id: I54c8dc468856c0f98495bdaf4ddd504c2f56562f Signed-off-by: Szymon Kłos <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177782 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx index a28182e51fe2..791faa85f692 100644 --- a/include/vcl/menu.hxx +++ b/include/vcl/menu.hxx @@ -32,6 +32,7 @@ #include <vcl/vclreferencebase.hxx> #include <com/sun/star/uno/Reference.hxx> #include <o3tl/typed_flags_set.hxx> +#include <tools/json_writer.hxx> #include <list> class OutputDevice; @@ -402,6 +403,8 @@ public: * Get the ID of the window. */ const OUString& get_id() const { return maID; } + + virtual void DumpAsPropertyTree(tools::JsonWriter&) const; }; struct MenuBarButtonCallbackArg diff --git a/sfx2/source/dialog/StyleList.cxx b/sfx2/source/dialog/StyleList.cxx index e7bdd9e3b4a3..0d23c4361f16 100644 --- a/sfx2/source/dialog/StyleList.cxx +++ b/sfx2/source/dialog/StyleList.cxx @@ -182,7 +182,7 @@ void StyleList::CreateContextMenu() m_bBindingUpdate = false; } mxMenu.reset(); - mxMenuBuilder = Application::CreateBuilder(nullptr, "sfx/ui/stylecontextmenu.ui"); + mxMenuBuilder = Application::CreateBuilder(m_pContainer, "sfx/ui/stylecontextmenu.ui"); mxMenu = mxMenuBuilder->weld_menu("menu"); mxMenu->set_sensitive("edit", m_bCanEdit); mxMenu->set_sensitive("delete", m_bCanDel); @@ -1472,13 +1472,14 @@ IMPL_LINK_NOARG(StyleList, Clear, void*, void) i.reset(); } +IMPL_LINK(StyleList, OnPopupEnd, const OUString&, sCommand, void) { MenuSelect(sCommand); } + void StyleList::ShowMenu(const CommandEvent& rCEvt) { CreateContextMenu(); weld::TreeView* pTreeView = m_xTreeBox->get_visible() ? m_xTreeBox.get() : m_xFmtLb.get(); - OUString sCommand( - mxMenu->popup_at_rect(pTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)))); - MenuSelect(sCommand); + mxMenu->connect_activate(LINK(this, StyleList, OnPopupEnd)); + mxMenu->popup_at_rect(pTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1))); } void StyleList::MenuSelect(const OUString& rIdent) @@ -1612,6 +1613,9 @@ IMPL_LINK_NOARG(StyleList, MenuSelectAsyncHdl, void*, void) HideHdl(); else if (sLastItemIdent == "show") ShowHdl(); + + mxMenu.reset(); + mxMenuBuilder.reset(); } // Double-click on a style sheet in the ListBox is applied. diff --git a/sfx2/source/inc/StyleList.hxx b/sfx2/source/inc/StyleList.hxx index fe4ff6269bd5..9cd478a84634 100644 --- a/sfx2/source/inc/StyleList.hxx +++ b/sfx2/source/inc/StyleList.hxx @@ -129,6 +129,7 @@ public: void FilterSelect(sal_uInt16 nActFilter, bool bsetFilter); DECL_LINK(NewMenuExecuteAction, void*, void); + DECL_LINK(OnPopupEnd, const OUString&, void); bool HasStylesHighlighterFeature() { return m_bModuleHasStylesHighlighterFeature; } void SetHighlightParaStyles(bool bSet) { m_bHighlightParaStyles = bSet; } diff --git a/vcl/inc/jsdialog/enabled.hxx b/vcl/inc/jsdialog/enabled.hxx index 422a8d80fb50..5c85f310f155 100644 --- a/vcl/inc/jsdialog/enabled.hxx +++ b/vcl/inc/jsdialog/enabled.hxx @@ -15,6 +15,7 @@ namespace jsdialog { bool isBuilderEnabled(std::u16string_view rUIFile, bool bMobile); bool isBuilderEnabledForPopup(std::u16string_view rUIFile); +bool isBuilderEnabledForMenu(std::u16string_view rUIFile); bool isBuilderEnabledForSidebar(std::u16string_view rUIFile); bool isBuilderEnabledForAddressInput(std::u16string_view rUIFile); bool isBuilderEnabledForFormulabar(std::u16string_view rUIFile); diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx index 25a5f969a1be..fc8f13fdd502 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -757,6 +757,9 @@ public: class JSMenu final : public SalInstanceMenu { + VclPtr<PopupMenu> m_pPopupMenu; + JSDialogSender* m_pSender; + public: JSMenu(JSDialogSender* pSender, PopupMenu* pMenu, SalInstanceBuilder* pBuilder, bool bTakeOwnership); diff --git a/vcl/inc/jsdialog/jsdialogmessages.hxx b/vcl/inc/jsdialog/jsdialogmessages.hxx index 6bbd4f166f4b..fba40e151d82 100644 --- a/vcl/inc/jsdialog/jsdialogmessages.hxx +++ b/vcl/inc/jsdialog/jsdialogmessages.hxx @@ -14,6 +14,7 @@ #include <rtl/ustring.hxx> #include <vcl/idle.hxx> #include <vcl/jsdialog/executor.hxx> +#include <vcl/menu.hxx> #include <vcl/window.hxx> namespace jsdialog @@ -25,7 +26,8 @@ enum MessageType Close, Action, Popup, - PopupClose + PopupClose, + Menu, }; } @@ -35,6 +37,7 @@ class JSDialogMessageInfo public: jsdialog::MessageType m_eType; VclPtr<vcl::Window> m_pWindow; + VclPtr<PopupMenu> m_pMenu; std::unique_ptr<jsdialog::ActionDataMap> m_pData; private: @@ -42,6 +45,7 @@ private: { this->m_eType = rInfo.m_eType; this->m_pWindow = rInfo.m_pWindow; + this->m_pMenu = rInfo.m_pMenu; if (rInfo.m_pData) { std::unique_ptr<jsdialog::ActionDataMap> pData( @@ -59,6 +63,14 @@ public: { } + JSDialogMessageInfo(jsdialog::MessageType eType, VclPtr<PopupMenu> pMenu, + std::unique_ptr<jsdialog::ActionDataMap> pData) + : m_eType(eType) + , m_pMenu(std::move(pMenu)) + , m_pData(std::move(pData)) + { + } + JSDialogMessageInfo(const JSDialogMessageInfo& rInfo) { copy(rInfo); } JSDialogMessageInfo& operator=(JSDialogMessageInfo aInfo) @@ -92,7 +104,8 @@ public: void clearQueue(); void forceUpdate(); - void sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow, + template <class VclType> + void sendMessage(jsdialog::MessageType eType, VclPtr<VclType> pWindow, std::unique_ptr<jsdialog::ActionDataMap> pData = nullptr); private: @@ -105,6 +118,7 @@ private: OString generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId) const; OString generateClosePopupMessage(OUString sWindowId) const; + OString generateMenuMessage(const VclPtr<PopupMenu>& pMenu) const; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/inc/jsdialog/jsdialogsender.hxx b/vcl/inc/jsdialog/jsdialogsender.hxx index f6a899a23d90..85066e10f37d 100644 --- a/vcl/inc/jsdialog/jsdialogsender.hxx +++ b/vcl/inc/jsdialog/jsdialogsender.hxx @@ -63,6 +63,7 @@ public: virtual void sendAction(VclPtr<vcl::Window> pWindow, std::unique_ptr<jsdialog::ActionDataMap> pData); virtual void sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId); + virtual void sendMenu(const VclPtr<PopupMenu>& pMenu); virtual void sendClosePopup(vcl::LOKWindowId nWindowId); void flush() { mpIdleNotify->Invoke(); } diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx index d8803bd46945..6ff842226e5b 100644 --- a/vcl/jsdialog/enabled.cxx +++ b/vcl/jsdialog/enabled.cxx @@ -338,6 +338,15 @@ bool isBuilderEnabledForPopup(std::u16string_view rUIFile) return false; } +bool isBuilderEnabledForMenu(std::u16string_view rUIFile) +{ + if (// sfx2 + rUIFile == u"sfx/ui/stylecontextmenu.ui") + return true; + + return false; +} + bool isBuilderEnabledForSidebar(std::u16string_view rUIFile) { return // scalc diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx index 6e42d9ac3eec..16ef9a715e33 100644 --- a/vcl/jsdialog/executor.cxx +++ b/vcl/jsdialog/executor.cxx @@ -81,10 +81,10 @@ bool ExecuteAction(const OUString& nWindowId, const OUString& rWidget, StringMap if (pWidget == nullptr) { // weld::Menu doesn't have base of weld::Widget - if (sControlType == "menu") + if (rWidget == "__MENU__") { weld::Menu* pMenu = JSInstanceBuilder::Menus().Find(nWindowId); - if (pMenu && sAction == "activated") + if (pMenu && sAction == "select") { LOKTrigger::trigger_activated(*pMenu, rData["data"]); return true; @@ -581,12 +581,17 @@ bool ExecuteAction(const OUString& nWindowId, const OUString& rWidget, StringMap sal_Int32 nEntryAbsPos = o3tl::toInt32(rData["data"]); std::unique_ptr<weld::TreeIter> itEntry(pTreeView->make_iterator()); - pTreeView->get_iter_abs_pos(*itEntry, nEntryAbsPos); - - tools::Rectangle aRect = pTreeView->get_row_area(*itEntry); - CommandEvent aCommand(aRect.Center(), CommandEventId::ContextMenu); + if (pTreeView->get_iter_abs_pos(*itEntry, nEntryAbsPos)) + { + tools::Rectangle aRect = pTreeView->get_row_area(*itEntry); + CommandEvent aCommand(aRect.Center(), CommandEventId::ContextMenu); - LOKTrigger::trigger_popup_menu(*pTreeView, aCommand); + LOKTrigger::trigger_popup_menu(*pTreeView, aCommand); + } + else + SAL_WARN("vcl", "No absolute position found for " << nEntryAbsPos + << " in treeview"); + return true; } } } diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx index c7b809147f29..8405622d48ea 100644 --- a/vcl/jsdialog/jsdialogbuilder.cxx +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -375,7 +375,7 @@ JSInstanceBuilder::~JSInstanceBuilder() jsdialog::SendFullUpdate(OUString::number(m_nWindowId), "__DIALOG__"); } - if (m_sTypeOfJSON == "popup") + if (m_sTypeOfJSON == "popup" || m_sTypeOfJSON == "menu") sendClosePopup(m_nWindowId); if (m_aWindowToRelease) @@ -399,6 +399,7 @@ JSInstanceBuilder::~JSInstanceBuilder() } JSInstanceBuilder::Popups().Forget(OUString::number(m_nWindowId)); + JSInstanceBuilder::Menus().Forget(OUString::number(m_nWindowId)); } const OUString& JSInstanceBuilder::GetTypeOfJSON() const { return m_sTypeOfJSON; } @@ -1960,19 +1961,21 @@ void JSMenuButton::set_active(bool bActive) } } -JSMenu::JSMenu(JSDialogSender* /*pSender*/, PopupMenu* pPopupMenu, SalInstanceBuilder* /*pBuilder*/, +JSMenu::JSMenu(JSDialogSender* pSender, PopupMenu* pPopupMenu, SalInstanceBuilder* /*pBuilder*/, bool bTakeOwnership) : SalInstanceMenu(pPopupMenu, bTakeOwnership) + , m_pPopupMenu(pPopupMenu) + , m_pSender(pSender) { } OUString JSMenu::popup_at_rect(weld::Widget* /*pParent*/, const tools::Rectangle& /*rRect*/, weld::Placement /*ePlace*/) { - // TODO: send message + // Do not block with SalInstanceMenu::popup_at_rect(pParent, rRect, ePlace); + m_pSender->sendMenu(m_pPopupMenu); - // first only send menu and cancel menu - // no return SalInstanceMenu::popup_at_rect(pParent, rRect, ePlace); + // Don't return any action - simulate canceled menu return ""; } diff --git a/vcl/jsdialog/jsdialogsender.cxx b/vcl/jsdialog/jsdialogsender.cxx index 7cecdbeb9eed..b166ed76cc6e 100644 --- a/vcl/jsdialog/jsdialogsender.cxx +++ b/vcl/jsdialog/jsdialogsender.cxx @@ -45,7 +45,8 @@ void JSDialogNotifyIdle::send(const OString& sMsg) } } -void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow, +template <class VclType> +void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<VclType> pTarget, std::unique_ptr<jsdialog::ActionDataMap> pData) { std::scoped_lock aGuard(m_aQueueMutex); @@ -53,10 +54,14 @@ void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Wi // 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(); + const VclReferenceBase* pRawTarget = static_cast<VclReferenceBase*>(pTarget); while (it != m_aMessageQueue.end()) { - if (it->m_eType == eType && it->m_pWindow == pWindow) + const VclReferenceBase* pRawWindow = static_cast<VclReferenceBase*>(it->m_pWindow.get()); + const VclReferenceBase* pRawMenu = it->m_pMenu.get(); + + if (it->m_eType == eType && (pRawWindow == pRawTarget || pRawMenu == pRawTarget)) { // actions should be always sent, eg. rendering of custom entries in combobox if (eType == jsdialog::MessageType::Action) @@ -70,7 +75,7 @@ void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Wi it++; } - JSDialogMessageInfo aMessage(eType, pWindow, std::move(pData)); + JSDialogMessageInfo aMessage(eType, pTarget, std::move(pData)); m_aMessageQueue.push_back(aMessage); } @@ -205,6 +210,30 @@ OString JSDialogNotifyIdle::generateClosePopupMessage(OUString sWindowId) const return aJsonWriter.finishAndGetAsOString(); } +OString JSDialogNotifyIdle::generateMenuMessage(const VclPtr<PopupMenu>& pMenu) const +{ + if (!pMenu || !m_aNotifierWindow) + return OString(); + + tools::JsonWriter aJsonWriter; + + { + auto aChildren = aJsonWriter.startArray("children"); + { + auto aStruct = aJsonWriter.startStruct(); + pMenu->DumpAsPropertyTree(aJsonWriter); + } + } + + aJsonWriter.put("jsontype", "dialog"); + aJsonWriter.put("type", "dropdown"); + aJsonWriter.put("cancellable", true); + aJsonWriter.put("popupParent", m_aNotifierWindow->get_id()); + aJsonWriter.put("id", m_aNotifierWindow->GetLOKWindowId()); + + return aJsonWriter.finishAndGetAsOString(); +} + void JSDialogNotifyIdle::Invoke() { std::deque<JSDialogMessageInfo> aMessageQueue; @@ -248,6 +277,12 @@ void JSDialogNotifyIdle::Invoke() case jsdialog::MessageType::PopupClose: send(generateClosePopupMessage((*rMessage.m_pData)[WINDOW_ID ""_ostr])); break; + + case jsdialog::MessageType::Menu: + { + send(generateMenuMessage(rMessage.m_pMenu)); + break; + } } } } @@ -273,7 +308,7 @@ void JSDialogSender::sendFullUpdate(bool bForce) if (bForce) mpIdleNotify->forceUpdate(); - mpIdleNotify->sendMessage(jsdialog::MessageType::FullUpdate, nullptr); + mpIdleNotify->sendMessage(jsdialog::MessageType::FullUpdate, VclPtr<vcl::Window>(nullptr)); mpIdleNotify->Start(); } @@ -283,7 +318,7 @@ void JSDialogSender::sendClose() return; mpIdleNotify->clearQueue(); - mpIdleNotify->sendMessage(jsdialog::MessageType::Close, nullptr); + mpIdleNotify->sendMessage(jsdialog::MessageType::Close, VclPtr<vcl::Window>(nullptr)); flush(); } @@ -328,8 +363,18 @@ void JSDialogSender::sendClosePopup(vcl::LOKWindowId nWindowId) std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>(); (*pData)[WINDOW_ID ""_ostr] = OUString::number(nWindowId); - mpIdleNotify->sendMessage(jsdialog::MessageType::PopupClose, nullptr, std::move(pData)); + mpIdleNotify->sendMessage(jsdialog::MessageType::PopupClose, VclPtr<vcl::Window>(nullptr), + std::move(pData)); flush(); } +void JSDialogSender::sendMenu(const VclPtr<PopupMenu>& pMenu) +{ + if (!mpIdleNotify) + return; + + mpIdleNotify->sendMessage(jsdialog::MessageType::Menu, pMenu); + mpIdleNotify->Start(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index 6344cd8e8871..43e954da025d 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -191,6 +191,8 @@ std::unique_ptr<weld::Builder> Application::CreateBuilder(weld::Widget* pParent, return JSInstanceBuilder::CreateSidebarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, nLOKWindowId); else if (jsdialog::isBuilderEnabledForPopup(rUIFile)) return JSInstanceBuilder::CreatePopupBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile); + else if (jsdialog::isBuilderEnabledForMenu(rUIFile)) + return JSInstanceBuilder::CreateMenuBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile); else if (jsdialog::isBuilderEnabled(rUIFile, bMobile)) return JSInstanceBuilder::CreateDialogBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile); } diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index a0a03be455cb..c3566b5f5617 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -2387,6 +2387,27 @@ void Menu::HighlightItem( sal_uInt16 nItemPos ) } } +void Menu::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) const +{ + rJsonWriter.put("id", "__MENU__"); // we have single instance of menu at the time per session + rJsonWriter.put("type", "menu"); + rJsonWriter.put("count", GetItemCount()); + { + auto aEntries = rJsonWriter.startArray("entries"); + for (size_t i = 0; i < GetItemCount(); i++) + { + auto aEntry = rJsonWriter.startStruct(); + sal_uInt16 nId = GetItemId(i); + rJsonWriter.put("row", GetItemIdent(nId)); + { + auto aColumns = rJsonWriter.startArray("columns"); + auto aColumn = rJsonWriter.startStruct(); + rJsonWriter.put("text", GetItemText(nId)); + } + } + } +} + MenuBarWindow* MenuBar::getMenuBarWindow() { // so far just a dynamic_cast, hopefully to be turned into something saner
