summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorSzymon Kłos <szymon.klos@collabora.com>2024-06-27 11:11:13 +0200
committerTomaž Vajngerl <quikee@gmail.com>2024-06-28 09:57:26 +0200
commit12ff4396d973e7aae4dd68b742d9790f8c88ea53 (patch)
treea2550ce4e0de0ab136bcca4f942760e3483cfb1a /vcl
parent5779dc944c5427d84c23a3a9c466a0caafb46689 (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.hxx12
-rw-r--r--vcl/inc/jsdialog/jsdialogbuilder.hxx18
-rw-r--r--vcl/inc/salvtables.hxx8
-rw-r--r--vcl/jsdialog/executor.cxx36
-rw-r--r--vcl/jsdialog/jsdialogbuilder.cxx16
-rw-r--r--vcl/source/app/salvtables.cxx16
-rw-r--r--vcl/source/treelist/iconview.cxx40
-rw-r--r--vcl/unx/gtk3/gtkinst.cxx2
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
}