sw/inc/strings.hrc                   |   10 +-
 sw/source/ui/frmdlg/column.cxx       |  140 ++++++++++++++++++++---------------
 sw/source/uibase/inc/column.hxx      |   29 ++-----
 sw/uiconfig/swriter/ui/columnpage.ui |   41 ++++++++--
 4 files changed, 131 insertions(+), 89 deletions(-)

New commits:
commit 36c925f517c82789004ba2a4f3462af6dc4973e9
Author:     Parth Raiyani <parth.raiy...@collabora.com>
AuthorDate: Thu Aug 7 11:28:08 2025 +0530
Commit:     Szymon Kłos <szymon.k...@collabora.com>
CommitDate: Sun Aug 10 20:59:00 2025 +0200

    Switch to IconView from ValueSet for column layout for improved UI handling
    
    - Updated column page UI from ValueSet to IconView
    - Added tooltip support
    - Removed unused ValueSet related logic
    - Replaced ValueSet based column names with IconView based names
    
    Change-Id: I9dbd46162f8373ded78bb3dd207fb94cd9567a3a
    Signed-off-by: Parth Raiyani <parth.raiy...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188954
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Szymon Kłos <szymon.k...@collabora.com>

diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 950b67c3bd01..ba582a6e9d54 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -229,11 +229,11 @@
 #define STR_POOLNUMRULE_BUL4                    NC_("STR_POOLNUMRULE_BUL4", 
"Bullet ➢")
 //Bullet \u2717
 #define STR_POOLNUMRULE_BUL5                    NC_("STR_POOLNUMRULE_BUL5", 
"Bullet ✗")
-#define STR_COLUMN_VALUESET_ITEM0               
NC_("STR_COLUMN_VALUESET_ITEM0", "1 column")
-#define STR_COLUMN_VALUESET_ITEM1               
NC_("STR_COLUMN_VALUESET_ITEM1", "2 columns with equal size")
-#define STR_COLUMN_VALUESET_ITEM2               
NC_("STR_COLUMN_VALUESET_ITEM2", "3 columns with equal size")
-#define STR_COLUMN_VALUESET_ITEM3               
NC_("STR_COLUMN_VALUESET_ITEM3", "2 columns with different size (left > right)")
-#define STR_COLUMN_VALUESET_ITEM4               
NC_("STR_COLUMN_VALUESET_ITEM4", "2 columns with different size (left < right)")
+#define STR_COLUMN_ICONVIEW_ITEM0               
NC_("STR_COLUMN_ICONVIEW_ITEM0", "1 column")
+#define STR_COLUMN_ICONVIEW_ITEM1               
NC_("STR_COLUMN_ICONVIEW_ITEM1", "2 columns with equal size")
+#define STR_COLUMN_ICONVIEW_ITEM2               
NC_("STR_COLUMN_ICONVIEW_ITEM2", "3 columns with equal size")
+#define STR_COLUMN_ICONVIEW_ITEM3               
NC_("STR_COLUMN_ICONVIEW_ITEM3", "2 columns with different size (left > right)")
+#define STR_COLUMN_ICONVIEW_ITEM4               
NC_("STR_COLUMN_ICONVIEW_ITEM4", "2 columns with different size (left < right)")
 // Table styles, Writer internal, others are taken from Svx
 #define STR_TABSTYLE_DEFAULT                    NC_("STR_TABSTYLE_DEFAULT", 
"Default Table Style")
 
