Introduce weld::IconView::insert_separator
[LibreOffice.git] / vcl / jsdialog / jsdialogbuilder.cxx
blobab1fdf7636c09f59aec1655a042745ad55ca94e5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <jsdialog/jsdialogbuilder.hxx>
11 #include <sal/log.hxx>
12 #include <comphelper/lok.hxx>
13 #include <vcl/tabpage.hxx>
14 #include <vcl/toolkit/button.hxx>
15 #include <vcl/toolkit/dialog.hxx>
16 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
17 #include <vcl/toolkit/combobox.hxx>
18 #include <messagedialog.hxx>
19 #include <tools/json_writer.hxx>
20 #include <o3tl/deleter.hxx>
21 #include <memory>
22 #include <vcl/toolbox.hxx>
23 #include <vcl/toolkit/vclmedit.hxx>
24 #include <boost/property_tree/json_parser.hpp>
25 #include <vcl/toolkit/treelistentry.hxx>
26 #include <vcl/jsdialog/executor.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <utility>
30 static std::map<std::string, vcl::Window*>& GetLOKPopupsMap()
32 // Map to remember the LOKWindowId <-> vcl popup binding.
33 static std::map<std::string, vcl::Window*> s_aLOKPopupsMap;
35 return s_aLOKPopupsMap;
38 namespace
40 void response_help(vcl::Window* pWindow)
42 ::Dialog* pDialog = dynamic_cast<::Dialog*>(pWindow);
43 if (!pDialog)
44 return;
46 vcl::Window* pButtonWindow = pDialog->get_widget_for_response(RET_HELP);
47 ::Button* pButton = dynamic_cast<::Button*>(pButtonWindow);
48 if (!pButton)
49 return;
51 pButton->Click();
55 JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aNotifierWindow,
56 VclPtr<vcl::Window> aContentWindow, std::string sTypeOfJSON)
57 : Idle("JSDialog notify")
58 , m_aNotifierWindow(aNotifierWindow)
59 , m_aContentWindow(aContentWindow)
60 , m_sTypeOfJSON(sTypeOfJSON)
61 , m_bForce(false)
63 SetPriority(TaskPriority::POST_PAINT);
66 void JSDialogNotifyIdle::forceUpdate() { m_bForce = true; }
68 void JSDialogNotifyIdle::send(tools::JsonWriter& aJsonWriter)
70 if (!m_aNotifierWindow)
72 free(aJsonWriter.extractData());
73 return;
76 const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier();
77 if (pNotifier)
79 if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage))
81 m_bForce = false;
82 m_LastNotificationMessage = aJsonWriter.extractAsStdString();
83 pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG,
84 m_LastNotificationMessage.c_str());
86 else
88 free(aJsonWriter.extractData());
91 else
93 free(aJsonWriter.extractData());
97 namespace
99 OUString extractActionType(const jsdialog::ActionDataMap& rData)
101 auto it = rData.find(ACTION_TYPE);
102 if (it != rData.end())
103 return it->second;
104 return "";
108 void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow,
109 std::unique_ptr<jsdialog::ActionDataMap> pData)
111 std::scoped_lock aGuard(m_aQueueMutex);
113 // we want only the latest update of same type
114 // TODO: also if we met full update - previous updates are not valid
115 auto it = m_aMessageQueue.begin();
117 while (it != m_aMessageQueue.end())
119 if (it->m_eType == eType && it->m_pWindow == pWindow)
121 if (it->m_pData && pData
122 && extractActionType(*it->m_pData) != extractActionType(*pData))
124 it++;
125 continue;
127 it = m_aMessageQueue.erase(it);
129 else
130 it++;
133 JSDialogMessageInfo aMessage(eType, pWindow, std::move(pData));
134 m_aMessageQueue.push_back(aMessage);
137 std::unique_ptr<tools::JsonWriter> JSDialogNotifyIdle::generateFullUpdate() const
139 std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
141 if (!m_aContentWindow || !m_aNotifierWindow)
142 return aJsonWriter;
144 m_aContentWindow->DumpAsPropertyTree(*aJsonWriter);
145 aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId());
146 aJsonWriter->put("jsontype", m_sTypeOfJSON);
148 return aJsonWriter;
151 std::unique_ptr<tools::JsonWriter>
152 JSDialogNotifyIdle::generateWidgetUpdate(VclPtr<vcl::Window> pWindow) const
154 std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
156 if (!pWindow || !m_aNotifierWindow)
157 return aJsonWriter;
159 aJsonWriter->put("jsontype", m_sTypeOfJSON);
160 aJsonWriter->put("action", "update");
161 aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId());
163 auto aEntries = aJsonWriter->startNode("control");
164 pWindow->DumpAsPropertyTree(*aJsonWriter);
167 return aJsonWriter;
170 std::unique_ptr<tools::JsonWriter> JSDialogNotifyIdle::generateCloseMessage() const
172 std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
173 if (m_aNotifierWindow)
174 aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId());
175 aJsonWriter->put("jsontype", m_sTypeOfJSON);
176 aJsonWriter->put("action", "close");
178 return aJsonWriter;
181 std::unique_ptr<tools::JsonWriter>
182 JSDialogNotifyIdle::generateActionMessage(VclPtr<vcl::Window> pWindow,
183 std::unique_ptr<jsdialog::ActionDataMap> pData) const
185 std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
187 aJsonWriter->put("jsontype", m_sTypeOfJSON);
188 aJsonWriter->put("action", "action");
189 aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId());
192 auto aDataNode = aJsonWriter->startNode("data");
193 aJsonWriter->put("control_id", pWindow->get_id());
195 for (auto it = pData->begin(); it != pData->end(); it++)
196 aJsonWriter->put(it->first.c_str(), it->second);
199 return aJsonWriter;
202 std::unique_ptr<tools::JsonWriter>
203 JSDialogNotifyIdle::generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId,
204 OUString sCloseId) const
206 std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
208 if (!pWindow || !m_aNotifierWindow)
209 return aJsonWriter;
211 if (!pWindow->GetParentWithLOKNotifier())
212 return aJsonWriter;
215 auto aChildren = aJsonWriter->startArray("children");
217 auto aStruct = aJsonWriter->startStruct();
218 pWindow->DumpAsPropertyTree(*aJsonWriter);
222 // try to get the position eg. for the autofilter
224 vcl::Window* pVclWindow = pWindow.get();
225 DockingWindow* pDockingWindow = dynamic_cast<DockingWindow*>(pVclWindow);
226 while (pVclWindow && !pDockingWindow)
228 pVclWindow = pVclWindow->GetParent();
229 pDockingWindow = dynamic_cast<DockingWindow*>(pVclWindow);
232 if (pDockingWindow)
234 Point aPos = pDockingWindow->GetFloatingPos();
235 aJsonWriter->put("posx", aPos.getX());
236 aJsonWriter->put("posy", aPos.getY());
237 if (!pDockingWindow->IsVisible())
238 aJsonWriter->put("visible", "false");
242 aJsonWriter->put("jsontype", "dialog");
243 aJsonWriter->put("type", "modalpopup");
244 aJsonWriter->put("cancellable", true);
245 aJsonWriter->put("popupParent", sParentId);
246 aJsonWriter->put("clickToClose", sCloseId);
247 aJsonWriter->put("id", pWindow->GetParentWithLOKNotifier()->GetLOKWindowId());
249 return aJsonWriter;
252 std::unique_ptr<tools::JsonWriter>
253 JSDialogNotifyIdle::generateClosePopupMessage(OUString sWindowId) const
255 std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter());
257 if (!m_aNotifierWindow)
258 return aJsonWriter;
260 aJsonWriter->put("jsontype", "dialog");
261 aJsonWriter->put("type", "modalpopup");
262 aJsonWriter->put("action", "close");
263 aJsonWriter->put("id", sWindowId);
265 return aJsonWriter;
268 void JSDialogNotifyIdle::Invoke()
270 std::deque<JSDialogMessageInfo> aMessageQueue;
272 std::scoped_lock aGuard(m_aQueueMutex);
274 std::swap(aMessageQueue, m_aMessageQueue);
277 for (auto& rMessage : aMessageQueue)
279 jsdialog::MessageType eType = rMessage.m_eType;
281 if (m_sTypeOfJSON == "formulabar" && eType != jsdialog::MessageType::Action)
282 continue;
284 switch (eType)
286 case jsdialog::MessageType::FullUpdate:
287 send(*generateFullUpdate());
288 break;
290 case jsdialog::MessageType::WidgetUpdate:
291 send(*generateWidgetUpdate(rMessage.m_pWindow));
292 break;
294 case jsdialog::MessageType::Close:
295 send(*generateCloseMessage());
296 break;
298 case jsdialog::MessageType::Action:
299 send(*generateActionMessage(rMessage.m_pWindow, std::move(rMessage.m_pData)));
300 break;
302 case jsdialog::MessageType::Popup:
303 send(*generatePopupMessage(rMessage.m_pWindow, (*rMessage.m_pData)[PARENT_ID],
304 (*rMessage.m_pData)[CLOSE_ID]));
305 break;
307 case jsdialog::MessageType::PopupClose:
308 send(*generateClosePopupMessage((*rMessage.m_pData)[WINDOW_ID]));
309 break;
314 void JSDialogNotifyIdle::clearQueue() { m_aMessageQueue.clear(); }
316 JSDialogSender::~JSDialogSender() COVERITY_NOEXCEPT_FALSE
318 sendClose();
320 if (mpIdleNotify)
321 mpIdleNotify->Stop();
324 void JSDialogSender::sendFullUpdate(bool bForce)
326 if (!mpIdleNotify)
327 return;
329 if (bForce)
330 mpIdleNotify->forceUpdate();
332 mpIdleNotify->sendMessage(jsdialog::MessageType::FullUpdate, nullptr);
333 mpIdleNotify->Start();
336 void JSDialogSender::sendClose()
338 if (!mpIdleNotify || !m_bCanClose)
339 return;
341 mpIdleNotify->clearQueue();
342 mpIdleNotify->sendMessage(jsdialog::MessageType::Close, nullptr);
343 flush();
346 void JSDialogSender::sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce)
348 if (!mpIdleNotify)
349 return;
351 if (bForce)
352 mpIdleNotify->forceUpdate();
354 mpIdleNotify->sendMessage(jsdialog::MessageType::WidgetUpdate, pWindow);
355 mpIdleNotify->Start();
358 void JSDialogSender::sendAction(VclPtr<vcl::Window> pWindow,
359 std::unique_ptr<jsdialog::ActionDataMap> pData)
361 if (!mpIdleNotify)
362 return;
364 mpIdleNotify->sendMessage(jsdialog::MessageType::Action, pWindow, std::move(pData));
365 mpIdleNotify->Start();
368 void JSDialogSender::sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId)
370 if (!mpIdleNotify)
371 return;
373 std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>();
374 (*pData)[PARENT_ID] = sParentId;
375 (*pData)[CLOSE_ID] = sCloseId;
376 mpIdleNotify->sendMessage(jsdialog::MessageType::Popup, pWindow, std::move(pData));
377 mpIdleNotify->Start();
380 void JSDialogSender::sendClosePopup(vcl::LOKWindowId nWindowId)
382 if (!mpIdleNotify)
383 return;
385 std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>();
386 (*pData)[WINDOW_ID] = OUString::number(nWindowId);
387 mpIdleNotify->sendMessage(jsdialog::MessageType::PopupClose, nullptr, std::move(pData));
388 flush();
391 namespace
393 vcl::Window* extract_sal_widget(weld::Widget* pParent)
395 SalInstanceWidget* pInstanceWidget = dynamic_cast<SalInstanceWidget*>(pParent);
396 return pInstanceWidget ? pInstanceWidget->getWidget() : nullptr;
400 // Drag and drop
402 namespace
404 class JSDropTargetDropContext
405 : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDropContext>
407 public:
408 JSDropTargetDropContext() {}
410 // XDropTargetDropContext
411 virtual void SAL_CALL acceptDrop(sal_Int8 /*dragOperation*/) override {}
413 virtual void SAL_CALL rejectDrop() override {}
415 virtual void SAL_CALL dropComplete(sal_Bool /*bSuccess*/) override {}
419 static JSTreeView* g_DragSource;
421 JSDropTarget::JSDropTarget() {}
423 void JSDropTarget::initialize(const css::uno::Sequence<css::uno::Any>& /*rArgs*/) {}
425 void JSDropTarget::addDropTargetListener(
426 const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>& xListener)
428 std::unique_lock aGuard(m_aMutex);
430 m_aListeners.push_back(xListener);
433 void JSDropTarget::removeDropTargetListener(
434 const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>& xListener)
436 std::unique_lock aGuard(m_aMutex);
438 m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), xListener),
439 m_aListeners.end());
442 sal_Bool JSDropTarget::isActive() { return false; }
444 void JSDropTarget::setActive(sal_Bool /*active*/) {}
446 sal_Int8 JSDropTarget::getDefaultActions() { return 0; }
448 void JSDropTarget::setDefaultActions(sal_Int8 /*actions*/) {}
450 OUString JSDropTarget::getImplementationName()
452 return "com.sun.star.datatransfer.dnd.JSDropTarget";
455 sal_Bool JSDropTarget::supportsService(OUString const& ServiceName)
457 return cppu::supportsService(this, ServiceName);
460 css::uno::Sequence<OUString> JSDropTarget::getSupportedServiceNames()
462 css::uno::Sequence<OUString> aRet{ "com.sun.star.datatransfer.dnd.JSDropTarget" };
463 return aRet;
466 void JSDropTarget::fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde)
468 std::unique_lock aGuard(m_aMutex);
469 std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(
470 m_aListeners);
471 aGuard.unlock();
473 for (auto const& listener : aListeners)
475 listener->drop(dtde);
479 void JSDropTarget::fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent& dtde)
481 std::unique_lock aGuard(m_aMutex);
482 std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(
483 m_aListeners);
484 aGuard.unlock();
486 for (auto const& listener : aListeners)
488 listener->dragEnter(dtde);
492 std::string JSInstanceBuilder::getMapIdFromWindowId() const
494 if (m_sTypeOfJSON == "sidebar" || m_sTypeOfJSON == "notebookbar"
495 || m_sTypeOfJSON == "formulabar")
496 return std::to_string(m_nWindowId) + m_sTypeOfJSON;
497 else
498 return std::to_string(m_nWindowId);
501 // used for dialogs
502 JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot,
503 const OUString& rUIFile, bool bPopup)
504 : SalInstanceBuilder(extract_sal_widget(pParent), rUIRoot, rUIFile)
505 , m_nWindowId(0)
506 , m_aParentDialog(nullptr)
507 , m_aContentWindow(nullptr)
508 , m_sTypeOfJSON("dialog")
509 , m_bHasTopLevelDialog(false)
510 , m_bIsNotebookbar(false)
511 , m_aWindowToRelease(nullptr)
513 // when it is a popup we initialize sender in weld_popover
514 if (bPopup)
515 return;
517 vcl::Window* pRoot = m_xBuilder->get_widget_root();
519 if (pRoot && pRoot->GetParent())
521 m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier();
522 if (m_aParentDialog)
523 m_nWindowId = m_aParentDialog->GetLOKWindowId();
524 InsertWindowToMap(getMapIdFromWindowId());
527 initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
530 // used for sidebar panels
531 JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot,
532 const OUString& rUIFile, sal_uInt64 nLOKWindowId)
533 : SalInstanceBuilder(extract_sal_widget(pParent), rUIRoot, rUIFile)
534 , m_nWindowId(nLOKWindowId)
535 , m_aParentDialog(nullptr)
536 , m_aContentWindow(nullptr)
537 , m_sTypeOfJSON("sidebar")
538 , m_bHasTopLevelDialog(false)
539 , m_bIsNotebookbar(false)
540 , m_aWindowToRelease(nullptr)
542 vcl::Window* pRoot = m_xBuilder->get_widget_root();
544 m_aParentDialog = pRoot->GetParentWithLOKNotifier();
546 if (rUIFile == "sfx/ui/panel.ui")
548 // builder for Panel, get SidebarDockingWindow as m_aContentWindow
549 m_aContentWindow = pRoot;
550 for (int i = 0; i < 7 && m_aContentWindow; i++)
551 m_aContentWindow = m_aContentWindow->GetParent();
553 else
555 // embedded fragments cannot send close message for whole sidebar
556 if (rUIFile == "modules/simpress/ui/customanimationfragment.ui")
557 m_bCanClose = false;
559 // builder for PanelLayout, get SidebarDockingWindow as m_aContentWindow
560 m_aContentWindow = pRoot;
561 for (int i = 0; i < 9 && m_aContentWindow; i++)
562 m_aContentWindow = m_aContentWindow->GetParent();
565 InsertWindowToMap(getMapIdFromWindowId());
567 initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
570 // used for notebookbar
571 JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot,
572 const OUString& rUIFile,
573 const css::uno::Reference<css::frame::XFrame>& rFrame,
574 sal_uInt64 nWindowId)
575 : SalInstanceBuilder(pParent, rUIRoot, rUIFile, rFrame)
576 , m_nWindowId(0)
577 , m_aParentDialog(nullptr)
578 , m_aContentWindow(nullptr)
579 , m_sTypeOfJSON("notebookbar")
580 , m_bHasTopLevelDialog(false)
581 , m_bIsNotebookbar(false)
582 , m_aWindowToRelease(nullptr)
584 vcl::Window* pRoot = m_xBuilder->get_widget_root();
585 if (pRoot && pRoot->GetParent())
587 m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier();
588 if (m_aParentDialog)
589 m_nWindowId = m_aParentDialog->GetLOKWindowId();
590 if (!m_nWindowId && nWindowId)
592 m_nWindowId = nWindowId;
593 m_bIsNotebookbar = true;
595 InsertWindowToMap(getMapIdFromWindowId());
598 initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
601 // used for formulabar
602 JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot,
603 const OUString& rUIFile, sal_uInt64 nLOKWindowId)
604 : SalInstanceBuilder(pParent, rUIRoot, rUIFile)
605 , m_nWindowId(nLOKWindowId)
606 , m_aParentDialog(nullptr)
607 , m_aContentWindow(nullptr)
608 , m_sTypeOfJSON("formulabar")
609 , m_bHasTopLevelDialog(false)
610 , m_bIsNotebookbar(false)
611 , m_aWindowToRelease(nullptr)
613 vcl::Window* pRoot = m_xBuilder->get_widget_root();
614 m_aContentWindow = pParent;
615 if (pRoot && pRoot->GetParent())
617 m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier();
618 InsertWindowToMap(getMapIdFromWindowId());
621 initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
624 std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreateDialogBuilder(weld::Widget* pParent,
625 const OUString& rUIRoot,
626 const OUString& rUIFile)
628 return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile);
631 std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreateNotebookbarBuilder(
632 vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile,
633 const css::uno::Reference<css::frame::XFrame>& rFrame, sal_uInt64 nWindowId)
635 return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, rFrame, nWindowId);
638 std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreateSidebarBuilder(weld::Widget* pParent,
639 const OUString& rUIRoot,
640 const OUString& rUIFile,
641 sal_uInt64 nLOKWindowId)
643 return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, nLOKWindowId);
646 std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreatePopupBuilder(weld::Widget* pParent,
647 const OUString& rUIRoot,
648 const OUString& rUIFile)
650 return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, true);
653 std::unique_ptr<JSInstanceBuilder>
654 JSInstanceBuilder::CreateFormulabarBuilder(vcl::Window* pParent, const OUString& rUIRoot,
655 const OUString& rUIFile, sal_uInt64 nLOKWindowId)
657 return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, nLOKWindowId);
660 JSInstanceBuilder::~JSInstanceBuilder()
662 if (m_aWindowToRelease)
664 m_aWindowToRelease->ReleaseLOKNotifier();
665 m_aWindowToRelease.clear();
668 if (m_nWindowId && (m_bHasTopLevelDialog || m_bIsNotebookbar))
670 GetLOKWeldWidgetsMap().erase(getMapIdFromWindowId());
672 else
674 auto it = GetLOKWeldWidgetsMap().find(getMapIdFromWindowId());
675 if (it != GetLOKWeldWidgetsMap().end())
677 std::for_each(m_aRememberedWidgets.begin(), m_aRememberedWidgets.end(),
678 [it](std::string& sId) { it->second.erase(sId.c_str()); });
682 GetLOKPopupsMap().erase(std::to_string(m_nWindowId));
685 std::map<std::string, WidgetMap>& JSInstanceBuilder::GetLOKWeldWidgetsMap()
687 // Map to remember the LOKWindowId <-> weld widgets binding.
688 static std::map<std::string, WidgetMap> s_aLOKWeldBuildersMap;
690 return s_aLOKWeldBuildersMap;
693 weld::Widget* JSInstanceBuilder::FindWeldWidgetsMap(const std::string& nWindowId,
694 const OString& rWidget)
696 const auto it = GetLOKWeldWidgetsMap().find(nWindowId);
698 if (it != GetLOKWeldWidgetsMap().end())
700 auto widgetIt = it->second.find(rWidget);
701 if (widgetIt != it->second.end())
702 return widgetIt->second;
705 return nullptr;
708 void JSInstanceBuilder::InsertWindowToMap(const std::string& nWindowId)
710 WidgetMap map;
711 auto it = GetLOKWeldWidgetsMap().find(nWindowId);
712 if (it == GetLOKWeldWidgetsMap().end())
713 GetLOKWeldWidgetsMap().insert(std::map<std::string, WidgetMap>::value_type(nWindowId, map));
716 void JSInstanceBuilder::RememberWidget(OString sId, weld::Widget* pWidget)
718 // do not use the same id for two widgets inside one builder
719 // exception is sidebar where we base our full invalidation on that "Panel" id sharing
720 if (m_sTypeOfJSON != "sidebar")
722 static std::atomic<unsigned long long int> nNotRepeatIndex = 0;
723 auto aWindowIt = GetLOKWeldWidgetsMap().find(getMapIdFromWindowId());
724 if (aWindowIt != GetLOKWeldWidgetsMap().end())
726 auto aWidgetIt = aWindowIt->second.find(sId);
727 if (aWidgetIt != aWindowIt->second.end())
729 unsigned long long int nIndex = nNotRepeatIndex++;
730 // found duplicated it -> add some number to the id and apply to the widget
731 sId = sId + OString::number(nIndex);
732 SalInstanceWidget* pSalWidget = dynamic_cast<SalInstanceWidget*>(pWidget);
733 assert(pSalWidget && "can only be a SalInstanceWidget");
734 vcl::Window* pVclWidget = pSalWidget->getWidget();
735 pVclWidget->set_id(pVclWidget->get_id() + OUString::number(nIndex));
740 RememberWidget(getMapIdFromWindowId(), sId, pWidget);
741 m_aRememberedWidgets.push_back(sId.getStr());
744 void JSInstanceBuilder::RememberWidget(const std::string& nWindowId, const OString& id,
745 weld::Widget* pWidget)
747 auto it = GetLOKWeldWidgetsMap().find(nWindowId);
748 if (it != GetLOKWeldWidgetsMap().end())
750 it->second.erase(id);
751 it->second.insert(WidgetMap::value_type(id, pWidget));
755 void JSInstanceBuilder::AddChildWidget(const std::string& nWindowId, const OString& id,
756 weld::Widget* pWidget)
758 auto it = GetLOKWeldWidgetsMap().find(nWindowId);
759 if (it != GetLOKWeldWidgetsMap().end())
761 it->second.erase(id);
762 it->second.insert(WidgetMap::value_type(id, pWidget));
766 void JSInstanceBuilder::RemoveWindowWidget(const std::string& nWindowId)
768 auto it = JSInstanceBuilder::GetLOKWeldWidgetsMap().find(nWindowId);
769 if (it != JSInstanceBuilder::GetLOKWeldWidgetsMap().end())
771 JSInstanceBuilder::GetLOKWeldWidgetsMap().erase(it);
775 void JSInstanceBuilder::RememberPopup(const std::string& nWindowId, VclPtr<vcl::Window> pWidget)
777 GetLOKPopupsMap()[nWindowId] = pWidget;
780 void JSInstanceBuilder::ForgetPopup(const std::string& nWindowId)
782 auto it = GetLOKPopupsMap().find(nWindowId);
783 if (it != GetLOKPopupsMap().end())
784 GetLOKPopupsMap().erase(it);
787 vcl::Window* JSInstanceBuilder::FindPopup(const std::string& nWindowId)
789 const auto it = GetLOKPopupsMap().find(nWindowId);
791 if (it != GetLOKPopupsMap().end())
792 return it->second;
794 return nullptr;
797 const std::string& JSInstanceBuilder::GetTypeOfJSON() const { return m_sTypeOfJSON; }
799 VclPtr<vcl::Window>& JSInstanceBuilder::GetContentWindow()
801 if (m_aContentWindow)
802 return m_aContentWindow;
803 else
804 return m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog;
807 VclPtr<vcl::Window>& JSInstanceBuilder::GetNotifierWindow()
809 return m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog;
812 std::unique_ptr<weld::Dialog> JSInstanceBuilder::weld_dialog(const OString& id)
814 std::unique_ptr<weld::Dialog> pRet;
815 ::Dialog* pDialog = m_xBuilder->get<::Dialog>(id);
817 if (pDialog)
819 m_nWindowId = pDialog->GetLOKWindowId();
820 pDialog->SetLOKTunnelingState(false);
822 InsertWindowToMap(getMapIdFromWindowId());
824 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
825 m_aOwnedToplevel.set(pDialog);
826 m_xBuilder->drop_ownership(pDialog);
827 m_bHasTopLevelDialog = true;
829 pRet.reset(new JSDialog(this, pDialog, this, false));
831 RememberWidget("__DIALOG__", pRet.get());
833 initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
834 sendFullUpdate();
837 return pRet;
840 std::unique_ptr<weld::MessageDialog> JSInstanceBuilder::weld_message_dialog(const OString& id)
842 std::unique_ptr<weld::MessageDialog> pRet;
843 ::MessageDialog* pMessageDialog = m_xBuilder->get<::MessageDialog>(id);
845 if (pMessageDialog)
847 m_nWindowId = pMessageDialog->GetLOKWindowId();
848 pMessageDialog->SetLOKTunnelingState(false);
850 InsertWindowToMap(getMapIdFromWindowId());
852 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
853 m_aOwnedToplevel.set(pMessageDialog);
854 m_xBuilder->drop_ownership(pMessageDialog);
855 m_bHasTopLevelDialog = true;
857 initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
860 pRet.reset(pMessageDialog ? new JSMessageDialog(this, pMessageDialog, this, false) : nullptr);
862 if (pRet)
863 RememberWidget("__DIALOG__", pRet.get());
865 return pRet;
868 std::unique_ptr<weld::Container> JSInstanceBuilder::weld_container(const OString& id)
870 vcl::Window* pContainer = m_xBuilder->get<vcl::Window>(id);
871 auto pWeldWidget = std::make_unique<JSContainer>(this, pContainer, this, false);
873 if (pWeldWidget)
874 RememberWidget(id, pWeldWidget.get());
876 return pWeldWidget;
879 std::unique_ptr<weld::Label> JSInstanceBuilder::weld_label(const OString& id)
881 Control* pLabel = m_xBuilder->get<Control>(id);
882 auto pWeldWidget = std::make_unique<JSLabel>(this, pLabel, this, false);
884 if (pWeldWidget)
885 RememberWidget(id, pWeldWidget.get());
887 return pWeldWidget;
890 std::unique_ptr<weld::Button> JSInstanceBuilder::weld_button(const OString& id)
892 ::Button* pButton = m_xBuilder->get<::Button>(id);
893 auto pWeldWidget = pButton ? std::make_unique<JSButton>(this, pButton, this, false) : nullptr;
895 if (pWeldWidget)
896 RememberWidget(id, pWeldWidget.get());
898 return pWeldWidget;
901 std::unique_ptr<weld::Entry> JSInstanceBuilder::weld_entry(const OString& id)
903 Edit* pEntry = m_xBuilder->get<Edit>(id);
904 auto pWeldWidget = pEntry ? std::make_unique<JSEntry>(this, pEntry, this, false) : nullptr;
906 if (pWeldWidget)
907 RememberWidget(id, pWeldWidget.get());
909 return pWeldWidget;
912 std::unique_ptr<weld::ComboBox> JSInstanceBuilder::weld_combo_box(const OString& id)
914 vcl::Window* pWidget = m_xBuilder->get<vcl::Window>(id);
915 ::ComboBox* pComboBox = dynamic_cast<::ComboBox*>(pWidget);
916 std::unique_ptr<weld::ComboBox> pWeldWidget;
918 if (pComboBox)
920 pWeldWidget = std::make_unique<JSComboBox>(this, pComboBox, this, false);
922 else
924 ListBox* pListBox = dynamic_cast<ListBox*>(pWidget);
925 pWeldWidget = pListBox ? std::make_unique<JSListBox>(this, pListBox, this, false) : nullptr;
928 if (pWeldWidget)
929 RememberWidget(id, pWeldWidget.get());
931 return pWeldWidget;
934 std::unique_ptr<weld::Notebook> JSInstanceBuilder::weld_notebook(const OString& id)
936 TabControl* pNotebook = m_xBuilder->get<TabControl>(id);
937 auto pWeldWidget
938 = pNotebook ? std::make_unique<JSNotebook>(this, pNotebook, this, false) : nullptr;
940 if (pWeldWidget)
941 RememberWidget(id, pWeldWidget.get());
943 return pWeldWidget;
946 std::unique_ptr<weld::SpinButton> JSInstanceBuilder::weld_spin_button(const OString& id)
948 FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id);
949 auto pWeldWidget
950 = pSpinButton ? std::make_unique<JSSpinButton>(this, pSpinButton, this, false) : nullptr;
952 if (pWeldWidget)
953 RememberWidget(id, pWeldWidget.get());
955 return pWeldWidget;
958 std::unique_ptr<weld::CheckButton> JSInstanceBuilder::weld_check_button(const OString& id)
960 CheckBox* pCheckButton = m_xBuilder->get<CheckBox>(id);
961 auto pWeldWidget
962 = pCheckButton ? std::make_unique<JSCheckButton>(this, pCheckButton, this, false) : nullptr;
964 if (pWeldWidget)
965 RememberWidget(id, pWeldWidget.get());
967 return pWeldWidget;
970 std::unique_ptr<weld::DrawingArea>
971 JSInstanceBuilder::weld_drawing_area(const OString& id, const a11yref& rA11yImpl,
972 FactoryFunction pUITestFactoryFunction, void* pUserData)
974 VclDrawingArea* pArea = m_xBuilder->get<VclDrawingArea>(id);
975 auto pWeldWidget = pArea ? std::make_unique<JSDrawingArea>(this, pArea, this, rA11yImpl,
976 pUITestFactoryFunction, pUserData)
977 : nullptr;
979 if (pWeldWidget)
980 RememberWidget(id, pWeldWidget.get());
982 return pWeldWidget;
985 std::unique_ptr<weld::Toolbar> JSInstanceBuilder::weld_toolbar(const OString& id)
987 ToolBox* pToolBox = m_xBuilder->get<ToolBox>(id);
988 auto pWeldWidget
989 = pToolBox ? std::make_unique<JSToolbar>(this, pToolBox, this, false) : nullptr;
991 if (pWeldWidget)
992 RememberWidget(id, pWeldWidget.get());
994 return pWeldWidget;
997 std::unique_ptr<weld::TextView> JSInstanceBuilder::weld_text_view(const OString& id)
999 VclMultiLineEdit* pTextView = m_xBuilder->get<VclMultiLineEdit>(id);
1000 auto pWeldWidget
1001 = pTextView ? std::make_unique<JSTextView>(this, pTextView, this, false) : nullptr;
1003 if (pWeldWidget)
1004 RememberWidget(id, pWeldWidget.get());
1006 return pWeldWidget;
1009 std::unique_ptr<weld::TreeView> JSInstanceBuilder::weld_tree_view(const OString& id)
1011 SvTabListBox* pTreeView = m_xBuilder->get<SvTabListBox>(id);
1012 auto pWeldWidget
1013 = pTreeView ? std::make_unique<JSTreeView>(this, pTreeView, this, false) : nullptr;
1015 if (pWeldWidget)
1016 RememberWidget(id, pWeldWidget.get());
1018 return pWeldWidget;
1021 std::unique_ptr<weld::Expander> JSInstanceBuilder::weld_expander(const OString& id)
1023 VclExpander* pExpander = m_xBuilder->get<VclExpander>(id);
1024 auto pWeldWidget
1025 = pExpander ? std::make_unique<JSExpander>(this, pExpander, this, false) : nullptr;
1027 if (pWeldWidget)
1028 RememberWidget(id, pWeldWidget.get());
1030 return pWeldWidget;
1033 std::unique_ptr<weld::IconView> JSInstanceBuilder::weld_icon_view(const OString& id)
1035 ::IconView* pIconView = m_xBuilder->get<::IconView>(id);
1036 auto pWeldWidget
1037 = pIconView ? std::make_unique<JSIconView>(this, pIconView, this, false) : nullptr;
1039 if (pWeldWidget)
1040 RememberWidget(id, pWeldWidget.get());
1042 return pWeldWidget;
1045 std::unique_ptr<weld::RadioButton> JSInstanceBuilder::weld_radio_button(const OString& id)
1047 ::RadioButton* pRadioButton = m_xBuilder->get<::RadioButton>(id);
1048 auto pWeldWidget
1049 = pRadioButton ? std::make_unique<JSRadioButton>(this, pRadioButton, this, false) : nullptr;
1051 if (pWeldWidget)
1052 RememberWidget(id, pWeldWidget.get());
1054 return pWeldWidget;
1057 std::unique_ptr<weld::Frame> JSInstanceBuilder::weld_frame(const OString& id)
1059 ::VclFrame* pFrame = m_xBuilder->get<::VclFrame>(id);
1060 auto pWeldWidget = pFrame ? std::make_unique<JSFrame>(this, pFrame, this, false) : nullptr;
1062 if (pWeldWidget)
1063 RememberWidget(id, pWeldWidget.get());
1065 return pWeldWidget;
1068 std::unique_ptr<weld::MenuButton> JSInstanceBuilder::weld_menu_button(const OString& id)
1070 ::MenuButton* pMenuButton = m_xBuilder->get<::MenuButton>(id);
1071 auto pWeldWidget
1072 = pMenuButton ? std::make_unique<JSMenuButton>(this, pMenuButton, this, false) : nullptr;
1074 if (pWeldWidget)
1075 RememberWidget(id, pWeldWidget.get());
1077 return pWeldWidget;
1080 std::unique_ptr<weld::Popover> JSInstanceBuilder::weld_popover(const OString& id)
1082 DockingWindow* pDockingWindow = m_xBuilder->get<DockingWindow>(id);
1083 JSPopover* pPopover
1084 = pDockingWindow ? new JSPopover(this, pDockingWindow, this, false) : nullptr;
1085 std::unique_ptr<weld::Popover> pWeldWidget(pPopover);
1086 if (pDockingWindow)
1088 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
1089 m_aOwnedToplevel.set(pDockingWindow);
1090 m_xBuilder->drop_ownership(pDockingWindow);
1092 if (VclPtr<vcl::Window> pWin = pDockingWindow->GetParentWithLOKNotifier())
1094 vcl::Window* pPopupRoot = pDockingWindow->GetChild(0);
1095 pPopupRoot->SetLOKNotifier(pWin->GetLOKNotifier());
1096 m_aParentDialog = pPopupRoot;
1097 m_aWindowToRelease = pPopupRoot;
1098 m_nWindowId = m_aParentDialog->GetLOKWindowId();
1100 pPopover->set_window_id(m_nWindowId);
1101 JSInstanceBuilder::RememberPopup(std::to_string(m_nWindowId), pDockingWindow);
1103 InsertWindowToMap(getMapIdFromWindowId());
1104 initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON());
1108 if (pWeldWidget)
1109 RememberWidget("__POPOVER__", pWeldWidget.get());
1111 return pWeldWidget;
1114 std::unique_ptr<weld::Box> JSInstanceBuilder::weld_box(const OString& id)
1116 VclBox* pContainer = m_xBuilder->get<VclBox>(id);
1117 auto pWeldWidget
1118 = pContainer ? std::make_unique<JSBox>(this, pContainer, this, false) : nullptr;
1120 if (pWeldWidget)
1121 RememberWidget(id, pWeldWidget.get());
1123 return pWeldWidget;
1126 std::unique_ptr<weld::Widget> JSInstanceBuilder::weld_widget(const OString& id)
1128 vcl::Window* pWidget = m_xBuilder->get(id);
1129 auto pWeldWidget
1130 = pWidget ? std::make_unique<JSWidgetInstance>(this, pWidget, this, false) : nullptr;
1132 if (pWeldWidget)
1133 RememberWidget(id, pWeldWidget.get());
1135 return pWeldWidget;
1138 std::unique_ptr<weld::Image> JSInstanceBuilder::weld_image(const OString& id)
1140 FixedImage* pImage = m_xBuilder->get<FixedImage>(id);
1142 auto pWeldWidget = pImage ? std::make_unique<JSImage>(this, pImage, this, false) : nullptr;
1144 if (pWeldWidget)
1145 RememberWidget(id, pWeldWidget.get());
1147 return pWeldWidget;
1150 weld::MessageDialog* JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent,
1151 VclMessageType eMessageType,
1152 VclButtonsType eButtonType,
1153 const OUString& rPrimaryMessage)
1155 SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent);
1156 SystemWindow* pParentWidget = pParentInstance ? pParentInstance->getSystemWindow() : nullptr;
1157 VclPtrInstance<::MessageDialog> xMessageDialog(pParentWidget, rPrimaryMessage, eMessageType,
1158 eButtonType);
1160 const vcl::ILibreOfficeKitNotifier* pNotifier = xMessageDialog->GetLOKNotifier();
1161 if (pNotifier)
1163 tools::JsonWriter aJsonWriter;
1164 xMessageDialog->DumpAsPropertyTree(aJsonWriter);
1165 aJsonWriter.put("id", xMessageDialog->GetLOKWindowId());
1166 aJsonWriter.put("jsontype", "dialog");
1167 std::unique_ptr<char[], o3tl::free_delete> message(aJsonWriter.extractData());
1168 pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.get());
1171 xMessageDialog->SetLOKTunnelingState(false);
1172 std::string sWindowId = std::to_string(xMessageDialog->GetLOKWindowId());
1173 InsertWindowToMap(sWindowId);
1175 weld::MessageDialog* pRet = new JSMessageDialog(xMessageDialog, nullptr, true);
1177 if (pRet)
1178 RememberWidget(sWindowId, "__DIALOG__", pRet);
1180 return pRet;
1183 JSDialog::JSDialog(JSDialogSender* pSender, ::Dialog* pDialog, SalInstanceBuilder* pBuilder,
1184 bool bTakeOwnership)
1185 : JSWidget<SalInstanceDialog, ::Dialog>(pSender, pDialog, pBuilder, bTakeOwnership)
1189 void JSDialog::collapse(weld::Widget* pEdit, weld::Widget* pButton)
1191 SalInstanceDialog::collapse(pEdit, pButton);
1192 sendFullUpdate();
1195 void JSDialog::undo_collapse()
1197 SalInstanceDialog::undo_collapse();
1198 sendFullUpdate();
1201 void JSDialog::response(int response)
1203 if (response == RET_HELP)
1205 response_help(m_xWidget.get());
1206 return;
1209 sendClose();
1210 SalInstanceDialog::response(response);
1213 JSContainer::JSContainer(JSDialogSender* pSender, vcl::Window* pContainer,
1214 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1215 : JSWidget<SalInstanceContainer, vcl::Window>(pSender, pContainer, pBuilder, bTakeOwnership)
1219 JSLabel::JSLabel(JSDialogSender* pSender, Control* pLabel, SalInstanceBuilder* pBuilder,
1220 bool bTakeOwnership)
1221 : JSWidget<SalInstanceLabel, Control>(pSender, pLabel, pBuilder, bTakeOwnership)
1225 void JSLabel::set_label(const OUString& rText)
1227 SalInstanceLabel::set_label(rText);
1228 sendUpdate();
1231 JSButton::JSButton(JSDialogSender* pSender, ::Button* pButton, SalInstanceBuilder* pBuilder,
1232 bool bTakeOwnership)
1233 : JSWidget<SalInstanceButton, ::Button>(pSender, pButton, pBuilder, bTakeOwnership)
1237 JSEntry::JSEntry(JSDialogSender* pSender, ::Edit* pEntry, SalInstanceBuilder* pBuilder,
1238 bool bTakeOwnership)
1239 : JSWidget<SalInstanceEntry, ::Edit>(pSender, pEntry, pBuilder, bTakeOwnership)
1243 void JSEntry::set_text(const OUString& rText)
1245 SalInstanceEntry::set_text(rText);
1246 sendUpdate();
1249 void JSEntry::set_text_without_notify(const OUString& rText) { SalInstanceEntry::set_text(rText); }
1251 JSListBox::JSListBox(JSDialogSender* pSender, ::ListBox* pListBox, SalInstanceBuilder* pBuilder,
1252 bool bTakeOwnership)
1253 : JSWidget<SalInstanceComboBoxWithoutEdit, ::ListBox>(pSender, pListBox, pBuilder,
1254 bTakeOwnership)
1258 void JSListBox::insert(int pos, const OUString& rStr, const OUString* pId,
1259 const OUString* pIconName, VirtualDevice* pImageSurface)
1261 SalInstanceComboBoxWithoutEdit::insert(pos, rStr, pId, pIconName, pImageSurface);
1262 sendUpdate();
1265 void JSListBox::remove(int pos)
1267 SalInstanceComboBoxWithoutEdit::remove(pos);
1268 sendUpdate();
1271 void JSListBox::set_active(int pos)
1273 SalInstanceComboBoxWithoutEdit::set_active(pos);
1274 sendUpdate();
1277 JSComboBox::JSComboBox(JSDialogSender* pSender, ::ComboBox* pComboBox, SalInstanceBuilder* pBuilder,
1278 bool bTakeOwnership)
1279 : JSWidget<SalInstanceComboBoxWithEdit, ::ComboBox>(pSender, pComboBox, pBuilder,
1280 bTakeOwnership)
1284 void JSComboBox::insert(int pos, const OUString& rStr, const OUString* pId,
1285 const OUString* pIconName, VirtualDevice* pImageSurface)
1287 SalInstanceComboBoxWithEdit::insert(pos, rStr, pId, pIconName, pImageSurface);
1288 sendUpdate();
1291 void JSComboBox::remove(int pos)
1293 SalInstanceComboBoxWithEdit::remove(pos);
1294 sendUpdate();
1297 void JSComboBox::set_entry_text_without_notify(const OUString& rText)
1299 SalInstanceComboBoxWithEdit::set_entry_text(rText);
1302 void JSComboBox::set_entry_text(const OUString& rText)
1304 SalInstanceComboBoxWithEdit::set_entry_text(rText);
1305 sendUpdate();
1308 void JSComboBox::set_active(int pos)
1310 SalInstanceComboBoxWithEdit::set_active(pos);
1311 sendUpdate();
1314 bool JSComboBox::changed_by_direct_pick() const { return true; }
1316 JSNotebook::JSNotebook(JSDialogSender* pSender, ::TabControl* pControl,
1317 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1318 : JSWidget<SalInstanceNotebook, ::TabControl>(pSender, pControl, pBuilder, bTakeOwnership)
1322 void JSNotebook::set_current_page(int nPage)
1324 bool bForce = false;
1325 int nCurrent = get_current_page();
1326 if (nCurrent == nPage)
1327 bForce = true;
1329 SalInstanceNotebook::set_current_page(nPage);
1330 sendFullUpdate(bForce);
1332 m_aEnterPageHdl.Call(get_current_page_ident());
1335 void JSNotebook::set_current_page(const OString& rIdent)
1337 bool bForce = false;
1338 OString sCurrent = get_current_page_ident();
1339 if (sCurrent == rIdent)
1340 bForce = true;
1342 SalInstanceNotebook::set_current_page(rIdent);
1343 sendFullUpdate(bForce);
1345 m_aEnterPageHdl.Call(get_current_page_ident());
1348 void JSNotebook::remove_page(const OString& rIdent)
1350 SalInstanceNotebook::remove_page(rIdent);
1351 sendFullUpdate();
1354 void JSNotebook::insert_page(const OString& rIdent, const OUString& rLabel, int nPos)
1356 SalInstanceNotebook::insert_page(rIdent, rLabel, nPos);
1357 sendFullUpdate();
1360 JSSpinButton::JSSpinButton(JSDialogSender* pSender, ::FormattedField* pSpin,
1361 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1362 : JSWidget<SalInstanceSpinButton, ::FormattedField>(pSender, pSpin, pBuilder, bTakeOwnership)
1366 void JSSpinButton::set_value(sal_Int64 value)
1368 SalInstanceSpinButton::set_value(value);
1369 sendUpdate(true); // if input is limited we can receive the same JSON
1372 JSMessageDialog::JSMessageDialog(JSDialogSender* pSender, ::MessageDialog* pDialog,
1373 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1374 : JSWidget<SalInstanceMessageDialog, ::MessageDialog>(pSender, pDialog, pBuilder,
1375 bTakeOwnership)
1379 JSMessageDialog::JSMessageDialog(::MessageDialog* pDialog, SalInstanceBuilder* pBuilder,
1380 bool bTakeOwnership)
1381 : JSWidget<SalInstanceMessageDialog, ::MessageDialog>(nullptr, pDialog, pBuilder,
1382 bTakeOwnership)
1383 , m_pOwnedSender(new JSDialogSender(pDialog, pDialog, "dialog"))
1385 m_pSender = m_pOwnedSender.get();
1387 if (pBuilder)
1388 return;
1390 m_sWindowId = std::to_string(m_xMessageDialog->GetLOKWindowId());
1392 if (::OKButton* pOKBtn
1393 = dynamic_cast<::OKButton*>(m_xMessageDialog->get_widget_for_response(RET_OK)))
1395 m_pOK.reset(new JSButton(m_pSender, pOKBtn, nullptr, false));
1396 JSInstanceBuilder::AddChildWidget(m_sWindowId, pOKBtn->get_id().toUtf8(), m_pOK.get());
1397 m_pOK->connect_clicked(LINK(this, JSMessageDialog, OKHdl));
1400 if (::CancelButton* pCancelBtn
1401 = dynamic_cast<::CancelButton*>(m_xMessageDialog->get_widget_for_response(RET_CANCEL)))
1403 m_pCancel.reset(new JSButton(m_pSender, pCancelBtn, nullptr, false));
1404 JSInstanceBuilder::AddChildWidget(m_sWindowId, pCancelBtn->get_id().toUtf8(),
1405 m_pCancel.get());
1406 m_pCancel->connect_clicked(LINK(this, JSMessageDialog, CancelHdl));
1410 JSMessageDialog::~JSMessageDialog()
1412 if (m_pOK || m_pCancel)
1413 JSInstanceBuilder::RemoveWindowWidget(m_sWindowId);
1416 IMPL_LINK_NOARG(JSMessageDialog, OKHdl, weld::Button&, void) { response(RET_OK); }
1418 IMPL_LINK_NOARG(JSMessageDialog, CancelHdl, weld::Button&, void) { response(RET_CANCEL); }
1420 void JSMessageDialog::set_primary_text(const OUString& rText)
1422 SalInstanceMessageDialog::set_primary_text(rText);
1423 sendFullUpdate();
1426 void JSMessageDialog::set_secondary_text(const OUString& rText)
1428 SalInstanceMessageDialog::set_secondary_text(rText);
1429 sendFullUpdate();
1432 void JSMessageDialog::response(int response)
1434 if (response == RET_HELP)
1436 response_help(m_xWidget.get());
1437 return;
1440 sendClose();
1441 SalInstanceMessageDialog::response(response);
1444 JSCheckButton::JSCheckButton(JSDialogSender* pSender, ::CheckBox* pCheckBox,
1445 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1446 : JSWidget<SalInstanceCheckButton, ::CheckBox>(pSender, pCheckBox, pBuilder, bTakeOwnership)
1450 void JSCheckButton::set_active(bool active)
1452 bool bWasActive = get_active();
1453 SalInstanceCheckButton::set_active(active);
1454 if (bWasActive != active)
1455 sendUpdate();
1458 JSDrawingArea::JSDrawingArea(JSDialogSender* pSender, VclDrawingArea* pDrawingArea,
1459 SalInstanceBuilder* pBuilder, const a11yref& rAlly,
1460 FactoryFunction pUITestFactoryFunction, void* pUserData)
1461 : JSWidget<SalInstanceDrawingArea, VclDrawingArea>(pSender, pDrawingArea, pBuilder, rAlly,
1462 pUITestFactoryFunction, pUserData, false)
1466 void JSDrawingArea::queue_draw()
1468 SalInstanceDrawingArea::queue_draw();
1469 sendUpdate();
1472 void JSDrawingArea::queue_draw_area(int x, int y, int width, int height)
1474 SalInstanceDrawingArea::queue_draw_area(x, y, width, height);
1475 sendUpdate();
1478 JSToolbar::JSToolbar(JSDialogSender* pSender, ::ToolBox* pToolbox, SalInstanceBuilder* pBuilder,
1479 bool bTakeOwnership)
1480 : JSWidget<SalInstanceToolbar, ::ToolBox>(pSender, pToolbox, pBuilder, bTakeOwnership)
1484 void JSToolbar::set_menu_item_active(const OString& rIdent, bool bActive)
1486 bool bWasActive = get_menu_item_active(rIdent);
1487 SalInstanceToolbar::set_menu_item_active(rIdent, bActive);
1489 ToolBoxItemId nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent));
1490 VclPtr<vcl::Window> pFloat = m_aFloats[nItemId];
1492 if (!pFloat)
1493 return;
1495 // See WeldToolbarPopup : include/svtools/toolbarmenu.hxx
1496 // TopLevel (Popover) -> Container -> main container of the popup
1497 vcl::Window* pPopupRoot = pFloat->GetChild(0);
1498 if (pPopupRoot)
1499 pPopupRoot = pPopupRoot->GetChild(0);
1501 if (pPopupRoot)
1503 if (bActive)
1505 JSInstanceBuilder::RememberPopup(std::to_string(pPopupRoot->GetLOKWindowId()), pFloat);
1506 sendPopup(pPopupRoot, m_xToolBox->get_id(),
1507 OStringToOUString(rIdent, RTL_TEXTENCODING_ASCII_US));
1509 else if (bWasActive)
1511 JSInstanceBuilder::ForgetPopup(std::to_string(pPopupRoot->GetLOKWindowId()));
1512 sendClosePopup(pPopupRoot->GetLOKWindowId());
1517 void JSToolbar::set_item_sensitive(const OString& rIdent, bool bSensitive)
1519 SalInstanceToolbar::set_item_sensitive(rIdent, bSensitive);
1520 sendUpdate();
1523 void JSToolbar::set_item_icon_name(const OString& rIdent, const OUString& rIconName)
1525 SalInstanceToolbar::set_item_icon_name(rIdent, rIconName);
1526 sendUpdate();
1529 JSTextView::JSTextView(JSDialogSender* pSender, ::VclMultiLineEdit* pTextView,
1530 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1531 : JSWidget<SalInstanceTextView, ::VclMultiLineEdit>(pSender, pTextView, pBuilder,
1532 bTakeOwnership)
1536 void JSTextView::set_text(const OUString& rText)
1538 SalInstanceTextView::set_text(rText);
1539 sendUpdate();
1542 JSTreeView::JSTreeView(JSDialogSender* pSender, ::SvTabListBox* pTreeView,
1543 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1544 : JSWidget<SalInstanceTreeView, ::SvTabListBox>(pSender, pTreeView, pBuilder, bTakeOwnership)
1548 void JSTreeView::set_toggle(int pos, TriState eState, int col)
1550 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, 0);
1552 while (pEntry && pos--)
1553 pEntry = m_xTreeView->Next(pEntry);
1555 if (pEntry)
1557 SalInstanceTreeView::set_toggle(pEntry, eState, col);
1558 signal_toggled(iter_col(SalInstanceTreeIter(pEntry), col));
1560 sendUpdate();
1564 void JSTreeView::set_toggle(const weld::TreeIter& rIter, TriState bOn, int col)
1566 SalInstanceTreeView::set_toggle(rIter, bOn, col);
1567 sendUpdate();
1570 void JSTreeView::select(int pos)
1572 assert(m_xTreeView->IsUpdateMode() && "don't select when frozen");
1573 disable_notify_events();
1574 if (pos == -1 || (pos == 0 && n_children() == 0))
1575 m_xTreeView->SelectAll(false);
1576 else
1578 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, 0);
1580 while (pEntry && pos--)
1581 pEntry = m_xTreeView->Next(pEntry);
1583 if (pEntry)
1585 m_xTreeView->Select(pEntry, true);
1586 m_xTreeView->MakeVisible(pEntry);
1589 enable_notify_events();
1590 sendUpdate();
1593 weld::TreeView* JSTreeView::get_drag_source() const { return g_DragSource; }
1595 void JSTreeView::drag_start() { g_DragSource = this; }
1597 void JSTreeView::drag_end()
1599 css::datatransfer::dnd::XDropTarget* xDropTarget = m_xDropTarget.get();
1600 if (xDropTarget)
1602 css::datatransfer::dnd::DropTargetDropEvent aEvent;
1603 aEvent.Source = xDropTarget;
1604 aEvent.Context = new JSDropTargetDropContext();
1605 // dummy values
1606 aEvent.LocationX = 50;
1607 aEvent.LocationY = 50;
1608 aEvent.DropAction = css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT;
1609 aEvent.SourceActions = css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT;
1611 m_xDropTarget->fire_drop(aEvent);
1613 sendUpdate();
1614 if (g_DragSource)
1615 g_DragSource->sendUpdate();
1618 g_DragSource = nullptr;
1621 void JSTreeView::insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
1622 const OUString* pId, const OUString* pIconName,
1623 VirtualDevice* pImageSurface, bool bChildrenOnDemand, weld::TreeIter* pRet)
1625 SalInstanceTreeView::insert(pParent, pos, pStr, pId, pIconName, pImageSurface,
1626 bChildrenOnDemand, pRet);
1628 sendUpdate();
1631 void JSTreeView::set_text(int row, const OUString& rText, int col)
1633 SalInstanceTreeView::set_text(row, rText, col);
1634 sendUpdate();
1637 void JSTreeView::set_text(const weld::TreeIter& rIter, const OUString& rStr, int col)
1639 SalInstanceTreeView::set_text(rIter, rStr, col);
1640 sendUpdate();
1643 void JSTreeView::remove(int pos)
1645 SalInstanceTreeView::remove(pos);
1646 sendUpdate();
1649 void JSTreeView::remove(const weld::TreeIter& rIter)
1651 SalInstanceTreeView::remove(rIter);
1652 sendUpdate();
1655 void JSTreeView::clear()
1657 SalInstanceTreeView::clear();
1658 sendUpdate();
1661 void JSTreeView::expand_row(const weld::TreeIter& rIter)
1663 SalInstanceTreeView::expand_row(rIter);
1664 sendUpdate();
1667 void JSTreeView::collapse_row(const weld::TreeIter& rIter)
1669 SalInstanceTreeView::collapse_row(rIter);
1670 sendUpdate();
1673 JSExpander::JSExpander(JSDialogSender* pSender, ::VclExpander* pExpander,
1674 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1675 : JSWidget<SalInstanceExpander, ::VclExpander>(pSender, pExpander, pBuilder, bTakeOwnership)
1679 void JSExpander::set_expanded(bool bExpand)
1681 SalInstanceExpander::set_expanded(bExpand);
1682 sendUpdate();
1685 JSIconView::JSIconView(JSDialogSender* pSender, ::IconView* pIconView, SalInstanceBuilder* pBuilder,
1686 bool bTakeOwnership)
1687 : JSWidget<SalInstanceIconView, ::IconView>(pSender, pIconView, pBuilder, bTakeOwnership)
1691 void JSIconView::insert(int pos, const OUString* pStr, const OUString* pId,
1692 const OUString* pIconName, weld::TreeIter* pRet)
1694 SalInstanceIconView::insert(pos, pStr, pId, pIconName, pRet);
1695 sendUpdate();
1698 void JSIconView::insert(int pos, const OUString* pStr, const OUString* pId,
1699 const VirtualDevice* pIcon, weld::TreeIter* pRet)
1701 SalInstanceIconView::insert(pos, pStr, pId, pIcon, pRet);
1702 sendUpdate();
1705 void JSIconView::insert_separator(int pos, const OUString* pId)
1707 SalInstanceIconView::insert_separator(pos, pId);
1708 sendUpdate();
1711 void JSIconView::clear()
1713 SalInstanceIconView::clear();
1714 sendUpdate();
1717 void JSIconView::select(int pos)
1719 SalInstanceIconView::select(pos);
1721 std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>();
1722 (*pMap)[ACTION_TYPE] = "select";
1723 (*pMap)["position"] = OUString::number(pos);
1724 sendAction(std::move(pMap));
1727 void JSIconView::unselect(int pos)
1729 SalInstanceIconView::unselect(pos);
1730 sendUpdate();
1733 JSRadioButton::JSRadioButton(JSDialogSender* pSender, ::RadioButton* pRadioButton,
1734 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1735 : JSWidget<SalInstanceRadioButton, ::RadioButton>(pSender, pRadioButton, pBuilder,
1736 bTakeOwnership)
1740 void JSRadioButton::set_active(bool active)
1742 SalInstanceRadioButton::set_active(active);
1743 sendUpdate();
1746 JSFrame::JSFrame(JSDialogSender* pSender, ::VclFrame* pFrame, SalInstanceBuilder* pBuilder,
1747 bool bTakeOwnership)
1748 : JSWidget<SalInstanceFrame, ::VclFrame>(pSender, pFrame, pBuilder, bTakeOwnership)
1752 JSMenuButton::JSMenuButton(JSDialogSender* pSender, ::MenuButton* pMenuButton,
1753 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1754 : JSWidget<SalInstanceMenuButton, ::MenuButton>(pSender, pMenuButton, pBuilder, bTakeOwnership)
1758 void JSMenuButton::set_label(const OUString& rText)
1760 OUString aPreviousLabel = get_label();
1761 SalInstanceMenuButton::set_label(rText);
1762 if (aPreviousLabel != rText)
1763 sendUpdate();
1766 void JSMenuButton::set_image(VirtualDevice* pDevice)
1768 SalInstanceMenuButton::set_image(pDevice);
1769 sendUpdate();
1772 void JSMenuButton::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage)
1774 SalInstanceMenuButton::set_image(rImage);
1775 sendUpdate();
1778 void JSMenuButton::set_active(bool bActive)
1780 SalInstanceMenuButton::set_active(bActive);
1782 VclPtr<vcl::Window> pPopup = m_xMenuButton->GetPopover();
1783 if (pPopup)
1785 if (bActive)
1786 sendPopup(pPopup->GetChild(0), m_xMenuButton->get_id(), m_xMenuButton->get_id());
1787 else
1788 sendClosePopup(pPopup->GetChild(0)->GetLOKWindowId());
1792 JSPopover::JSPopover(JSDialogSender* pSender, DockingWindow* pDockingWindow,
1793 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
1794 : JSWidget<SalInstancePopover, DockingWindow>(pSender, pDockingWindow, pBuilder, bTakeOwnership)
1798 void JSPopover::popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect,
1799 weld::Placement ePlace)
1801 SalInstancePopover::popup_at_rect(pParent, rRect, ePlace);
1802 sendPopup(getWidget()->GetChild(0), "_POPOVER_", "_POPOVER_");
1805 void JSPopover::popdown()
1807 vcl::Window* pPopup = JSInstanceBuilder::FindPopup(std::to_string(mnWindowId));
1809 if (pPopup)
1811 sendClosePopup(mnWindowId);
1812 vcl::Window::GetDockingManager()->EndPopupMode(pPopup);
1815 if (getWidget() && getWidget()->GetChild(0))
1816 sendClosePopup(getWidget()->GetChild(0)->GetLOKWindowId());
1818 SalInstancePopover::popdown();
1821 JSBox::JSBox(JSDialogSender* pSender, VclBox* pBox, SalInstanceBuilder* pBuilder,
1822 bool bTakeOwnership)
1823 : JSWidget<SalInstanceBox, VclBox>(pSender, pBox, pBuilder, bTakeOwnership)
1827 void JSBox::reorder_child(weld::Widget* pWidget, int nNewPosition)
1829 SalInstanceBox::reorder_child(pWidget, nNewPosition);
1830 sendUpdate();
1833 JSImage::JSImage(JSDialogSender* pSender, FixedImage* pImage, SalInstanceBuilder* pBuilder,
1834 bool bTakeOwnership)
1835 : JSWidget<SalInstanceImage, FixedImage>(pSender, pImage, pBuilder, bTakeOwnership)
1839 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */