From 0de158b4eb6d48d2c1a7cfcd638a73d7b69d45a7 Mon Sep 17 00:00:00 2001 From: Szymon Kłos Date: Fri, 30 Oct 2020 10:51:08 +0100 Subject: jsdialog: implement TreeView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7c1cc683e8c5d5bdc00c1e3d3d0a2c85846bbda0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106560 Tested-by: Jenkins Reviewed-by: Szymon Kłos --- desktop/source/lib/init.cxx | 22 +------- include/vcl/jsdialog/executor.hxx | 6 ++ include/vcl/weld.hxx | 2 + vcl/inc/jsdialog/jsdialogbuilder.hxx | 23 +++++++- vcl/inc/salvtables.hxx | 2 +- vcl/jsdialog/executor.cxx | 52 +++++++++++++++++ vcl/jsdialog/jsdialogbuilder.cxx | 105 +++++++++++++++++++++++++++++------ 7 files changed, 171 insertions(+), 41 deletions(-) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 06d0a1de31d2..bc8b46a94c43 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -441,24 +441,6 @@ std::vector desktop::jsonToPropertyValuesVector(const char } -static 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.c_str())] = OUString::fromUtf8(rPair.second.get_value(".").c_str()); - } - } - return aArgs; -} - - static boost::property_tree::ptree unoAnyToPropertyTree(const uno::Any& anyItem) { boost::property_tree::ptree aTree; @@ -3710,7 +3692,7 @@ static void doc_sendDialogEvent(LibreOfficeKitDocument* /*pThis*/, unsigned long { SolarMutexGuard aGuard; - StringMap aMap(jsonToStringMap(pArguments)); + StringMap aMap(jsdialog::jsonToStringMap(pArguments)); VclPtr pWindow = vcl::Window::FindLOKWindow(nWindowId); if (!pWindow && nWindowId >= 1000000000 /* why unsigned? */) @@ -5686,7 +5668,7 @@ static void doc_sendFormFieldEvent(LibreOfficeKitDocument* pThis, const char* pA if (doc_getDocumentType(pThis) != LOK_DOCTYPE_TEXT) return; - StringMap aMap(jsonToStringMap(pArguments)); + StringMap aMap(jsdialog::jsonToStringMap(pArguments)); ITiledRenderable* pDoc = getTiledRenderable(pThis); if (!pDoc) { diff --git a/include/vcl/jsdialog/executor.hxx b/include/vcl/jsdialog/executor.hxx index 1cfa24c28a8a..e49190f31e5f 100644 --- a/include/vcl/jsdialog/executor.hxx +++ b/include/vcl/jsdialog/executor.hxx @@ -22,6 +22,11 @@ public: static void trigger_changed(weld::ComboBox& rComboBox) { rComboBox.signal_changed(); } + static void trigger_row_activated(weld::TreeView& rTreeView) + { + rTreeView.signal_row_activated(); + } + static void trigger_clicked(weld::Toolbar& rToolbar, const OString& rIdent) { rToolbar.signal_clicked(rIdent); @@ -36,6 +41,7 @@ public: namespace jsdialog { VCL_DLLPUBLIC bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rData); +VCL_DLLPUBLIC StringMap jsonToStringMap(const char* pJSON); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 10686ffe705e..04285ee63778 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -782,6 +782,8 @@ public: */ class VCL_DLLPUBLIC TreeView : virtual public Container { + friend class ::LOKTrigger; + public: typedef std::pair iter_col; typedef std::pair iter_string; diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx index 91640f7a4ccd..8c379857e4b3 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -22,6 +22,7 @@ class ToolBox; class ComboBox; class VclMultiLineEdit; +class SvTabListBox; typedef std::map WidgetMap; @@ -108,8 +109,9 @@ public: weld_drawing_area(const OString& id, const a11yref& rA11yImpl = nullptr, FactoryFunction pUITestFactoryFunction = nullptr, void* pUserData = nullptr) override; - std::unique_ptr weld_toolbar(const OString& id) override; - std::unique_ptr weld_text_view(const OString& id) override; + virtual std::unique_ptr weld_toolbar(const OString& id) override; + virtual std::unique_ptr weld_text_view(const OString& id) override; + virtual std::unique_ptr weld_tree_view(const OString& id) override; static weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, @@ -145,6 +147,7 @@ public: notifyDialogState(); } + using BaseInstanceClass::set_sensitive; virtual void set_sensitive(bool sensitive) override { BaseInstanceClass::set_sensitive(sensitive); @@ -290,4 +293,20 @@ public: virtual void set_text(const OUString& rText) override; }; +class JSTreeView : public JSWidget +{ +public: + JSTreeView(VclPtr aNotifierWindow, VclPtr aContentWindow, + ::SvTabListBox* pTextView, SalInstanceBuilder* pBuilder, bool bTakeOwnership, + std::string sTypeOfJSON); + + using SalInstanceTreeView::set_toggle; + /// pos is used differently here, it defines how many steps of iterator we need to perform to take entry + virtual void set_toggle(int pos, TriState eState, int col = -1) override; + + using SalInstanceTreeView::select; + /// pos is used differently here, it defines how many steps of iterator we need to perform to take entry + virtual void select(int pos) override; +}; + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index cb7ccc7b12e3..343da9cf79f0 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -1302,7 +1302,7 @@ public: class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView { -private: +protected: // owner for UserData std::vector> m_aUserData; VclPtr m_xTreeView; diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx index 53fded14e1c1..9863d0c2edb9 100644 --- a/vcl/jsdialog/executor.cxx +++ b/vcl/jsdialog/executor.cxx @@ -11,9 +11,29 @@ #include #include #include +#include +#include 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.c_str())] + = OUString::fromUtf8(rPair.second.get_value(".").c_str()); + } + } + return aArgs; +} + bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rData) { weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget); @@ -143,6 +163,38 @@ bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rDat } } } + else if (sControlType == "treeview") + { + auto pTreeView = dynamic_cast(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())); + + OString nRowString = OUStringToOString(aMap["row"], RTL_TEXTENCODING_ASCII_US); + int nRow = std::atoi(nRowString.getStr()); + bool bValue = aMap["value"] == "true"; + + pTreeView->set_toggle(nRow, bValue ? TRISTATE_TRUE : TRISTATE_FALSE); + + return true; + } + else if (sAction == "select") + { + OString nRowString + = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US); + int nRow = std::atoi(nRowString.getStr()); + + pTreeView->select(nRow); + LOKTrigger::trigger_row_activated(*pTreeView); + } + } + } } return false; diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx index 88e2b9cc6eee..f2bc205d8b88 100644 --- a/vcl/jsdialog/jsdialogbuilder.cxx +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -22,6 +22,8 @@ #include #include #include +#include +#include JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr aNotifierWindow, VclPtr aContentWindow, std::string sTypeOfJSON) @@ -39,30 +41,42 @@ void JSDialogNotifyIdle::ForceUpdate() { m_bForce = true; } void JSDialogNotifyIdle::Invoke() { - try + if (!m_aNotifierWindow) + return; + + const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier(); + if (pNotifier) { - if (!m_aNotifierWindow) - return; + tools::JsonWriter aJsonWriter; + m_aContentWindow->DumpAsPropertyTree(aJsonWriter); + aJsonWriter.put("id", m_aNotifierWindow->GetLOKWindowId()); + aJsonWriter.put("jsontype", m_sTypeOfJSON); - const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier(); - if (pNotifier) + if (m_sTypeOfJSON == "autofilter") { - tools::JsonWriter aJsonWriter; - m_aContentWindow->DumpAsPropertyTree(aJsonWriter); - aJsonWriter.put("id", m_aNotifierWindow->GetLOKWindowId()); - aJsonWriter.put("jsontype", m_sTypeOfJSON); - if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage)) + vcl::Window* pWindow = m_aContentWindow.get(); + DockingWindow* pDockingWIndow = dynamic_cast(pWindow); + while (pWindow && !pDockingWIndow) + { + pWindow = pWindow->GetParent(); + pDockingWIndow = dynamic_cast(pWindow); + } + + if (pDockingWIndow) { - m_bForce = false; - m_LastNotificationMessage = aJsonWriter.extractAsStdString(); - pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, - m_LastNotificationMessage.c_str()); + Point aPos = pDockingWIndow->GetFloatingPos(); + aJsonWriter.put("posx", aPos.getX()); + aJsonWriter.put("posy", aPos.getY()); } } - } - catch (boost::property_tree::json_parser::json_parser_error& rError) - { - SAL_WARN("vcl", rError.message()); + + if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage)) + { + m_bForce = false; + m_LastNotificationMessage = aJsonWriter.extractAsStdString(); + pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, + m_LastNotificationMessage.c_str()); + } } } @@ -412,6 +426,20 @@ std::unique_ptr JSInstanceBuilder::weld_text_view(const OString& return pWeldWidget; } +std::unique_ptr JSInstanceBuilder::weld_tree_view(const OString& id) +{ + SvTabListBox* pTreeView = m_xBuilder->get(id); + auto pWeldWidget = pTreeView + ? std::make_unique(GetNotifierWindow(), GetContentWindow(), + pTreeView, this, false, m_sTypeOfJSON) + : nullptr; + + if (pWeldWidget) + RememberWidget(id, pWeldWidget.get()); + + return pWeldWidget; +} + weld::MessageDialog* JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, VclButtonsType eButtonType, @@ -693,4 +721,45 @@ void JSTextView::set_text(const OUString& rText) notifyDialogState(); } +JSTreeView::JSTreeView(VclPtr aNotifierWindow, VclPtr aContentWindow, + ::SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership, + std::string sTypeOfJSON) + : JSWidget(aNotifierWindow, aContentWindow, pTreeView, + pBuilder, bTakeOwnership, sTypeOfJSON) +{ +} + +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); +} + +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(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ -- cgit