diff --git a/sw/source/ui/frmdlg/column.cxx b/sw/source/ui/frmdlg/column.cxx
index 8352bd72ff66..0efb70b0e4a8 100644
--- a/sw/source/ui/frmdlg/column.cxx
+++ b/sw/source/ui/frmdlg/column.cxx
@@ -402,7 +402,7 @@ SwColumnPage::SwColumnPage(weld::Container* pPage, 
weld::DialogController* pCont
     , m_xEd3(new 
SwPercentField(m_xBuilder->weld_metric_spin_button(u"width3mf"_ustr, 
FieldUnit::CM)))
     , m_xDistEd1(new 
SwPercentField(m_xBuilder->weld_metric_spin_button(u"spacing1mf"_ustr, 
FieldUnit::CM)))
     , m_xDistEd2(new 
SwPercentField(m_xBuilder->weld_metric_spin_button(u"spacing2mf"_ustr, 
FieldUnit::CM)))
-    , m_xDefaultVS(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, 
m_aDefaultVS))
+    , m_xDefaultIV(m_xBuilder->weld_icon_view(u"column-iconview"_ustr))
     , m_xPgeExampleWN(new weld::CustomWeld(*m_xBuilder, u"pageexample"_ustr, 
m_aPgeExampleWN))
     , m_xFrameExampleWN(new weld::CustomWeld(*m_xBuilder, 
u"frameexample"_ustr, m_aFrameExampleWN))
     , m_xApplyToFT(m_xBuilder->weld_label(u"applytoft"_ustr))
