sc/inc/column.hxx              |   37 +++++++++++++-----
 sc/inc/table.hxx               |   35 +++++++++++++++++
 sc/source/core/data/column.cxx |   84 ++++-------------------------------------
 sc/source/core/data/table2.cxx |   68 ++++-----------------------------
 4 files changed, 81 insertions(+), 143 deletions(-)

New commits:
commit 7e5a345897e633083ce0194a34c4faac54d28371
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Dec 30 18:08:56 2023 +0600
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Dec 30 14:43:38 2023 +0100

    tdf#158254: generalize and use algorithm to apply with allocation
    
    Commit 17bcf1073bf21088b9845e36fe735622d8f88fd7 (introduce ScColumnData
    for ScColumn/ScTable code sharing, 2022-05-05) implemented an algorithm
    to only allocate needed amount of columns, and/or apply to default data
    when needed. It was done for ApplySelectionCache, ChangeSelectionIndent,
    ClearSelectionItems. Yet, many other functions need the same approach.
    
    This change introduces ScTable::ApplyWithAllocation template, which
    allows to use this algorithm uniformly to any operation on a selection,
    which ultimately applies to ScColumnData. The code in the functions
    mentioned above is replaced with its use; and ApplySelectionStyle is
    fixed using it.
    
    Change-Id: Ic8890d9980fcb01b61bb111183b355c623f866a2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161441
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 87273f0f83ba..0e07ed8142b0 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -145,8 +145,9 @@ public:
 
     const ScPatternAttr*    GetPattern( SCROW nRow ) const;
     const ScPatternAttr*    GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow 
) const;
-    SCROW       ApplySelectionCache( ScItemPoolCache& rCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged,
-                                     SCCOL nCol );
+    void        ApplySelectionStyle(const ScStyleSheet& rStyle, SCROW nTop, 
SCROW nBottom);
+    void        ApplySelectionCache(ScItemPoolCache& rCache, SCROW nStartRow, 
SCROW nEndRow,
+                                    ScEditDataArray* pDataArray, bool* 
pIsChanged);
     void        ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const 
ScPatternAttr& rPatAttr,
                                   ScEditDataArray* pDataArray = nullptr,
                                   bool* const pIsChanged = nullptr);
@@ -168,12 +169,17 @@ public:
 
     bool        IsAllAttrEqual( const ScColumnData& rCol, SCROW nStartRow, 
SCROW nEndRow ) const;
 
-    void        ClearSelectionItems( const sal_uInt16* pWhich, const 
ScMarkData& rMark, SCCOL nCol );
-    void        ChangeSelectionIndent( bool bIncrement, const ScMarkData& 
rMark, SCCOL nCol );
+    void        ClearSelectionItems(const sal_uInt16* pWhich, SCROW nStartRow, 
SCROW nEndRow);
+    void        ChangeSelectionIndent(bool bIncrement, SCROW nStartRow, SCROW 
nEndRow);
 
     bool        TestInsertRow( SCSIZE nSize ) const;
     void        InsertRow( SCROW nStartRow, SCSIZE nSize );
     void        DeleteRow( SCROW nStartRow, SCSIZE nSize );
+
+    // Applies a function to the selected ranges.
+    // The function looks like
+    //     ApplyDataFunc(ScColumnData& applyTo, SCROW nTop, SCROW nBottom)
+    template <typename ApplyDataFunc> void Apply(const ScMarkData&, SCCOL, 
ApplyDataFunc);
 };
 
 // Use protected inheritance to prevent publishing some internal ScColumnData
@@ -549,7 +555,6 @@ public:
                             const ScPatternAttr& rPattern, SvNumFormatType 
nNewType );
 
     void        ApplyStyle( SCROW nRow, const ScStyleSheet* rStyle );
-    void        ApplySelectionStyle(const ScStyleSheet& rStyle, const 
ScMarkData& rMark);
     void        ApplySelectionLineStyle( const ScMarkData& rMark,
                                     const ::editeng::SvxBorderLine* pLine, 
bool bColorOnly );
     void        AddCondFormat(SCROW nStartRow, SCROW nEndRow, sal_uInt32 
nIndex );
@@ -576,12 +581,8 @@ public:
 
     void        RemoveProtected( SCROW nStartRow, SCROW nEndRow );
 
-    SCROW       ApplySelectionCache( ScItemPoolCache& rCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged );
     void DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMark, 
bool bBroadcast );
 
-    void        ClearSelectionItems( const sal_uInt16* pWhich, const 
ScMarkData& rMark );
-    void        ChangeSelectionIndent( bool bIncrement, const ScMarkData& 
rMark );
-
     tools::Long GetNeededSize(
         SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
         const Fraction& rZoomX, const Fraction& rZoomY,
@@ -1067,4 +1068,22 @@ inline void ScColumnData::DeleteRow(SCROW nStartRow, 
SCSIZE nSize)
     pAttrArray->DeleteRow( nStartRow, nSize );
 }
 
+template <typename ApplyDataFunc>
+void ScColumnData::Apply(const ScMarkData& rMark, SCCOL nCol, ApplyDataFunc 
apply)
+{
+    if (rMark.IsMultiMarked())
+    {
+        ScMultiSelIter aMultiIter(rMark.GetMultiSelData(), nCol);
+        SCROW nTop, nBottom;
+        while (aMultiIter.Next(nTop, nBottom))
+            apply(*this, nTop, nBottom);
+    }
+    else if (rMark.IsMarked())
+    {
+        const ScRange& aRange = rMark.GetMarkArea();
+        if (aRange.aStart.Col() <= nCol && nCol <= aRange.aEnd.Col())
+            apply(*this, aRange.aStart.Row(), aRange.aEnd.Row());
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 72e78b195986..8f749a273707 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -34,6 +34,7 @@
 #include "drwlayer.hxx"
 #include "SparklineList.hxx"
 #include "SolverSettings.hxx"
+#include "markdata.hxx"
 
 #include <algorithm>
 #include <atomic>
@@ -1427,6 +1428,40 @@ private:
         SCROW mnUBound;
     };
 
+    // Applies a function to the selected ranges; makes sure to only allocate
+    // as few columns as needed, and applies the rest to default column data.
+    // The function looks like
+    //     ApplyDataFunc(ScColumnData& applyTo, SCROW nTop, SCROW nBottom)
+    template <typename ApplyDataFunc>
+    void ApplyWithAllocation(const ScMarkData&, ApplyDataFunc);
 };
 
+template <typename ApplyDataFunc>
+void ScTable::ApplyWithAllocation(const ScMarkData& rMark, ApplyDataFunc apply)
+{
+    if (!rMark.GetTableSelect(nTab) || !(rMark.IsMultiMarked() || 
rMark.IsMarked()))
+        return;
+    SCCOL lastChangeCol;
+    if (rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
+    {
+        // For the same unallocated columns until the end we can change just 
the default.
+        lastChangeCol = rMark.GetStartOfEqualColumns(GetDoc().MaxCol(), 
aCol.size()) - 1;
+        // Allocate needed different columns before changing the default.
+        if (lastChangeCol >= 0)
+            CreateColumnIfNotExists(lastChangeCol);
+
+        aDefaultColData.Apply(rMark, GetDoc().MaxCol(), apply);
+    }
+    else // need to allocate all columns affected
+    {
+        lastChangeCol = rMark.GetArea().aEnd.Col();
+        CreateColumnIfNotExists(lastChangeCol);
+    }
+
+    // The loop should go not to lastChangeCol, but over all columns, to apply 
to already allocated
+    // in the "StartOfEqualColumns" range
+    for (SCCOL i = 0; i < aCol.size(); i++)
+        aCol[i].Apply(rMark, i, apply);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 198e56fb7158..59b9b8c78117 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -375,81 +375,23 @@ sal_uInt32 ScColumnData::GetNumberFormat( SCROW 
nStartRow, SCROW nEndRow ) const
     return nFormat;
 }
 
-SCROW ScColumn::ApplySelectionCache( ScItemPoolCache& rCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray,
-                                     bool* const pIsChanged )
+void ScColumnData::ApplySelectionCache(ScItemPoolCache& rCache, SCROW 
nStartRow, SCROW nEndRow,
+                                       ScEditDataArray* pDataArray, bool* 
pIsChanged)
 {
-    return ScColumnData::ApplySelectionCache( rCache, rMark, pDataArray, 
pIsChanged, nCol );
+    pAttrArray->ApplyCacheArea(nStartRow, nEndRow, rCache, pDataArray, 
pIsChanged);
 }
 
-SCROW ScColumnData::ApplySelectionCache( ScItemPoolCache& rCache, const 
ScMarkData& rMark, ScEditDataArray* pDataArray,
-                                         bool* const pIsChanged, SCCOL nCol )
+void ScColumnData::ChangeSelectionIndent(bool bIncrement, SCROW nStartRow, 
SCROW nEndRow)
 {
-    SCROW nTop = 0;
-    SCROW nBottom = 0;
-    bool bFound = false;
-
-    if ( rMark.IsMultiMarked() )
-    {
-        ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
-        while (aMultiIter.Next( nTop, nBottom ))
-        {
-            pAttrArray->ApplyCacheArea( nTop, nBottom, rCache, pDataArray, 
pIsChanged );
-            bFound = true;
-        }
-    }
-
-    if (!bFound)
-        return -1;
-    else if (nTop==0 && nBottom==GetDoc().MaxRow())
-        return 0;
-    else
-        return nBottom;
-}
-
-void ScColumnData::ChangeSelectionIndent( bool bIncrement, const ScMarkData& 
rMark, SCCOL nCol )
-{
-    assert(rMark.IsMultiMarked());
-    if ( pAttrArray && rMark.IsMultiMarked() )
-    {
-        ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
-        SCROW nTop;
-        SCROW nBottom;
-        while (aMultiIter.Next( nTop, nBottom ))
-            pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
-    }
-}
-
-void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark 
)
-{
-    return ScColumnData::ChangeSelectionIndent( bIncrement, rMark, nCol );
+    pAttrArray->ChangeIndent(nStartRow, nEndRow, bIncrement);
 }
 
-void ScColumnData::ClearSelectionItems( const sal_uInt16* pWhich,const 
ScMarkData& rMark, SCCOL nCol )
+void ScColumnData::ClearSelectionItems(const sal_uInt16* pWhich, SCROW 
nStartRow, SCROW nEndRow)
 {
     if (!pAttrArray)
         return;
 
-    if (rMark.IsMultiMarked() )
-    {
-        ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
-        SCROW nTop;
-        SCROW nBottom;
-        while (aMultiIter.Next( nTop, nBottom ))
-            pAttrArray->ClearItems(nTop, nBottom, pWhich);
-    }
-    else if (rMark.IsMarked())
-    {
-        const ScRange& aRange = rMark.GetMarkArea();
-        if (aRange.aStart.Col() <= nCol && nCol <= aRange.aEnd.Col())
-        {
-            pAttrArray->ClearItems(aRange.aStart.Row(), aRange.aEnd.Row(), 
pWhich);
-        }
-    }
-}
-
-void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& 
rMark )
-{
-    ScColumnData::ClearSelectionItems( pWhich, rMark, nCol );
+    pAttrArray->ClearItems(nStartRow, nEndRow, pWhich);
 }
 
 void ScColumn::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& 
rMark, bool bBroadcast )
@@ -522,17 +464,9 @@ void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet* 
rStyle )
     pAttrArray->SetPattern(nRow, CellAttributeHolder(pNewPattern, true));
 }
 
-void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const 
ScMarkData& rMark)
+void ScColumnData::ApplySelectionStyle(const ScStyleSheet& rStyle, SCROW nTop, 
SCROW nBottom)
 {
-    SCROW nTop;
-    SCROW nBottom;
-
-    if ( rMark.IsMultiMarked() )
-    {
-        ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
-        while (aMultiIter.Next( nTop, nBottom ))
-            pAttrArray->ApplyStyleArea(nTop, nBottom, rStyle);
-    }
+    pAttrArray->ApplyStyleArea(nTop, nBottom, rStyle);
 }
 
 void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index b995aec2e7b4..6ce0a1637346 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -3073,8 +3073,8 @@ void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW 
nStartRow, SCCOL nEndCol, S
 
 void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const 
ScMarkData& rMark)
 {
-    for (SCCOL i=0; i < aCol.size(); i++)
-        aCol[i].ApplySelectionStyle( rStyle, rMark );
+    ApplyWithAllocation(rMark, [&rStyle](ScColumnData& applyTo, SCROW nTop, 
SCROW nBottom)
+                        { applyTo.ApplySelectionStyle(rStyle, nTop, nBottom); 
});
 }
 
 void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark,
@@ -3236,71 +3236,21 @@ void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const 
SfxPoolItem& rAttr )
 void ScTable::ApplySelectionCache( ScItemPoolCache& rCache, const ScMarkData& 
rMark,
                                    ScEditDataArray* pDataArray, bool* const 
pIsChanged )
 {
-    if(!rMark.GetTableSelect(nTab))
-        return;
-    SCCOL lastChangeCol;
-    if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
-    {
-        // For the same unallocated columns until the end we can change just 
the default.
-        lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), 
aCol.size()) - 1;
-        if( lastChangeCol >= 0 )
-            CreateColumnIfNotExists(lastChangeCol); // Allocate needed 
different columns before changing the default.
-        aDefaultColData.ApplySelectionCache( rCache, rMark, pDataArray, 
pIsChanged, GetDoc().MaxCol());
-    }
-    else // need to allocate all columns affected
-    {
-        lastChangeCol = rMark.GetArea().aEnd.Col();
-        CreateColumnIfNotExists(lastChangeCol);
-    }
-
-    for (SCCOL i=0; i <= lastChangeCol; i++)
-        aCol[i].ApplySelectionCache( rCache, rMark, pDataArray, pIsChanged );
+    ApplyWithAllocation(
+        rMark, [&rCache, pDataArray, pIsChanged](ScColumnData& applyTo, SCROW 
nTop, SCROW nBottom)
+        { applyTo.ApplySelectionCache(rCache, nTop, nBottom, pDataArray, 
pIsChanged); });
 }
 
 void ScTable::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
 {
-    if(!rMark.GetTableSelect(nTab))
-        return;
-    SCCOL lastChangeCol;
-    if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
-    {
-        // For the same unallocated columns until the end we can change just 
the default.
-        lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), 
aCol.size()) - 1;
-        if( lastChangeCol >= 0 )
-            CreateColumnIfNotExists(lastChangeCol); // Allocate needed 
different columns before changing the default.
-        aDefaultColData.ChangeSelectionIndent( bIncrement, rMark, 
GetDoc().MaxCol());
-    }
-    else
-    {
-        lastChangeCol = rMark.GetArea().aEnd.Col();
-        CreateColumnIfNotExists(lastChangeCol);
-    }
-
-    for (SCCOL i=0; i <= lastChangeCol; i++)
-        aCol[i].ChangeSelectionIndent( bIncrement, rMark );
+    ApplyWithAllocation(rMark, [&bIncrement](ScColumnData& applyTo, SCROW 
nTop, SCROW nBottom)
+                        { applyTo.ChangeSelectionIndent(bIncrement, nTop, 
nBottom); });
 }
 
 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& 
rMark )
 {
-    if(!rMark.GetTableSelect(nTab))
-        return;
-    SCCOL lastChangeCol;
-    if( rMark.GetArea().aEnd.Col() == GetDoc().MaxCol())
-    {
-        // For the same unallocated columns until the end we can change just 
the default.
-        lastChangeCol = rMark.GetStartOfEqualColumns( GetDoc().MaxCol(), 
aCol.size()) - 1;
-        if( lastChangeCol >= 0 )
-            CreateColumnIfNotExists(lastChangeCol); // Allocate needed 
different columns before changing the default.
-        aDefaultColData.ClearSelectionItems( pWhich, rMark, GetDoc().MaxCol());
-    }
-    else
-    {
-        lastChangeCol = rMark.GetArea().aEnd.Col();
-        CreateColumnIfNotExists(lastChangeCol);
-    }
-
-    for (SCCOL i=0; i <= lastChangeCol; i++)
-        aCol[i].ClearSelectionItems( pWhich, rMark );
+    ApplyWithAllocation(rMark, [pWhich](ScColumnData& applyTo, SCROW nTop, 
SCROW nBottom)
+                        { applyTo.ClearSelectionItems(pWhich, nTop, nBottom); 
});
 }
 
 //  Column widths / Row heights

Reply via email to