diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2024-06-27 11:11:13 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2024-06-28 09:57:26 +0200 |
commit | 12ff4396d973e7aae4dd68b742d9790f8c88ea53 (patch) | |
tree | a2550ce4e0de0ab136bcca4f942760e3483cfb1a /vcl | |
parent | 5779dc944c5427d84c23a3a9c466a0caafb46689 (diff) |
jsdialog: support on demand rendering for icon view
- rename action: rendered_combobox_entry -> rendered_entry
- change generic get json property callback to more specialized
image getter as it wasn't used anywhere apart of that and we need
image enceded as base64 only not JSON
- add to the full update of icon view "ondemand" property to the entries
with images so LOK client will know it has to download the render
- it will be possible to support HiDPI renders in the future: added TODO
Signed-off-by: Szymon Kłos <szymon.klos@collabora.com>
Change-Id: I83a6e91133f8f9cb03e0bc794b51e1947435fa90
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169622
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/iconview.hxx | 12 | ||||
-rw-r--r-- | vcl/inc/jsdialog/jsdialogbuilder.hxx | 18 | ||||
-rw-r--r-- | vcl/inc/salvtables.hxx | 8 | ||||
-rw-r--r-- | vcl/jsdialog/executor.cxx | 36 | ||||
-rw-r--r-- | vcl/jsdialog/jsdialogbuilder.cxx | 16 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 16 | ||||
-rw-r--r-- | vcl/source/treelist/iconview.cxx | 40 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtkinst.cxx | 2 |
8 files changed, 99 insertions, 49 deletions
diff --git a/vcl/inc/iconview.hxx b/vcl/inc/iconview.hxx index 54c2681a9e79..438590b083ab 100644 --- a/vcl/inc/iconview.hxx +++ b/vcl/inc/iconview.hxx @@ -47,20 +47,22 @@ public: virtual FactoryFunction GetUITestFactory() const override; virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; + typedef std::tuple<OUString&, SvTreeListEntry*> encoded_image_query; - typedef std::tuple<tools::JsonWriter&, SvTreeListEntry*, std::string_view> json_prop_query; - - void SetDumpElemToPropertyTreeHdl(const Link<const json_prop_query&, bool>& rLink) + void SetDumpImageHdl(const Link<const encoded_image_query&, bool>& rLink) { - maDumpElemToPropertyTreeHdl = rLink; + maDumpImageHdl = rLink; } + /// returns string with encoded image for an entry + OUString renderEntry(int pos, int dpix, int dpiy) const; + protected: virtual void CalcEntryHeight(SvTreeListEntry const* pEntry) override; private: Link<SvTreeListEntry*, OUString> maEntryAccessibleDescriptionHdl; - Link<const json_prop_query&, bool> maDumpElemToPropertyTreeHdl; + Link<const encoded_image_query&, bool> maDumpImageHdl; void DumpEntryAndSiblings(tools::JsonWriter& rJsonWriter, SvTreeListEntry* pEntry); }; diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx index 71061c27cb3b..58f8d431d258 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -353,6 +353,12 @@ public: virtual void sendClosePopup(vcl::LOKWindowId nWindowId) = 0; }; +class SAL_LOPLUGIN_ANNOTATE("crosscast") OnDemandRenderingHandler +{ +public: + virtual void render_entry(int pos, int dpix, int dpiy) = 0; +}; + template <class BaseInstanceClass, class VclClass> class JSWidget : public BaseInstanceClass, public BaseJSWidget { @@ -616,7 +622,8 @@ public: virtual void set_active(int pos) override; }; -class JSComboBox final : public JSWidget<SalInstanceComboBoxWithEdit, ::ComboBox> +class JSComboBox final : public JSWidget<SalInstanceComboBoxWithEdit, ::ComboBox>, + public OnDemandRenderingHandler { public: JSComboBox(JSDialogSender* pSender, ::ComboBox* pComboBox, SalInstanceBuilder* pBuilder, @@ -630,7 +637,8 @@ public: virtual void set_active_id(const OUString& rText) override; virtual bool changed_by_direct_pick() const override; - void render_entry(int pos, int dpix, int dpiy); + // OnDemandRenderingHandler + virtual void render_entry(int pos, int dpix, int dpiy) override; }; class JSNotebook final : public JSWidget<SalInstanceNotebook, ::TabControl> @@ -804,7 +812,8 @@ public: virtual void set_expanded(bool bExpand) override; }; -class JSIconView final : public JSWidget<SalInstanceIconView, ::IconView> +class JSIconView final : public JSWidget<SalInstanceIconView, ::IconView>, + public OnDemandRenderingHandler { public: JSIconView(JSDialogSender* pSender, ::IconView* pIconView, SalInstanceBuilder* pBuilder, @@ -821,6 +830,9 @@ public: virtual void clear() override; virtual void select(int pos) override; virtual void unselect(int pos) override; + + // OnDemandRenderingHandler + virtual void render_entry(int pos, int dpix, int dpiy) override; }; class JSRadioButton final : public JSWidget<SalInstanceRadioButton, ::RadioButton> diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 59d9d2061807..079d9b78af5e 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -1917,10 +1917,12 @@ public: class SalInstanceIconView : public SalInstanceWidget, public virtual weld::IconView { +protected: + VclPtr<::IconView> m_xIconView; + private: // owner for UserData std::vector<std::unique_ptr<OUString>> m_aUserData; - VclPtr<::IconView> m_xIconView; DECL_LINK(SelectHdl, SvTreeListBox*, void); DECL_LINK(DeSelectHdl, SvTreeListBox*, void); @@ -1928,7 +1930,7 @@ private: DECL_LINK(CommandHdl, const CommandEvent&, bool); DECL_LINK(TooltipHdl, SvTreeListEntry*, OUString); DECL_LINK(EntryAccessibleDescriptionHdl, SvTreeListEntry*, OUString); - DECL_LINK(DumpElemToPropertyTreeHdl, const ::IconView::json_prop_query&, bool); + DECL_LINK(DumpImageHdl, const ::IconView::encoded_image_query&, bool); public: SalInstanceIconView(::IconView* pIconView, SalInstanceBuilder* pBuilder, bool bTakeOwnership); @@ -1951,7 +1953,7 @@ public: virtual void connect_query_tooltip(const Link<const weld::TreeIter&, OUString>& rLink) override; virtual void - connect_get_property_tree_elem(const Link<const weld::json_prop_query&, bool>& rLink) override; + connect_get_image(const Link<const weld::encoded_image_query&, bool>& rLink) override; virtual OUString get_selected_id() const override; diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx index 3eebd350ef88..891e7cedd378 100644 --- a/vcl/jsdialog/executor.cxx +++ b/vcl/jsdialog/executor.cxx @@ -76,11 +76,31 @@ bool ExecuteAction(const OUString& nWindowId, const OUString& rWidget, StringMap if (pWidget != nullptr) { + // shared actions + if (sAction == "grab_focus") { pWidget->grab_focus(); return true; } + else if (sAction == "render_entry") + { + auto pRenderer = dynamic_cast<OnDemandRenderingHandler*>(pWidget); + if (pRenderer) + { + // 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, ';'); + + pRenderer->render_entry(o3tl::toInt32(aPos), o3tl::toInt32(aDpiScaleX), + o3tl::toInt32(aDpiScaleY)); + } + return true; + } + + // depends on type if (sControlType == "tabcontrol") { @@ -129,22 +149,6 @@ bool ExecuteAction(const OUString& nWindowId, const OUString& rWidget, StringMap 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") diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx index 709f4461470e..c127f6c3b984 100644 --- a/vcl/jsdialog/jsdialogbuilder.cxx +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -11,6 +11,7 @@ #include <sal/log.hxx> #include <comphelper/base64.hxx> #include <comphelper/lok.hxx> +#include <iconview.hxx> #include <utility> #include <vcl/tabpage.hxx> #include <vcl/toolbox.hxx> @@ -1710,7 +1711,7 @@ void JSComboBox::render_entry(int pos, int dpix, int dpiy) ::comphelper::Base64::encode(aBuffer, aSeq); std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); - (*pMap)[ACTION_TYPE ""_ostr] = "rendered_combobox_entry"; + (*pMap)[ACTION_TYPE ""_ostr] = "rendered_entry"; (*pMap)["pos"_ostr] = OUString::number(pos); (*pMap)["image"_ostr] = aBuffer; sendAction(std::move(pMap)); @@ -2253,6 +2254,19 @@ void JSIconView::unselect(int pos) sendUpdate(); } +void JSIconView::render_entry(int pos, int dpix, int dpiy) +{ + OUString sImage = m_xIconView->renderEntry(pos, dpix, dpiy); + if (sImage.isEmpty()) + return; + + std::unique_ptr<jsdialog::ActionDataMap> pMap = std::make_unique<jsdialog::ActionDataMap>(); + (*pMap)[ACTION_TYPE ""_ostr] = "rendered_entry"; + (*pMap)["pos"_ostr] = OUString::number(pos); + (*pMap)["image"_ostr] = sImage; + sendAction(std::move(pMap)); +} + JSRadioButton::JSRadioButton(JSDialogSender* pSender, ::RadioButton* pRadioButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership) : JSWidget<SalInstanceRadioButton, ::RadioButton>(pSender, pRadioButton, pBuilder, diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 868163577bdd..35a02638422f 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -5534,20 +5534,18 @@ void SalInstanceIconView::connect_query_tooltip(const Link<const weld::TreeIter& m_xIconView->SetTooltipHdl(LINK(this, SalInstanceIconView, TooltipHdl)); } -IMPL_LINK(SalInstanceIconView, DumpElemToPropertyTreeHdl, const ::IconView::json_prop_query&, - rQuery, bool) +IMPL_LINK(SalInstanceIconView, DumpImageHdl, const ::IconView::encoded_image_query&, rQuery, bool) { SvTreeListEntry* pEntry = std::get<1>(rQuery); - return m_aGetPropertyTreeElemHdl.Call(weld::json_prop_query( - std::get<0>(rQuery), SalInstanceTreeIter(pEntry), std::get<2>(rQuery))); + return m_aGetPropertyTreeElemHdl.Call( + weld::encoded_image_query(std::get<0>(rQuery), SalInstanceTreeIter(pEntry))); } -void SalInstanceIconView::connect_get_property_tree_elem( - const Link<const weld::json_prop_query&, bool>& rLink) +void SalInstanceIconView::connect_get_image( + const Link<const weld::encoded_image_query&, bool>& rLink) { - weld::IconView::connect_get_property_tree_elem(rLink); - m_xIconView->SetDumpElemToPropertyTreeHdl( - LINK(this, SalInstanceIconView, DumpElemToPropertyTreeHdl)); + weld::IconView::connect_get_image(rLink); + m_xIconView->SetDumpImageHdl(LINK(this, SalInstanceIconView, DumpImageHdl)); } OUString SalInstanceIconView::get_selected_id() const diff --git a/vcl/source/treelist/iconview.cxx b/vcl/source/treelist/iconview.cxx index e80a29b0bc0b..57bf2aea4bda 100644 --- a/vcl/source/treelist/iconview.cxx +++ b/vcl/source/treelist/iconview.cxx @@ -278,6 +278,30 @@ static OString extractPngString(const SvLBoxContextBmp* pBmpItem) return ""_ostr; } +OUString IconView::renderEntry(int pos, int /*dpix*/, int /*dpiy*/) const +{ + // TODO: support various DPI + SvTreeListEntry* pEntry = GetEntry(pos); + if (!pEntry) + return ""; + + OUString sResult; + const bool bHandled + = maDumpImageHdl.IsSet() && maDumpImageHdl.Call(encoded_image_query(sResult, pEntry)); + + if (!bHandled) + { + if (const SvLBoxItem* pIt = pEntry->GetFirstItem(SvLBoxItemType::ContextBmp)) + { + const SvLBoxContextBmp* pBmpItem = static_cast<const SvLBoxContextBmp*>(pIt); + if (pBmpItem) + return OStringToOUString(extractPngString(pBmpItem), RTL_TEXTENCODING_ASCII_US); + } + } + + return sResult; +} + void IconView::DumpEntryAndSiblings(tools::JsonWriter& rJsonWriter, SvTreeListEntry* pEntry) { while (pEntry) @@ -289,18 +313,12 @@ void IconView::DumpEntryAndSiblings(tools::JsonWriter& rJsonWriter, SvTreeListEn if (pIt) rJsonWriter.put("text", static_cast<const SvLBoxString*>(pIt)->GetText()); - const bool bHandled - = maDumpElemToPropertyTreeHdl.IsSet() - && maDumpElemToPropertyTreeHdl.Call(json_prop_query(rJsonWriter, pEntry, "image")); - if (!bHandled) + pIt = pEntry->GetFirstItem(SvLBoxItemType::ContextBmp); + if (pIt) { - pIt = pEntry->GetFirstItem(SvLBoxItemType::ContextBmp); - if (pIt) - { - const SvLBoxContextBmp* pBmpItem = static_cast<const SvLBoxContextBmp*>(pIt); - if (pBmpItem) - rJsonWriter.put("image", extractPngString(pBmpItem)); - } + const SvLBoxContextBmp* pBmpItem = static_cast<const SvLBoxContextBmp*>(pIt); + if (pBmpItem) + rJsonWriter.put("ondemand", true); } if (const OUString tooltip = GetEntryTooltip(pEntry); !tooltip.isEmpty()) diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index 6a06947d4cd2..3b9ce8bc0de9 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -17158,7 +17158,7 @@ public: gtk_widget_set_has_tooltip(GTK_WIDGET(m_pIconView), true); } - virtual void connect_get_property_tree_elem(const Link<const weld::json_prop_query&, bool>& /*rLink*/) override + virtual void connect_get_image(const Link<const weld::encoded_image_query&, bool>& /*rLink*/) override { //not implemented for the gtk variant } |