@@ -420,34 +420,11 @@ SwColumnPage::SwColumnPage(weld::Container* pPage, 
weld::DialogController* pCont
 
     SetExchangeSupport();
 
-    m_aDefaultVS.SetColCount(5);
+    // Initialize column layout items
+    InitColumnLayouts();
 
-    for (int i = 0; i < 5; ++i)
-    //Set accessible name one by one
-    {
-        OUString aItemText;
-        switch( i )
-        {
-            case 0:
-                aItemText =  SwResId( STR_COLUMN_VALUESET_ITEM0 ) ;
-                break;
-            case 1:
-                aItemText =  SwResId( STR_COLUMN_VALUESET_ITEM1 ) ;
-                break;
-            case 2:
-                aItemText =  SwResId( STR_COLUMN_VALUESET_ITEM2 ) ;
-                break;
-            case 3:
-                aItemText =  SwResId( STR_COLUMN_VALUESET_ITEM3 );
-                break;
-            default:
-                aItemText =  SwResId( STR_COLUMN_VALUESET_ITEM4 );
-                break;
-        }
-        m_aDefaultVS.InsertItem( i + 1, aItemText, i );
-    }
-
-    m_aDefaultVS.SetSelectHdl(LINK(this, SwColumnPage, SetDefaultsHdl));
+    m_xDefaultIV->connect_item_activated(LINK(this, SwColumnPage, 
SetDefaultsHdl));
+    m_xDefaultIV->connect_query_tooltip(LINK(this, SwColumnPage, 
QueryTooltipHdl));
 
     Link<weld::SpinButton&,void> aCLNrLk = LINK(this, SwColumnPage, ColModify);
     m_xCLNrEdt->connect_value_changed(aCLNrLk);
@@ -499,7 +476,7 @@ SwColumnPage::~SwColumnPage()
 {
     m_xFrameExampleWN.reset();
     m_xPgeExampleWN.reset();
-    m_xDefaultVS.reset();
+    m_xDefaultIV.reset();
     m_xDistEd2.reset();
     m_xDistEd1.reset();
     m_xEd3.reset();
@@ -510,6 +487,52 @@ SwColumnPage::~SwColumnPage()
     m_xTextDirectionLB.reset();
 }
 
+void SwColumnPage::InitColumnLayouts()
+{
+    m_xDefaultIV->freeze();
+
+    for (int i = 0; i < 5; ++i)
+    {
+        OUString aItemText = GetColumnLayoutText(i);
+        OUString aItemId = OUString::number(i);
+
+        VclPtr<VirtualDevice> aColumnVDev = CreateColumnLayoutVDev(i + 1);
+        m_xDefaultIV->insert(i, &aItemText, &aItemId, aColumnVDev, nullptr);
+    }
+
+    m_xDefaultIV->thaw();
+}
+
+OUString SwColumnPage::GetColumnLayoutText(sal_Int32 nId) {
+    OUString aItemText;
+    switch( nId )
+    {
+        case 0:
+            aItemText =  SwResId( STR_COLUMN_ICONVIEW_ITEM0 );
+            break;
+        case 1:
+            aItemText =  SwResId( STR_COLUMN_ICONVIEW_ITEM1 );
+            break;
+        case 2:
+            aItemText =  SwResId( STR_COLUMN_ICONVIEW_ITEM2 );
+            break;
+        case 3:
+            aItemText =  SwResId( STR_COLUMN_ICONVIEW_ITEM3 );
+            break;
+        default:
+            aItemText =  SwResId( STR_COLUMN_ICONVIEW_ITEM4 );
+            break;
+    }
+
+    return aItemText;
+}
+
+IMPL_LINK(SwColumnPage, QueryTooltipHdl, const weld::TreeIter&, iter, OUString)
+{
+    const OUString sId = m_xDefaultIV->get_id(iter);
+    return !sId.isEmpty() ? GetColumnLayoutText(sId.toInt32()) : OUString();
+}
+
 void SwColumnPage::SetPageWidth(tools::Long nPageWidth)
 {
     tools::Long nNewMaxWidth = static_cast< tools::Long 
>(m_xEd1->NormalizePercent(nPageWidth));
@@ -916,7 +939,7 @@ void SwColumnPage::ColModify(bool bForceColReset)
         return;
 
     if (!bForceColReset)
-        m_aDefaultVS.SetNoSelection();
+        m_xDefaultIV->unselect_all();
     tools::Long nDist = static_cast< tools::Long 
>(m_xDistEd1->DenormalizePercent(m_xDistEd1->get_value(FieldUnit::TWIP)));
     m_xColMgr->SetCount(m_nCols, o3tl::narrowing<sal_uInt16>(nDist));
     for(sal_uInt16 i = 0; i < m_nCols; i++)
@@ -1258,12 +1281,16 @@ DeactivateRC SwColumnPage::DeactivatePage(SfxItemSet 
*_pSet)
     return DeactivateRC::LeavePage;
 }
 
-IMPL_LINK(SwColumnPage, SetDefaultsHdl, ValueSet *, pVS, void)
+IMPL_LINK(SwColumnPage, SetDefaultsHdl, weld::IconView&, rIconView, bool)
 {
-    const sal_uInt16 nItem = pVS->GetSelectedItemId();
-    if( nItem < 4 )
+    OUString sSelectedId = rIconView.get_selected_id();
+    if (sSelectedId.isEmpty())
+        return false;
+
+    const sal_Int32 nItem = sSelectedId.toInt32();
+    if( nItem < 3 )
     {
-        m_xCLNrEdt->set_value(nItem);
+        m_xCLNrEdt->set_value(nItem + 1);
         m_xAutoWidthBox->set_active(true);
         m_xDistEd1->set_value(50, FieldUnit::CM);
         ColModify(/*bForceColReset=*/true);
@@ -1277,7 +1304,7 @@ IMPL_LINK(SwColumnPage, SetDefaultsHdl, ValueSet *, pVS, 
void)
         ColModify(/*bForceColReset=*/true);
         // now set the width ratio to 2 : 1 or 1 : 2 respectively
         const tools::Long nSmall = static_cast< tools::Long 
>(m_xColMgr->GetActualSize() / 3);
-        if(nItem == 4)
+        if(nItem == 3)
         {
             m_xEd2->set_value(m_xEd2->NormalizePercent(nSmall), 
FieldUnit::TWIP);
             m_pModifiedField = m_xEd2.get();
@@ -1291,6 +1318,8 @@ IMPL_LINK(SwColumnPage, SetDefaultsHdl, ValueSet *, pVS, 
void)
         Timeout();
 
     }
+
+    return true;
 }
 
 void SwColumnPage::SetFrameMode(bool bMod)
@@ -1307,27 +1336,30 @@ void SwColumnPage::SetInSection(bool bSet)
     m_xTextDirectionLB->set_visible(bSet);
 }
 
-void ColumnValueSet::UserDraw(const UserDrawEvent& rUDEvt)
+VclPtr<VirtualDevice> SwColumnPage::CreateColumnLayoutVDev(sal_uInt16 nItemId)
 {
-    vcl::RenderContext* pDev = rUDEvt.GetRenderContext();
+    VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create();
+    const Size aSize(30, 30);
+    pVDev->SetOutputSizePixel(aSize);
+
     const StyleSettings& rStyleSettings = 
Application::GetSettings().GetStyleSettings();
 
-    tools::Rectangle aRect = rUDEvt.GetRect();
-    const sal_uInt16 nItemId = rUDEvt.GetItemId();
+    pVDev->SetFillColor(rStyleSettings.GetFieldColor());
+    pVDev->SetLineColor(rStyleSettings.GetFieldTextColor());
+
+    tools::Rectangle aRect(Point(0, 0), aSize);
     tools::Long nRectWidth = aRect.GetWidth();
     tools::Long nRectHeight = aRect.GetHeight();
 
     Point aBLPos = aRect.TopLeft();
-    pDev->Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
-    pDev->SetFillColor(rStyleSettings.GetFieldColor());
-    pDev->SetLineColor(rStyleSettings.GetFieldTextColor());
 
-    tools::Long nStep = std::abs(std::abs(nRectHeight * 95 /100) / 11);
-    tools::Long nTop = (nRectHeight - 11 * nStep ) / 2;
+    tools::Long nStep = std::abs(std::abs(nRectHeight * 95 / 100) / 11);
+    tools::Long nTop = (nRectHeight - 11 * nStep) / 2;
     sal_uInt16 nCols = 0;
     tools::Long nStarts[3];
     tools::Long nEnds[3];
     nStarts[0] = nRectWidth * 10 / 100;
+
     switch( nItemId )
     {
         case 1:
@@ -1357,25 +1389,19 @@ void ColumnValueSet::UserDraw(const UserDrawEvent& 
rUDEvt)
             nEnds[1] = nRectWidth * 9 / 10;
         break;
     }
-    for(sal_uInt16 j = 0; j < nCols; j++ )
+
+    for(sal_uInt16 j = 0; j < nCols; j++)
     {
         Point aStart(aBLPos.X() + nStarts[j], 0);
         Point aEnd(aBLPos.X() + nEnds[j], 0);
-        for( sal_uInt16 i = 0; i < 12; i ++)
+        for(sal_uInt16 i = 0; i < 12; i++)
         {
-            aStart.setY( aBLPos.Y() + nTop + i * nStep);
-            aEnd.setY( aStart.Y() );
-            pDev->DrawLine(aStart, aEnd);
+            aStart.setY(aBLPos.Y() + nTop + i * nStep);
+            aEnd.setY(aStart.Y());
+            pVDev->DrawLine(aStart, aEnd);
         }
     }
-    pDev->Pop();
-}
 
-void ColumnValueSet::StyleUpdated()
-{
-    SetFormat();
-    Invalidate();
-    ValueSet::StyleUpdated();
+    return pVDev;
 }
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/column.hxx b/sw/source/uibase/inc/column.hxx
index 6eabca9db70c..ed2c6971f90f 100644
--- a/sw/source/uibase/inc/column.hxx
+++ b/sw/source/uibase/inc/column.hxx
@@ -19,11 +19,11 @@
 #pragma once
 
 #include <svtools/ctrlbox.hxx>
-#include <svtools/valueset.hxx>
 #include <sfx2/basedlgs.hxx>
 #include <sfx2/tabdlg.hxx>
 #include <svx/colorbox.hxx>
 #include <svx/frmdirlbox.hxx>
+#include <vcl/virdev.hxx>
 #include <map>
 #include "colex.hxx"
 #include "prcntfld.hxx"
@@ -64,22 +64,6 @@ public:
     virtual ~SwColumnDlg() override;
 };
 
-class ColumnValueSet final : public ValueSet
-{
-public:
-    ColumnValueSet()
-        : ValueSet(nullptr)
-    {
-    }
-    virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override
-    {
-        ValueSet::SetDrawingArea(pDrawingArea);
-        SetStyle(WB_TABSTOP | WB_ITEMBORDER | WB_DOUBLEBORDER);
-    }
-    virtual void UserDraw(const UserDrawEvent& rUDEvt) override;
-    virtual void StyleUpdated() override;
-};
-
 // column dialog now as TabPage
 class SwColumnPage final : public SfxTabPage
 {
@@ -98,7 +82,6 @@ class SwColumnPage final : public SfxTabPage
     bool            m_bHtmlMode;
     bool            m_bLockUpdate;
 
-    ColumnValueSet m_aDefaultVS;
     SwColExample m_aPgeExampleWN;
     SwColumnOnlyExample m_aFrameExampleWN;
 
@@ -127,7 +110,7 @@ class SwColumnPage final : public SfxTabPage
     std::unique_ptr<SwPercentField> m_xEd3;
     std::unique_ptr<SwPercentField> m_xDistEd1;
     std::unique_ptr<SwPercentField> m_xDistEd2;
-    std::unique_ptr<weld::CustomWeld> m_xDefaultVS;
+    std::unique_ptr<weld::IconView> m_xDefaultIV;
     // Example
     std::unique_ptr<weld::CustomWeld> m_xPgeExampleWN;
     std::unique_ptr<weld::CustomWeld> m_xFrameExampleWN;
@@ -141,7 +124,8 @@ class SwColumnPage final : public SfxTabPage
     DECL_LINK(GapModify, weld::MetricSpinButton&, void);
     DECL_LINK(EdModify, weld::MetricSpinButton&, void);
     DECL_LINK(AutoWidthHdl, weld::Toggleable&, void );
-    DECL_LINK(SetDefaultsHdl, ValueSet *, void);
+    DECL_LINK(SetDefaultsHdl, weld::IconView&, bool);
+    DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
 
     DECL_LINK(Up, weld::Button&, void);
     DECL_LINK(Down, weld::Button&, void);
@@ -162,6 +146,11 @@ class SwColumnPage final : public SfxTabPage
 
     void connectPercentField(SwPercentField &rWrap);
 
+    void InitColumnLayouts();
+    static OUString GetColumnLayoutText(sal_Int32 nId);
+    static VclPtr<VirtualDevice> CreateColumnLayoutVDev(sal_uInt16 nItemId);
+
+
     bool isLineNotNone() const;
 
     static const WhichRangesContainer s_aPageRg;
diff --git a/sw/uiconfig/swriter/ui/columnpage.ui 
b/sw/uiconfig/swriter/ui/columnpage.ui
index 9ead17ea0895..e103ebe86527 100644
--- a/sw/uiconfig/swriter/ui/columnpage.ui
+++ b/sw/uiconfig/swriter/ui/columnpage.ui
@@ -658,6 +658,14 @@
             <property name="shadow-type">none</property>
             <child>
               <!-- n-columns=2 n-rows=2 -->
+              <object class="GtkTreeStore" id="liststore1">
+                <columns>
+                  <!-- column-name pixbuf -->
+                  <column type="GdkPixbuf"/>
+                  <!-- column-name id -->
+                  <column type="gchararray"/>
+                </columns>
+              </object>
               <object class="GtkGrid" id="grid4">
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
@@ -830,17 +838,36 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkDrawingArea" id="valueset">
+                  <object class="GtkScrolledWindow">
                     <property name="width-request">160</property>
                     <property name="height-request">35</property>
                     <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>
-                    <child internal-child="accessible">
-                      <object class="AtkObject" id="valueset-atkobject">
-                        <property name="AtkObject::accessible-description" 
translatable="yes" context="columnpage|extended_tip|valueset">Enter the number 
of columns that you want in the page, frame, or section.</property>
+                    <property name="hscrollbar-policy">never</property>
+                    <property name="vscrollbar-policy">never</property>
+                    <property name="shadow-type">in</property>
+                    <child>
+                      <object class="GtkIconView" id="column-iconview">
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="hexpand">False</property>
+                        <property name="vexpand">False</property>
+                        <property name="model">liststore1</property>
+                        <property name="pixbuf-column">0</property>
+                        <property name="selection-mode">single</property>
+                        <property name="columns">5</property>
+                        <property name="item-width">32</property>
+                        <property name="item-padding">2</property>
+                        <property name="spacing">2</property>
+                        <property name="row-spacing">2</property>
+                        <property name="column-spacing">2</property>
+                        <property name="margin">2</property>
+                        <property 
name="activate-on-single-click">True</property>
+                        <child internal-child="accessible">
+                          <object class="AtkObject" 
id="column-iconview-atkobject">
+                            <property name="AtkObject::accessible-description" 
translatable="yes" context="columnpage|extended_tip|column-iconview">Enter the 
number of columns that you want in the page, frame, or section.</property>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>

Reply via email to