include/svx/itemwin.hxx              |    8 +-
 svx/source/tbxctrls/linectrl.cxx     |  122 ++++++++++++++++++++++++-----------
 svx/uiconfig/ui/floatinglinestyle.ui |   38 ++++++----
 3 files changed, 114 insertions(+), 54 deletions(-)

New commits:
commit 4583f8e239a33f2eeb587111a4b69d892e339849
Author:     Parth Raiyani <[email protected]>
AuthorDate: Wed Aug 20 17:35:04 2025 +0530
Commit:     Caolán McNamara <[email protected]>
CommitDate: Wed Feb 25 09:18:57 2026 +0100

    Replaces ValueSet with IconView for line style selection
    
    - Updates the UI layout to use GtkIconView with better configuration 
options.
    - Simplifies logic for filling and updating the selection view.
    - Adds support for tooltips and single-click activation.
    - Removes obsolete code related to ValueSet, including custom sizing logic.
    
    Change-Id: Ie8ba152b12440593d86bbdde156c4132445c8d72
    Signed-off-by: Parth Raiyani <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189881
    Reviewed-by: Szymon Kłos <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200223
    Reviewed-by: Caolán McNamara <[email protected]>
    Tested-by: Caolán McNamara <[email protected]>

diff --git a/include/svx/itemwin.hxx b/include/svx/itemwin.hxx
index 3c72ca4c9060..bcaa4005af51 100644
--- a/include/svx/itemwin.hxx
+++ b/include/svx/itemwin.hxx
@@ -24,19 +24,19 @@
 #include <svx/xtable.hxx>
 #include <vcl/customweld.hxx>
 
-class ValueSet;
+class SfxObjectShell;
 class SvxLineStyleToolBoxControl;
 
 class SvxLineBox final : public WeldToolbarPopup
 {
     rtl::Reference<SvxLineStyleToolBoxControl> mxControl;
-    std::unique_ptr<ValueSet> mxLineStyleSet;
-    std::unique_ptr<weld::CustomWeld> mxLineStyleSetWin;
+    std::unique_ptr<weld::IconView> mxLineStyleIV;
 
     void FillControl();
     void Fill(const XDashListRef& pList);
 
-    DECL_LINK(SelectHdl, ValueSet*, void);
+    DECL_LINK(ItemActivatedHdl, weld::IconView&, bool);
+    DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
 
     virtual void GrabFocus() override;
 
diff --git a/svx/source/tbxctrls/linectrl.cxx b/svx/source/tbxctrls/linectrl.cxx
index b2941241529f..7e6dc264abac 100644
--- a/svx/source/tbxctrls/linectrl.cxx
+++ b/svx/source/tbxctrls/linectrl.cxx
@@ -26,7 +26,6 @@
 
 #include <svtools/toolbarmenu.hxx>
 #include <svtools/popupwindowcontroller.hxx>
-#include <svtools/valueset.hxx>
 
 #include <svx/strings.hrc>
 #include <svx/svxids.hrc>
@@ -56,7 +55,6 @@ using namespace ::com::sun::star::frame;
 using namespace ::com::sun::star;
 
 // For End Line Controller
-#define MAX_LINES 12
 
 SvxLineStyleToolBoxControl::SvxLineStyleToolBoxControl( const 
css::uno::Reference<css::uno::XComponentContext>& rContext )
     : svt::PopupWindowController( rContext, nullptr, OUString() )
@@ -552,21 +550,27 @@ 
com_sun_star_comp_svx_LineEndToolBoxControl_get_implementation(
 SvxLineBox::SvxLineBox(SvxLineStyleToolBoxControl* pControl, weld::Widget* 
pParent, int nInitialIndex)
     : WeldToolbarPopup(pControl->getFrameInterface(), pParent, 
u"svx/ui/floatinglinestyle.ui"_ustr, u"FloatingLineStyle"_ustr)
     , mxControl(pControl)
-    , mxLineStyleSet(new 
ValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true)))
-    , mxLineStyleSetWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, 
*mxLineStyleSet))
+    , 
mxLineStyleIV(m_xBuilder->weld_icon_view(u"floating_line_style_iconview"_ustr))
 {
-    mxLineStyleSet->SetStyle(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | 
WB_NO_DIRECTSELECT);
-
     FillControl();
 
-    mxLineStyleSet->SelectItem(nInitialIndex + 1);
+    if (nInitialIndex >= 0)
+        mxLineStyleIV->select(nInitialIndex);
+
+    mxLineStyleIV->connect_item_activated( LINK( this, SvxLineBox, 
ItemActivatedHdl ) );
 
-    mxLineStyleSet->SetSelectHdl( LINK( this, SvxLineBox, SelectHdl ) );
+    // Avoid LibreOffice Kit crash: tooltip handlers cause segfault during 
JSDialog
+    // serialization when popup widgets are destroyed/recreated during 
character formatting resets.
+    // Tooltip event binding is not needed for LibreOffice Kit
+    if (!comphelper::LibreOfficeKit::isActive())
+    {
+        mxLineStyleIV->connect_query_tooltip(LINK(this, SvxLineBox, 
QueryTooltipHdl));
+    }
 }
 
 void SvxLineBox::GrabFocus()
 {
-    mxLineStyleSet->GrabFocus();
+    mxLineStyleIV->grab_focus();
 }
 
 SvxLineBox::~SvxLineBox()
@@ -577,18 +581,26 @@ SvxLineBox::~SvxLineBox()
 
 void SvxLineBox::Fill( const XDashListRef &pList )
 {
-    mxLineStyleSet->Clear();
+    mxLineStyleIV->clear();
 
     if( !pList.is() )
         return;
 
     // entry for 'none'
-    mxLineStyleSet->InsertItem(1, Image(), pList->GetStringForUiNoLine());
+    ScopedVclPtrInstance< VirtualDevice > pVDEmpty;
+    
pVDEmpty->SetOutputSizePixel(pList->GetBitmapForUISolidLine().GetSizePixel(), 
false);
+    pVDEmpty->Erase(); // Uses default white background
+    Bitmap aBmpEmpty = pVDEmpty->GetBitmap(Point(), 
pVDEmpty->GetOutputSizePixel());
+    mxLineStyleIV->append(u"1"_ustr, pList->GetStringForUiNoLine(), 
&aBmpEmpty);
 
     // entry for solid line
-    const auto& rBmp = pList->GetBitmapForUISolidLine();
+    ScopedVclPtrInstance< VirtualDevice > pVDSolid;
+    const Bitmap& rBmp = pList->GetBitmapForUISolidLine();
     Size aBmpSize = rBmp.GetSizePixel();
-    mxLineStyleSet->InsertItem(2, Image(rBmp), 
pList->GetStringForUiSolidLine());
+    pVDSolid->SetOutputSizePixel(aBmpSize, false);
+    pVDSolid->DrawBitmap(Point(), rBmp);
+    Bitmap aBmpSolid = pVDSolid->GetBitmap(Point(), aBmpSize);
+    mxLineStyleIV->append(u"2"_ustr, pList->GetStringForUiSolidLine(), 
&aBmpSolid);
 
     // entries for dashed lines
     tools::Long nCount = pList->Count();
@@ -597,34 +609,25 @@ void SvxLineBox::Fill( const XDashListRef &pList )
         const XDashEntry* pEntry = pList->GetDash(i);
         const Bitmap aBitmap = pList->GetUiBitmap(i);
 
-        mxLineStyleSet->InsertItem(i + 3, Image(aBitmap), pEntry->GetName());
-    }
-
-    sal_uInt16 nLines = std::min( static_cast<sal_uInt16>(nCount + 2), 
sal_uInt16(MAX_LINES) );
-    mxLineStyleSet->SetLineCount(nLines);
-
-    WinBits nBits = mxLineStyleSet->GetStyle();
-    if ( nLines == mxLineStyleSet->GetItemCount() )
-        nBits &= ~WB_VSCROLL;
-    else
-        nBits |= WB_VSCROLL;
-    mxLineStyleSet->SetStyle( nBits );
+        ScopedVclPtrInstance< VirtualDevice > pVDDash;
+        Size aDashSize = aBitmap.GetSizePixel();
+        pVDDash->SetOutputSizePixel(aDashSize, false);
+        pVDDash->DrawBitmap(Point(), aBitmap);
 
-    Size aSize(aBmpSize);
-    aSize.AdjustWidth(6);
-    aSize.AdjustHeight(6);
-    aSize = mxLineStyleSet->CalcWindowSizePixel(aSize);
-    if (nBits & WB_VSCROLL)
-        aSize.AdjustWidth(mxLineStyleSet->GetScrollWidth());
-    mxLineStyleSet->GetDrawingArea()->set_size_request(aSize.Width(), 
aSize.Height());
-    mxLineStyleSet->SetOutputSizePixel(aSize);
+        Bitmap aBmpDash = pVDDash->GetBitmap(Point(), aDashSize);
+        mxLineStyleIV->append(OUString::number(i + 3), pEntry->GetName(), 
&aBmpDash);
+    }
 }
 
-IMPL_LINK_NOARG(SvxLineBox, SelectHdl, ValueSet*, void)
+IMPL_LINK_NOARG(SvxLineBox, ItemActivatedHdl, weld::IconView&, bool)
 {
+    OUString sId = mxLineStyleIV->get_selected_id();
+    if (sId.isEmpty())
+        return false;
+
     drawing::LineStyle eXLS;
-    sal_Int32 nPos = mxLineStyleSet->GetSelectedItemId();
-    --nPos; // ids start at 1, get the pos of the id
+    sal_Int32 nPos = sId.toUInt32();
+    --nPos; // Convert from 1-based ID to 0-based position
 
     switch ( nPos )
     {
@@ -674,6 +677,53 @@ IMPL_LINK_NOARG(SvxLineBox, SelectHdl, ValueSet*, void)
     mxControl->dispatchLineStyleCommand(u".uno:XLineStyle"_ustr, aArgs);
 
     mxControl->EndPopupMode();
+
+    return true;
+}
+
+IMPL_LINK(SvxLineBox, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString)
+{
+    OUString sId = mxLineStyleIV->get_id(rIter);
+    if (sId.isEmpty())
+        return OUString();
+
+    sal_Int32 nPos = sId.toUInt32();
+    --nPos; // Convert from 1-based ID to 0-based position
+
+    SfxObjectShell* pSh = SfxObjectShell::Current();
+    if (!pSh)
+        return OUString();
+
+    const SvxDashListItem* pItem = pSh->GetItem(SID_DASH_LIST);
+    if (!pItem)
+        return OUString();
+
+    XDashListRef pList = pItem->GetDashList();
+    if (!pList.is())
+        return OUString();
+
+    switch (nPos)
+    {
+        case 0:
+            return pList->GetStringForUiNoLine();
+        case 1:
+            return pList->GetStringForUiSolidLine();
+        default:
+        {
+            tools::Long nDashIndex = nPos - 2;
+            if (nDashIndex >= 0 && nDashIndex < pList->Count())
+            {
+                const XDashEntry* pEntry = pList->GetDash(nDashIndex);
+                if (pEntry)
+                {
+                    return pEntry->GetName();
+                }
+            }
+            break;
+        }
+    }
+
+    return OUString();
 }
 
 void SvxLineBox::FillControl()
diff --git a/svx/uiconfig/ui/floatinglinestyle.ui 
b/svx/uiconfig/ui/floatinglinestyle.ui
index 7fdd3eae4a42..a512d440097e 100644
--- a/svx/uiconfig/ui/floatinglinestyle.ui
+++ b/svx/uiconfig/ui/floatinglinestyle.ui
@@ -2,6 +2,14 @@
 <!-- Generated with glade 3.22.1 -->
 <interface domain="svx">
   <requires lib="gtk+" version="3.24"/>
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name pixbuf -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
   <object class="GtkPopover" id="FloatingLineStyle">
     <property name="can_focus">False</property>
     <property name="no_show_all">True</property>
@@ -14,27 +22,29 @@
         <property name="orientation">vertical</property>
         <property name="spacing">6</property>
         <child>
-          <object class="GtkScrolledWindow" id="valuesetwin">
+          <object class="GtkScrolledWindow">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="hexpand">True</property>
             <property name="vexpand">True</property>
-            <property name="hscrollbar_policy">never</property>
-            <property name="vscrollbar_policy">never</property>
+            <property name="hscrollbar-policy">never</property>
+            <property name="vscrollbar-policy">always</property>
             <property name="shadow_type">in</property>
+            <property name="height-request">264</property>
             <child>
-              <object class="GtkViewport">
+              <object class="GtkIconView" id="floating_line_style_iconview">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkDrawingArea" id="valueset">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="events">GDK_BUTTON_PRESS_MASK | 
GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | 
GDK_STRUCTURE_MASK</property>
-                    <property name="hexpand">True</property>
-                    <property name="vexpand">True</property>
-                  </object>
-                </child>
+                <property name="can-focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="model">liststore1</property>
+                <property name="pixbuf-column">0</property>
+                <property name="selection-mode">single</property>
+                <property name="activate-on-single-click">True</property>
+                <property name="item-padding">2</property>
+                <property name="row-spacing">2</property>
+                <property name="column-spacing">2</property>
+                <property name="margin">2</property>
               </object>
             </child>
           </object>

Reply via email to