diff options
author | Marco Cecchetti <marco.cecchetti@collabora.com> | 2017-04-19 22:37:13 +0200 |
---|---|---|
committer | Marco Cecchetti <mrcekets@gmail.com> | 2017-10-02 18:42:57 +0200 |
commit | 6388a50c1e3ef2e25132f63547bb91d08a0f416c (patch) | |
tree | e9eccab1f95b42eed7feb7bbb3e50ec912290678 | |
parent | b9e89a201064b0c0aef5769766bce8d995fed46d (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.hxx | 3 | ||||
-rw-r--r-- | sc/inc/markarr.hxx | 3 | ||||
-rw-r--r-- | sc/inc/markdata.hxx | 3 | ||||
-rw-r--r-- | sc/inc/markmulti.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/markarr.cxx | 117 | ||||
-rw-r--r-- | sc/source/core/data/markdata.cxx | 27 | ||||
-rw-r--r-- | sc/source/core/data/markmulti.cxx | 74 | ||||
-rw-r--r-- | sc/source/core/tool/address.cxx | 40 | ||||
-rw-r--r-- | sc/source/ui/app/inputhdl.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/docshell/docfunc.cxx | 33 | ||||
-rw-r--r-- | sc/source/ui/inc/viewdata.hxx | 5 | ||||
-rw-r--r-- | sc/source/ui/inc/viewfunc.hxx | 4 | ||||
-rw-r--r-- | sc/source/ui/undo/undoblk.cxx | 44 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwsh4.cxx | 13 | ||||
-rw-r--r-- | sc/source/ui/view/viewdata.cxx | 39 | ||||
-rw-r--r-- | sc/source/ui/view/viewfunc.cxx | 97 |
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 ) |