nss: upgrade to release 3.73
[LibreOffice.git] / vcl / jsdialog / jsdialogbuilder.cxx
blobd18561d80e3b60ca4bde109ddb89c030bc5e44eb
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>
26 JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aWindow)
27 : Idle("JSDialog notify")
28 , m_aWindow(aWindow)
29 , m_LastNotificationMessage()
30 , m_bForce(false)
32 SetPriority(TaskPriority::POST_PAINT);
35 void JSDialogNotifyIdle::ForceUpdate() { m_bForce = true; }
37 void JSDialogNotifyIdle::Invoke()
39 try
41 if (!m_aWindow)
42 return;
44 const vcl::ILibreOfficeKitNotifier* pNotifier = m_aWindow->GetLOKNotifier();
45 if (pNotifier)
47 tools::JsonWriter aJsonWriter;
48 m_aWindow->DumpAsPropertyTree(aJsonWriter);
49 aJsonWriter.put("id", m_aWindow->GetLOKWindowId());
50 if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage))
52 m_bForce = false;
53 m_LastNotificationMessage = aJsonWriter.extractAsStdString();
54 pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG,
55 m_LastNotificationMessage.c_str());
59 catch (boost::property_tree::json_parser::json_parser_error& rError)
61 SAL_WARN("vcl", rError.message());
65 void JSDialogSender::notifyDialogState(bool bForce)
67 if (bForce)
68 mpIdleNotify->ForceUpdate();
69 mpIdleNotify->Start();
72 namespace
74 vcl::Window* extract_sal_widget(weld::Widget* pParent)
76 SalInstanceWidget* pInstanceWidget = dynamic_cast<SalInstanceWidget*>(pParent);
77 return pInstanceWidget ? pInstanceWidget->getWidget() : nullptr;
81 JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot,
82 const OUString& rUIFile)
83 : SalInstanceBuilder(extract_sal_widget(pParent), rUIRoot, rUIFile)
84 , m_nWindowId(0)
85 , m_aParentDialog(nullptr)
86 , m_bHasTopLevelDialog(false)
87 , m_bIsNotebookbar(false)
89 vcl::Window* pRoot = m_xBuilder->get_widget_root();
90 if (pRoot && pRoot->GetParent())
92 m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier();
93 if (m_aParentDialog)
94 m_nWindowId = m_aParentDialog->GetLOKWindowId();
95 InsertWindowToMap(m_nWindowId);
99 JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot,
100 const OUString& rUIFile,
101 const css::uno::Reference<css::frame::XFrame>& rFrame,
102 sal_uInt64 nWindowId)
103 : SalInstanceBuilder(pParent, rUIRoot, rUIFile, rFrame)
104 , m_nWindowId(0)
105 , m_aParentDialog(nullptr)
106 , m_bHasTopLevelDialog(false)
107 , m_bIsNotebookbar(false)
109 vcl::Window* pRoot = m_xBuilder->get_widget_root();
110 if (pRoot && pRoot->GetParent())
112 m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier();
113 if (m_aParentDialog)
114 m_nWindowId = m_aParentDialog->GetLOKWindowId();
115 if (!m_nWindowId && nWindowId)
117 m_nWindowId = nWindowId;
118 m_bIsNotebookbar = true;
120 InsertWindowToMap(m_nWindowId);
124 JSInstanceBuilder::~JSInstanceBuilder()
126 if (m_nWindowId && (m_bHasTopLevelDialog || m_bIsNotebookbar))
127 GetLOKWeldWidgetsMap().erase(m_nWindowId);
130 std::map<sal_uInt64, WidgetMap>& JSInstanceBuilder::GetLOKWeldWidgetsMap()
132 // Map to remember the LOKWindowId <-> weld widgets binding.
133 static std::map<sal_uInt64, WidgetMap> s_aLOKWeldBuildersMap;
135 return s_aLOKWeldBuildersMap;
138 weld::Widget* JSInstanceBuilder::FindWeldWidgetsMap(sal_uInt64 nWindowId, const OString& rWidget)
140 const auto it = GetLOKWeldWidgetsMap().find(nWindowId);
142 if (it != GetLOKWeldWidgetsMap().end())
144 auto widgetIt = it->second.find(rWidget);
145 if (widgetIt != it->second.end())
146 return widgetIt->second;
149 return nullptr;
152 void JSInstanceBuilder::InsertWindowToMap(sal_uInt64 nWindowId)
154 WidgetMap map;
155 auto it = GetLOKWeldWidgetsMap().find(nWindowId);
156 if (it == GetLOKWeldWidgetsMap().end())
157 GetLOKWeldWidgetsMap().insert(std::map<sal_uInt64, WidgetMap>::value_type(nWindowId, map));
160 void JSInstanceBuilder::RememberWidget(const OString& id, weld::Widget* pWidget)
162 auto it = GetLOKWeldWidgetsMap().find(m_nWindowId);
163 if (it != GetLOKWeldWidgetsMap().end())
165 it->second.erase(id);
166 it->second.insert(WidgetMap::value_type(id, pWidget));
170 std::unique_ptr<weld::Dialog> JSInstanceBuilder::weld_dialog(const OString& id)
172 ::Dialog* pDialog = m_xBuilder->get<::Dialog>(id);
173 m_nWindowId = pDialog->GetLOKWindowId();
175 InsertWindowToMap(m_nWindowId);
177 std::unique_ptr<weld::Dialog> pRet(
178 pDialog ? new JSDialog(m_aOwnedToplevel, pDialog, this, false) : nullptr);
179 if (pDialog)
181 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
182 m_aOwnedToplevel.set(pDialog);
183 m_xBuilder->drop_ownership(pDialog);
184 m_bHasTopLevelDialog = true;
187 const vcl::ILibreOfficeKitNotifier* pNotifier = pDialog->GetLOKNotifier();
188 if (pNotifier)
190 tools::JsonWriter aJsonWriter;
191 m_aOwnedToplevel->DumpAsPropertyTree(aJsonWriter);
192 aJsonWriter.put("id", m_aOwnedToplevel->GetLOKWindowId());
193 pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, aJsonWriter.extractData());
196 return pRet;
199 std::unique_ptr<weld::Label> JSInstanceBuilder::weld_label(const OString& id)
201 ::FixedText* pLabel = m_xBuilder->get<FixedText>(id);
202 auto pWeldWidget = std::make_unique<JSLabel>(
203 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog, pLabel, this, false);
205 if (pWeldWidget)
206 RememberWidget(id, pWeldWidget.get());
208 return pWeldWidget;
211 std::unique_ptr<weld::Button> JSInstanceBuilder::weld_button(const OString& id)
213 ::Button* pButton = m_xBuilder->get<::Button>(id);
214 auto pWeldWidget = pButton ? std::make_unique<JSButton>(m_bHasTopLevelDialog ? m_aOwnedToplevel
215 : m_aParentDialog,
216 pButton, this, false)
217 : nullptr;
219 if (pWeldWidget)
220 RememberWidget(id, pWeldWidget.get());
222 return pWeldWidget;
225 std::unique_ptr<weld::Entry> JSInstanceBuilder::weld_entry(const OString& id)
227 Edit* pEntry = m_xBuilder->get<Edit>(id);
228 auto pWeldWidget = pEntry ? std::make_unique<JSEntry>(m_bHasTopLevelDialog ? m_aOwnedToplevel
229 : m_aParentDialog,
230 pEntry, this, false)
231 : nullptr;
233 if (pWeldWidget)
234 RememberWidget(id, pWeldWidget.get());
236 return pWeldWidget;
239 std::unique_ptr<weld::ComboBox> JSInstanceBuilder::weld_combo_box(const OString& id)
241 vcl::Window* pWidget = m_xBuilder->get<vcl::Window>(id);
242 ::ComboBox* pComboBox = dynamic_cast<::ComboBox*>(pWidget);
243 std::unique_ptr<weld::ComboBox> pWeldWidget;
245 if (pComboBox)
247 pWeldWidget = std::make_unique<JSComboBox>(
248 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog, pComboBox, this, false);
250 else
252 ListBox* pListBox = dynamic_cast<ListBox*>(pWidget);
253 pWeldWidget = pListBox ? std::make_unique<JSListBox>(m_bHasTopLevelDialog ? m_aOwnedToplevel
254 : m_aParentDialog,
255 pListBox, this, false)
256 : nullptr;
259 if (pWeldWidget)
260 RememberWidget(id, pWeldWidget.get());
262 return pWeldWidget;
265 std::unique_ptr<weld::Notebook> JSInstanceBuilder::weld_notebook(const OString& id)
267 TabControl* pNotebook = m_xBuilder->get<TabControl>(id);
268 auto pWeldWidget = pNotebook ? std::make_unique<JSNotebook>(
269 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog,
270 pNotebook, this, false)
271 : nullptr;
273 if (pWeldWidget)
274 RememberWidget(id, pWeldWidget.get());
276 return pWeldWidget;
279 std::unique_ptr<weld::SpinButton> JSInstanceBuilder::weld_spin_button(const OString& id)
281 FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id);
282 auto pWeldWidget = pSpinButton ? std::make_unique<JSSpinButton>(
283 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog,
284 pSpinButton, this, false)
285 : nullptr;
287 if (pWeldWidget)
288 RememberWidget(id, pWeldWidget.get());
290 return pWeldWidget;
293 std::unique_ptr<weld::CheckButton> JSInstanceBuilder::weld_check_button(const OString& id)
295 CheckBox* pCheckButton = m_xBuilder->get<CheckBox>(id);
296 auto pWeldWidget = pCheckButton ? std::make_unique<JSCheckButton>(
297 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog,
298 pCheckButton, this, false)
299 : nullptr;
301 if (pWeldWidget)
302 RememberWidget(id, pWeldWidget.get());
304 return pWeldWidget;
307 std::unique_ptr<weld::DrawingArea>
308 JSInstanceBuilder::weld_drawing_area(const OString& id, const a11yref& rA11yImpl,
309 FactoryFunction pUITestFactoryFunction, void* pUserData)
311 VclDrawingArea* pArea = m_xBuilder->get<VclDrawingArea>(id);
312 auto pWeldWidget = pArea ? std::make_unique<JSDrawingArea>(
313 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog, pArea,
314 this, rA11yImpl, pUITestFactoryFunction, pUserData)
315 : nullptr;
317 if (pWeldWidget)
318 RememberWidget(id, pWeldWidget.get());
320 return pWeldWidget;
323 std::unique_ptr<weld::Toolbar> JSInstanceBuilder::weld_toolbar(const OString& id)
325 ToolBox* pToolBox = m_xBuilder->get<ToolBox>(id);
326 auto pWeldWidget = pToolBox ? std::make_unique<JSToolbar>(
327 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog,
328 pToolBox, this, false)
329 : nullptr;
331 if (pWeldWidget)
332 RememberWidget(id, pWeldWidget.get());
334 return pWeldWidget;
337 std::unique_ptr<weld::TextView> JSInstanceBuilder::weld_text_view(const OString& id)
339 VclMultiLineEdit* pTextView = m_xBuilder->get<VclMultiLineEdit>(id);
340 auto pWeldWidget = pTextView ? std::make_unique<JSTextView>(
341 m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog,
342 pTextView, this, false)
343 : nullptr;
345 if (pWeldWidget)
346 RememberWidget(id, pWeldWidget.get());
348 return pWeldWidget;
351 weld::MessageDialog* JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent,
352 VclMessageType eMessageType,
353 VclButtonsType eButtonType,
354 const OUString& rPrimaryMessage)
356 SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent);
357 SystemWindow* pParentWidget = pParentInstance ? pParentInstance->getSystemWindow() : nullptr;
358 VclPtrInstance<::MessageDialog> xMessageDialog(pParentWidget, rPrimaryMessage, eMessageType,
359 eButtonType);
361 const vcl::ILibreOfficeKitNotifier* pNotifier = xMessageDialog->GetLOKNotifier();
362 if (pNotifier)
364 tools::JsonWriter aJsonWriter;
365 xMessageDialog->DumpAsPropertyTree(aJsonWriter);
366 aJsonWriter.put("id", xMessageDialog->GetLOKWindowId());
367 std::unique_ptr<char[], o3tl::free_delete> message(aJsonWriter.extractData());
368 pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.get());
371 return new JSMessageDialog(xMessageDialog, nullptr, true);
374 JSDialog::JSDialog(VclPtr<vcl::Window> aOwnedToplevel, ::Dialog* pDialog,
375 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
376 : JSWidget<SalInstanceDialog, ::Dialog>(aOwnedToplevel, pDialog, pBuilder, bTakeOwnership)
380 void JSDialog::collapse(weld::Widget* pEdit, weld::Widget* pButton)
382 SalInstanceDialog::collapse(pEdit, pButton);
383 notifyDialogState();
386 void JSDialog::undo_collapse()
388 SalInstanceDialog::undo_collapse();
389 notifyDialogState();
392 JSLabel::JSLabel(VclPtr<vcl::Window> aOwnedToplevel, FixedText* pLabel,
393 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
394 : JSWidget<SalInstanceLabel, FixedText>(aOwnedToplevel, pLabel, pBuilder, bTakeOwnership)
398 void JSLabel::set_label(const OUString& rText)
400 SalInstanceLabel::set_label(rText);
401 notifyDialogState();
404 JSButton::JSButton(VclPtr<vcl::Window> aOwnedToplevel, ::Button* pButton,
405 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
406 : JSWidget<SalInstanceButton, ::Button>(aOwnedToplevel, pButton, pBuilder, bTakeOwnership)
410 JSEntry::JSEntry(VclPtr<vcl::Window> aOwnedToplevel, ::Edit* pEntry, SalInstanceBuilder* pBuilder,
411 bool bTakeOwnership)
412 : JSWidget<SalInstanceEntry, ::Edit>(aOwnedToplevel, pEntry, pBuilder, bTakeOwnership)
416 void JSEntry::set_text(const OUString& rText)
418 SalInstanceEntry::set_text(rText);
419 notifyDialogState();
422 JSListBox::JSListBox(VclPtr<vcl::Window> aOwnedToplevel, ::ListBox* pListBox,
423 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
424 : JSWidget<SalInstanceComboBoxWithoutEdit, ::ListBox>(aOwnedToplevel, pListBox, pBuilder,
425 bTakeOwnership)
429 void JSListBox::insert(int pos, const OUString& rStr, const OUString* pId,
430 const OUString* pIconName, VirtualDevice* pImageSurface)
432 SalInstanceComboBoxWithoutEdit::insert(pos, rStr, pId, pIconName, pImageSurface);
433 notifyDialogState();
436 void JSListBox::remove(int pos)
438 SalInstanceComboBoxWithoutEdit::remove(pos);
439 notifyDialogState();
442 void JSListBox::set_active(int pos)
444 SalInstanceComboBoxWithoutEdit::set_active(pos);
445 notifyDialogState();
448 JSComboBox::JSComboBox(VclPtr<vcl::Window> aOwnedToplevel, ::ComboBox* pComboBox,
449 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
450 : JSWidget<SalInstanceComboBoxWithEdit, ::ComboBox>(aOwnedToplevel, pComboBox, pBuilder,
451 bTakeOwnership)
455 void JSComboBox::insert(int pos, const OUString& rStr, const OUString* pId,
456 const OUString* pIconName, VirtualDevice* pImageSurface)
458 SalInstanceComboBoxWithEdit::insert(pos, rStr, pId, pIconName, pImageSurface);
459 notifyDialogState();
462 void JSComboBox::remove(int pos)
464 SalInstanceComboBoxWithEdit::remove(pos);
465 notifyDialogState();
468 void JSComboBox::set_entry_text(const OUString& rText)
470 SalInstanceComboBoxWithEdit::set_entry_text(rText);
471 notifyDialogState();
474 void JSComboBox::set_active(int pos)
476 SalInstanceComboBoxWithEdit::set_active(pos);
477 notifyDialogState();
480 JSNotebook::JSNotebook(VclPtr<vcl::Window> aOwnedToplevel, ::TabControl* pControl,
481 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
482 : JSWidget<SalInstanceNotebook, ::TabControl>(aOwnedToplevel, pControl, pBuilder,
483 bTakeOwnership)
487 void JSNotebook::set_current_page(int nPage)
489 bool bForce = false;
490 int nCurrent = get_current_page();
491 if (nCurrent == nPage)
492 bForce = true;
494 SalInstanceNotebook::set_current_page(nPage);
495 notifyDialogState(bForce);
498 void JSNotebook::set_current_page(const OString& rIdent)
500 bool bForce = false;
501 OString sCurrent = get_current_page_ident();
502 if (sCurrent == rIdent)
503 bForce = true;
505 SalInstanceNotebook::set_current_page(rIdent);
506 notifyDialogState(bForce);
509 void JSNotebook::remove_page(const OString& rIdent)
511 SalInstanceNotebook::remove_page(rIdent);
512 notifyDialogState();
515 void JSNotebook::insert_page(const OString& rIdent, const OUString& rLabel, int nPos)
517 SalInstanceNotebook::insert_page(rIdent, rLabel, nPos);
518 notifyDialogState();
521 JSSpinButton::JSSpinButton(VclPtr<vcl::Window> aOwnedToplevel, ::FormattedField* pSpin,
522 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
523 : JSWidget<SalInstanceSpinButton, ::FormattedField>(aOwnedToplevel, pSpin, pBuilder,
524 bTakeOwnership)
528 void JSSpinButton::set_value(int value)
530 SalInstanceSpinButton::set_value(value);
531 notifyDialogState();
534 JSMessageDialog::JSMessageDialog(::MessageDialog* pDialog, SalInstanceBuilder* pBuilder,
535 bool bTakeOwnership)
536 : SalInstanceMessageDialog(pDialog, pBuilder, bTakeOwnership)
537 , JSDialogSender(m_xMessageDialog)
541 void JSMessageDialog::set_primary_text(const OUString& rText)
543 SalInstanceMessageDialog::set_primary_text(rText);
544 notifyDialogState();
547 void JSMessageDialog::set_secondary_text(const OUString& rText)
549 SalInstanceMessageDialog::set_secondary_text(rText);
550 notifyDialogState();
553 JSCheckButton::JSCheckButton(VclPtr<vcl::Window> aOwnedToplevel, ::CheckBox* pCheckBox,
554 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
555 : JSWidget<SalInstanceCheckButton, ::CheckBox>(aOwnedToplevel, pCheckBox, pBuilder,
556 bTakeOwnership)
560 void JSCheckButton::set_active(bool active)
562 SalInstanceCheckButton::set_active(active);
563 notifyDialogState();
566 JSDrawingArea::JSDrawingArea(VclPtr<vcl::Window> aOwnedToplevel, VclDrawingArea* pDrawingArea,
567 SalInstanceBuilder* pBuilder, const a11yref& rAlly,
568 FactoryFunction pUITestFactoryFunction, void* pUserData)
569 : SalInstanceDrawingArea(pDrawingArea, pBuilder, rAlly, pUITestFactoryFunction, pUserData,
570 false)
571 , JSDialogSender(aOwnedToplevel)
575 void JSDrawingArea::queue_draw()
577 SalInstanceDrawingArea::queue_draw();
578 notifyDialogState();
581 void JSDrawingArea::queue_draw_area(int x, int y, int width, int height)
583 SalInstanceDrawingArea::queue_draw_area(x, y, width, height);
584 notifyDialogState();
587 JSToolbar::JSToolbar(VclPtr<vcl::Window> aOwnedToplevel, ::ToolBox* pToolbox,
588 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
589 : JSWidget<SalInstanceToolbar, ::ToolBox>(aOwnedToplevel, pToolbox, pBuilder, bTakeOwnership)
593 void JSToolbar::signal_clicked(const OString& rIdent)
595 SalInstanceToolbar::signal_clicked(rIdent);
596 notifyDialogState();
599 JSTextView::JSTextView(VclPtr<vcl::Window> aOwnedToplevel, ::VclMultiLineEdit* pTextView,
600 SalInstanceBuilder* pBuilder, bool bTakeOwnership)
601 : JSWidget<SalInstanceTextView, ::VclMultiLineEdit>(aOwnedToplevel, pTextView, pBuilder,
602 bTakeOwnership)
606 void JSTextView::set_text(const OUString& rText)
608 SalInstanceTextView::set_text(rText);
609 notifyDialogState();
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */