summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-07-10 16:32:39 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-07-11 00:25:37 -0400
commit0797dd8714413f8319515df9831a86703b589558 (patch)
treecd12f739ef0ac620fa4b4eaa35f6d1f50a3ec97b /sc/source
parent217896aa33e40b113fafdaa109d02992f7d9506a (diff)
Group formula cells in ScColumn::MixData().
Change-Id: I38186e2bf82ed56fbe859b17dcc1d31f36471bd8
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/column.cxx20
-rw-r--r--sc/source/core/data/column2.cxx4
-rw-r--r--sc/source/core/data/column3.cxx170
-rw-r--r--sc/source/core/tool/sharedformula.cxx18
4 files changed, 122 insertions, 90 deletions
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ad51473472eb..b777905332b7 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -39,6 +39,7 @@
#include "mtvcellfunc.hxx"
#include "columnspanset.hxx"
#include "scopetools.hxx"
+#include "sharedformula.hxx"
#include <svl/poolcach.hxx>
#include <svl/zforlist.hxx>
@@ -868,8 +869,8 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
// TODO: Find out a way to adjust references without cloning new instances.
boost::scoped_ptr<ScFormulaCell> pOld1(*itf1);
boost::scoped_ptr<ScFormulaCell> pOld2(*itf2);
- DetouchFormulaCell(aPos1, **itf1);
- DetouchFormulaCell(aPos2, **itf2);
+ DetachFormulaCell(aPos1, **itf1);
+ DetachFormulaCell(aPos2, **itf2);
ScFormulaCell* pNew1 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *pOld2);
ScFormulaCell* pNew2 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *pOld1);
*itf1 = pNew1;
@@ -920,7 +921,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
{
// cell 1 is empty and cell 2 is a formula cell.
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
maCells.set_empty(it1, nRow2, nRow2); // original formula cell gets deleted.
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -964,7 +965,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
{
// cell 1 is a formula cell and cell 2 is empty.
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
- DetouchFormulaCell(aPos1, *aCell1.mpFormula);
+ DetachFormulaCell(aPos1, *aCell1.mpFormula);
it1 = maCells.set_empty(it1, nRow1, nRow1); // original formula cell is gone.
it1 = maCells.set(it1, nRow2, pNew);
ActivateNewFormulaCell(it1, nRow2, *pNew);
@@ -999,7 +1000,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
break;
case CELLTYPE_FORMULA:
{
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -1032,7 +1033,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
case CELLTYPE_FORMULA:
{
// cell 1 - string, cell 2 - formula
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -1061,7 +1062,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
break;
case CELLTYPE_FORMULA:
{
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -1078,7 +1079,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
case CELLTYPE_FORMULA:
{
// cell 1 is a formula cell and cell 2 is not.
- DetouchFormulaCell(aPos1, *aCell1.mpFormula);
+ DetachFormulaCell(aPos1, *aCell1.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
switch (aCell2.meType)
{
@@ -1371,7 +1372,8 @@ public:
}
// Group the cloned formula cells.
- groupFormulaCells(aCloned);
+ if (!aCloned.empty())
+ sc::SharedFormulaUtil::groupFormulaCells(aCloned.begin(), aCloned.end());
sc::CellStoreType& rDestCells = mrDestCol.GetCellStore();
maDestPos.miCellPos = rDestCells.set(
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index aa4dd0ec6c58..7b38918c099b 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1530,10 +1530,6 @@ void ScColumn::CellStorageModified()
#endif
}
-void ScColumn::RegroupFormulaCells( SCROW /*nRow1*/, SCROW /*nRow2*/ )
-{
-}
-
#if DEBUG_COLUMN_STORAGE
namespace {
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 8352d4653ab9..4fb06c3bec33 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -45,6 +45,7 @@
#include "mtvcellfunc.hxx"
#include "scopetools.hxx"
#include "editutil.hxx"
+#include "sharedformula.hxx"
#include <com/sun/star/i18n/LocaleDataItem.hpp>
@@ -91,29 +92,6 @@ void ScColumn::BroadcastCells( const std::vector<SCROW>& rRows )
broadcastCells(*pDocument, nCol, nTab, rRows);
}
-namespace {
-
-class EndListeningHandler
-{
- ScDocument* mpDoc;
-public:
- EndListeningHandler(ScDocument* pDoc) : mpDoc(pDoc) {}
-
- void operator() (size_t, ScFormulaCell* p)
- {
- p->EndListeningTo(mpDoc);
- }
-};
-
-}
-
-void ScColumn::EndFormulaListening( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 )
-{
- EndListeningHandler aFunc(pDocument);
- rBlockPos.miCellPos =
- sc::ProcessFormula(rBlockPos.miCellPos, maCells, nRow1, nRow2, aFunc);
-}
-
struct DirtyCellInterpreter
{
void operator() (size_t, ScFormulaCell* p)
@@ -411,8 +389,8 @@ void ScColumn::JoinNewFormulaCell(
}
}
-void ScColumn::DetouchFormulaCell(
- const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const
+void ScColumn::DetachFormulaCell(
+ const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell )
{
if (!pDocument->IsClipOrUndo())
// Have the dying formula cell stop listening.
@@ -422,6 +400,42 @@ void ScColumn::DetouchFormulaCell(
UnshareFormulaCell(aPos, rCell);
}
+namespace {
+
+class DetachFormulaCellsHandler
+{
+ ScDocument* mpDoc;
+public:
+ DetachFormulaCellsHandler(ScDocument* pDoc) : mpDoc(pDoc) {}
+
+ void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
+ {
+ pCell->EndListeningTo(mpDoc);
+ }
+};
+
+}
+
+void ScColumn::DetachFormulaCells(
+ const sc::CellStoreType::position_type& aPos, size_t nLength )
+{
+ // Split formula grouping at the top and bottom boundaries.
+ SplitFormulaCellGroup(aPos);
+ size_t nRow = aPos.first->position + aPos.second;
+ size_t nNextTopRow = nRow + nLength; // start row of next formula group.
+ if (ValidRow(nNextTopRow))
+ {
+ sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow);
+ SplitFormulaCellGroup(aPos2);
+ }
+
+ if (pDocument->IsClipOrUndo())
+ return;
+
+ DetachFormulaCellsHandler aFunc(pDocument);
+ sc::ProcessFormula(aPos.first, maCells, nRow, nNextTopRow-1, aFunc);
+}
+
void ScColumn::UnshareFormulaCell(
const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const
{
@@ -617,7 +631,7 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreTy
if (itRet->type == sc::element_type_formula)
{
ScFormulaCell& rCell = *sc::formula_block::at(*itRet->data, aPos.second);
- DetouchFormulaCell(aPos, rCell);
+ DetachFormulaCell(aPos, rCell);
}
return itRet;
@@ -1240,11 +1254,7 @@ void lcl_AddCode( ScTokenArray& rArr, const ScFormulaCell* pCell )
class MixDataHandler
{
ScColumn& mrDestColumn;
-
- sc::CellStoreType& mrDestCells;
- sc::CellStoreType::iterator miDestPos;
-
- sc::CellTextAttrStoreType& mrDestAttrs;
+ sc::ColumnBlockPosition& mrBlockPos;
sc::CellStoreType maNewCells;
sc::CellStoreType::iterator miNewCellsPos;
@@ -1256,37 +1266,30 @@ class MixDataHandler
public:
MixDataHandler(
- sc::ColumnBlockPosition* pBlockPos,
+ sc::ColumnBlockPosition& rBlockPos,
ScColumn& rDestColumn,
- sc::CellStoreType& rDestCells,
- sc::CellTextAttrStoreType& rDestAttrs,
SCROW nRow1, SCROW nRow2,
sal_uInt16 nFunction, bool bSkipEmpty) :
mrDestColumn(rDestColumn),
- mrDestCells(rDestCells),
- mrDestAttrs(rDestAttrs),
+ mrBlockPos(rBlockPos),
maNewCells(nRow2 - nRow1 + 1),
miNewCellsPos(maNewCells.begin()),
mnRowOffset(nRow1),
mnFunction(nFunction),
mbSkipEmpty(bSkipEmpty)
{
- if (pBlockPos)
- miDestPos = pBlockPos->miCellPos;
- else
- miDestPos = mrDestCells.begin();
}
void operator() (size_t nRow, double f)
{
- std::pair<sc::CellStoreType::iterator, size_t> aPos = mrDestCells.position(miDestPos, nRow);
- miDestPos = aPos.first;
- switch (miDestPos->type)
+ sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nRow);
+ mrBlockPos.miCellPos = aPos.first;
+ switch (aPos.first->type)
{
case sc::element_type_numeric:
{
// Both src and dest are of numeric type.
- bool bOk = lcl_DoFunction(f, sc::numeric_block::at(*miDestPos->data, aPos.second), mnFunction);
+ bool bOk = lcl_DoFunction(f, sc::numeric_block::at(*aPos.first->data, aPos.second), mnFunction);
if (bOk)
miNewCellsPos = maNewCells.set(miNewCellsPos, nRow-mnRowOffset, f);
@@ -1321,7 +1324,7 @@ public:
aArr.AddOpCode(eOp); // Function
// Second row
- ScFormulaCell* pDest = sc::formula_block::at(*miDestPos->data, aPos.second);
+ ScFormulaCell* pDest = sc::formula_block::at(*aPos.first->data, aPos.second);
lcl_AddCode(aArr, pDest);
miNewCellsPos = maNewCells.set(
@@ -1355,9 +1358,9 @@ public:
void operator() (size_t nRow, const ScFormulaCell* p)
{
- std::pair<sc::CellStoreType::iterator, size_t> aPos = mrDestCells.position(miDestPos, nRow);
- miDestPos = aPos.first;
- switch (miDestPos->type)
+ sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nRow);
+ mrBlockPos.miCellPos = aPos.first;
+ switch (aPos.first->type)
{
case sc::element_type_numeric:
{
@@ -1379,7 +1382,7 @@ public:
aArr.AddOpCode(eOp); // Function
// Second row
- aArr.AddDouble(sc::numeric_block::at(*miDestPos->data, aPos.second));
+ aArr.AddDouble(sc::numeric_block::at(*aPos.first->data, aPos.second));
miNewCellsPos = maNewCells.set(
miNewCellsPos, nRow-mnRowOffset,
@@ -1407,7 +1410,7 @@ public:
aArr.AddOpCode(eOp); // Function
// Second row
- ScFormulaCell* pDest = sc::formula_block::at(*miDestPos->data, aPos.second);
+ ScFormulaCell* pDest = sc::formula_block::at(*aPos.first->data, aPos.second);
lcl_AddCode(aArr, pDest);
miNewCellsPos = maNewCells.set(
@@ -1443,9 +1446,9 @@ public:
for (size_t i = 0; i < nDataSize; ++i)
{
size_t nDestRow = nTopRow + i;
- std::pair<sc::CellStoreType::iterator, size_t> aPos = mrDestCells.position(miDestPos, nDestRow);
- miDestPos = aPos.first;
- switch (miDestPos->type)
+ sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nDestRow);
+ mrBlockPos.miCellPos = aPos.first;
+ switch (aPos.first->type)
{
case sc::element_type_numeric:
case sc::element_type_string:
@@ -1457,7 +1460,7 @@ public:
ScTokenArray aArr;
// First row
- ScFormulaCell* pSrc = sc::formula_block::at(*miDestPos->data, aPos.second);
+ ScFormulaCell* pSrc = sc::formula_block::at(*aPos.first->data, aPos.second);
lcl_AddCode( aArr, pSrc);
// Operator
@@ -1488,21 +1491,17 @@ public:
/**
* Set the new cells to the destination (this) column.
*/
- void commit(sc::ColumnBlockPosition* pDestBlockPos)
+ void commit()
{
- sc::ColumnBlockPosition aDestBlockPos;
- if (pDestBlockPos)
- aDestBlockPos = *pDestBlockPos;
- else
- mrDestColumn.InitBlockPosition(aDestBlockPos);
+ sc::CellStoreType& rDestCells = mrDestColumn.GetCellStore();
// Stop all formula cells in the destination range first.
- sc::ColumnBlockPosition aCopy = aDestBlockPos;
- mrDestColumn.EndFormulaListening(aCopy, mnRowOffset, mnRowOffset + maNewCells.size() - 1);
+ sc::CellStoreType::position_type aPos = rDestCells.position(mrBlockPos.miCellPos, mnRowOffset);
+ mrDestColumn.DetachFormulaCells(aPos, maNewCells.size());
// Move the new cells to the destination range.
- sc::CellStoreType::iterator& itDestPos = aDestBlockPos.miCellPos;
- sc::CellTextAttrStoreType::iterator& itDestAttrPos = aDestBlockPos.miCellTextAttrPos;
+ sc::CellStoreType::iterator& itDestPos = mrBlockPos.miCellPos;
+ sc::CellTextAttrStoreType::iterator& itDestAttrPos = mrBlockPos.miCellTextAttrPos;
sc::CellStoreType::iterator it = maNewCells.begin(), itEnd = maNewCells.end();
for (; it != itEnd; ++it)
@@ -1516,33 +1515,50 @@ public:
{
sc::numeric_block::iterator itData = sc::numeric_block::begin(*it->data);
sc::numeric_block::iterator itDataEnd = sc::numeric_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+ itDestPos = mrDestColumn.GetCellStore().set(itDestPos, nDestRow, itData, itDataEnd);
}
break;
case sc::element_type_string:
{
sc::string_block::iterator itData = sc::string_block::begin(*it->data);
sc::string_block::iterator itDataEnd = sc::string_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+ itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
}
break;
case sc::element_type_edittext:
{
sc::edittext_block::iterator itData = sc::edittext_block::begin(*it->data);
sc::edittext_block::iterator itDataEnd = sc::edittext_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+ itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
}
break;
case sc::element_type_formula:
{
sc::formula_block::iterator itData = sc::formula_block::begin(*it->data);
sc::formula_block::iterator itDataEnd = sc::formula_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+
+ // Group new formula cells before inserting them.
+ sc::SharedFormulaUtil::groupFormulaCells(itData, itDataEnd);
+
+ // Insert the formula cells to the column.
+ itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+
+ // Merge with the previous formula group (if any).
+ aPos = rDestCells.position(itDestPos, nDestRow);
+ mrDestColumn.JoinFormulaCellAbove(aPos);
+
+ // Merge with the next formula group (if any).
+ size_t nNextRow = nDestRow + it->size;
+ if (ValidRow(nNextRow))
+ {
+ aPos = rDestCells.position(aPos.first, nNextRow);
+ mrDestColumn.JoinFormulaCellAbove(aPos);
+ }
}
break;
case sc::element_type_empty:
{
- itDestPos = mrDestCells.set_empty(itDestPos, nDestRow, nDestRow+it->size-1);
+ itDestPos = rDestCells.set_empty(itDestPos, nDestRow, nDestRow+it->size-1);
bHasContent = false;
}
break;
@@ -1550,19 +1566,17 @@ public:
;
}
+ sc::CellTextAttrStoreType& rDestAttrs = mrDestColumn.GetCellAttrStore();
if (bHasContent)
{
std::vector<sc::CellTextAttr> aAttrs(it->size, sc::CellTextAttr());
- itDestAttrPos = mrDestAttrs.set(itDestAttrPos, nDestRow, aAttrs.begin(), aAttrs.end());
+ itDestAttrPos = rDestAttrs.set(itDestAttrPos, nDestRow, aAttrs.begin(), aAttrs.end());
}
else
- itDestAttrPos = mrDestAttrs.set_empty(itDestAttrPos, nDestRow, nDestRow+it->size-1);
+ itDestAttrPos = rDestAttrs.set_empty(itDestAttrPos, nDestRow, nDestRow+it->size-1);
}
maNewCells.release();
-
- if (pDestBlockPos)
- *pDestBlockPos = aDestBlockPos;
}
};
@@ -1575,11 +1589,13 @@ void ScColumn::MixData(
// destination (this column) block position.
sc::ColumnBlockPosition* p = rCxt.getBlockPosition(nTab, nCol);
- MixDataHandler aFunc(p, *this, maCells, maCellTextAttrs, nRow1, nRow2, nFunction, bSkipEmpty);
+ if (!p)
+ return;
+
+ MixDataHandler aFunc(*p, *this, nRow1, nRow2, nFunction, bSkipEmpty);
sc::ParseAll(rSrcCol.maCells.begin(), rSrcCol.maCells, nRow1, nRow2, aFunc, aFunc);
- aFunc.commit(p);
- RegroupFormulaCells(nRow1, nRow2);
+ aFunc.commit();
CellStorageModified();
}
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
new file mode 100644
index 000000000000..7b6ac84cc8c8
--- /dev/null
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "sharedformula.hxx"
+
+namespace sc {
+
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */