summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-20 21:43:25 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-20 22:22:29 -0500
commitc0e74352b1a1c7bdcfd15acdd8780df9f4d18200 (patch)
tree497a4eb9f8a02aeaa23c64562a8014b4e970adcf /sc/source/core
parent52b7e6bfc848a467baf02c320c29e7f77b92cc93 (diff)
Adjust InsertRow() for group area listeners.
Change-Id: I813b45d015eb1ae8dc7bd1242152ef734b5fe08c (cherry picked from commit 01e14bd403e749116844b6ab0b0a7afc66347e90)
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/data/column4.cxx70
-rw-r--r--sc/source/core/data/document.cxx26
-rw-r--r--sc/source/core/data/document10.cxx29
-rw-r--r--sc/source/core/data/table7.cxx19
4 files changed, 140 insertions, 4 deletions
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index ba6d01546f0e..43946e53503c 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1357,4 +1357,74 @@ void ScColumn::EndListeningFormulaCells(
*pEndRow = aFunc.getEndRow();
}
+void ScColumn::EndListeningIntersectedGroups(
+ sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2, std::vector<ScAddress>* pGroupPos )
+{
+ // Only end the intersected group.
+ sc::CellStoreType::position_type aPos = maCells.position(nRow1);
+ sc::CellStoreType::iterator it = aPos.first;
+ if (it->type == sc::element_type_formula)
+ {
+ ScFormulaCell* pFC = sc::formula_block::at(*it->data, aPos.second);
+ ScFormulaCellGroupRef xGroup = pFC->GetCellGroup();
+ if (xGroup && !pFC->IsSharedTop())
+ {
+ // End listening.
+ pFC->EndListeningTo(rCxt);
+ if (pGroupPos)
+ // Record the position of the top cell of the group.
+ pGroupPos->push_back(xGroup->mpTopCell->aPos);
+ }
+ }
+
+ aPos = maCells.position(it, nRow2);
+ it = aPos.first;
+ if (it->type == sc::element_type_formula)
+ {
+ ScFormulaCell* pFC = sc::formula_block::at(*it->data, aPos.second);
+ ScFormulaCellGroupRef xGroup = pFC->GetCellGroup();
+ if (xGroup && !pFC->IsSharedTop())
+ {
+ // End listening.
+ pFC->EndListeningTo(rCxt);
+ if (pGroupPos)
+ {
+ // Record the position of the bottom cell of the group.
+ ScAddress aPosLast = xGroup->mpTopCell->aPos;
+ aPosLast.IncRow(xGroup->mnLength-1);
+ pGroupPos->push_back(aPosLast);
+ }
+ }
+ }
+}
+
+void ScColumn::SetNeedsListeningGroup( SCROW nRow )
+{
+ sc::CellStoreType::position_type aPos = maCells.position(nRow);
+ if (aPos.first->type != sc::element_type_formula)
+ // not a formula cell.
+ return;
+
+ ScFormulaCell** pp = &sc::formula_block::at(*aPos.first->data, aPos.second);
+
+ ScFormulaCellGroupRef xGroup = (*pp)->GetCellGroup();
+ if (!xGroup)
+ {
+ // not a formula group.
+ (*pp)->SetNeedsListening(true);
+ return;
+ }
+
+ // Move back to the top cell.
+ SCROW nTopDelta = (*pp)->aPos.Row() - xGroup->mpTopCell->aPos.Row();
+ for (SCROW i = 0; i < nTopDelta; ++i)
+ --pp;
+
+ // Set the needs listening flag to all cells in the group.
+ assert(*pp == xGroup->mpTopCell);
+ ScFormulaCell** ppEnd = pp + xGroup->mnLength;
+ for (; pp != ppEnd; ++pp)
+ (*pp)->SetNeedsListening(true);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 9f9e45ee41ee..a4133883d104 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1218,11 +1218,22 @@ bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
SCTAB nTabRangeStart = nStartTab;
SCTAB nTabRangeEnd = nEndTab;
lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
+ ScRange aShiftedRange(nStartCol, nStartRow, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
+ sc::EndListeningContext aEndListenCxt(*this);
+
+ std::vector<ScAddress> aGroupPos;
do
{
- UpdateBroadcastAreas( URM_INSDEL, ScRange(
- ScAddress( nStartCol, nStartRow, nTabRangeStart ),
- ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, static_cast<SCsROW>(nSize), 0 );
+ aShiftedRange.aStart.SetTab(nTabRangeStart);
+ aShiftedRange.aEnd.SetTab(nTabRangeEnd);
+
+ // Collect all formula groups that will get split by the shifting,
+ // and end all their listening. Record the position of the top
+ // cell of the topmost group, and the postion of the bottom cell
+ // of the bottommost group.
+ EndListeningIntersectedGroups(aEndListenCxt, aShiftedRange, &aGroupPos);
+
+ UpdateBroadcastAreas(URM_INSDEL, aShiftedRange, 0, static_cast<SCsROW>(nSize), 0);
}
while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
@@ -1230,14 +1241,21 @@ bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
sc::RefUpdateContext aCxt(*this);
aCxt.meMode = URM_INSDEL;
- aCxt.maRange = ScRange(nStartCol, nStartRow, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
+ aCxt.maRange = aShiftedRange;
aCxt.mnRowDelta = nSize;
do
{
+ aCxt.maRange.aStart.SetTab(nTabRangeStart);
+ aCxt.maRange.aEnd.SetTab(nTabRangeEnd);
UpdateReference(aCxt, pRefUndoDoc, false); // without drawing objects
}
while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
+ // UpdateReference should have set "needs listening" flags to those
+ // whose references have been modified. We also need to set this flag
+ // to those that were in the groups that got split by shifting.
+ SetNeedsListeningGroups(aGroupPos);
+
for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
maTabs[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize );
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 1f14d5dd16cd..c426a196cf56 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -355,4 +355,33 @@ bool ScDocument::HasFormulaCell( const ScRange& rRange ) const
return false;
}
+void ScDocument::EndListeningIntersectedGroups(
+ sc::EndListeningContext& rCxt, const ScRange& rRange, std::vector<ScAddress>* pGroupPos )
+{
+ for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+ {
+ ScTable* pTab = FetchTable(nTab);
+ if (!pTab)
+ continue;
+
+ pTab->EndListeningIntersectedGroups(
+ rCxt, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(),
+ pGroupPos);
+ }
+}
+
+void ScDocument::SetNeedsListeningGroups( const std::vector<ScAddress>& rPosArray )
+{
+ std::vector<ScAddress>::const_iterator it = rPosArray.begin(), itEnd = rPosArray.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScAddress& rPos = *it;
+ ScTable* pTab = FetchTable(rPos.Tab());
+ if (!pTab)
+ return;
+
+ pTab->SetNeedsListeningGroup(rPos.Col(), rPos.Row());
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index 79a645cbbf5e..f9e429a49f06 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -199,4 +199,23 @@ bool ScTable::HasFormulaCell( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2
return false;
}
+void ScTable::EndListeningIntersectedGroups(
+ sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+ std::vector<ScAddress>* pGroupPos )
+{
+ if (nCol2 < nCol1 || !ValidCol(nCol1) || !ValidCol(nCol2))
+ return;
+
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ aCol[nCol].EndListeningIntersectedGroups(rCxt, nRow1, nRow2, pGroupPos);
+}
+
+void ScTable::SetNeedsListeningGroup( SCCOL nCol, SCROW nRow )
+{
+ if (!ValidCol(nCol))
+ return;
+
+ aCol[nCol].SetNeedsListeningGroup(nRow);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */