diff options
Diffstat (limited to 'vcl/jsdialog')
-rw-r--r-- | vcl/jsdialog/enabled.cxx | 395 | ||||
-rw-r--r-- | vcl/jsdialog/executor.cxx | 677 | ||||
-rw-r--r-- | vcl/jsdialog/jsdialogbuilder.cxx | 2370 |
3 files changed, 3442 insertions, 0 deletions
diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx new file mode 100644 index 0000000000..993a6f4568 --- /dev/null +++ b/vcl/jsdialog/enabled.cxx @@ -0,0 +1,395 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <comphelper/string.hxx> +#include <jsdialog/enabled.hxx> +#include <vector> + +namespace jsdialog +{ +bool isBuilderEnabled(std::u16string_view rUIFile, bool bMobile) +{ + // mobile only dialogs + if (bMobile) + { + if (// swriter + rUIFile == u"modules/swriter/ui/watermarkdialog.ui" + || rUIFile == u"modules/swriter/ui/wordcount-mobile.ui" + // svx + || rUIFile == u"svx/ui/findreplacedialog-mobile.ui") + { + return true; + } + } + + if (// cui + rUIFile == u"cui/ui/areatabpage.ui" + || rUIFile == u"cui/ui/areadialog.ui" + || rUIFile == u"cui/ui/asiantypography.ui" + || rUIFile == u"cui/ui/borderpage.ui" + || rUIFile == u"cui/ui/bulletandposition.ui" + || rUIFile == u"cui/ui/cellalignment.ui" + || rUIFile == u"cui/ui/charnamepage.ui" + || rUIFile == u"cui/ui/colorpage.ui" + || rUIFile == u"cui/ui/colorpickerdialog.ui" + || rUIFile == u"cui/ui/croppage.ui" + || rUIFile == u"cui/ui/effectspage.ui" + || rUIFile == u"cui/ui/eventassigndialog.ui" + || rUIFile == u"cui/ui/fontfeaturesdialog.ui" + || rUIFile == u"cui/ui/formatcellsdialog.ui" + || rUIFile == u"cui/ui/formatnumberdialog.ui" + || rUIFile == u"cui/ui/gradientpage.ui" + || rUIFile == u"cui/ui/hatchpage.ui" + || rUIFile == u"cui/ui/hyperlinkdialog.ui" + || rUIFile == u"cui/ui/hyperlinkinternetpage.ui" + || rUIFile == u"cui/ui/hyperlinkmailpage.ui" + || rUIFile == u"cui/ui/imagetabpage.ui" + || rUIFile == u"cui/ui/linedialog.ui" + || rUIFile == u"cui/ui/lineendstabpage.ui" + || rUIFile == u"cui/ui/linestyletabpage.ui" + || rUIFile == u"cui/ui/linetabpage.ui" + || rUIFile == u"cui/ui/macroselectordialog.ui" + || rUIFile == u"cui/ui/numberingformatpage.ui" + || rUIFile == u"cui/ui/numberingoptionspage.ui" + || rUIFile == u"cui/ui/numberingpositionpage.ui" + || rUIFile == u"cui/ui/optlingupage.ui" + || rUIFile == u"cui/ui/pageformatpage.ui" + || rUIFile == u"cui/ui/paragalignpage.ui" + || rUIFile == u"cui/ui/paraindentspacing.ui" + || rUIFile == u"cui/ui/paratabspage.ui" + || rUIFile == u"cui/ui/password.ui" + || rUIFile == u"cui/ui/pastespecial.ui" + || rUIFile == u"cui/ui/patterntabpage.ui" + || rUIFile == u"cui/ui/pickbulletpage.ui" + || rUIFile == u"cui/ui/pickgraphicpage.ui" + || rUIFile == u"cui/ui/picknumberingpage.ui" + || rUIFile == u"cui/ui/pickoutlinepage.ui" + || rUIFile == u"cui/ui/positionpage.ui" + || rUIFile == u"cui/ui/positionsizedialog.ui" + || rUIFile == u"cui/ui/possizetabpage.ui" + || rUIFile == u"cui/ui/rotationtabpage.ui" + || rUIFile == u"cui/ui/shadowtabpage.ui" + || rUIFile == u"cui/ui/slantcornertabpage.ui" + || rUIFile == u"cui/ui/spinbox.ui" + || rUIFile == u"cui/ui/queryduplicatedialog.ui" + || rUIFile == u"cui/ui/similaritysearchdialog.ui" + || rUIFile == u"cui/ui/specialcharacters.ui" + || rUIFile == u"cui/ui/spellingdialog.ui" + || rUIFile == u"cui/ui/spelloptionsdialog.ui" + || rUIFile == u"cui/ui/splitcellsdialog.ui" + || rUIFile == u"cui/ui/textflowpage.ui" + || rUIFile == u"cui/ui/thesaurus.ui" + || rUIFile == u"cui/ui/transparencytabpage.ui" + || rUIFile == u"cui/ui/twolinespage.ui" + || rUIFile == u"cui/ui/widgettestdialog.ui" + || rUIFile == u"cui/ui/qrcodegen.ui" + // formula + || rUIFile == u"formula/ui/formuladialog.ui" + || rUIFile == u"formula/ui/functionpage.ui" + || rUIFile == u"formula/ui/parameter.ui" + || rUIFile == u"formula/ui/structpage.ui" + // scalc + || rUIFile == u"modules/scalc/ui/advancedfilterdialog.ui" + || rUIFile == u"modules/scalc/ui/analysisofvariancedialog.ui" + || rUIFile == u"modules/scalc/ui/chardialog.ui" + || rUIFile == u"modules/scalc/ui/chisquaretestdialog.ui" + || rUIFile == u"modules/scalc/ui/colwidthdialog.ui" + || rUIFile == u"modules/scalc/ui/conditionaleasydialog.ui" + || rUIFile == u"modules/scalc/ui/condformatmanager.ui" + || rUIFile == u"modules/scalc/ui/correlationdialog.ui" + || rUIFile == u"modules/scalc/ui/covariancedialog.ui" + || rUIFile == u"modules/scalc/ui/datafielddialog.ui" + || rUIFile == u"modules/scalc/ui/datafieldoptionsdialog.ui" + || rUIFile == u"modules/scalc/ui/definename.ui" + || rUIFile == u"modules/scalc/ui/deletecells.ui" + || rUIFile == u"modules/scalc/ui/deletecontents.ui" + || rUIFile == u"modules/scalc/ui/descriptivestatisticsdialog.ui" + || rUIFile == u"modules/scalc/ui/erroralerttabpage.ui" + || rUIFile == u"modules/scalc/ui/exponentialsmoothingdialog.ui" + || rUIFile == u"modules/scalc/ui/formatcellsdialog.ui" + || rUIFile == u"modules/scalc/ui/fourieranalysisdialog.ui" + || rUIFile == u"modules/scalc/ui/goalseekdlg.ui" + || rUIFile == u"modules/scalc/ui/groupdialog.ui" + || rUIFile == u"modules/scalc/ui/headerfootercontent.ui" + || rUIFile == u"modules/scalc/ui/headerfooterdialog.ui" + || rUIFile == u"modules/scalc/ui/insertcells.ui" + || rUIFile == u"modules/scalc/ui/managenamesdialog.ui" + || rUIFile == u"modules/scalc/ui/movingaveragedialog.ui" + || rUIFile == u"modules/scalc/ui/optimalcolwidthdialog.ui" + || rUIFile == u"modules/scalc/ui/optimalrowheightdialog.ui" + || rUIFile == u"modules/scalc/ui/pagetemplatedialog.ui" + || rUIFile == u"modules/scalc/ui/paratemplatedialog.ui" + || rUIFile == u"modules/scalc/ui/pivotfielddialog.ui" + || rUIFile == u"modules/scalc/ui/pivottablelayoutdialog.ui" + || rUIFile == u"modules/scalc/ui/regressiondialog.ui" + || rUIFile == u"modules/scalc/ui/rowheightdialog.ui" + || rUIFile == u"modules/scalc/ui/samplingdialog.ui" + || rUIFile == u"modules/scalc/ui/selectsource.ui" + || rUIFile == u"modules/scalc/ui/sheetprintpage.ui" + || rUIFile == u"modules/scalc/ui/simplerefdialog.ui" + || rUIFile == u"modules/scalc/ui/sortcriteriapage.ui" + || rUIFile == u"modules/scalc/ui/sortdialog.ui" + || rUIFile == u"modules/scalc/ui/sortkey.ui" + || rUIFile == u"modules/scalc/ui/sortoptionspage.ui" + || rUIFile == u"modules/scalc/ui/sparklinedialog.ui" + || rUIFile == u"modules/scalc/ui/standardfilterdialog.ui" + || rUIFile == u"modules/scalc/ui/textimportcsv.ui" + || rUIFile == u"modules/scalc/ui/ttestdialog.ui" + || rUIFile == u"modules/scalc/ui/ungroupdialog.ui" + || rUIFile == u"modules/scalc/ui/validationcriteriapage.ui" + || rUIFile == u"modules/scalc/ui/validationdialog.ui" + || rUIFile == u"modules/scalc/ui/validationhelptabpage.ui" + || rUIFile == u"modules/scalc/ui/ztestdialog.ui" + // schart + || rUIFile == u"modules/schart/ui/attributedialog.ui" + || rUIFile == u"modules/schart/ui/charttypedialog.ui" + || rUIFile == u"modules/schart/ui/datarangedialog.ui" + || rUIFile == u"modules/schart/ui/insertaxisdlg.ui" + || rUIFile == u"modules/schart/ui/inserttitledlg.ui" + || rUIFile == u"modules/schart/ui/smoothlinesdlg.ui" + || rUIFile == u"modules/schart/ui/steppedlinesdlg.ui" + || rUIFile == u"modules/schart/ui/tp_ChartType.ui" + || rUIFile == u"modules/schart/ui/tp_DataSource.ui" + || rUIFile == u"modules/schart/ui/tp_RangeChooser.ui" + || rUIFile == u"modules/schart/ui/tp_Trendline.ui" + || rUIFile == u"modules/schart/ui/wizelementspage.ui" + // sdraw + || rUIFile == u"modules/sdraw/ui/drawchardialog.ui" + || rUIFile == u"modules/sdraw/ui/drawpagedialog.ui" + || rUIFile == u"modules/sdraw/ui/drawparadialog.ui" + // simpress + || rUIFile == u"modules/simpress/ui/headerfooterdialog.ui" + || rUIFile == u"modules/simpress/ui/headerfootertab.ui" + // swriter + || rUIFile == u"modules/swriter/ui/bulletsandnumbering.ui" + || rUIFile == u"modules/swriter/ui/captionoptions.ui" + || rUIFile == u"modules/swriter/ui/characterproperties.ui" + || rUIFile == u"modules/swriter/ui/charurlpage.ui" + || rUIFile == u"modules/swriter/ui/columndialog.ui" + || rUIFile == u"modules/swriter/ui/columnpage.ui" + || rUIFile == u"modules/swriter/ui/contentcontroldlg.ui" + || rUIFile == u"modules/swriter/ui/contentcontrollistitemdlg.ui" + || rUIFile == u"modules/swriter/ui/dropcapspage.ui" + || rUIFile == u"modules/swriter/ui/dropdownfielddialog.ui" + || rUIFile == u"modules/swriter/ui/endnotepage.ui" + || rUIFile == u"modules/swriter/ui/footendnotedialog.ui" + || rUIFile == u"modules/swriter/ui/footnoteareapage.ui" + || rUIFile == u"modules/swriter/ui/footnotepage.ui" + || rUIFile == u"modules/swriter/ui/footnotesendnotestabpage.ui" + || rUIFile == u"modules/swriter/ui/formatsectiondialog.ui" + || rUIFile == u"modules/swriter/ui/formattablepage.ui" + || rUIFile == u"modules/swriter/ui/framedialog.ui" + || rUIFile == u"modules/swriter/ui/frmaddpage.ui" + || rUIFile == u"modules/swriter/ui/frmurlpage.ui" + || rUIFile == u"modules/swriter/ui/frmtypepage.ui" + || rUIFile == u"modules/swriter/ui/indentpage.ui" + || rUIFile == u"modules/swriter/ui/indexentry.ui" + || rUIFile == u"modules/swriter/ui/inforeadonlydialog.ui" + || rUIFile == u"modules/swriter/ui/insertbreak.ui" + || rUIFile == u"modules/swriter/ui/insertcaption.ui" + || rUIFile == u"modules/swriter/ui/insertsectiondialog.ui" + || rUIFile == u"modules/swriter/ui/linenumbering.ui" + || rUIFile == u"modules/swriter/ui/newuserindexdialog.ui" + || rUIFile == u"modules/swriter/ui/numparapage.ui" + || rUIFile == u"modules/swriter/ui/pagenumberdlg.ui" + || rUIFile == u"modules/swriter/ui/paradialog.ui" + || rUIFile == u"modules/swriter/ui/picturedialog.ui" + || rUIFile == u"modules/swriter/ui/picturepage.ui" + || rUIFile == u"modules/swriter/ui/sectionpage.ui" + || rUIFile == u"modules/swriter/ui/sortdialog.ui" + || rUIFile == u"modules/swriter/ui/splittable.ui" + || rUIFile == u"modules/swriter/ui/tablecolumnpage.ui" + || rUIFile == u"modules/swriter/ui/tableproperties.ui" + || rUIFile == u"modules/swriter/ui/tabletextflowpage.ui" + || rUIFile == u"modules/swriter/ui/templatedialog1.ui" + || rUIFile == u"modules/swriter/ui/templatedialog2.ui" + || rUIFile == u"modules/swriter/ui/templatedialog8.ui" + || rUIFile == u"modules/swriter/ui/textgridpage.ui" + || rUIFile == u"modules/swriter/ui/titlepage.ui" + || rUIFile == u"modules/swriter/ui/tocdialog.ui" + || rUIFile == u"modules/swriter/ui/tocentriespage.ui" + || rUIFile == u"modules/swriter/ui/tocindexpage.ui" + || rUIFile == u"modules/swriter/ui/tocstylespage.ui" + || rUIFile == u"modules/swriter/ui/translationdialog.ui" + || rUIFile == u"modules/swriter/ui/watermarkdialog.ui" + || rUIFile == u"modules/swriter/ui/wordcount.ui" + || rUIFile == u"modules/swriter/ui/wrappage.ui" + // sfx + || rUIFile == u"sfx/ui/cmisinfopage.ui" + || rUIFile == u"sfx/ui/custominfopage.ui" + || rUIFile == u"sfx/ui/descriptioninfopage.ui" + || rUIFile == u"sfx/ui/documentinfopage.ui" + || rUIFile == u"sfx/ui/documentpropertiesdialog.ui" + || rUIFile == u"sfx/ui/editdurationdialog.ui" + || rUIFile == u"svx/ui/headfootformatpage.ui" + || rUIFile == u"sfx/ui/linefragment.ui" + || rUIFile == u"sfx/ui/managestylepage.ui" + || rUIFile == u"sfx/ui/password.ui" + // svx + || rUIFile == u"svx/ui/acceptrejectchangesdialog.ui" + || rUIFile == u"svx/ui/accessibilitycheckdialog.ui" + || rUIFile == u"svx/ui/accessibilitycheckentry.ui" + || rUIFile == u"svx/ui/compressgraphicdialog.ui" + || rUIFile == u"svx/ui/findreplacedialog.ui" + || rUIFile == u"svx/ui/fontworkgallerydialog.ui" + || rUIFile == u"svx/ui/headfootformatpage.ui" + || rUIFile == u"svx/ui/redlinecontrol.ui" + || rUIFile == u"svx/ui/redlinefilterpage.ui" + || rUIFile == u"svx/ui/redlineviewpage.ui" + || rUIFile == u"svx/ui/themecoloreditdialog.ui" + || rUIFile == u"svx/ui/themedialog.ui" + // uui + || rUIFile == u"uui/ui/macrowarnmedium.ui" + // vcl + || rUIFile == u"vcl/ui/wizard.ui" + // filter + || rUIFile == u"filter/ui/pdfgeneralpage.ui" + || rUIFile == u"filter/ui/pdflinkspage.ui" + || rUIFile == u"filter/ui/pdfoptionsdialog.ui" + || rUIFile == u"filter/ui/pdfsecuritypage.ui" + || rUIFile == u"filter/ui/pdfsignpage.ui" + || rUIFile == u"filter/ui/pdfuserinterfacepage.ui" + || rUIFile == u"filter/ui/pdfviewpage.ui" + || rUIFile == u"filter/ui/warnpdfdialog.ui" + // writerperfect + || rUIFile == u"writerperfect/ui/exportepub.ui" + // xmlsec + || rUIFile == u"xmlsec/ui/certgeneral.ui" + || rUIFile == u"xmlsec/ui/certpage.ui" + || rUIFile == u"xmlsec/ui/digitalsignaturesdialog.ui" + || rUIFile == u"xmlsec/ui/viewcertdialog.ui" + ) + { + return true; + } + + const char* pEnabledDialog = getenv("SAL_JSDIALOG_ENABLE"); + if (pEnabledDialog) + { + OUString sAllEnabledDialogs(pEnabledDialog, strlen(pEnabledDialog), RTL_TEXTENCODING_UTF8); + std::vector<OUString> aEnabledDialogsVector + = comphelper::string::split(sAllEnabledDialogs, ':'); + for (const auto& rDialog : aEnabledDialogsVector) + { + if (rUIFile == rDialog) + return true; + } + } + + return false; +} + +bool isBuilderEnabledForPopup(std::u16string_view rUIFile) +{ + if (// scalc + rUIFile == u"modules/scalc/ui/filterdropdown.ui" + || rUIFile == u"modules/scalc/ui/filterlist.ui" + || rUIFile == u"modules/scalc/ui/filtersubdropdown.ui" + || rUIFile == u"modules/scalc/ui/floatingborderstyle.ui" + || rUIFile == u"modules/scalc/ui/floatinglinestyle.ui" + // svt + || rUIFile == u"svt/ui/datewindow.ui" + || rUIFile == u"svt/ui/linewindow.ui" + // svx + || rUIFile == u"svx/ui/colorwindow.ui" + || rUIFile == u"svx/ui/currencywindow.ui" + || rUIFile == u"svx/ui/floatingareastyle.ui" + || rUIFile == u"svx/ui/floatinglineend.ui" + || rUIFile == u"svx/ui/floatinglineproperty.ui" + || rUIFile == u"svx/ui/floatinglinestyle.ui" + || rUIFile == u"svx/ui/fontworkalignmentcontrol.ui" + || rUIFile == u"svx/ui/fontworkcharacterspacingcontrol.ui" + || rUIFile == u"svx/ui/numberingwindow.ui" + || rUIFile == u"svx/ui/paralinespacingcontrol.ui" + || rUIFile == u"svx/ui/textcharacterspacingcontrol.ui" + || rUIFile == u"svx/ui/textunderlinecontrol.ui") + return true; + + return false; +} + +bool isBuilderEnabledForSidebar(std::u16string_view rUIFile) +{ + if (// scalc + rUIFile == u"modules/scalc/ui/functionpanel.ui" + || rUIFile == u"modules/scalc/ui/navigatorpanel.ui" + || rUIFile == u"modules/scalc/ui/sidebaralignment.ui" + || rUIFile == u"modules/scalc/ui/sidebarcellappearance.ui" + || rUIFile == u"modules/scalc/ui/sidebarnumberformat.ui" + // schart + || rUIFile == u"modules/schart/ui/sidebaraxis.ui" + || rUIFile == u"modules/schart/ui/sidebarelements.ui" + || rUIFile == u"modules/schart/ui/sidebarerrorbar.ui" + || rUIFile == u"modules/schart/ui/sidebarseries.ui" + || rUIFile == u"modules/schart/ui/sidebartype.ui" + // simpress + || rUIFile == u"modules/simpress/ui/customanimationfragment.ui" + || rUIFile == u"modules/simpress/ui/customanimationspanel.ui" + || rUIFile == u"modules/simpress/ui/layoutpanel.ui" + || rUIFile == u"modules/simpress/ui/masterpagepanel.ui" + || rUIFile == u"modules/simpress/ui/masterpagepanelall.ui" + || rUIFile == u"modules/simpress/ui/masterpagepanelrecent.ui" + || rUIFile == u"modules/simpress/ui/navigatorpanel.ui" + || rUIFile == u"modules/simpress/ui/sidebarslidebackground.ui" + || rUIFile == u"modules/simpress/ui/slidetransitionspanel.ui" + || rUIFile == u"modules/simpress/ui/tabledesignpanel.ui" + // smath + || rUIFile == u"modules/smath/ui/sidebarelements_math.ui" + || rUIFile == u"modules/smath/ui/sidebarproperties_math.ui" + // swriter + || rUIFile == u"modules/swriter/ui/managechangessidebar.ui" + || rUIFile == u"modules/swriter/ui/navigatorpanel.ui" + || rUIFile == u"modules/swriter/ui/pagefooterpanel.ui" + || rUIFile == u"modules/swriter/ui/pageformatpanel.ui" + || rUIFile == u"modules/swriter/ui/pageheaderpanel.ui" + || rUIFile == u"modules/swriter/ui/pagestylespanel.ui" + || rUIFile == u"modules/swriter/ui/sidebarstylepresets.ui" + || rUIFile == u"modules/swriter/ui/sidebartableedit.ui" + || rUIFile == u"modules/swriter/ui/sidebartheme.ui" + || rUIFile == u"modules/swriter/ui/sidebarwrap.ui" + // sfx + || rUIFile == u"sfx/ui/panel.ui" + || rUIFile == u"sfx/ui/templatepanel.ui" + // svx + || rUIFile == u"svx/ui/defaultshapespanel.ui" + || rUIFile == u"svx/ui/inspectortextpanel.ui" + || rUIFile == u"svx/ui/mediaplayback.ui" + || rUIFile == u"svx/ui/sidebararea.ui" + || rUIFile == u"svx/ui/sidebareffect.ui" + || rUIFile == u"svx/ui/sidebarempty.ui" + || rUIFile == u"svx/ui/sidebarfontwork.ui" + || rUIFile == u"svx/ui/sidebargallery.ui" + || rUIFile == u"svx/ui/sidebargraphic.ui" + || rUIFile == u"svx/ui/sidebarline.ui" + || rUIFile == u"svx/ui/sidebarlists.ui" + || rUIFile == u"svx/ui/sidebarparagraph.ui" + || rUIFile == u"svx/ui/sidebarpossize.ui" + || rUIFile == u"svx/ui/sidebarshadow.ui" + || rUIFile == u"svx/ui/sidebarstylespanel.ui" + || rUIFile == u"svx/ui/sidebartextpanel.ui") + return true; + + return false; +} + +bool isInterimBuilderEnabledForNotebookbar(std::u16string_view rUIFile) +{ + if (rUIFile == u"modules/scalc/ui/numberbox.ui" + || rUIFile == u"svx/ui/fontnamebox.ui" + || rUIFile == u"svx/ui/fontsizebox.ui" + || rUIFile == u"svx/ui/stylespreview.ui") + { + return true; + } + + return false; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx new file mode 100644 index 0000000000..7c36eb3bdc --- /dev/null +++ b/vcl/jsdialog/executor.cxx @@ -0,0 +1,677 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <jsdialog/jsdialogbuilder.hxx> +#include <o3tl/string_view.hxx> +#include <vcl/weld.hxx> +#include <vcl/jsdialog/executor.hxx> +#include <sal/log.hxx> +#include <rtl/uri.hxx> +#include <boost/property_tree/json_parser.hpp> + +namespace jsdialog +{ +StringMap jsonToStringMap(const char* pJSON) +{ + StringMap aArgs; + if (pJSON && pJSON[0] != '\0') + { + std::stringstream aStream(pJSON); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + for (const auto& rPair : aTree) + { + aArgs[OUString::fromUtf8(rPair.first)] + = OUString::fromUtf8(rPair.second.get_value<std::string>(".")); + } + } + return aArgs; +} + +void SendFullUpdate(const OUString& nWindowId, const OUString& rWidget) +{ + weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget); + if (auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget)) + pJSWidget->sendFullUpdate(); +} + +void SendAction(const OUString& nWindowId, const OUString& rWidget, + std::unique_ptr<ActionDataMap> pData) +{ + weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget); + if (auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget)) + pJSWidget->sendAction(std::move(pData)); +} + +bool ExecuteAction(const OUString& nWindowId, const OUString& rWidget, StringMap& rData) +{ + weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget); + + OUString sControlType = rData["type"]; + OUString sAction = rData["cmd"]; + + if (sControlType == "responsebutton") + { + auto pButton = dynamic_cast<weld::Button*>(pWidget); + if (pWidget == nullptr || (pButton && !pButton->is_custom_handler_set())) + { + // welded wrapper not found - use response code instead + pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, "__DIALOG__"); + sControlType = "dialog"; + sAction = "response"; + } + else + { + // welded wrapper for button found - use it + sControlType = "pushbutton"; + } + } + + if (pWidget != nullptr) + { + if (sAction == "grab_focus") + { + pWidget->grab_focus(); + return true; + } + + if (sControlType == "tabcontrol") + { + auto pNotebook = dynamic_cast<weld::Notebook*>(pWidget); + if (pNotebook) + { + if (sAction == "selecttab") + { + sal_Int32 page = o3tl::toInt32(rData["data"]); + + OUString aCurrentPage = pNotebook->get_current_page_ident(); + LOKTrigger::leave_page(*pNotebook, aCurrentPage); + pNotebook->set_current_page(page); + LOKTrigger::enter_page(*pNotebook, pNotebook->get_page_ident(page)); + + return true; + } + } + } + else if (sControlType == "combobox") + { + auto pCombobox = dynamic_cast<weld::ComboBox*>(pWidget); + if (pCombobox) + { + if (sAction == "selected") + { + OUString sSelectedData = rData["data"]; + int separatorPos = sSelectedData.indexOf(';'); + if (separatorPos > 0) + { + std::u16string_view entryPos = sSelectedData.subView(0, separatorPos); + sal_Int32 pos = o3tl::toInt32(entryPos); + pCombobox->set_active(pos); + LOKTrigger::trigger_changed(*pCombobox); + return true; + } + } + else if (sAction == "change") + { + // it might be other class than JSComboBox + auto pJSCombobox = dynamic_cast<JSComboBox*>(pWidget); + if (pJSCombobox) + pJSCombobox->set_entry_text_without_notify(rData["data"]); + else + pCombobox->set_entry_text(rData["data"]); + LOKTrigger::trigger_changed(*pCombobox); + return true; + } + else if (sAction == "render_entry") + { + auto pJSCombobox = dynamic_cast<JSComboBox*>(pWidget); + if (pJSCombobox) + { + // pos;dpix;dpiy + const OUString& sParams = rData["data"]; + const OUString aPos = sParams.getToken(0, ';'); + const OUString aDpiScaleX = sParams.getToken(1, ';'); + const OUString aDpiScaleY = sParams.getToken(2, ';'); + + pJSCombobox->render_entry(o3tl::toInt32(aPos), o3tl::toInt32(aDpiScaleX), + o3tl::toInt32(aDpiScaleY)); + } + return true; + } + } + } + else if (sControlType == "pushbutton") + { + auto pButton = dynamic_cast<weld::Button*>(pWidget); + if (pButton) + { + if (sAction == "click") + { + pButton->clicked(); + return true; + } + else if (sAction == "toggle") + { + LOKTrigger::trigger_toggled(dynamic_cast<weld::Toggleable&>(*pWidget)); + return true; + } + } + } + else if (sControlType == "menubutton") + { + auto pButton = dynamic_cast<weld::MenuButton*>(pWidget); + if (pButton) + { + if (sAction == "toggle") + { + if (pButton->get_active()) + pButton->set_active(false); + else + pButton->set_active(true); + + BaseJSWidget* pMenuButton = dynamic_cast<BaseJSWidget*>(pButton); + if (pMenuButton) + pMenuButton->sendUpdate(true); + + return true; + } + else if (sAction == "select") + { + LOKTrigger::trigger_selected(*pButton, rData["data"]); + return true; + } + } + } + else if (sControlType == "checkbox") + { + auto pCheckButton = dynamic_cast<weld::CheckButton*>(pWidget); + if (pCheckButton) + { + if (sAction == "change") + { + bool bChecked = rData["data"] == "true"; + pCheckButton->set_state(bChecked ? TRISTATE_TRUE : TRISTATE_FALSE); + LOKTrigger::trigger_toggled(*static_cast<weld::Toggleable*>(pCheckButton)); + return true; + } + } + } + else if (sControlType == "drawingarea") + { + auto pArea = dynamic_cast<weld::DrawingArea*>(pWidget); + if (pArea) + { + if (sAction == "click" || sAction == "dblclick" || sAction == "mousemove" + || sAction == "mousedown" || sAction == "mouseup") + { + OUString sClickData = rData["data"]; + int nSeparatorPos = sClickData.indexOf(';'); + if (nSeparatorPos > 0) + { + // x;y + std::u16string_view nClickPosX = sClickData.subView(0, nSeparatorPos); + std::u16string_view nClickPosY = sClickData.subView(nSeparatorPos + 1); + + if (nClickPosX.empty() || nClickPosY.empty()) + return true; + + double fPosX = o3tl::toDouble(nClickPosX); + double fPosY = o3tl::toDouble(nClickPosY); + OutputDevice& rRefDevice = pArea->get_ref_device(); + // We send OutPutSize for the drawing area bitmap + // get_size_request is not necessarily updated + // therefore it may be incorrect. + Size size = rRefDevice.GetOutputSizePixel(); + fPosX = fPosX * size.Width(); + fPosY = fPosY * size.Height(); + + if (sAction == "click") + LOKTrigger::trigger_click(*pArea, Point(fPosX, fPosY)); + else if (sAction == "dblclick") + LOKTrigger::trigger_dblclick(*pArea, Point(fPosX, fPosY)); + else if (sAction == "mouseup") + LOKTrigger::trigger_mouse_up(*pArea, Point(fPosX, fPosY)); + else if (sAction == "mousedown") + LOKTrigger::trigger_mouse_down(*pArea, Point(fPosX, fPosY)); + else if (sAction == "mousemove") + LOKTrigger::trigger_mouse_move(*pArea, Point(fPosX, fPosY)); + } + + return true; + } + else if (sAction == "keypress") + { + sal_uInt32 nKeyNo = rData["data"].toUInt32(); + LOKTrigger::trigger_key_press(*pArea, KeyEvent(nKeyNo, vcl::KeyCode(nKeyNo))); + LOKTrigger::trigger_key_release(*pArea, KeyEvent(nKeyNo, vcl::KeyCode(nKeyNo))); + return true; + } + else if (sAction == "textselection") + { + OUString sTextData = rData["data"]; + int nSeparatorPos = sTextData.indexOf(';'); + if (nSeparatorPos <= 0) + return true; + + int nSeparator2Pos = sTextData.indexOf(';', nSeparatorPos + 1); + int nSeparator3Pos = 0; + + if (nSeparator2Pos > 0) + { + // start;end;startPara;endPara + nSeparator3Pos = sTextData.indexOf(';', nSeparator2Pos + 1); + if (nSeparator3Pos <= 0) + return true; + } + else + { + // start;end + nSeparator2Pos = 0; + nSeparator3Pos = 0; + } + + std::u16string_view aStartPos = sTextData.subView(0, nSeparatorPos); + std::u16string_view aEndPos + = sTextData.subView(nSeparatorPos + 1, nSeparator2Pos - nSeparatorPos + 1); + + if (aStartPos.empty() || aEndPos.empty()) + return true; + + sal_Int32 nStart = o3tl::toInt32(aStartPos); + sal_Int32 nEnd = o3tl::toInt32(aEndPos); + sal_Int32 nStartPara = 0; + sal_Int32 nEndPara = 0; + + // multiline case + if (nSeparator2Pos && nSeparator3Pos) + { + std::u16string_view aStartPara = sTextData.subView( + nSeparator2Pos + 1, nSeparator3Pos - nSeparator2Pos + 1); + std::u16string_view aEndPara = sTextData.subView(nSeparator3Pos + 1); + + if (aStartPara.empty() || aEndPara.empty()) + return true; + + nStartPara = o3tl::toInt32(aStartPara); + nEndPara = o3tl::toInt32(aEndPara); + } + + // pass information about paragraph number in the additional data + // handled in sc/source/ui/app/inputwin.cxx + Point* pParaPoint = new Point(nStartPara, nEndPara); + const void* pCmdData = pParaPoint; + + Point aPos(nStart, nEnd); + CommandEvent aCEvt(aPos, CommandEventId::CursorPos, false, pCmdData); + LOKTrigger::command(*pArea, aCEvt); + + return true; + } + } + } + else if (sControlType == "spinfield") + { + auto pSpinField = dynamic_cast<weld::SpinButton*>(pWidget); + if (pSpinField) + { + if (sAction == "change" || sAction == "value") + { + if (rData["data"] == "undefined") + return true; + + // The Document will not scroll if that is in focus + // maybe we could send a message with: sAction == "grab_focus" + pWidget->grab_focus(); + + double nValue = o3tl::toDouble(rData["data"]); + pSpinField->set_value(nValue + * weld::SpinButton::Power10(pSpinField->get_digits())); + LOKTrigger::trigger_value_changed(*pSpinField); + return true; + } + if (sAction == "plus") + { + pSpinField->set_value(pSpinField->get_value() + 1); + LOKTrigger::trigger_value_changed(*pSpinField); + return true; + } + else if (sAction == "minus") + { + pSpinField->set_value(pSpinField->get_value() - 1); + LOKTrigger::trigger_value_changed(*pSpinField); + return true; + } + } + + auto pFormattedField = dynamic_cast<weld::FormattedSpinButton*>(pWidget); + if (pFormattedField) + { + if (sAction == "change") + { + pFormattedField->set_text(rData["data"]); + LOKTrigger::trigger_changed(*pFormattedField); + LOKTrigger::trigger_value_changed(*pFormattedField); + return true; + } + } + } + else if (sControlType == "toolbox") + { + auto pToolbar = dynamic_cast<weld::Toolbar*>(pWidget); + if (pToolbar) + { + if (sAction == "click") + { + LOKTrigger::trigger_clicked(*pToolbar, rData["data"]); + return true; + } + else if (sAction == "togglemenu") + { + const OUString& sId = rData["data"]; + bool bIsActive = pToolbar->get_menu_item_active(sId); + pToolbar->set_menu_item_active(sId, !bIsActive); + return true; + } + else if (sAction == "closemenu") + { + pToolbar->set_menu_item_active(rData["data"], false); + return true; + } + else if (sAction == "openmenu") + { + pToolbar->set_menu_item_active(rData["data"], true); + return true; + } + } + } + else if (sControlType == "edit") + { + auto pEdit = dynamic_cast<JSEntry*>(pWidget); + if (pEdit) + { + if (sAction == "change") + { + pEdit->set_text_without_notify(rData["data"]); + LOKTrigger::trigger_changed(*pEdit); + return true; + } + } + + auto pTextView = dynamic_cast<JSTextView*>(pWidget); + if (pTextView) + { + if (sAction == "change") + { + int rStartPos, rEndPos; + pTextView->get_selection_bounds(rStartPos, rEndPos); + pTextView->set_text_without_notify(rData["data"]); + pTextView->select_region(rStartPos, rEndPos); + LOKTrigger::trigger_changed(*pTextView); + return true; + } + else if (sAction == "textselection") + { + // start;end + OUString sTextData = rData["data"]; + int nSeparatorPos = sTextData.indexOf(';'); + if (nSeparatorPos <= 0) + return true; + + std::u16string_view aStartPos = sTextData.subView(0, nSeparatorPos); + std::u16string_view aEndPos = sTextData.subView(nSeparatorPos + 1); + + if (aStartPos.empty() || aEndPos.empty()) + return true; + + sal_Int32 nStart = o3tl::toInt32(aStartPos); + sal_Int32 nEnd = o3tl::toInt32(aEndPos); + + pTextView->select_region(nStart, nEnd); + LOKTrigger::trigger_changed(*pTextView); + + return true; + } + } + } + else if (sControlType == "treeview") + { + auto pTreeView = dynamic_cast<JSTreeView*>(pWidget); + if (pTreeView) + { + if (sAction == "change") + { + OUString sDataJSON = rtl::Uri::decode( + rData["data"], rtl_UriDecodeMechanism::rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8); + StringMap aMap(jsonToStringMap( + OUStringToOString(sDataJSON, RTL_TEXTENCODING_ASCII_US).getStr())); + + sal_Int32 nRow = o3tl::toInt32(aMap["row"]); + bool bValue = aMap["value"] == "true"; + + pTreeView->set_toggle(nRow, bValue ? TRISTATE_TRUE : TRISTATE_FALSE); + + return true; + } + else if (sAction == "select") + { + sal_Int32 nAbsPos = o3tl::toInt32(rData["data"]); + + pTreeView->unselect_all(); + + std::unique_ptr<weld::TreeIter> itEntry(pTreeView->make_iterator()); + if (pTreeView->get_iter_abs_pos(*itEntry, nAbsPos)) + { + pTreeView->select(*itEntry); + pTreeView->set_cursor_without_notify(*itEntry); + } + else + SAL_WARN("vcl", + "No absolute position found for " << nAbsPos << " in treeview"); + pTreeView->grab_focus(); + LOKTrigger::trigger_changed(*pTreeView); + return true; + } + else if (sAction == "activate") + { + sal_Int32 nRow = o3tl::toInt32(rData["data"]); + + pTreeView->unselect_all(); + std::unique_ptr<weld::TreeIter> itEntry(pTreeView->make_iterator()); + if (pTreeView->get_iter_abs_pos(*itEntry, nRow)) + { + pTreeView->select(nRow); + pTreeView->set_cursor_without_notify(*itEntry); + } + else + SAL_WARN("vcl", + "No absolute position found for " << nRow << " in treeview"); + pTreeView->grab_focus(); + LOKTrigger::trigger_changed(*pTreeView); + LOKTrigger::trigger_row_activated(*pTreeView); + return true; + } + else if (sAction == "expand") + { + sal_Int32 nAbsPos = o3tl::toInt32(rData["data"]); + std::unique_ptr<weld::TreeIter> itEntry(pTreeView->make_iterator()); + if (pTreeView->get_iter_abs_pos(*itEntry, nAbsPos)) + { + pTreeView->set_cursor_without_notify(*itEntry); + pTreeView->grab_focus(); + pTreeView->expand_row(*itEntry); + } + else + SAL_WARN("vcl", + "No absolute position found for " << nAbsPos << " in treeview"); + return true; + } + else if (sAction == "collapse") + { + sal_Int32 nAbsPos = o3tl::toInt32(rData["data"]); + std::unique_ptr<weld::TreeIter> itEntry(pTreeView->make_iterator()); + if (pTreeView->get_iter_abs_pos(*itEntry, nAbsPos)) + { + pTreeView->set_cursor_without_notify(*itEntry); + pTreeView->grab_focus(); + pTreeView->collapse_row(*itEntry); + } + else + SAL_WARN("vcl", + "No absolute position found for " << nAbsPos << " in treeview"); + return true; + } + else if (sAction == "dragstart") + { + sal_Int32 nRow = o3tl::toInt32(rData["data"]); + + pTreeView->select(nRow); + pTreeView->drag_start(); + + return true; + } + else if (sAction == "dragend") + { + pTreeView->drag_end(); + return true; + } + } + } + else if (sControlType == "iconview") + { + auto pIconView = dynamic_cast<weld::IconView*>(pWidget); + if (pIconView) + { + if (sAction == "select") + { + sal_Int32 nPos = o3tl::toInt32(rData["data"]); + + pIconView->select(nPos); + LOKTrigger::trigger_changed(*pIconView); + + return true; + } + else if (sAction == "activate") + { + sal_Int32 nPos = o3tl::toInt32(rData["data"]); + + pIconView->select(nPos); + LOKTrigger::trigger_changed(*pIconView); + LOKTrigger::trigger_item_activated(*pIconView); + + return true; + } + } + } + else if (sControlType == "expander") + { + auto pExpander = dynamic_cast<weld::Expander*>(pWidget); + if (pExpander) + { + if (sAction == "toggle") + { + pExpander->set_expanded(!pExpander->get_expanded()); + return true; + } + } + } + else if (sControlType == "dialog") + { + auto pDialog = dynamic_cast<weld::Dialog*>(pWidget); + if (pDialog) + { + if (sAction == "close") + { + pDialog->response(RET_CANCEL); + return true; + } + else if (sAction == "response") + { + sal_Int32 nResponse = o3tl::toInt32(rData["data"]); + pDialog->response(nResponse); + return true; + } + } + } + else if (sControlType == "popover") + { + auto pPopover = dynamic_cast<weld::Popover*>(pWidget); + if (pPopover) + { + if (sAction == "close") + { + LOKTrigger::trigger_closed(*pPopover); + return true; + } + } + } + else if (sControlType == "radiobutton") + { + auto pRadioButton = dynamic_cast<weld::RadioButton*>(pWidget); + if (pRadioButton) + { + if (sAction == "change") + { + bool bChecked = rData["data"] == "true"; + pRadioButton->set_state(bChecked ? TRISTATE_TRUE : TRISTATE_FALSE); + LOKTrigger::trigger_toggled(*static_cast<weld::Toggleable*>(pRadioButton)); + return true; + } + } + } + else if (sControlType == "scrolledwindow") + { + auto pScrolledWindow = dynamic_cast<JSScrolledWindow*>(pWidget); + if (pScrolledWindow) + { + if (sAction == "scrollv") + { + sal_Int32 nValue = o3tl::toInt32(rData["data"]); + pScrolledWindow->vadjustment_set_value_no_notification(nValue); + LOKTrigger::trigger_scrollv(*pScrolledWindow); + return true; + } + else if (sAction == "scrollh") + { + sal_Int32 nValue = o3tl::toInt32(rData["data"]); + pScrolledWindow->hadjustment_set_value_no_notification(nValue); + LOKTrigger::trigger_scrollh(*pScrolledWindow); + return true; + } + } + } + else if (sControlType == "calendar") + { + auto pCalendar = dynamic_cast<weld::Calendar*>(pWidget); + if (pCalendar && sAction == "selectdate") + { + // MM/DD/YYYY + OUString aDate = rData["data"]; + + if (aDate.getLength() < 10) + return false; + + sal_Int32 aMonth = o3tl::toInt32(aDate.subView(0, 2)); + sal_Int32 aDay = o3tl::toInt32(aDate.subView(3, 2)); + sal_Int32 aYear = o3tl::toInt32(aDate.subView(6, 4)); + + pCalendar->set_date(Date(aDay, aMonth, aYear)); + LOKTrigger::trigger_selected(*pCalendar); + LOKTrigger::trigger_activated(*pCalendar); + return true; + } + } + } + + return false; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx new file mode 100644 index 0000000000..48946baa15 --- /dev/null +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -0,0 +1,2370 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <jsdialog/jsdialogbuilder.hxx> +#include <sal/log.hxx> +#include <comphelper/base64.hxx> +#include <comphelper/lok.hxx> +#include <utility> +#include <vcl/tabpage.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/toolkit/button.hxx> +#include <vcl/toolkit/combobox.hxx> +#include <vcl/toolkit/dialog.hxx> +#include <vcl/toolkit/treelistentry.hxx> +#include <vcl/toolkit/vclmedit.hxx> +#include <verticaltabctrl.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <messagedialog.hxx> +#include <tools/json_writer.hxx> +#include <o3tl/deleter.hxx> +#include <memory> +#include <boost/property_tree/json_parser.hpp> +#include <vcl/jsdialog/executor.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <tools/stream.hxx> + +#include <vcl/cvtgrf.hxx> + +#include <wizdlg.hxx> + +static std::map<OUString, vcl::Window*>& GetLOKPopupsMap() +{ + // Map to remember the LOKWindowId <-> vcl popup binding. + static std::map<OUString, vcl::Window*> s_aLOKPopupsMap; + + return s_aLOKPopupsMap; +} + +namespace +{ +void response_help(vcl::Window* pWindow) +{ + ::Dialog* pDialog = dynamic_cast<::Dialog*>(pWindow); + if (!pDialog) + return; + + vcl::Window* pButtonWindow = pDialog->get_widget_for_response(RET_HELP); + ::Button* pButton = dynamic_cast<::Button*>(pButtonWindow); + if (!pButton) + { + // Is it a wizard dialog? + vcl::RoadmapWizard* pWizard = dynamic_cast<vcl::RoadmapWizard*>(pWindow); + if (!pWizard || !pWizard->m_pHelp) + return; + pWizard->m_pHelp->Click(); + return; + } + + pButton->Click(); +} +} + +JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aNotifierWindow, + VclPtr<vcl::Window> aContentWindow, + const OUString& sTypeOfJSON) + : Idle("JSDialog notify") + , m_aNotifierWindow(std::move(aNotifierWindow)) + , m_aContentWindow(std::move(aContentWindow)) + , m_sTypeOfJSON(sTypeOfJSON) + , m_bForce(false) +{ + SetPriority(TaskPriority::POST_PAINT); +} + +void JSDialogNotifyIdle::forceUpdate() { m_bForce = true; } + +void JSDialogNotifyIdle::send(tools::JsonWriter& aJsonWriter) +{ + if (!m_aNotifierWindow) + { + aJsonWriter.finishAndGetAsOString(); + return; + } + + const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier(); + if (pNotifier) + { + if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage)) + { + m_bForce = false; + m_LastNotificationMessage = aJsonWriter.finishAndGetAsOString(); + pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, m_LastNotificationMessage); + } + else + { + aJsonWriter.finishAndGetAsOString(); + } + } + else + { + aJsonWriter.finishAndGetAsOString(); + } +} + +void JSDialogNotifyIdle::sendMessage(jsdialog::MessageType eType, VclPtr<vcl::Window> pWindow, + std::unique_ptr<jsdialog::ActionDataMap> pData) +{ + std::scoped_lock aGuard(m_aQueueMutex); + + // 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(); + + while (it != m_aMessageQueue.end()) + { + if (it->m_eType == eType && it->m_pWindow == pWindow) + { + // actions should be always sent, eg. rendering of custom entries in combobox + if (eType == jsdialog::MessageType::Action) + { + it++; + continue; + } + it = m_aMessageQueue.erase(it); + } + else + it++; + } + + JSDialogMessageInfo aMessage(eType, pWindow, std::move(pData)); + m_aMessageQueue.push_back(aMessage); +} + +std::unique_ptr<tools::JsonWriter> JSDialogNotifyIdle::generateFullUpdate() const +{ + std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter()); + + if (!m_aContentWindow || !m_aNotifierWindow) + return aJsonWriter; + + m_aContentWindow->DumpAsPropertyTree(*aJsonWriter); + if (m_aNotifierWindow) + aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId()); + aJsonWriter->put("jsontype", m_sTypeOfJSON); + + return aJsonWriter; +} + +std::unique_ptr<tools::JsonWriter> +JSDialogNotifyIdle::generateWidgetUpdate(VclPtr<vcl::Window> pWindow) const +{ + std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter()); + + if (!pWindow || !m_aNotifierWindow) + return aJsonWriter; + + aJsonWriter->put("jsontype", m_sTypeOfJSON); + aJsonWriter->put("action", "update"); + if (m_aNotifierWindow) + aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId()); + { + auto aEntries = aJsonWriter->startNode("control"); + pWindow->DumpAsPropertyTree(*aJsonWriter); + } + + return aJsonWriter; +} + +std::unique_ptr<tools::JsonWriter> JSDialogNotifyIdle::generateCloseMessage() const +{ + std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter()); + if (m_aNotifierWindow) + aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId()); + aJsonWriter->put("jsontype", m_sTypeOfJSON); + aJsonWriter->put("action", "close"); + + return aJsonWriter; +} + +std::unique_ptr<tools::JsonWriter> +JSDialogNotifyIdle::generateActionMessage(VclPtr<vcl::Window> pWindow, + std::unique_ptr<jsdialog::ActionDataMap> pData) const +{ + std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter()); + + aJsonWriter->put("jsontype", m_sTypeOfJSON); + aJsonWriter->put("action", "action"); + if (m_aNotifierWindow) + aJsonWriter->put("id", m_aNotifierWindow->GetLOKWindowId()); + + { + auto aDataNode = aJsonWriter->startNode("data"); + aJsonWriter->put("control_id", pWindow->get_id()); + + for (auto it = pData->begin(); it != pData->end(); it++) + aJsonWriter->put(it->first, it->second); + } + + return aJsonWriter; +} + +std::unique_ptr<tools::JsonWriter> +JSDialogNotifyIdle::generatePopupMessage(VclPtr<vcl::Window> pWindow, OUString sParentId, + OUString sCloseId) const +{ + std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter()); + + if (!pWindow || !m_aNotifierWindow) + return aJsonWriter; + + if (!pWindow->GetParentWithLOKNotifier()) + return aJsonWriter; + + { + auto aChildren = aJsonWriter->startArray("children"); + { + auto aStruct = aJsonWriter->startStruct(); + pWindow->DumpAsPropertyTree(*aJsonWriter); + } + } + + // try to get the position eg. for the autofilter + { + vcl::Window* pVclWindow = pWindow.get(); + DockingWindow* pDockingWindow = dynamic_cast<DockingWindow*>(pVclWindow); + while (pVclWindow && !pDockingWindow) + { + pVclWindow = pVclWindow->GetParent(); + pDockingWindow = dynamic_cast<DockingWindow*>(pVclWindow); + } + + if (pDockingWindow) + { + Point aPos = pDockingWindow->GetFloatingPos(); + aJsonWriter->put("posx", aPos.getX()); + aJsonWriter->put("posy", aPos.getY()); + if (!pDockingWindow->IsVisible()) + aJsonWriter->put("visible", "false"); + } + } + + aJsonWriter->put("jsontype", "dialog"); + aJsonWriter->put("type", "modalpopup"); + aJsonWriter->put("cancellable", true); + aJsonWriter->put("popupParent", sParentId); + aJsonWriter->put("clickToClose", sCloseId); + aJsonWriter->put("id", pWindow->GetParentWithLOKNotifier()->GetLOKWindowId()); + + return aJsonWriter; +} + +std::unique_ptr<tools::JsonWriter> +JSDialogNotifyIdle::generateClosePopupMessage(OUString sWindowId) const +{ + std::unique_ptr<tools::JsonWriter> aJsonWriter(new tools::JsonWriter()); + + if (!m_aNotifierWindow) + return aJsonWriter; + + aJsonWriter->put("jsontype", "dialog"); + aJsonWriter->put("type", "modalpopup"); + aJsonWriter->put("action", "close"); + aJsonWriter->put("id", sWindowId); + + return aJsonWriter; +} + +void JSDialogNotifyIdle::Invoke() +{ + std::deque<JSDialogMessageInfo> aMessageQueue; + { + std::scoped_lock aGuard(m_aQueueMutex); + + std::swap(aMessageQueue, m_aMessageQueue); + } + + for (auto& rMessage : aMessageQueue) + { + jsdialog::MessageType eType = rMessage.m_eType; + + if (m_sTypeOfJSON == "formulabar" && eType != jsdialog::MessageType::Action) + continue; + + switch (eType) + { + case jsdialog::MessageType::FullUpdate: + send(*generateFullUpdate()); + break; + + case jsdialog::MessageType::WidgetUpdate: + send(*generateWidgetUpdate(rMessage.m_pWindow)); + break; + + case jsdialog::MessageType::Close: + send(*generateCloseMessage()); + break; + + case jsdialog::MessageType::Action: + send(*generateActionMessage(rMessage.m_pWindow, std::move(rMessage.m_pData))); + break; + + case jsdialog::MessageType::Popup: + send(*generatePopupMessage(rMessage.m_pWindow, + (*rMessage.m_pData)[PARENT_ID ""_ostr], + (*rMessage.m_pData)[CLOSE_ID ""_ostr])); + break; + + case jsdialog::MessageType::PopupClose: + send(*generateClosePopupMessage((*rMessage.m_pData)[WINDOW_ID ""_ostr])); + break; + } + } +} + +void JSDialogNotifyIdle::clearQueue() { m_aMessageQueue.clear(); } + +JSDialogSender::~JSDialogSender() COVERITY_NOEXCEPT_FALSE +{ + sendClose(); + + if (mpIdleNotify) + mpIdleNotify->Stop(); +} + +void JSDialogSender::sendFullUpdate(bool bForce) +{ + if (!mpIdleNotify) + return; + + if (bForce) + mpIdleNotify->forceUpdate(); + + mpIdleNotify->sendMessage(jsdialog::MessageType::FullUpdate, nullptr); + mpIdleNotify->Start(); +} + +void JSDialogSender::sendClose() +{ + if (!mpIdleNotify || !m_bCanClose) + return; + + mpIdleNotify->clearQueue(); + mpIdleNotify->sendMessage(jsdialog::MessageType::Close, nullptr); + flush(); +} + +void JSDialogSender::sendUpdate(VclPtr<vcl::Window> pWindow, bool bForce) +{ + if (!mpIdleNotify) + return; + + if (bForce) + mpIdleNotify->forceUpdate(); + + mpIdleNotify->sendMessage(jsdialog::MessageType::WidgetUpdate, pWindow); + mpIdleNotify->Start(); +} + +void JSDialogSender::sendAction(VclPtr<vcl::Window> pWindow, + std::unique_ptr<jsdialog::ActionDataMap> pData) +{ + if (!mpIdleNotify) + return; + + mpIdleNotify->sendMessage(jsdialog::MessageType::Action, pWindow, std::move(pData)); + mpIdleNotify->Start(); +} + +void JSDialogSender::sendPopup(VclPtr<vcl::Window> pWindow, OUString sParentId, OUString sCloseId) +{ + if (!mpIdleNotify) + return; + + std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>(); + (*pData)[PARENT_ID ""_ostr] = sParentId; + (*pData)[CLOSE_ID ""_ostr] = sCloseId; + mpIdleNotify->sendMessage(jsdialog::MessageType::Popup, pWindow, std::move(pData)); + mpIdleNotify->Start(); +} + +void JSDialogSender::sendClosePopup(vcl::LOKWindowId nWindowId) +{ + if (!mpIdleNotify) + return; + + 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)); + flush(); +} + +namespace +{ +vcl::Window* extract_sal_widget(weld::Widget* pParent) +{ + SalInstanceWidget* pInstanceWidget = dynamic_cast<SalInstanceWidget*>(pParent); + return pInstanceWidget ? pInstanceWidget->getWidget() : nullptr; +} +} + +// Drag and drop + +namespace +{ +class JSDropTargetDropContext + : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDropContext> +{ +public: + JSDropTargetDropContext() {} + + // XDropTargetDropContext + virtual void SAL_CALL acceptDrop(sal_Int8 /*dragOperation*/) override {} + + virtual void SAL_CALL rejectDrop() override {} + + virtual void SAL_CALL dropComplete(sal_Bool /*bSuccess*/) override {} +}; +} + +static JSTreeView* g_DragSource; + +JSDropTarget::JSDropTarget() {} + +void JSDropTarget::initialize(const css::uno::Sequence<css::uno::Any>& /*rArgs*/) {} + +void JSDropTarget::addDropTargetListener( + const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>& xListener) +{ + std::unique_lock aGuard(m_aMutex); + + m_aListeners.push_back(xListener); +} + +void JSDropTarget::removeDropTargetListener( + const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>& xListener) +{ + std::unique_lock aGuard(m_aMutex); + + std::erase(m_aListeners, xListener); +} + +sal_Bool JSDropTarget::isActive() { return false; } + +void JSDropTarget::setActive(sal_Bool /*active*/) {} + +sal_Int8 JSDropTarget::getDefaultActions() { return 0; } + +void JSDropTarget::setDefaultActions(sal_Int8 /*actions*/) {} + +OUString JSDropTarget::getImplementationName() +{ + return "com.sun.star.datatransfer.dnd.JSDropTarget"; +} + +sal_Bool JSDropTarget::supportsService(OUString const& ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence<OUString> JSDropTarget::getSupportedServiceNames() +{ + css::uno::Sequence<OUString> aRet{ "com.sun.star.datatransfer.dnd.JSDropTarget" }; + return aRet; +} + +void JSDropTarget::fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde) +{ + std::unique_lock aGuard(m_aMutex); + std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners( + m_aListeners); + aGuard.unlock(); + + for (auto const& listener : aListeners) + { + listener->drop(dtde); + } +} + +void JSDropTarget::fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent& dtde) +{ + std::unique_lock aGuard(m_aMutex); + std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners( + m_aListeners); + aGuard.unlock(); + + for (auto const& listener : aListeners) + { + listener->dragEnter(dtde); + } +} + +OUString JSInstanceBuilder::getMapIdFromWindowId() const +{ + if (m_sTypeOfJSON == "sidebar" || m_sTypeOfJSON == "notebookbar" + || m_sTypeOfJSON == "formulabar") + return OUString::number(m_nWindowId) + m_sTypeOfJSON; + else + return OUString::number(m_nWindowId); +} + +// used for dialogs +JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot, + const OUString& rUIFile, bool bPopup) + : SalInstanceBuilder(extract_sal_widget(pParent), rUIRoot, rUIFile) + , m_nWindowId(0) + , m_aParentDialog(nullptr) + , m_aContentWindow(nullptr) + , m_sTypeOfJSON("dialog") + , m_bHasTopLevelDialog(false) + , m_bIsNotebookbar(false) + , m_bSentInitialUpdate(false) + , m_bIsNestedBuilder(false) + , m_aWindowToRelease(nullptr) +{ + // when it is a popup we initialize sender in weld_popover + if (bPopup) + { + m_sTypeOfJSON = "popup"; + return; + } + + vcl::Window* pRoot = m_xBuilder->get_widget_root(); + + if (pRoot && pRoot->GetParent()) + { + m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier(); + if (m_aParentDialog) + m_nWindowId = m_aParentDialog->GetLOKWindowId(); + InsertWindowToMap(getMapIdFromWindowId()); + } + + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); +} + +// used for sidebar panels +JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot, + const OUString& rUIFile, sal_uInt64 nLOKWindowId) + : SalInstanceBuilder(extract_sal_widget(pParent), rUIRoot, rUIFile) + , m_nWindowId(nLOKWindowId) + , m_aParentDialog(nullptr) + , m_aContentWindow(nullptr) + , m_sTypeOfJSON("sidebar") + , m_bHasTopLevelDialog(false) + , m_bIsNotebookbar(false) + , m_bSentInitialUpdate(false) + , m_bIsNestedBuilder(false) + , m_aWindowToRelease(nullptr) +{ + vcl::Window* pRoot = m_xBuilder->get_widget_root(); + + m_aParentDialog = pRoot->GetParentWithLOKNotifier(); + + if (rUIFile == "sfx/ui/panel.ui") + { + // builder for Panel, get SidebarDockingWindow as m_aContentWindow + m_aContentWindow = pRoot; + for (int i = 0; i < 7 && m_aContentWindow; i++) + m_aContentWindow = m_aContentWindow->GetParent(); + } + else + { + // embedded fragments cannot send close message for whole sidebar + if (rUIFile == "modules/simpress/ui/customanimationfragment.ui") + m_bCanClose = false; + + // builder for PanelLayout, get SidebarDockingWindow as m_aContentWindow + m_aContentWindow = pRoot; + for (int i = 0; i < 9 && m_aContentWindow; i++) + m_aContentWindow = m_aContentWindow->GetParent(); + } + + InsertWindowToMap(getMapIdFromWindowId()); + + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); +} + +// used for notebookbar +JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot, + const OUString& rUIFile, + const css::uno::Reference<css::frame::XFrame>& rFrame, + sal_uInt64 nWindowId) + : SalInstanceBuilder(pParent, rUIRoot, rUIFile, rFrame) + , m_nWindowId(0) + , m_aParentDialog(nullptr) + , m_aContentWindow(nullptr) + , m_sTypeOfJSON("notebookbar") + , m_bHasTopLevelDialog(false) + , m_bIsNotebookbar(false) + , m_bSentInitialUpdate(false) + , m_bIsNestedBuilder(false) + , m_aWindowToRelease(nullptr) +{ + vcl::Window* pRoot = m_xBuilder->get_widget_root(); + if (pRoot && pRoot->GetParent()) + { + m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier(); + if (m_aParentDialog) + m_nWindowId = m_aParentDialog->GetLOKWindowId(); + if (!m_nWindowId && nWindowId) + { + m_nWindowId = nWindowId; + m_bIsNotebookbar = true; + } + InsertWindowToMap(getMapIdFromWindowId()); + } + + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); +} + +// used for formulabar +JSInstanceBuilder::JSInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot, + const OUString& rUIFile, sal_uInt64 nLOKWindowId) + : SalInstanceBuilder(pParent, rUIRoot, rUIFile) + , m_nWindowId(nLOKWindowId) + , m_aParentDialog(nullptr) + , m_aContentWindow(nullptr) + , m_sTypeOfJSON("formulabar") + , m_bHasTopLevelDialog(false) + , m_bIsNotebookbar(false) + , m_bSentInitialUpdate(false) + , m_bIsNestedBuilder(false) + , m_aWindowToRelease(nullptr) +{ + vcl::Window* pRoot = m_xBuilder->get_widget_root(); + m_aContentWindow = pParent; + if (pRoot && pRoot->GetParent()) + { + m_aParentDialog = pRoot->GetParent()->GetParentWithLOKNotifier(); + InsertWindowToMap(getMapIdFromWindowId()); + } + + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); +} + +std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreateDialogBuilder(weld::Widget* pParent, + const OUString& rUIRoot, + const OUString& rUIFile) +{ + return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile); +} + +std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreateNotebookbarBuilder( + vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile, + const css::uno::Reference<css::frame::XFrame>& rFrame, sal_uInt64 nWindowId) +{ + return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, rFrame, nWindowId); +} + +std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreateSidebarBuilder(weld::Widget* pParent, + const OUString& rUIRoot, + const OUString& rUIFile, + sal_uInt64 nLOKWindowId) +{ + return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, nLOKWindowId); +} + +std::unique_ptr<JSInstanceBuilder> JSInstanceBuilder::CreatePopupBuilder(weld::Widget* pParent, + const OUString& rUIRoot, + const OUString& rUIFile) +{ + return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, true); +} + +std::unique_ptr<JSInstanceBuilder> +JSInstanceBuilder::CreateFormulabarBuilder(vcl::Window* pParent, const OUString& rUIRoot, + const OUString& rUIFile, sal_uInt64 nLOKWindowId) +{ + return std::make_unique<JSInstanceBuilder>(pParent, rUIRoot, rUIFile, nLOKWindowId); +} + +JSInstanceBuilder::~JSInstanceBuilder() +{ + // tab page closed -> refresh parent window + if (m_bIsNestedBuilder && m_sTypeOfJSON == "dialog") + { + jsdialog::SendFullUpdate(OUString::number(m_nWindowId), "__DIALOG__"); + } + + if (m_sTypeOfJSON == "popup") + sendClosePopup(m_nWindowId); + + if (m_aWindowToRelease) + { + m_aWindowToRelease->ReleaseLOKNotifier(); + m_aWindowToRelease.clear(); + } + + if (m_nWindowId && (m_bHasTopLevelDialog || m_bIsNotebookbar)) + { + GetLOKWeldWidgetsMap().erase(getMapIdFromWindowId()); + } + else + { + auto it = GetLOKWeldWidgetsMap().find(getMapIdFromWindowId()); + if (it != GetLOKWeldWidgetsMap().end()) + { + std::for_each(m_aRememberedWidgets.begin(), m_aRememberedWidgets.end(), + [it](const OUString& sId) { it->second.erase(sId); }); + } + } + + GetLOKPopupsMap().erase(OUString::number(m_nWindowId)); +} + +std::map<OUString, WidgetMap>& JSInstanceBuilder::GetLOKWeldWidgetsMap() +{ + // Map to remember the LOKWindowId <-> weld widgets binding. + static std::map<OUString, WidgetMap> s_aLOKWeldBuildersMap; + + return s_aLOKWeldBuildersMap; +} + +weld::Widget* JSInstanceBuilder::FindWeldWidgetsMap(const OUString& nWindowId, + const OUString& rWidget) +{ + const auto it = GetLOKWeldWidgetsMap().find(nWindowId); + + if (it != GetLOKWeldWidgetsMap().end()) + { + auto widgetIt = it->second.find(rWidget); + if (widgetIt != it->second.end()) + return widgetIt->second; + } + + return nullptr; +} + +void JSInstanceBuilder::InsertWindowToMap(const OUString& nWindowId) +{ + WidgetMap map; + auto it = GetLOKWeldWidgetsMap().find(nWindowId); + if (it == GetLOKWeldWidgetsMap().end()) + GetLOKWeldWidgetsMap().insert({ nWindowId, map }); +} + +void JSInstanceBuilder::RememberWidget(OUString sId, weld::Widget* pWidget) +{ + // do not use the same id for two widgets inside one builder + // exception is sidebar where we base our full invalidation on that "Panel" id sharing + if (m_sTypeOfJSON != "sidebar") + { + static std::atomic<unsigned long long int> nNotRepeatIndex = 0; + auto aWindowIt = GetLOKWeldWidgetsMap().find(getMapIdFromWindowId()); + if (aWindowIt != GetLOKWeldWidgetsMap().end()) + { + auto aWidgetIt = aWindowIt->second.find(sId); + if (aWidgetIt != aWindowIt->second.end()) + { + unsigned long long int nIndex = nNotRepeatIndex++; + // found duplicated it -> add some number to the id and apply to the widget + sId = sId + OUString::number(nIndex); + SalInstanceWidget* pSalWidget = dynamic_cast<SalInstanceWidget*>(pWidget); + assert(pSalWidget && "can only be a SalInstanceWidget"); + vcl::Window* pVclWidget = pSalWidget->getWidget(); + pVclWidget->set_id(pVclWidget->get_id() + OUString::number(nIndex)); + } + } + } + + RememberWidget(getMapIdFromWindowId(), sId, pWidget); + m_aRememberedWidgets.push_back(sId); +} + +void JSInstanceBuilder::RememberWidget(const OUString& nWindowId, const OUString& id, + weld::Widget* pWidget) +{ + auto it = GetLOKWeldWidgetsMap().find(nWindowId); + if (it != GetLOKWeldWidgetsMap().end()) + { + it->second.erase(id); + it->second.insert(WidgetMap::value_type(id, pWidget)); + } +} + +void JSInstanceBuilder::AddChildWidget(const OUString& nWindowId, const OUString& id, + weld::Widget* pWidget) +{ + auto it = GetLOKWeldWidgetsMap().find(nWindowId); + if (it != GetLOKWeldWidgetsMap().end()) + { + it->second.erase(id); + it->second.insert(WidgetMap::value_type(id, pWidget)); + } +} + +void JSInstanceBuilder::RemoveWindowWidget(const OUString& nWindowId) +{ + auto it = JSInstanceBuilder::GetLOKWeldWidgetsMap().find(nWindowId); + if (it != JSInstanceBuilder::GetLOKWeldWidgetsMap().end()) + { + JSInstanceBuilder::GetLOKWeldWidgetsMap().erase(it); + } +} + +void JSInstanceBuilder::RememberPopup(const OUString& nWindowId, VclPtr<vcl::Window> pWidget) +{ + GetLOKPopupsMap()[nWindowId] = pWidget; +} + +void JSInstanceBuilder::ForgetPopup(const OUString& nWindowId) +{ + auto it = GetLOKPopupsMap().find(nWindowId); + if (it != GetLOKPopupsMap().end()) + GetLOKPopupsMap().erase(it); +} + +vcl::Window* JSInstanceBuilder::FindPopup(const OUString& nWindowId) +{ + const auto it = GetLOKPopupsMap().find(nWindowId); + + if (it != GetLOKPopupsMap().end()) + return it->second; + + return nullptr; +} + +const OUString& JSInstanceBuilder::GetTypeOfJSON() const { return m_sTypeOfJSON; } + +VclPtr<vcl::Window>& JSInstanceBuilder::GetContentWindow() +{ + if (m_aContentWindow) + return m_aContentWindow; + else + return m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog; +} + +VclPtr<vcl::Window>& JSInstanceBuilder::GetNotifierWindow() +{ + return m_bHasTopLevelDialog ? m_aOwnedToplevel : m_aParentDialog; +} + +std::unique_ptr<weld::Dialog> JSInstanceBuilder::weld_dialog(const OUString& id) +{ + std::unique_ptr<weld::Dialog> pRet; + ::Dialog* pDialog = m_xBuilder->get<::Dialog>(id); + + if (pDialog) + { + m_nWindowId = pDialog->GetLOKWindowId(); + pDialog->SetLOKTunnelingState(false); + + InsertWindowToMap(getMapIdFromWindowId()); + + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pDialog); + m_xBuilder->drop_ownership(pDialog); + m_bHasTopLevelDialog = true; + + pRet.reset(new JSDialog(this, pDialog, this, false)); + + RememberWidget("__DIALOG__", pRet.get()); + + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); + m_bSentInitialUpdate = true; + } + + return pRet; +} + +std::unique_ptr<weld::Assistant> JSInstanceBuilder::weld_assistant(const OUString& id) +{ + vcl::RoadmapWizard* pDialog = m_xBuilder->get<vcl::RoadmapWizard>(id); + std::unique_ptr<JSAssistant> pRet(pDialog ? new JSAssistant(this, pDialog, this, false) + : nullptr); + if (pDialog) + { + m_nWindowId = pDialog->GetLOKWindowId(); + pDialog->SetLOKTunnelingState(false); + + InsertWindowToMap(getMapIdFromWindowId()); + + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pDialog); + m_xBuilder->drop_ownership(pDialog); + m_bHasTopLevelDialog = true; + + pRet.reset(new JSAssistant(this, pDialog, this, false)); + + RememberWidget("__DIALOG__", pRet.get()); + + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); + m_bSentInitialUpdate = true; + } + + return pRet; +} + +std::unique_ptr<weld::MessageDialog> JSInstanceBuilder::weld_message_dialog(const OUString& id) +{ + std::unique_ptr<weld::MessageDialog> pRet; + ::MessageDialog* pMessageDialog = m_xBuilder->get<::MessageDialog>(id); + + if (pMessageDialog) + { + m_nWindowId = pMessageDialog->GetLOKWindowId(); + pMessageDialog->SetLOKTunnelingState(false); + + InsertWindowToMap(getMapIdFromWindowId()); + + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pMessageDialog); + m_xBuilder->drop_ownership(pMessageDialog); + m_bHasTopLevelDialog = true; + + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); + m_bSentInitialUpdate = true; + } + + pRet.reset(pMessageDialog ? new JSMessageDialog(this, pMessageDialog, this, false) : nullptr); + + if (pRet) + RememberWidget("__DIALOG__", pRet.get()); + + return pRet; +} + +std::unique_ptr<weld::Container> JSInstanceBuilder::weld_container(const OUString& id) +{ + vcl::Window* pContainer = m_xBuilder->get<vcl::Window>(id); + auto pWeldWidget + = pContainer ? std::make_unique<JSContainer>(this, pContainer, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + if (!m_bSentInitialUpdate && pContainer) + { + m_bSentInitialUpdate = true; + + // use parent builder to send update - avoid multiple calls from many builders + vcl::Window* pParent = pContainer->GetParent(); + OUString sId = OUString::number(m_nWindowId); + while (pParent && !FindWeldWidgetsMap(sId, pParent->get_id())) + pParent = pParent->GetParent(); + + if (pParent) + jsdialog::SendFullUpdate(sId, pParent->get_id()); + + // this is nested builder, don't close parent dialog on destroy (eg. single tab page is closed) + m_bCanClose = false; + m_bIsNestedBuilder = true; + } + + return pWeldWidget; +} + +std::unique_ptr<weld::ScrolledWindow> +JSInstanceBuilder::weld_scrolled_window(const OUString& id, bool bUserManagedScrolling) +{ + VclScrolledWindow* pScrolledWindow = m_xBuilder->get<VclScrolledWindow>(id); + auto pWeldWidget = pScrolledWindow + ? std::make_unique<JSScrolledWindow>(this, pScrolledWindow, this, false, + bUserManagedScrolling) + : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Label> JSInstanceBuilder::weld_label(const OUString& id) +{ + Control* pLabel = m_xBuilder->get<Control>(id); + auto pWeldWidget = std::make_unique<JSLabel>(this, pLabel, this, false); + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Button> JSInstanceBuilder::weld_button(const OUString& id) +{ + ::Button* pButton = m_xBuilder->get<::Button>(id); + auto pWeldWidget = pButton ? std::make_unique<JSButton>(this, pButton, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::LinkButton> JSInstanceBuilder::weld_link_button(const OUString& id) +{ + ::FixedHyperlink* pButton = m_xBuilder->get<::FixedHyperlink>(id); + auto pWeldWidget + = pButton ? std::make_unique<JSLinkButton>(this, pButton, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::ToggleButton> JSInstanceBuilder::weld_toggle_button(const OUString& id) +{ + ::PushButton* pButton = m_xBuilder->get<::PushButton>(id); + auto pWeldWidget + = pButton ? std::make_unique<JSToggleButton>(this, pButton, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Entry> JSInstanceBuilder::weld_entry(const OUString& id) +{ + Edit* pEntry = m_xBuilder->get<Edit>(id); + auto pWeldWidget = pEntry ? std::make_unique<JSEntry>(this, pEntry, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::ComboBox> JSInstanceBuilder::weld_combo_box(const OUString& id) +{ + vcl::Window* pWidget = m_xBuilder->get<vcl::Window>(id); + ::ComboBox* pComboBox = dynamic_cast<::ComboBox*>(pWidget); + std::unique_ptr<weld::ComboBox> pWeldWidget; + + if (pComboBox) + { + pWeldWidget = std::make_unique<JSComboBox>(this, pComboBox, this, false); + } + else + { + ListBox* pListBox = dynamic_cast<ListBox*>(pWidget); + pWeldWidget = pListBox ? std::make_unique<JSListBox>(this, pListBox, this, false) : nullptr; + } + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Notebook> JSInstanceBuilder::weld_notebook(const OUString& id) +{ + std::unique_ptr<weld::Notebook> pWeldWidget; + vcl::Window* pNotebook = m_xBuilder->get(id); + + if (pNotebook && pNotebook->GetType() == WindowType::TABCONTROL) + pWeldWidget + = std::make_unique<JSNotebook>(this, static_cast<TabControl*>(pNotebook), this, false); + else if (pNotebook->GetType() == WindowType::VERTICALTABCONTROL) + pWeldWidget = std::make_unique<JSVerticalNotebook>( + this, static_cast<VerticalTabControl*>(pNotebook), this, false); + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::SpinButton> JSInstanceBuilder::weld_spin_button(const OUString& id) +{ + FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id); + auto pWeldWidget + = pSpinButton ? std::make_unique<JSSpinButton>(this, pSpinButton, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::FormattedSpinButton> +JSInstanceBuilder::weld_formatted_spin_button(const OUString& id) +{ + FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id); + auto pWeldWidget = pSpinButton + ? std::make_unique<JSFormattedSpinButton>(this, pSpinButton, this, false) + : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::CheckButton> JSInstanceBuilder::weld_check_button(const OUString& id) +{ + CheckBox* pCheckButton = m_xBuilder->get<CheckBox>(id); + auto pWeldWidget + = pCheckButton ? std::make_unique<JSCheckButton>(this, pCheckButton, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::DrawingArea> +JSInstanceBuilder::weld_drawing_area(const OUString& id, const a11yref& rA11yImpl, + FactoryFunction pUITestFactoryFunction, void* pUserData) +{ + VclDrawingArea* pArea = m_xBuilder->get<VclDrawingArea>(id); + auto pWeldWidget = pArea ? std::make_unique<JSDrawingArea>(this, pArea, this, rA11yImpl, + pUITestFactoryFunction, pUserData) + : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Toolbar> JSInstanceBuilder::weld_toolbar(const OUString& id) +{ + ToolBox* pToolBox = m_xBuilder->get<ToolBox>(id); + auto pWeldWidget + = pToolBox ? std::make_unique<JSToolbar>(this, pToolBox, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::TextView> JSInstanceBuilder::weld_text_view(const OUString& id) +{ + VclMultiLineEdit* pTextView = m_xBuilder->get<VclMultiLineEdit>(id); + auto pWeldWidget + = pTextView ? std::make_unique<JSTextView>(this, pTextView, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::TreeView> JSInstanceBuilder::weld_tree_view(const OUString& id) +{ + SvTabListBox* pTreeView = m_xBuilder->get<SvTabListBox>(id); + auto pWeldWidget + = pTreeView ? std::make_unique<JSTreeView>(this, pTreeView, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Expander> JSInstanceBuilder::weld_expander(const OUString& id) +{ + VclExpander* pExpander = m_xBuilder->get<VclExpander>(id); + auto pWeldWidget + = pExpander ? std::make_unique<JSExpander>(this, pExpander, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::IconView> JSInstanceBuilder::weld_icon_view(const OUString& id) +{ + ::IconView* pIconView = m_xBuilder->get<::IconView>(id); + auto pWeldWidget + = pIconView ? std::make_unique<JSIconView>(this, pIconView, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::RadioButton> JSInstanceBuilder::weld_radio_button(const OUString& id) +{ + ::RadioButton* pRadioButton = m_xBuilder->get<::RadioButton>(id); + auto pWeldWidget + = pRadioButton ? std::make_unique<JSRadioButton>(this, pRadioButton, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Frame> JSInstanceBuilder::weld_frame(const OUString& id) +{ + ::VclFrame* pFrame = m_xBuilder->get<::VclFrame>(id); + auto pWeldWidget = pFrame ? std::make_unique<JSFrame>(this, pFrame, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::MenuButton> JSInstanceBuilder::weld_menu_button(const OUString& id) +{ + ::MenuButton* pMenuButton = m_xBuilder->get<::MenuButton>(id); + auto pWeldWidget + = pMenuButton ? std::make_unique<JSMenuButton>(this, pMenuButton, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Popover> JSInstanceBuilder::weld_popover(const OUString& id) +{ + DockingWindow* pDockingWindow = m_xBuilder->get<DockingWindow>(id); + JSPopover* pPopover + = pDockingWindow ? new JSPopover(this, pDockingWindow, this, false) : nullptr; + std::unique_ptr<weld::Popover> pWeldWidget(pPopover); + if (pDockingWindow) + { + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pDockingWindow); + m_xBuilder->drop_ownership(pDockingWindow); + + if (VclPtr<vcl::Window> pWin = pDockingWindow->GetParentWithLOKNotifier()) + { + vcl::Window* pPopupRoot = pDockingWindow->GetChild(0); + pPopupRoot->SetLOKNotifier(pWin->GetLOKNotifier()); + m_aParentDialog = pPopupRoot; + m_aWindowToRelease = pPopupRoot; + m_nWindowId = m_aParentDialog->GetLOKWindowId(); + + pPopover->set_window_id(m_nWindowId); + JSInstanceBuilder::RememberPopup(OUString::number(m_nWindowId), pDockingWindow); + + InsertWindowToMap(getMapIdFromWindowId()); + initializeSender(GetNotifierWindow(), GetContentWindow(), GetTypeOfJSON()); + } + } + + if (pWeldWidget) + RememberWidget("__POPOVER__", pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Box> JSInstanceBuilder::weld_box(const OUString& id) +{ + VclBox* pContainer = m_xBuilder->get<VclBox>(id); + auto pWeldWidget + = pContainer ? std::make_unique<JSBox>(this, pContainer, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Widget> JSInstanceBuilder::weld_widget(const OUString& id) +{ + vcl::Window* pWidget = m_xBuilder->get(id); + auto pWeldWidget + = pWidget ? std::make_unique<JSWidgetInstance>(this, pWidget, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Image> JSInstanceBuilder::weld_image(const OUString& id) +{ + FixedImage* pImage = m_xBuilder->get<FixedImage>(id); + + auto pWeldWidget = pImage ? std::make_unique<JSImage>(this, pImage, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +std::unique_ptr<weld::Calendar> JSInstanceBuilder::weld_calendar(const OUString& id) +{ + ::Calendar* pCalendar = m_xBuilder->get<::Calendar>(id); + + auto pWeldWidget + = pCalendar ? std::make_unique<JSCalendar>(this, pCalendar, this, false) : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + +weld::MessageDialog* +JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, + VclButtonsType eButtonType, const OUString& rPrimaryMessage, + const vcl::ILibreOfficeKitNotifier* pNotifier) +{ + SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent); + SystemWindow* pParentWidget = pParentInstance ? pParentInstance->getSystemWindow() : nullptr; + VclPtrInstance<::MessageDialog> xMessageDialog(pParentWidget, rPrimaryMessage, eMessageType, + eButtonType); + + if (pNotifier) + xMessageDialog->SetLOKNotifier(pNotifier); + + pNotifier = xMessageDialog->GetLOKNotifier(); + if (pNotifier) + { + tools::JsonWriter aJsonWriter; + xMessageDialog->DumpAsPropertyTree(aJsonWriter); + aJsonWriter.put("id", xMessageDialog->GetLOKWindowId()); + aJsonWriter.put("jsontype", "dialog"); + OString message(aJsonWriter.finishAndGetAsOString()); + pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message); + + OUString sWindowId = OUString::number(xMessageDialog->GetLOKWindowId()); + InsertWindowToMap(sWindowId); + xMessageDialog->SetLOKTunnelingState(false); + + return new JSMessageDialog(xMessageDialog, nullptr, true); + } + else + SAL_WARN("vcl", "No notifier in JSInstanceBuilder::CreateMessageDialog"); + + return new JSMessageDialog(xMessageDialog, nullptr, true); +} + +JSDialog::JSDialog(JSDialogSender* pSender, ::Dialog* pDialog, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceDialog, ::Dialog>(pSender, pDialog, pBuilder, bTakeOwnership) +{ +} + +void JSDialog::collapse(weld::Widget* pEdit, weld::Widget* pButton) +{ + SalInstanceDialog::collapse(pEdit, pButton); + sendFullUpdate(); +} + +void JSDialog::undo_collapse() +{ + SalInstanceDialog::undo_collapse(); + sendFullUpdate(); +} + +void JSDialog::response(int response) +{ + if (response == RET_HELP) + { + response_help(m_xWidget.get()); + return; + } + + sendClose(); + SalInstanceDialog::response(response); +} + +void JSAssistant::response(int response) +{ + if (response == RET_HELP) + { + response_help(m_xWidget.get()); + return; + } + + sendClose(); + SalInstanceAssistant::response(response); +} + +int JSDialog::run() +{ + sendFullUpdate(true); + int ret = SalInstanceDialog::run(); + return ret; +} + +bool JSDialog::runAsync(std::shared_ptr<weld::DialogController> aOwner, + const std::function<void(sal_Int32)>& rEndDialogFn) +{ + bool ret = SalInstanceDialog::runAsync(aOwner, rEndDialogFn); + sendFullUpdate(); + return ret; +} + +bool JSDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf, + const std::function<void(sal_Int32)>& func) +{ + bool ret = SalInstanceDialog::runAsync(rxSelf, func); + sendFullUpdate(); + return ret; +} + +int JSAssistant::run() +{ + sendFullUpdate(true); + int ret = SalInstanceDialog::run(); + return ret; +} + +bool JSAssistant::runAsync(std::shared_ptr<weld::DialogController> aOwner, + const std::function<void(sal_Int32)>& rEndDialogFn) +{ + bool ret = SalInstanceDialog::runAsync(aOwner, rEndDialogFn); + sendFullUpdate(); + return ret; +} + +bool JSAssistant::runAsync(std::shared_ptr<Dialog> const& rxSelf, + const std::function<void(sal_Int32)>& func) +{ + bool ret = SalInstanceDialog::runAsync(rxSelf, func); + sendFullUpdate(); + return ret; +} + +weld::Button* JSDialog::weld_widget_for_response(int nResponse) +{ + PushButton* pButton + = dynamic_cast<::PushButton*>(m_xDialog->get_widget_for_response(nResponse)); + auto pWeldWidget = pButton ? new JSButton(m_pSender, pButton, nullptr, false) : nullptr; + + if (pWeldWidget) + { + auto pParentDialog = m_xDialog->GetParentWithLOKNotifier(); + if (pParentDialog) + JSInstanceBuilder::RememberWidget(OUString::number(pParentDialog->GetLOKWindowId()), + pButton->get_id(), pWeldWidget); + } + + return pWeldWidget; +} + +weld::Button* JSAssistant::weld_widget_for_response(int nResponse) +{ + ::PushButton* pButton = nullptr; + JSButton* pWeldWidget = nullptr; + if (nResponse == RET_YES) + pButton = m_xWizard->m_pNextPage; + else if (nResponse == RET_NO) + pButton = m_xWizard->m_pPrevPage; + else if (nResponse == RET_OK) + pButton = m_xWizard->m_pFinish; + else if (nResponse == RET_CANCEL) + pButton = m_xWizard->m_pCancel; + else if (nResponse == RET_HELP) + pButton = m_xWizard->m_pHelp; + if (pButton) + pWeldWidget = new JSButton(m_pSender, pButton, nullptr, false); + + if (pWeldWidget) + { + auto pParentDialog = m_xWizard->GetParentWithLOKNotifier(); + if (pParentDialog) + JSInstanceBuilder::RememberWidget(OUString::number(pParentDialog->GetLOKWindowId()), + pButton->get_id(), pWeldWidget); + } + + return pWeldWidget; +} + +JSAssistant::JSAssistant(JSDialogSender* pSender, vcl::RoadmapWizard* pDialog, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceAssistant, vcl::RoadmapWizard>(pSender, pDialog, pBuilder, bTakeOwnership) +{ +} + +void JSAssistant::set_current_page(int nPage) +{ + SalInstanceAssistant::set_current_page(nPage); + sendFullUpdate(); +} + +void JSAssistant::set_current_page(const OUString& rIdent) +{ + SalInstanceAssistant::set_current_page(rIdent); + sendFullUpdate(); +} + +JSContainer::JSContainer(JSDialogSender* pSender, vcl::Window* pContainer, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceContainer, vcl::Window>(pSender, pContainer, pBuilder, bTakeOwnership) +{ +} + +JSScrolledWindow::JSScrolledWindow(JSDialogSender* pSender, ::VclScrolledWindow* pContainer, + SalInstanceBuilder* pBuilder, bool bTakeOwnership, + bool bUserManagedScrolling) + : JSWidget<SalInstanceScrolledWindow, ::VclScrolledWindow>( + pSender, pContainer, pBuilder, bTakeOwnership, bUserManagedScrolling) +{ +} + +void JSScrolledWindow::vadjustment_configure(int value, int lower, int upper, int step_increment, + int page_increment, int page_size) +{ + SalInstanceScrolledWindow::vadjustment_configure(value, lower, upper, step_increment, + page_increment, page_size); + sendUpdate(); +} + +void JSScrolledWindow::vadjustment_set_value(int value) +{ + SalInstanceScrolledWindow::vadjustment_set_value(value); + sendUpdate(); +} + +void JSScrolledWindow::vadjustment_set_value_no_notification(int value) +{ + SalInstanceScrolledWindow::vadjustment_set_value(value); +} + +void JSScrolledWindow::vadjustment_set_page_size(int size) +{ + SalInstanceScrolledWindow::vadjustment_set_page_size(size); + sendUpdate(); +} + +void JSScrolledWindow::set_vpolicy(VclPolicyType eVPolicy) +{ + SalInstanceScrolledWindow::set_vpolicy(eVPolicy); + sendUpdate(); +} + +void JSScrolledWindow::hadjustment_configure(int value, int lower, int upper, int step_increment, + int page_increment, int page_size) +{ + SalInstanceScrolledWindow::hadjustment_configure(value, lower, upper, step_increment, + page_increment, page_size); + sendUpdate(); +} + +void JSScrolledWindow::hadjustment_set_value(int value) +{ + SalInstanceScrolledWindow::hadjustment_set_value(value); + sendUpdate(); +} + +void JSScrolledWindow::hadjustment_set_value_no_notification(int value) +{ + SalInstanceScrolledWindow::hadjustment_set_value(value); +} + +void JSScrolledWindow::hadjustment_set_page_size(int size) +{ + SalInstanceScrolledWindow::hadjustment_set_page_size(size); + sendUpdate(); +} + +void JSScrolledWindow::set_hpolicy(VclPolicyType eVPolicy) +{ + SalInstanceScrolledWindow::set_hpolicy(eVPolicy); + sendUpdate(); +} + +JSLabel::JSLabel(JSDialogSender* pSender, Control* pLabel, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceLabel, Control>(pSender, pLabel, pBuilder, bTakeOwnership) +{ +} + +void JSLabel::set_label(const OUString& rText) +{ + SalInstanceLabel::set_label(rText); + sendUpdate(); +}; + +JSButton::JSButton(JSDialogSender* pSender, ::Button* pButton, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceButton, ::Button>(pSender, pButton, pBuilder, bTakeOwnership) +{ +} + +JSLinkButton::JSLinkButton(JSDialogSender* pSender, ::FixedHyperlink* pButton, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceLinkButton, ::FixedHyperlink>(pSender, pButton, pBuilder, bTakeOwnership) +{ +} + +JSToggleButton::JSToggleButton(JSDialogSender* pSender, ::PushButton* pButton, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceToggleButton, ::PushButton>(pSender, pButton, pBuilder, bTakeOwnership) +{ +} + +JSEntry::JSEntry(JSDialogSender* pSender, ::Edit* pEntry, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceEntry, ::Edit>(pSender, pEntry, pBuilder, bTakeOwnership) +{ +} + +void JSEntry::set_text(const OUString& rText) +{ + SalInstanceEntry::set_text(rText); + sendUpdate(); +} + +void JSEntry::set_text_without_notify(const OUString& rText) { SalInstanceEntry::set_text(rText); } + +void JSEntry::replace_selection(const OUString& rText) +{ + SalInstanceEntry::replace_selection(rText); + sendUpdate(); +} + +JSListBox::JSListBox(JSDialogSender* pSender, ::ListBox* pListBox, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceComboBoxWithoutEdit, ::ListBox>(pSender, pListBox, pBuilder, + bTakeOwnership) +{ +} + +void JSListBox::insert(int pos, const OUString& rStr, const OUString* pId, + const OUString* pIconName, VirtualDevice* pImageSurface) +{ + SalInstanceComboBoxWithoutEdit::insert(pos, rStr, pId, pIconName, pImageSurface); + sendUpdate(); +} + +void JSListBox::remove(int pos) +{ + SalInstanceComboBoxWithoutEdit::remove(pos); + sendUpdate(); +} + +void JSListBox::set_active(int pos) +{ + SalInstanceComboBoxWithoutEdit::set_active(pos); + sendUpdate(); +} + +JSComboBox::JSComboBox(JSDialogSender* pSender, ::ComboBox* pComboBox, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceComboBoxWithEdit, ::ComboBox>(pSender, pComboBox, pBuilder, + bTakeOwnership) +{ +} + +void JSComboBox::insert(int pos, const OUString& rStr, const OUString* pId, + const OUString* pIconName, VirtualDevice* pImageSurface) +{ + SalInstanceComboBoxWithEdit::insert(pos, rStr, pId, pIconName, pImageSurface); + sendUpdate(); +} + +void JSComboBox::remove(int pos) +{ + SalInstanceComboBoxWithEdit::remove(pos); + sendUpdate(); +} + +void JSComboBox::set_entry_text_without_notify(const OUString& rText) +{ + SalInstanceComboBoxWithEdit::set_entry_text(rText); +} + +void JSComboBox::set_entry_text(const OUString& rText) +{ + SalInstanceComboBoxWithEdit::set_entry_text(rText); + + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); + (*pMap)[ACTION_TYPE ""_ostr] = "setText"; + (*pMap)["text"_ostr] = rText; + sendAction(std::move(pMap)); +} + +void JSComboBox::set_active(int pos) +{ + if (pos == get_active()) + return; + + SalInstanceComboBoxWithEdit::set_active(pos); + + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); + (*pMap)[ACTION_TYPE ""_ostr] = "select"; + (*pMap)["position"_ostr] = OUString::number(pos); + sendAction(std::move(pMap)); +} + +void JSComboBox::set_active_id(const OUString& rStr) +{ + sal_uInt16 nPos = find_id(rStr); + set_active(nPos); +} + +bool JSComboBox::changed_by_direct_pick() const { return true; } + +void JSComboBox::render_entry(int pos, int dpix, int dpiy) +{ + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::WITH_ALPHA); + pDevice->SetDPIX(96.0 * dpix / 100); + pDevice->SetDPIY(96.0 * dpiy / 100); + + Size aRenderSize = signal_custom_get_size(*pDevice); + pDevice->SetOutputSize(aRenderSize); + + signal_custom_render(*pDevice, tools::Rectangle(Point(0, 0), aRenderSize), false, get_id(pos)); + + BitmapEx aImage = pDevice->GetBitmapEx(Point(0, 0), aRenderSize); + + SvMemoryStream aOStm(65535, 65535); + if (GraphicConverter::Export(aOStm, aImage, ConvertDataFormat::PNG) == ERRCODE_NONE) + { + css::uno::Sequence<sal_Int8> aSeq(static_cast<sal_Int8 const*>(aOStm.GetData()), + aOStm.Tell()); + OUStringBuffer aBuffer("data:image/png;base64,"); + ::comphelper::Base64::encode(aBuffer, aSeq); + + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); + (*pMap)[ACTION_TYPE ""_ostr] = "rendered_combobox_entry"; + (*pMap)["pos"_ostr] = OUString::number(pos); + (*pMap)["image"_ostr] = aBuffer; + sendAction(std::move(pMap)); + } +} + +JSNotebook::JSNotebook(JSDialogSender* pSender, ::TabControl* pControl, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceNotebook, ::TabControl>(pSender, pControl, pBuilder, bTakeOwnership) +{ +} + +void JSNotebook::remove_page(const OUString& rIdent) +{ + SalInstanceNotebook::remove_page(rIdent); + sendFullUpdate(); +} + +void JSNotebook::insert_page(const OUString& rIdent, const OUString& rLabel, int nPos) +{ + SalInstanceNotebook::insert_page(rIdent, rLabel, nPos); + sendFullUpdate(); +} + +JSVerticalNotebook::JSVerticalNotebook(JSDialogSender* pSender, ::VerticalTabControl* pControl, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceVerticalNotebook, ::VerticalTabControl>(pSender, pControl, pBuilder, + bTakeOwnership) +{ +} + +void JSVerticalNotebook::remove_page(const OUString& rIdent) +{ + SalInstanceVerticalNotebook::remove_page(rIdent); + sendFullUpdate(); +} + +void JSVerticalNotebook::insert_page(const OUString& rIdent, const OUString& rLabel, int nPos) +{ + SalInstanceVerticalNotebook::insert_page(rIdent, rLabel, nPos); + sendFullUpdate(); +} + +JSSpinButton::JSSpinButton(JSDialogSender* pSender, ::FormattedField* pSpin, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceSpinButton, ::FormattedField>(pSender, pSpin, pBuilder, bTakeOwnership) +{ +} + +void JSSpinButton::set_value(sal_Int64 value) +{ + SalInstanceSpinButton::set_value(value); + + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); + (*pMap)[ACTION_TYPE ""_ostr] = "setText"; + (*pMap)["text"_ostr] = OUString::number(m_rFormatter.GetValue()); + sendAction(std::move(pMap)); +} + +JSFormattedSpinButton::JSFormattedSpinButton(JSDialogSender* pSender, ::FormattedField* pSpin, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceFormattedSpinButton, ::FormattedField>(pSender, pSpin, pBuilder, + bTakeOwnership) +{ +} + +void JSFormattedSpinButton::set_text(const OUString& rText) +{ + SalInstanceFormattedSpinButton::set_text(rText); + sendUpdate(); +} + +void JSFormattedSpinButton::set_text_without_notify(const OUString& rText) +{ + SalInstanceFormattedSpinButton::set_text(rText); +} + +JSMessageDialog::JSMessageDialog(JSDialogSender* pSender, ::MessageDialog* pDialog, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceMessageDialog, ::MessageDialog>(pSender, pDialog, pBuilder, + bTakeOwnership) +{ +} + +JSMessageDialog::JSMessageDialog(::MessageDialog* pDialog, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceMessageDialog, ::MessageDialog>(nullptr, pDialog, pBuilder, + bTakeOwnership) + , m_pOwnedSender(new JSDialogSender(pDialog, pDialog, "dialog")) +{ + m_pSender = m_pOwnedSender.get(); + + if (pBuilder) + return; + + m_sWindowId = OUString::number(m_xMessageDialog->GetLOKWindowId()); + + if (::OKButton* pOKBtn + = dynamic_cast<::OKButton*>(m_xMessageDialog->get_widget_for_response(RET_OK))) + { + m_pOK.reset(new JSButton(m_pSender, pOKBtn, nullptr, false)); + JSInstanceBuilder::AddChildWidget(m_sWindowId, pOKBtn->get_id(), m_pOK.get()); + m_pOK->connect_clicked(LINK(this, JSMessageDialog, OKHdl)); + } + + if (::CancelButton* pCancelBtn + = dynamic_cast<::CancelButton*>(m_xMessageDialog->get_widget_for_response(RET_CANCEL))) + { + m_pCancel.reset(new JSButton(m_pSender, pCancelBtn, nullptr, false)); + JSInstanceBuilder::AddChildWidget(m_sWindowId, pCancelBtn->get_id(), m_pCancel.get()); + m_pCancel->connect_clicked(LINK(this, JSMessageDialog, CancelHdl)); + } +} + +JSMessageDialog::~JSMessageDialog() +{ + if (m_pOK || m_pCancel) + JSInstanceBuilder::RemoveWindowWidget(m_sWindowId); +} + +void JSMessageDialog::RememberMessageDialog() +{ + static constexpr OUString sWidgetName = u"__DIALOG__"_ustr; + OUString sWindowId = OUString::number(m_xMessageDialog->GetLOKWindowId()); + if (JSInstanceBuilder::FindWeldWidgetsMap(sWindowId, sWidgetName) != nullptr) + return; + + JSInstanceBuilder::InsertWindowToMap(sWindowId); + JSInstanceBuilder::RememberWidget(sWindowId, sWidgetName, this); +} + +int JSMessageDialog::run() +{ + if (GetLOKNotifier()) + { + RememberMessageDialog(); + sendFullUpdate(); + } + + int bRet = SalInstanceMessageDialog::run(); + return bRet; +} + +bool JSMessageDialog::runAsync(std::shared_ptr<weld::DialogController> aOwner, + const std::function<void(sal_Int32)>& rEndDialogFn) +{ + bool bRet = SalInstanceMessageDialog::runAsync(aOwner, rEndDialogFn); + + RememberMessageDialog(); + sendFullUpdate(); + + return bRet; +} + +bool JSMessageDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf, + const std::function<void(sal_Int32)>& rEndDialogFn) +{ + bool bRet = SalInstanceMessageDialog::runAsync(rxSelf, rEndDialogFn); + + RememberMessageDialog(); + sendFullUpdate(); + + return bRet; +} + +IMPL_LINK_NOARG(JSMessageDialog, OKHdl, weld::Button&, void) { response(RET_OK); } + +IMPL_LINK_NOARG(JSMessageDialog, CancelHdl, weld::Button&, void) { response(RET_CANCEL); } + +void JSMessageDialog::set_primary_text(const OUString& rText) +{ + SalInstanceMessageDialog::set_primary_text(rText); + sendFullUpdate(); +} + +void JSMessageDialog::set_secondary_text(const OUString& rText) +{ + SalInstanceMessageDialog::set_secondary_text(rText); + sendFullUpdate(); +} + +void JSMessageDialog::response(int response) +{ + if (response == RET_HELP) + { + response_help(m_xWidget.get()); + return; + } + + sendClose(); + SalInstanceMessageDialog::response(response); +} + +JSCheckButton::JSCheckButton(JSDialogSender* pSender, ::CheckBox* pCheckBox, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceCheckButton, ::CheckBox>(pSender, pCheckBox, pBuilder, bTakeOwnership) +{ +} + +void JSCheckButton::set_active(bool active) +{ + bool bWasActive = get_active(); + SalInstanceCheckButton::set_active(active); + if (bWasActive != active) + sendUpdate(); +} + +JSDrawingArea::JSDrawingArea(JSDialogSender* pSender, VclDrawingArea* pDrawingArea, + SalInstanceBuilder* pBuilder, const a11yref& rAlly, + FactoryFunction pUITestFactoryFunction, void* pUserData) + : JSWidget<SalInstanceDrawingArea, VclDrawingArea>(pSender, pDrawingArea, pBuilder, rAlly, + std::move(pUITestFactoryFunction), pUserData, + false) +{ +} + +void JSDrawingArea::queue_draw() +{ + SalInstanceDrawingArea::queue_draw(); + sendUpdate(); +} + +void JSDrawingArea::queue_draw_area(int x, int y, int width, int height) +{ + SalInstanceDrawingArea::queue_draw_area(x, y, width, height); + sendUpdate(); +} + +JSToolbar::JSToolbar(JSDialogSender* pSender, ::ToolBox* pToolbox, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceToolbar, ::ToolBox>(pSender, pToolbox, pBuilder, bTakeOwnership) +{ +} + +void JSToolbar::set_menu_item_active(const OUString& rIdent, bool bActive) +{ + bool bWasActive = get_menu_item_active(rIdent); + SalInstanceToolbar::set_menu_item_active(rIdent, bActive); + + ToolBoxItemId nItemId = m_xToolBox->GetItemId(rIdent); + VclPtr<vcl::Window> pFloat = m_aFloats[nItemId]; + + if (!pFloat) + return; + + // See WeldToolbarPopup : include/svtools/toolbarmenu.hxx + // TopLevel (Popover) -> Container -> main container of the popup + vcl::Window* pPopupRoot = pFloat->GetChild(0); + if (pPopupRoot) + pPopupRoot = pPopupRoot->GetChild(0); + + if (pPopupRoot) + { + if (bActive) + { + JSInstanceBuilder::RememberPopup(OUString::number(pPopupRoot->GetLOKWindowId()), + pFloat); + sendPopup(pPopupRoot, m_xToolBox->get_id(), rIdent); + } + else if (bWasActive) + { + JSInstanceBuilder::ForgetPopup(OUString::number(pPopupRoot->GetLOKWindowId())); + sendClosePopup(pPopupRoot->GetLOKWindowId()); + } + } +} + +void JSToolbar::set_item_sensitive(const OUString& rIdent, bool bSensitive) +{ + bool bWasSensitive = get_item_sensitive(rIdent); + SalInstanceToolbar::set_item_sensitive(rIdent, bSensitive); + if (bWasSensitive != bSensitive) + sendUpdate(); +} + +void JSToolbar::set_item_icon_name(const OUString& rIdent, const OUString& rIconName) +{ + SalInstanceToolbar::set_item_icon_name(rIdent, rIconName); + sendUpdate(); +} + +JSTextView::JSTextView(JSDialogSender* pSender, ::VclMultiLineEdit* pTextView, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceTextView, ::VclMultiLineEdit>(pSender, pTextView, pBuilder, + bTakeOwnership) +{ +} + +void JSTextView::set_text(const OUString& rText) +{ + SalInstanceTextView::set_text(rText); + sendUpdate(); +} + +void JSTextView::set_text_without_notify(const OUString& rText) +{ + SalInstanceTextView::set_text(rText); +} + +void JSTextView::replace_selection(const OUString& rText) +{ + SalInstanceTextView::replace_selection(rText); + sendUpdate(); +} + +JSTreeView::JSTreeView(JSDialogSender* pSender, ::SvTabListBox* pTreeView, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceTreeView, ::SvTabListBox>(pSender, pTreeView, pBuilder, bTakeOwnership) +{ +} + +void JSTreeView::set_toggle(int pos, TriState eState, int col) +{ + SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, 0); + + while (pEntry && pos--) + pEntry = m_xTreeView->Next(pEntry); + + if (pEntry) + { + SalInstanceTreeView::set_toggle(pEntry, eState, col); + signal_toggled(iter_col(SalInstanceTreeIter(pEntry), col)); + + sendUpdate(); + } +} + +void JSTreeView::set_toggle(const weld::TreeIter& rIter, TriState bOn, int col) +{ + SalInstanceTreeView::set_toggle(rIter, bOn, col); + sendUpdate(); +} + +void JSTreeView::select(int pos) +{ + assert(m_xTreeView->IsUpdateMode() && "don't select when frozen"); + disable_notify_events(); + if (pos == -1 || (pos == 0 && n_children() == 0)) + m_xTreeView->SelectAll(false); + else + { + SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, 0); + + while (pEntry && pos--) + pEntry = m_xTreeView->Next(pEntry); + + if (pEntry) + { + m_xTreeView->Select(pEntry, true); + m_xTreeView->MakeVisible(pEntry); + } + } + enable_notify_events(); + + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); + (*pMap)[ACTION_TYPE ""_ostr] = "select"; + (*pMap)["position"_ostr] = OUString::number(pos); + sendAction(std::move(pMap)); +} + +weld::TreeView* JSTreeView::get_drag_source() const { return g_DragSource; } + +void JSTreeView::drag_start() { g_DragSource = this; } + +void JSTreeView::drag_end() +{ + css::datatransfer::dnd::XDropTarget* xDropTarget = m_xDropTarget.get(); + if (xDropTarget) + { + css::datatransfer::dnd::DropTargetDropEvent aEvent; + aEvent.Source = xDropTarget; + aEvent.Context = new JSDropTargetDropContext(); + // dummy values + aEvent.LocationX = 50; + aEvent.LocationY = 50; + aEvent.DropAction = css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT; + aEvent.SourceActions = css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT; + + m_xDropTarget->fire_drop(aEvent); + + sendUpdate(); + if (g_DragSource) + g_DragSource->sendUpdate(); + } + + g_DragSource = nullptr; +} + +void JSTreeView::insert(const weld::TreeIter* pParent, int pos, const OUString* pStr, + const OUString* pId, const OUString* pIconName, + VirtualDevice* pImageSurface, bool bChildrenOnDemand, weld::TreeIter* pRet) +{ + SalInstanceTreeView::insert(pParent, pos, pStr, pId, pIconName, pImageSurface, + bChildrenOnDemand, pRet); + + sendUpdate(); +} + +void JSTreeView::set_text(int row, const OUString& rText, int col) +{ + SalInstanceTreeView::set_text(row, rText, col); + sendUpdate(); +} + +void JSTreeView::set_text(const weld::TreeIter& rIter, const OUString& rStr, int col) +{ + SalInstanceTreeView::set_text(rIter, rStr, col); + sendUpdate(); +} + +void JSTreeView::remove(int pos) +{ + SalInstanceTreeView::remove(pos); + sendUpdate(); +} + +void JSTreeView::remove(const weld::TreeIter& rIter) +{ + SalInstanceTreeView::remove(rIter); + sendUpdate(); +} + +void JSTreeView::clear() +{ + SalInstanceTreeView::clear(); + sendUpdate(); +} + +void JSTreeView::set_cursor_without_notify(const weld::TreeIter& rIter) +{ + SalInstanceTreeView::set_cursor(rIter); +} + +void JSTreeView::set_cursor(const weld::TreeIter& rIter) +{ + SalInstanceTreeView::set_cursor(rIter); + sendUpdate(); +} + +void JSTreeView::set_cursor(int pos) +{ + SalInstanceTreeView::set_cursor(pos); + sendUpdate(); +} + +void JSTreeView::expand_row(const weld::TreeIter& rIter) +{ + bool bNotify = false; + const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); + if (!m_xTreeView->IsExpanded(rVclIter.iter)) + bNotify = true; + + SalInstanceTreeView::expand_row(rIter); + + if (bNotify) + sendUpdate(); +} + +void JSTreeView::collapse_row(const weld::TreeIter& rIter) +{ + bool bNotify = false; + const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); + if (m_xTreeView->IsExpanded(rVclIter.iter)) + bNotify = true; + + SalInstanceTreeView::collapse_row(rIter); + + if (bNotify) + sendUpdate(); +} + +JSExpander::JSExpander(JSDialogSender* pSender, ::VclExpander* pExpander, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceExpander, ::VclExpander>(pSender, pExpander, pBuilder, bTakeOwnership) +{ +} + +void JSExpander::set_expanded(bool bExpand) +{ + SalInstanceExpander::set_expanded(bExpand); + sendUpdate(); +} + +JSIconView::JSIconView(JSDialogSender* pSender, ::IconView* pIconView, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceIconView, ::IconView>(pSender, pIconView, pBuilder, bTakeOwnership) +{ +} + +void JSIconView::insert(int pos, const OUString* pStr, const OUString* pId, + const OUString* pIconName, weld::TreeIter* pRet) +{ + SalInstanceIconView::insert(pos, pStr, pId, pIconName, pRet); + sendUpdate(); +} + +void JSIconView::insert(int pos, const OUString* pStr, const OUString* pId, + const VirtualDevice* pIcon, weld::TreeIter* pRet) +{ + SalInstanceIconView::insert(pos, pStr, pId, pIcon, pRet); + sendUpdate(); +} + +void JSIconView::insert_separator(int pos, const OUString* pId) +{ + SalInstanceIconView::insert_separator(pos, pId); + sendUpdate(); +} + +void JSIconView::clear() +{ + SalInstanceIconView::clear(); + sendUpdate(); +} + +void JSIconView::select(int pos) +{ + SalInstanceIconView::select(pos); + + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); + (*pMap)[ACTION_TYPE ""_ostr] = "select"; + (*pMap)["position"_ostr] = OUString::number(pos); + sendAction(std::move(pMap)); +} + +void JSIconView::unselect(int pos) +{ + SalInstanceIconView::unselect(pos); + sendUpdate(); +} + +JSRadioButton::JSRadioButton(JSDialogSender* pSender, ::RadioButton* pRadioButton, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceRadioButton, ::RadioButton>(pSender, pRadioButton, pBuilder, + bTakeOwnership) +{ +} + +void JSRadioButton::set_active(bool active) +{ + SalInstanceRadioButton::set_active(active); + sendUpdate(); +} + +JSFrame::JSFrame(JSDialogSender* pSender, ::VclFrame* pFrame, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceFrame, ::VclFrame>(pSender, pFrame, pBuilder, bTakeOwnership) +{ +} + +JSMenuButton::JSMenuButton(JSDialogSender* pSender, ::MenuButton* pMenuButton, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstanceMenuButton, ::MenuButton>(pSender, pMenuButton, pBuilder, bTakeOwnership) +{ +} + +void JSMenuButton::set_label(const OUString& rText) +{ + OUString aPreviousLabel = get_label(); + SalInstanceMenuButton::set_label(rText); + if (aPreviousLabel != rText) + sendUpdate(); +} + +void JSMenuButton::set_image(VirtualDevice* pDevice) +{ + SalInstanceMenuButton::set_image(pDevice); + sendUpdate(); +} + +void JSMenuButton::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) +{ + SalInstanceMenuButton::set_image(rImage); + sendUpdate(); +} + +void JSMenuButton::set_active(bool bActive) +{ + SalInstanceMenuButton::set_active(bActive); + + VclPtr<vcl::Window> pPopup = m_xMenuButton->GetPopover(); + if (pPopup) + { + if (bActive) + sendPopup(pPopup->GetChild(0), m_xMenuButton->get_id(), m_xMenuButton->get_id()); + else + sendClosePopup(pPopup->GetChild(0)->GetLOKWindowId()); + } +} + +JSPopover::JSPopover(JSDialogSender* pSender, DockingWindow* pDockingWindow, + SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : JSWidget<SalInstancePopover, DockingWindow>(pSender, pDockingWindow, pBuilder, bTakeOwnership) + , mnWindowId(0) +{ +} + +void JSPopover::popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect, + weld::Placement ePlace) +{ + SalInstancePopover::popup_at_rect(pParent, rRect, ePlace); + sendPopup(getWidget()->GetChild(0), "_POPOVER_", "_POPOVER_"); +} + +void JSPopover::popdown() +{ + vcl::Window* pPopup = JSInstanceBuilder::FindPopup(OUString::number(mnWindowId)); + + if (pPopup) + { + sendClosePopup(mnWindowId); + vcl::Window::GetDockingManager()->EndPopupMode(pPopup); + } + + if (getWidget() && getWidget()->GetChild(0)) + sendClosePopup(getWidget()->GetChild(0)->GetLOKWindowId()); + + SalInstancePopover::popdown(); +} + +JSBox::JSBox(JSDialogSender* pSender, VclBox* pBox, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceBox, VclBox>(pSender, pBox, pBuilder, bTakeOwnership) +{ +} + +void JSBox::reorder_child(weld::Widget* pWidget, int nNewPosition) +{ + SalInstanceBox::reorder_child(pWidget, nNewPosition); + sendUpdate(); +} + +JSImage::JSImage(JSDialogSender* pSender, FixedImage* pImage, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceImage, FixedImage>(pSender, pImage, pBuilder, bTakeOwnership) +{ +} + +void JSImage::set_image(VirtualDevice* pDevice) +{ + SalInstanceImage::set_image(pDevice); + sendUpdate(); +} + +void JSImage::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) +{ + SalInstanceImage::set_image(rImage); + sendUpdate(); +} + +JSCalendar::JSCalendar(JSDialogSender* pSender, ::Calendar* pCalendar, SalInstanceBuilder* pBuilder, + bool bTakeOwnership) + : JSWidget<SalInstanceCalendar, ::Calendar>(pSender, pCalendar, pBuilder, bTakeOwnership) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |