summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Cecchetti <marco.cecchetti@collabora.com>2017-04-19 22:37:13 +0200
committerMarco Cecchetti <mrcekets@gmail.com>2017-10-02 18:42:57 +0200
commit6388a50c1e3ef2e25132f63547bb91d08a0f416c (patch)
treee9eccab1f95b42eed7feb7bbb3e50ec912290678
parentb9e89a201064b0c0aef5769766bce8d995fed46d (diff)
lok: sc: overlays and edit view misplaced by other view actions
The edit view, the cell cursor and the cell selection overlays become misplaced when another user inserts, deletes or resizes a row. The same is true for columns. The solution takes care of the current tab each view is displaying and of undo/redo actions. Change-Id: I24c94f774f3b18028c9356a904e1b14b07c5c61a Reviewed-on: https://gerrit.libreoffice.org/40016 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Marco Cecchetti <mrcekets@gmail.com>
-rw-r--r--sc/inc/address.hxx3
-rw-r--r--sc/inc/markarr.hxx3
-rw-r--r--sc/inc/markdata.hxx3
-rw-r--r--sc/inc/markmulti.hxx2
-rw-r--r--sc/source/core/data/markarr.cxx117
-rw-r--r--sc/source/core/data/markdata.cxx27
-rw-r--r--sc/source/core/data/markmulti.cxx74
-rw-r--r--sc/source/core/tool/address.cxx40
-rw-r--r--sc/source/ui/app/inputhdl.cxx4
-rw-r--r--sc/source/ui/docshell/docfunc.cxx33
-rw-r--r--sc/source/ui/inc/viewdata.hxx5
-rw-r--r--sc/source/ui/inc/viewfunc.hxx4
-rw-r--r--sc/source/ui/undo/undoblk.cxx44
-rw-r--r--sc/source/ui/view/tabvwsh4.cxx13
-rw-r--r--sc/source/ui/view/viewdata.cxx39
-rw-r--r--sc/source/ui/view/viewfunc.cxx97
16 files changed, 495 insertions, 13 deletions
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 8f6ba1f32296..b5b7f1ad689a 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -621,6 +621,9 @@ public:
SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool MoveSticky( SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
ScRange& rErrorRange );
+ SC_DLLPUBLIC void IncColIfNotLessThan(SCCOL nStartCol, SCCOL nOffset);
+ SC_DLLPUBLIC void IncRowIfNotLessThan(SCROW nStartRow, SCROW nOffset);
+
SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
SC_DLLPUBLIC bool Intersects( const ScRange& rRange ) const; // do two ranges intersect?
diff --git a/sc/inc/markarr.hxx b/sc/inc/markarr.hxx
index 548d023db4d4..4b538d9131fe 100644
--- a/sc/inc/markarr.hxx
+++ b/sc/inc/markarr.hxx
@@ -60,6 +60,9 @@ public:
/// Including current row, may return -1 if bUp and not found
SCROW GetNextMarked( SCROW nRow, bool bUp ) const;
SCROW GetMarkEnd( SCROW nRow, bool bUp ) const;
+
+ void Shift( SCROW nStartRow, long nOffset );
+ void Intersect( const ScMarkArray& rOther );
};
class ScMarkArrayIter // iterate over selected range
diff --git a/sc/inc/markdata.hxx b/sc/inc/markdata.hxx
index 51f63a477d67..26387109b833 100644
--- a/sc/inc/markdata.hxx
+++ b/sc/inc/markdata.hxx
@@ -142,6 +142,9 @@ public:
void InsertTab( SCTAB nTab );
void DeleteTab( SCTAB nTab );
+ void ShiftCols(SCCOL nStartCol, long nColOffset);
+ void ShiftRows(SCROW nStartRow, long nRowOffset);
+
// Generate envelopes if multimarked and fills the passed ScRange object with
// the smallest range that includes the marked area plus its envelopes.
void GetSelectionCover( ScRange& rRange );
diff --git a/sc/inc/markmulti.hxx b/sc/inc/markmulti.hxx
index 6ada78c243e6..cf68a403fb21 100644
--- a/sc/inc/markmulti.hxx
+++ b/sc/inc/markmulti.hxx
@@ -63,6 +63,8 @@ public:
void Clear();
void MarkAllCols( SCROW nStartRow, SCROW nEndRow );
bool HasAnyMarks() const;
+ void ShiftCols(SCCOL nStartCol, long nColOffset);
+ void ShiftRows(SCROW nStartRow, long nRowOffset);
// For faster access from within ScMarkData, instead of creating
// ScMultiSelIter with ScFlatBoolRowSegments bottleneck.
diff --git a/sc/source/core/data/markarr.cxx b/sc/source/core/data/markarr.cxx
index 248ddd0cb4c0..81c8f94fbac4 100644
--- a/sc/source/core/data/markarr.cxx
+++ b/sc/source/core/data/markarr.cxx
@@ -172,10 +172,10 @@ void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, bool bMarked )
}
}
else
- {
+ {
nInsert = 0;
ni = 0;
- }
+ }
SCSIZE nj = ni; // stop position of range to replace
while ( nj < nCount && pData[nj].nRow <= nEndRow )
@@ -369,6 +369,119 @@ SCROW ScMarkArray::GetMarkEnd( SCROW nRow, bool bUp ) const
return nRet;
}
+void ScMarkArray::Shift(SCROW nStartRow, long nOffset)
+{
+ if (!pData || nOffset == 0 || nStartRow > MAXROW)
+ return;
+
+ for (size_t i=0; i < nCount; ++i)
+ {
+ auto& rEntry = pData[i];
+
+ if (rEntry.nRow < nStartRow)
+ continue;
+ rEntry.nRow += nOffset;
+ if (rEntry.nRow < 0)
+ {
+ rEntry.nRow = 0;
+ }
+ else if (rEntry.nRow > MAXROW)
+ {
+ rEntry.nRow = MAXROW;
+ }
+ }
+}
+
+void ScMarkArray::Intersect(const ScMarkArray& rOther)
+{
+ if (!pData || !rOther.pData)
+ return;
+
+ size_t i = 0;
+ size_t j = 0;
+
+ std::vector<ScMarkEntry> aEntryArray;
+ aEntryArray.reserve(std::max(nCount, rOther.nCount));
+
+ while (i < nCount && j < rOther.nCount)
+ {
+ const auto& rEntry = pData[i];
+ const auto& rOtherEntry = rOther.pData[j];
+
+ if (rEntry.bMarked != rOtherEntry.bMarked)
+ {
+ if (!rOtherEntry.bMarked)
+ {
+ aEntryArray.push_back(rOther.pData[j++]);
+ while (i < nCount && pData[i].nRow <= rOtherEntry.nRow)
+ ++i;
+ }
+ else // rEntry not marked
+ {
+ aEntryArray.push_back(pData[i++]);
+ while (j < rOther.nCount && rOther.pData[j].nRow <= rEntry.nRow)
+ ++j;
+ }
+ }
+ else // rEntry.bMarked == rOtherEntry.bMarked
+ {
+ if (rEntry.bMarked) // both marked
+ {
+ if (rEntry.nRow <= rOtherEntry.nRow)
+ {
+ aEntryArray.push_back(pData[i++]); // upper row
+ if (rEntry.nRow == rOtherEntry.nRow)
+ ++j;
+ }
+ else
+ {
+ aEntryArray.push_back(rOther.pData[j++]); // upper row
+ }
+ }
+ else // both not marked
+ {
+ if (rEntry.nRow <= rOtherEntry.nRow)
+ {
+ aEntryArray.push_back(rOther.pData[j++]); // lower row
+ while (i < nCount && pData[i].nRow <= rOtherEntry.nRow)
+ ++i;
+ }
+ else
+ {
+ aEntryArray.push_back(pData[i++]); // lower row
+ while (j < rOther.nCount && rOther.pData[j].nRow <= rEntry.nRow)
+ ++j;
+ }
+ }
+ }
+ }
+
+ OSL_ENSURE(i == nCount || j == rOther.nCount, "Unexpected case.");
+
+ if (i == nCount)
+ {
+ for (; j < rOther.nCount; ++j)
+ {
+ aEntryArray.push_back(rOther.pData[j]);
+ }
+ }
+ else // j == rOther.nCount
+ {
+ for (; i < nCount; ++i)
+ {
+ aEntryArray.push_back(pData[i]);
+ }
+ }
+
+ size_t nSize = aEntryArray.size();
+ OSL_ENSURE(nSize > 0, "Unexpected case.");
+
+ pData.reset(new ScMarkEntry[nSize]);
+ memcpy(pData.get(), &(aEntryArray[0]), nSize * sizeof(ScMarkEntry));
+ nCount = nLimit = nSize;
+}
+
+
// -------------- Iterator ----------------------------------------------
ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx
index 8c94f196f45d..93a66f8cd68a 100644
--- a/sc/source/core/data/markdata.cxx
+++ b/sc/source/core/data/markdata.cxx
@@ -623,6 +623,33 @@ void ScMarkData::DeleteTab( SCTAB nTab )
maTabMarked.swap(tabMarked);
}
+void ScMarkData::ShiftCols(SCCOL nStartCol, long nColOffset)
+{
+ if (bMarked)
+ {
+ aMarkRange.IncColIfNotLessThan(nStartCol, nColOffset);
+ }
+ else if (bMultiMarked)
+ {
+ aMultiSel.ShiftCols(nStartCol, nColOffset);
+ aMultiRange.IncColIfNotLessThan(nStartCol, nColOffset);
+ }
+}
+
+void ScMarkData::ShiftRows(SCROW nStartRow, long nRowOffset)
+{
+ if (bMarked)
+ {
+ aMarkRange.IncRowIfNotLessThan(nStartRow, nRowOffset);
+ }
+ else if (bMultiMarked)
+ {
+ aMultiSel.ShiftRows(nStartRow, nRowOffset);
+ aMultiRange.IncRowIfNotLessThan(nStartRow, nRowOffset);
+ }
+
+}
+
static void lcl_AddRanges(ScRange& rRangeDest, const ScRange& rNewRange )
{
SCCOL nStartCol = rNewRange.aStart.Col();
diff --git a/sc/source/core/data/markmulti.cxx b/sc/source/core/data/markmulti.cxx
index 091c91eae9ff..d8ac507dcaa7 100644
--- a/sc/source/core/data/markmulti.cxx
+++ b/sc/source/core/data/markmulti.cxx
@@ -296,6 +296,80 @@ bool ScMultiSel::HasAnyMarks() const
return false;
}
+void ScMultiSel::ShiftCols(SCCOL nStartCol, long nColOffset)
+{
+ if (nStartCol > MAXCOL)
+ return;
+
+ ScMultiSel aNewMultiSel(*this);
+ Clear();
+
+ if (nColOffset < 0)
+ {
+ // columns that would be moved on the left of nStartCol must be removed
+ const SCCOL nEndPos = nStartCol - nColOffset;
+ for (SCCOL nSearchPos = nStartCol; nSearchPos < nEndPos; ++nSearchPos)
+ {
+ const auto& aColIt = aNewMultiSel.aMultiSelContainer.find(nSearchPos);
+ if (aColIt != aNewMultiSel.aMultiSelContainer.end())
+ {
+ aNewMultiSel.aMultiSelContainer.erase(aColIt);
+ }
+ }
+ }
+
+ MapType::iterator aDestEnd = aMultiSelContainer.end();
+ MapType::iterator aDestIter = aDestEnd;
+ for (const auto& aSourcePair : aNewMultiSel.aMultiSelContainer)
+ {
+ SCCOL nCol = aSourcePair.first;
+ if (aSourcePair.first >= nStartCol)
+ {
+ nCol += nColOffset;
+ if (nCol < 0)
+ nCol = 0;
+ else if (nCol > MAXCOL)
+ nCol = MAXCOL;
+ }
+ // correct hint is always aDestEnd as keys come in ascending order
+ // Amortized constant time operation as we always give the correct hint
+ aDestIter = aMultiSelContainer.emplace_hint( aDestEnd, nCol, ScMarkArray() );
+ aSourcePair.second.CopyMarksTo(aDestIter->second);
+ }
+ aNewMultiSel.aRowSel.CopyMarksTo(aRowSel);
+
+ if (nColOffset > 0 && nStartCol > 0)
+ {
+ // insert nColOffset new columns, and select their cells if they are selected
+ // both in the old column at nStartPos and in the previous column
+ const auto& aPrevPosIt = aNewMultiSel.aMultiSelContainer.find(nStartCol - 1);
+ if (aPrevPosIt != aNewMultiSel.aMultiSelContainer.end())
+ {
+ const auto& aStartPosIt = aNewMultiSel.aMultiSelContainer.find(nStartCol);
+ if (aStartPosIt != aNewMultiSel.aMultiSelContainer.end())
+ {
+ MapType::iterator aNewColIt = aMultiSelContainer.emplace_hint(aDestEnd, nStartCol, ScMarkArray());
+ aStartPosIt->second.CopyMarksTo(aNewColIt->second);
+ aNewColIt->second.Intersect(aPrevPosIt->second);
+ for (long i = 1; i < nColOffset; ++i)
+ {
+ aDestIter = aMultiSelContainer.emplace_hint(aDestEnd, nStartCol + i, ScMarkArray());
+ aNewColIt->second.CopyMarksTo(aDestIter->second);
+ }
+ }
+ }
+ }
+}
+
+void ScMultiSel::ShiftRows(SCROW nStartRow, long nRowOffset)
+{
+ for (auto& aPair: aMultiSelContainer)
+ {
+ aPair.second.Shift(nStartRow, nRowOffset);
+ }
+ aRowSel.Shift(nStartRow, nRowOffset);
+}
+
const ScMarkArray& ScMultiSel::GetRowSelArray() const
{
return aRowSel;
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 9899044e6ef7..e8c5ed4622ef 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -2382,6 +2382,46 @@ bool ScRange::MoveSticky( SCCOL dx, SCROW dy, SCTAB dz, ScRange& rErrorRange )
return b1 && b2;
}
+void ScRange::IncColIfNotLessThan(SCCOL nStartCol, SCCOL nOffset)
+{
+ if (aStart.Col() >= nStartCol)
+ {
+ aStart.IncCol(nOffset);
+ if (aStart.Col() < 0)
+ aStart.SetCol(0);
+ else if(aStart.Col() > MAXCOL)
+ aStart.SetCol(MAXCOL);
+ }
+ if (aEnd.Col() >= nStartCol)
+ {
+ aEnd.IncCol(nOffset);
+ if (aEnd.Col() < 0)
+ aEnd.SetCol(0);
+ else if(aEnd.Col() > MAXCOL)
+ aEnd.SetCol(MAXCOL);
+ }
+}
+
+void ScRange::IncRowIfNotLessThan(SCROW nStartRow, SCROW nOffset)
+{
+ if (aStart.Row() >= nStartRow)
+ {
+ aStart.IncRow(nOffset);
+ if (aStart.Row() < 0)
+ aStart.SetRow(0);
+ else if(aStart.Row() > MAXROW)
+ aStart.SetRow(MAXROW);
+ }
+ if (aEnd.Row() >= nStartRow)
+ {
+ aEnd.IncRow(nOffset);
+ if (aEnd.Row() < 0)
+ aEnd.SetRow(0);
+ else if(aEnd.Row() > MAXROW)
+ aEnd.SetRow(MAXROW);
+ }
+}
+
void ScRange::IncEndColSticky( SCCOL nDelta )
{
SCCOL nCol = aEnd.Col();
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index a3df618d8cd6..5a0436f6a745 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -2590,6 +2590,10 @@ static void lcl_SelectionToEnd( EditView* pView )
void ScInputHandler::EnterHandler( ScEnterMode nBlockMode )
{
+ if (!mbDocumentDisposing && comphelper::LibreOfficeKit::isActive()
+ && pActiveViewSh != SfxViewShell::Current())
+ return;
+
// Macro calls for validity can cause a lot of problems, so inhibit
// nested calls of EnterHandler().
if (bInEnterHandler) return;
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index c9abf98d6147..7a85a367d36d 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -2132,6 +2132,24 @@ bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark,
rDocShell.ErrorMessage(STR_INSERT_FULL); // column/row full
}
+ // The cursor position needs to be modified earlier than updating
+ // any enabled edit view which is triggered by SetDocumentModified below.
+ if (bSuccess)
+ {
+ bool bInsertCols = ( eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER);
+ bool bInsertRows = ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER );
+
+ if (bInsertCols)
+ {
+ pViewSh->OnLOKInsertDeleteColumn(rRange.aStart.Col(), 1);
+ }
+
+ if (bInsertRows)
+ {
+ pViewSh->OnLOKInsertDeleteRow(rRange.aStart.Row(), 1);
+ }
+ }
+
aModificator.SetDocumentModified();
SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );
@@ -2658,6 +2676,21 @@ bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark,
}
}
+ // The cursor position needs to be modified earlier than updating
+ // any enabled edit view which is triggered by SetDocumentModified below.
+ ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
+ if (pViewSh)
+ {
+ if (eCmd == DEL_DELCOLS)
+ {
+ pViewSh->OnLOKInsertDeleteColumn(rRange.aStart.Col(), -1);
+ }
+ if (eCmd == DEL_DELROWS)
+ {
+ pViewSh->OnLOKInsertDeleteRow(rRange.aStart.Row(), -1);
+ }
+ }
+
aModificator.SetDocumentModified();
SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );
diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx
index 93df48d61dc1..bd1288d6ba9c 100644
--- a/sc/source/ui/inc/viewdata.hxx
+++ b/sc/source/ui/inc/viewdata.hxx
@@ -298,8 +298,11 @@ public:
SCROW GetPosY( ScVSplitPos eWhich ) const { return pThisTab->nPosY[eWhich]; }
SCCOL GetCurX() const { return pThisTab->nCurX; }
SCROW GetCurY() const { return pThisTab->nCurY; }
+ SCCOL GetCurXForTab( SCTAB nTabIndex ) const;
+ SCROW GetCurYForTab( SCTAB nTabIndex ) const;
SCCOL GetOldCurX() const;
SCROW GetOldCurY() const;
+
ScSplitMode GetHSplitMode() const { return pThisTab->eHSplitMode; }
ScSplitMode GetVSplitMode() const { return pThisTab->eVSplitMode; }
long GetHSplitPos() const { return pThisTab->nHSplitPos; }
@@ -317,6 +320,8 @@ public:
void SetPosY( ScVSplitPos eWhich, SCROW nNewPosY );
void SetCurX( SCCOL nNewCurX ) { pThisTab->nCurX = nNewCurX; }
void SetCurY( SCROW nNewCurY ) { pThisTab->nCurY = nNewCurY; }
+ void SetCurXForTab( SCCOL nNewCurX, SCTAB nTabIndex );
+ void SetCurYForTab( SCCOL nNewCurY, SCTAB nTabIndex );
void SetOldCursor( SCCOL nNewX, SCROW nNewY );
void ResetOldCursor();
void SetHSplitMode( ScSplitMode eMode ) { pThisTab->eHSplitMode = eMode; }
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index 507d6adb44d0..20ed2bccb09e 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -322,6 +322,10 @@ public:
std::vector<VclPtr<Edit> >& aEdits,
sal_uInt16 aColLength );
void UpdateSelectionArea( const ScMarkData& rSel, ScPatternAttr* pAttr = nullptr );
+
+ void OnLOKInsertDeleteColumn(SCCOL nStartCol, long nOffset);
+ void OnLOKInsertDeleteRow(SCROW nStartRow, long nOffset);
+
// Internal helper functions
protected:
static void UpdateLineAttrs( ::editeng::SvxBorderLine& rLine,
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 5ca8efebab7c..3b7de1a31273 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -156,6 +156,7 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
// refresh of merged cells has to be after inserting/deleting
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
switch (eCmd)
{
case INS_INSROWS_BEFORE:
@@ -163,12 +164,19 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
case INS_CELLSDOWN:
for( i=0; i<nCount; i++ )
{
+
if (bUndo)
rDoc.DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
else
rDoc.InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+
+ if (pViewShell)
+ {
+ const long nSign = bUndo ? -1 : 1;
+ pViewShell->OnLOKInsertDeleteRow(aEffRange.aStart.Row(), nSign * (aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+ }
}
break;
case INS_INSCOLS_BEFORE:
@@ -182,6 +190,12 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
else
rDoc.InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+
+ if (pViewShell)
+ {
+ const long nSign = bUndo ? -1 : 1;
+ pViewShell->OnLOKInsertDeleteColumn(aEffRange.aStart.Col(), nSign * (aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+ }
}
break;
default:
@@ -207,7 +221,7 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
// Undo for displaced attributes?
PaintPartFlags nPaint = PaintPartFlags::Grid;
- ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
switch (eCmd)
{
case INS_INSROWS_BEFORE:
@@ -380,6 +394,8 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
else
SetChangeTrack();
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
switch (eCmd)
{
case DEL_DELROWS:
@@ -392,6 +408,12 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
else
rDoc.DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+
+ if (pViewShell)
+ {
+ const long nSign = bUndo ? 1 : -1;
+ pViewShell->OnLOKInsertDeleteRow(aEffRange.aStart.Row(), nSign * (aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
+ }
}
break;
case DEL_DELCOLS:
@@ -404,6 +426,12 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
else
rDoc.DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+
+ if (pViewShell)
+ {
+ const long nSign = bUndo ? 1 : -1;
+ pViewShell->OnLOKInsertDeleteColumn(aEffRange.aStart.Col(), nSign * (aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
+ }
}
break;
default:
@@ -502,6 +530,20 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
pDocShell->PostDataChanged();
// CellContentChanged comes with the selection
+
+ if (pViewShell)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (eCmd == DEL_DELCOLS || eCmd == DEL_CELLSLEFT)
+ ScTabViewShell::notifyAllViewsHeaderInvalidation("column", pViewShell->GetViewData().GetTabNo());
+
+ if (eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP)
+ ScTabViewShell::notifyAllViewsHeaderInvalidation("row", pViewShell->GetViewData().GetTabNo());
+ }
+
+ }
+
}
void ScUndoDeleteCells::Undo()
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index 244aec9bfc06..5f15c438b891 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -1746,6 +1746,14 @@ ScTabViewShell::~ScTabViewShell()
SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_CELL_VIEW_CURSOR, "rectangle", "EMPTY");
+ // all to NULL, in case the TabView-dtor tries to access them
+ //! (should not really! ??!?!)
+ if (mpInputHandler)
+ mpInputHandler->SetDocumentDisposing(true);
+ // We end edit mode, before destroying the input handler and the edit engine
+ // and before end listening (in order to call ScTabViewShell::KillEditView())
+ mpInputHandler->EnterHandler();
+
ScDocShell* pDocSh = GetViewData().GetDocShell();
EndListening(*pDocSh);
EndListening(*GetViewFrame());
@@ -1756,11 +1764,6 @@ ScTabViewShell::~ScTabViewShell()
RemoveSubShell(); // all
SetWindow(nullptr);
- // all to NULL, in case the TabView-dtor tries to access them
- //! (should not really! ??!?!)
- if (mpInputHandler)
- mpInputHandler->SetDocumentDisposing(true);
-
DELETEZ(pFontworkBarShell);
DELETEZ(pExtrusionBarShell);
DELETEZ(pCellShell);
diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index d978ef826292..92647acb5a5e 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -971,6 +971,38 @@ void ScViewData::ResetOldCursor()
pThisTab->mbOldCursorValid = false;
}
+SCCOL ScViewData::GetCurXForTab( SCTAB nTabIndex ) const
+{
+ if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+ return -1;
+
+ return maTabData[nTabIndex]->nCurX;
+}
+
+SCROW ScViewData::GetCurYForTab( SCTAB nTabIndex ) const
+{
+ if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+ return -1;
+
+ return maTabData[nTabIndex]->nCurY;
+}
+
+void ScViewData::SetCurXForTab( SCCOL nNewCurX, SCTAB nTabIndex )
+{
+ if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+ return;
+
+ maTabData[nTabIndex]->nCurX = nNewCurX;
+}
+
+void ScViewData::SetCurYForTab( SCCOL nNewCurY, SCTAB nTabIndex )
+{
+ if (!ValidTab(nTabIndex) || !(nTabIndex < static_cast<SCTAB>(maTabData.size())))
+ return;
+
+ maTabData[nTabIndex]->nCurY = nNewCurY;
+}
+
tools::Rectangle ScViewData::GetEditArea( ScSplitPos eWhich, SCCOL nPosX, SCROW nPosY,
vcl::Window* pWin, const ScPatternAttr* pPattern,
bool bForceToTop )
@@ -984,10 +1016,6 @@ void ScViewData::SetEditEngine( ScSplitPos eWhich,
ScEditEngineDefaulter* pNewEngine,
vcl::Window* pWin, SCCOL nNewX, SCROW nNewY )
{
- if (comphelper::LibreOfficeKit::isActive()
- && GetViewShell() != SfxViewShell::Current())
- return;
-
bool bLayoutRTL = pDoc->IsLayoutRTL( nTabNo );
ScHSplitPos eHWhich = WhichH(eWhich);
@@ -1023,7 +1051,8 @@ void ScViewData::SetEditEngine( ScSplitPos eWhich,
}
// add windows from other views
- if (comphelper::LibreOfficeKit::isActive())
+ if (!bWasThere && comphelper::LibreOfficeKit::isActive())
+ //if (comphelper::LibreOfficeKit::isActive())
{
ScTabViewShell* pThisViewShell = GetViewShell();
SCTAB nThisTabNo = GetTabNo();
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 3a33dcb514d7..5eae272a9a43 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -1465,6 +1465,103 @@ void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
pHdl->ForgetLastPattern();
}
+
+void ScViewFunc::OnLOKInsertDeleteColumn(SCCOL nStartCol, long nOffset)
+{
+ if (!comphelper::LibreOfficeKit::isActive() || nOffset == 0)
+ return;
+
+ SCTAB nCurrentTabIndex = GetViewData().GetTabNo();
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ while (pViewShell)
+ {
+ ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
+ if (pTabViewShell)
+ {
+ // if we remove a column the cursor position and the current selection
+ // in other views could need to be moved on the left by one column.
+ if (pTabViewShell != this)
+ {
+ if (pTabViewShell->getPart() == nCurrentTabIndex)
+ {
+ SCCOL nX = pTabViewShell->GetViewData().GetCurX();
+ if (nX > nStartCol || (nX == nStartCol && nOffset > 0))
+ {
+ SCROW nY = pTabViewShell->GetViewData().GetCurY();
+ pTabViewShell->SetCursor(nX + nOffset, nY);
+ }
+
+ ScMarkData aMultiMark( pTabViewShell->GetViewData().GetMarkData() );
+ aMultiMark.SetMarking( false );
+ aMultiMark.MarkToMulti();
+ if (aMultiMark.IsMultiMarked())
+ {
+ aMultiMark.ShiftCols(nStartCol, nOffset);
+ pTabViewShell->SetMarkData(aMultiMark);
+ }
+ }
+ else
+ {
+ SCROW nX = pTabViewShell->GetViewData().GetCurXForTab(nCurrentTabIndex);
+ if (nX > nStartCol || (nX == nStartCol && nOffset > 0))
+ {
+ pTabViewShell->GetViewData().SetCurXForTab(nX + nOffset, nCurrentTabIndex);
+ }
+ }
+ }
+ }
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+}
+
+void ScViewFunc::OnLOKInsertDeleteRow(SCROW nStartRow, long nOffset)
+{
+ if (!comphelper::LibreOfficeKit::isActive() || nOffset == 0)
+ return;
+
+ SCTAB nCurrentTabIndex = GetViewData().GetTabNo();
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ while (pViewShell)
+ {
+ ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
+ if (pTabViewShell)
+ {
+ // if we remove a row the cursor position and the current selection
+ // in other views could need to be moved up by one row.
+ if (pTabViewShell != this)
+ {
+ if (pTabViewShell->getPart() == nCurrentTabIndex)
+ {
+ SCROW nY = pTabViewShell->GetViewData().GetCurY();
+ if (nY > nStartRow || (nY == nStartRow && nOffset > 0))
+ {
+ SCCOL nX = pTabViewShell->GetViewData().GetCurX();
+ pTabViewShell->SetCursor(nX, nY + nOffset);
+ }
+
+ ScMarkData aMultiMark( pTabViewShell->GetViewData().GetMarkData() );
+ aMultiMark.SetMarking( false );
+ aMultiMark.MarkToMulti();
+ if (aMultiMark.IsMultiMarked())
+ {
+ aMultiMark.ShiftRows(nStartRow, nOffset);
+ pTabViewShell->SetMarkData(aMultiMark);
+ }
+ }
+ else
+ {
+ SCROW nY = pTabViewShell->GetViewData().GetCurYForTab(nCurrentTabIndex);
+ if (nY >= nStartRow || (nY == nStartRow && nOffset > 0))
+ {
+ pTabViewShell->GetViewData().SetCurYForTab(nY + nOffset, nCurrentTabIndex);
+ }
+ }
+ }
+ }
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+}
+
// insert cells - undo OK
bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste )