include/vcl/toolkit/svlbitm.hxx      |    1 
 include/vcl/toolkit/treelistbox.hxx  |    1 
 sfx2/source/dialog/StyleList.cxx     |    5 ++--
 vcl/inc/jsdialog/jsdialogbuilder.hxx |   33 ++++++++++++++++++++++++++++-
 vcl/jsdialog/jsdialogbuilder.cxx     |   39 +++++++++++++++++++----------------
 vcl/source/treelist/svtabbx.cxx      |    6 +++--
 6 files changed, 63 insertions(+), 22 deletions(-)

New commits:
commit 990c4f2ac632305a09c09be0c4c89f91e3785d3b
Author:     Szymon Kłos <[email protected]>
AuthorDate: Wed Jan 22 18:39:49 2025 +0100
Commit:     Caolán McNamara <[email protected]>
CommitDate: Thu Jul 3 09:41:54 2025 +0200

    jsdialog: handle custom rendering in treeview
    
    Client can demand rendering of custom entries for treeview.
    Used in style list sidebar to render font previews.
    Let's use more width for LOK to fit all text into image.
    Core seems to ignore it and render based on size of passed
    device.
    
    Change-Id: If21b33a7e5ce36a5304b6aa2b8218f3b3460ea26
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186789
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/include/vcl/toolkit/svlbitm.hxx b/include/vcl/toolkit/svlbitm.hxx
index b4001287d012..0a7968a27fd8 100644
--- a/include/vcl/toolkit/svlbitm.hxx
+++ b/include/vcl/toolkit/svlbitm.hxx
@@ -129,6 +129,7 @@ public:
     bool IsEmphasized() const { return mbEmphasized; }
 
     void SetCustomRender() { mbCustom = true; }
+    bool IsCustomRender() const { return mbCustom; }
 
     const OUString& GetText() const
     {
diff --git a/include/vcl/toolkit/treelistbox.hxx 
b/include/vcl/toolkit/treelistbox.hxx
index 78db5bcc2231..47850505cc52 100644
--- a/include/vcl/toolkit/treelistbox.hxx
+++ b/include/vcl/toolkit/treelistbox.hxx
@@ -188,6 +188,7 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox
     friend class SalInstanceIconView;
     friend class SalInstanceTreeView;
     friend class SalInstanceEntryTreeView;
+    friend class JSTreeView;
 
     std::unique_ptr<SvTreeListBoxImpl> mpImpl;
     Link<SvTreeListBox*,void>  aScrolledHdl;
diff --git a/sfx2/source/dialog/StyleList.cxx b/sfx2/source/dialog/StyleList.cxx
index c62b125ceb37..2363ca06749d 100644
--- a/sfx2/source/dialog/StyleList.cxx
+++ b/sfx2/source/dialog/StyleList.cxx
@@ -1781,7 +1781,7 @@ IMPL_LINK(StyleList, CustomRenderHdl, 
weld::TreeView::render_args, aPayload, voi
     ::tools::Rectangle aRect(
         rRect.TopLeft(),
         Size(rRenderContext.GetOutputSize().Width() - rRect.Left(), 
rRect.GetHeight()));
-    bool bSelected = std::get<2>(aPayload);
+    bool bSelected = comphelper::LibreOfficeKit::isActive() ? false : 
std::get<2>(aPayload);
     const OUString& rId = std::get<3>(aPayload);
 
     rRenderContext.Push(vcl::PushFlags::TEXTCOLOR);
@@ -1980,7 +1980,8 @@ const SfxStyleFamilyItem& 
StyleList::GetFamilyItemByIndex(size_t i) const
 IMPL_STATIC_LINK(StyleList, CustomGetSizeHdl, weld::TreeView::get_size_args, 
aPayload, Size)
 {
     vcl::RenderContext& rRenderContext = aPayload.first;
-    return Size(42, 32 * rRenderContext.GetDPIScaleFactor());
+    return Size(comphelper::LibreOfficeKit::isActive() ? 200 : 42,
+                32 * rRenderContext.GetDPIScaleFactor());
 }
 
 IMPL_LINK(StyleList, PopupFlatMenuHdl, const CommandEvent&, rCEvt, bool)
diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx 
b/vcl/inc/jsdialog/jsdialogbuilder.hxx
index 4fbed1fbde23..29bd359bbf38 100644
--- a/vcl/inc/jsdialog/jsdialogbuilder.hxx
+++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx
@@ -13,7 +13,9 @@
 #include <jsdialog/jsdialogmessages.hxx>
 #include <jsdialog/jsdialogsender.hxx>
 
+#include <tools/stream.hxx>
 #include <utility>
+#include <vcl/cvtgrf.hxx>
 #include <vcl/weld.hxx>
 #include <vcl/virdev.hxx>
 #include <salvtables.hxx>
@@ -24,6 +26,8 @@
 #include <com/sun/star/lang/XInitialization.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+
+#include <comphelper/base64.hxx>
 #include <comphelper/compbase.hxx>
 
 #include <list>
@@ -256,6 +260,29 @@ class SAL_LOPLUGIN_ANNOTATE("crosscast") 
OnDemandRenderingHandler
 {
 public:
     virtual void render_entry(int pos, int dpix, int dpiy) = 0;
+
+    static bool imageToActionData(const BitmapEx& rImage, sal_Int32 nPos,
+                                  jsdialog::ActionDataMap& rMap)
+    {
+        if (rImage.IsEmpty())
+            return false;
+
+        SvMemoryStream aOStm(65535, 65535);
+
+        if (GraphicConverter::Export(aOStm, rImage, ConvertDataFormat::PNG) != 
ERRCODE_NONE)
+            return false;
+
+        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);
+
+        rMap[ACTION_TYPE ""_ostr] = "rendered_entry";
+        rMap["pos"_ostr] = OUString::number(nPos);
+        rMap["image"_ostr] = aBuffer;
+
+        return true;
+    }
 };
 
 template <class BaseInstanceClass, class VclClass>
@@ -675,7 +702,8 @@ public:
     virtual void replace_selection(const OUString& rText) override;
 };
 
-class JSTreeView final : public JSWidget<SalInstanceTreeView, ::SvTabListBox>
+class JSTreeView final : public JSWidget<SalInstanceTreeView, ::SvTabListBox>,
+                         public OnDemandRenderingHandler
 {
 public:
     JSTreeView(JSDialogSender* pSender, ::SvTabListBox* pTextView, 
SalInstanceBuilder* pBuilder,
@@ -721,6 +749,9 @@ public:
 
     void drag_start();
     void drag_end();
+
+    // OnDemandRenderingHandler
+    virtual void render_entry(int pos, int dpix, int dpiy) override;
 };
 
 class JSExpander final : public JSWidget<SalInstanceExpander, ::VclExpander>
diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx
index 3e2981446836..580d96a70826 100644
--- a/vcl/jsdialog/jsdialogbuilder.cxx
+++ b/vcl/jsdialog/jsdialogbuilder.cxx
@@ -9,9 +9,7 @@
 
 #include <jsdialog/jsdialogbuilder.hxx>
 #include <sal/log.hxx>
-#include <comphelper/base64.hxx>
 #include <iconview.hxx>
-#include <utility>
 #include <vcl/menu.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/toolbox.hxx>
@@ -26,8 +24,7 @@
 #include <memory>
 #include <vcl/jsdialog/executor.hxx>
 #include <cppuhelper/supportsservice.hxx>
-#include <tools/stream.hxx>
-#include <vcl/cvtgrf.hxx>
+
 #include <wizdlg.hxx>
 #include <jsdialog/enabled.hxx>
 
@@ -1331,20 +1328,9 @@ void JSComboBox::render_entry(int pos, int dpix, int 
dpiy)
 
     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_entry";
-        (*pMap)["pos"_ostr] = OUString::number(pos);
-        (*pMap)["image"_ostr] = aBuffer;
+    std::unique_ptr<jsdialog::ActionDataMap> pMap = 
std::make_unique<jsdialog::ActionDataMap>();
+    if (OnDemandRenderingHandler::imageToActionData(aImage, pos, *pMap))
         sendAction(std::move(pMap));
-    }
 }
 
 JSNotebook::JSNotebook(JSDialogSender* pSender, ::TabControl* pControl,
@@ -1863,6 +1849,25 @@ void JSTreeView::collapse_row(const weld::TreeIter& 
rIter)
         sendUpdate();
 }
 
+void JSTreeView::render_entry(int pos, int dpix, int dpiy)
+{
+    ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::WITHOUT_ALPHA);
+    pDevice->SetDPIX(96.0 * dpix / 100);
+    pDevice->SetDPIY(96.0 * dpiy / 100);
+
+    SvTreeListEntry* rEntry = m_xTreeView->GetEntryAtAbsPos(pos);
+
+    Size aRenderSize = signal_custom_get_size(*pDevice, get_id(pos));
+    pDevice->SetOutputSize(aRenderSize);
+    m_xTreeView->DrawCustomEntry(*pDevice, tools::Rectangle(Point(0, 0), 
aRenderSize), *rEntry);
+
+    BitmapEx aImage = pDevice->GetBitmapEx(Point(0, 0), aRenderSize);
+
+    std::unique_ptr<jsdialog::ActionDataMap> pMap = 
std::make_unique<jsdialog::ActionDataMap>();
+    if (OnDemandRenderingHandler::imageToActionData(aImage, pos, *pMap))
+        sendAction(std::move(pMap));
+}
+
 JSExpander::JSExpander(JSDialogSender* pSender, ::VclExpander* pExpander,
                        SalInstanceBuilder* pBuilder, bool bTakeOwnership)
     : JSWidget<SalInstanceExpander, ::VclExpander>(pSender, pExpander, 
pBuilder, bTakeOwnership)
diff --git a/vcl/source/treelist/svtabbx.cxx b/vcl/source/treelist/svtabbx.cxx
index 97db9d8749b1..14dc8387d8ff 100644
--- a/vcl/source/treelist/svtabbx.cxx
+++ b/vcl/source/treelist/svtabbx.cxx
@@ -100,9 +100,11 @@ static void lcl_DumpEntryAndSiblings(tools::JsonWriter& 
rJsonWriter,
                         rJsonWriter.put("text", pStringItem->GetText());
 
                         SvLBoxTab* pTab = pTabListBox->GetTab( pEntry, &rItem 
);
-                        if ( pTab ) {
+                        if ( pTab )
                             rJsonWriter.put("editable", pTab->IsEditable());
-                        }
+
+                        if (pStringItem->IsCustomRender())
+                            rJsonWriter.put("customEntryRenderer", true);
                     }
                 }
                 else if (rItem.GetType() == SvLBoxItemType::ContextBmp)

Reply via email to