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 fcb0fbffc55ec78de10e74f7a6ab213c64c7a6cd
Author:     Szymon Kłos <[email protected]>
AuthorDate: Wed Jan 22 18:39:49 2025 +0100
Commit:     Szymon Kłos <[email protected]>
CommitDate: Fri Nov 14 07:18:24 2025 +0100

    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]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193948
    Reviewed-by: Szymon Kłos <[email protected]>
    Tested-by: Jenkins

diff --git a/include/vcl/toolkit/svlbitm.hxx b/include/vcl/toolkit/svlbitm.hxx
index 6e2bc7788f73..472a4bf38c16 100644
--- a/include/vcl/toolkit/svlbitm.hxx
+++ b/include/vcl/toolkit/svlbitm.hxx
@@ -125,6 +125,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 d6ee35bbcd6f..22a995a35178 100644
--- a/include/vcl/toolkit/treelistbox.hxx
+++ b/include/vcl/toolkit/treelistbox.hxx
@@ -190,6 +190,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 9a71c271fee2..9d7064b0c94b 100644
--- a/sfx2/source/dialog/StyleList.cxx
+++ b/sfx2/source/dialog/StyleList.cxx
@@ -1785,7 +1785,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);
 
     auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::TEXTCOLOR);
@@ -1981,7 +1981,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 8618a8c9a828..a0bdb99e46cf 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>
@@ -254,6 +258,29 @@ class SAL_LOPLUGIN_ANNOTATE("crosscast") 
OnDemandRenderingHandler
 {
 public:
     virtual void render_entry(int pos, int dpix, int dpiy) = 0;
+
+    static bool imageToActionData(const Bitmap& 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>
@@ -679,7 +706,8 @@ public:
     virtual void do_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,
@@ -725,6 +753,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 fc919817be8e..d4b85759028c 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)
 
     Bitmap aImage = pDevice->GetBitmap(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,
@@ -1869,6 +1855,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);
+
+    Bitmap aImage = pDevice->GetBitmap(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 6ad788c16eda..f38648a8eef9 100644
--- a/vcl/source/treelist/svtabbx.cxx
+++ b/vcl/source/treelist/svtabbx.cxx
@@ -101,9 +101,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