diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2018-08-17 17:52:52 +0200 |
---|---|---|
committer | Michael Stahl <Michael.Stahl@cib.de> | 2018-09-19 10:08:55 +0200 |
commit | 7fdba6a506533571455cb3ef0532c971dbee210c (patch) | |
tree | 8e60d4d8bd508d62520a21da158eb5c86b32baa7 | |
parent | 7273b79c542e37384b9b71e28163e496cd762a85 (diff) |
sw_redlinehide_2: invalidate when delete redline goes away
Add another new hint sw::RedlineUnDelText; the main use case is to send
it from DocumentRedlineManager::DeleteRedline() so the view is updated
accordingly.
Change-Id: Ia490116588dc8d3c695ec83c0c2ce8497736f76e
-rw-r--r-- | sw/inc/hints.hxx | 11 | ||||
-rw-r--r-- | sw/inc/redline.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/attr/hints.cxx | 5 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentRedlineManager.cxx | 18 | ||||
-rw-r--r-- | sw/source/core/doc/docredln.cxx | 27 | ||||
-rw-r--r-- | sw/source/core/layout/wsfrm.cxx | 2 | ||||
-rw-r--r-- | sw/source/core/text/txtfrm.cxx | 124 | ||||
-rw-r--r-- | sw/source/core/undo/unredln.cxx | 4 |
8 files changed, 158 insertions, 36 deletions
diff --git a/sw/inc/hints.hxx b/sw/inc/hints.hxx index dc31d7424756..bee0ebb1c21a 100644 --- a/sw/inc/hints.hxx +++ b/sw/inc/hints.hxx @@ -95,6 +95,7 @@ public: namespace sw { +/// new delete redline is created class RedlineDelText : public SfxHint { public: @@ -104,6 +105,16 @@ public: RedlineDelText(sal_Int32 nS, sal_Int32 nL); }; +/// delete redline is removed +class RedlineUnDelText : public SfxHint +{ +public: + sal_Int32 nStart; + sal_Int32 nLen; + + RedlineUnDelText(sal_Int32 nS, sal_Int32 nL); +}; + } class SwUpdateAttr : public SwMsgPoolItem diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx index c307792d80b0..8b6e2a27a0c3 100644 --- a/sw/inc/redline.hxx +++ b/sw/inc/redline.hxx @@ -253,8 +253,9 @@ public: /// Calculates the intersection with text node number nNdIdx. void CalcStartEnd(sal_uLong nNdIdx, sal_Int32& rStart, sal_Int32& rEnd) const; + enum class Invalidation { Add, Remove }; /// Initiate the layout. - void InvalidateRange(); + void InvalidateRange(Invalidation); bool IsOwnRedline( const SwRangeRedline& rRedl ) const { return GetAuthor() == rRedl.GetAuthor(); } diff --git a/sw/source/core/attr/hints.cxx b/sw/source/core/attr/hints.cxx index 44c60ff0fd17..7c1ff2a40aec 100644 --- a/sw/source/core/attr/hints.cxx +++ b/sw/source/core/attr/hints.cxx @@ -53,6 +53,11 @@ RedlineDelText::RedlineDelText(sal_Int32 const nS, sal_Int32 const nL) { } +RedlineUnDelText::RedlineUnDelText(sal_Int32 const nS, sal_Int32 const nL) + : nStart(nS), nLen(nL) +{ +} + } // namespace sw SwUpdateAttr::SwUpdateAttr( sal_Int32 nS, sal_Int32 nE, sal_uInt16 nW ) diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 95ed87d7c818..425a42b1a94a 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -140,7 +140,7 @@ namespace eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd ); } - pRedl->InvalidateRange(); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); switch( pRedl->GetType() ) { @@ -303,7 +303,7 @@ namespace eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd ); } - pRedl->InvalidateRange(); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); switch( pRedl->GetType() ) { @@ -783,7 +783,7 @@ DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCall if (IsRedlineOn() && !IsShowOriginal(meRedlineFlags)) { - pNewRedl->InvalidateRange(); + pNewRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); if( m_rDoc.IsAutoFormatRedline() ) { @@ -1932,7 +1932,7 @@ bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange ) break; case 3: - pRedline->InvalidateRange(); + pRedline->InvalidateRange(SwRangeRedline::Invalidation::Remove); mpRedlineTable->DeleteAndDestroy( n-- ); pRedline = nullptr; break; @@ -1992,13 +1992,13 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd { case SwComparePosition::Equal: case SwComparePosition::Outside: - pRedl->InvalidateRange(); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); mpRedlineTable->DeleteAndDestroy( n-- ); bChg = true; break; case SwComparePosition::OverlapBefore: - pRedl->InvalidateRange(); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); pRedl->SetStart( *pEnd, pRStt ); // re-insert mpRedlineTable->Remove( n ); @@ -2007,7 +2007,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd break; case SwComparePosition::OverlapBehind: - pRedl->InvalidateRange(); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); pRedl->SetEnd( *pStt, pREnd ); if( !pRedl->HasValidRange() ) { @@ -2021,7 +2021,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd case SwComparePosition::Inside: { // this one needs to be splitted - pRedl->InvalidateRange(); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); if( *pRStt == *pStt ) { pRedl->SetStart( *pEnd, pRStt ); @@ -2744,7 +2744,7 @@ void DocumentRedlineManager::UpdateRedlineAttr() for(SwRangeRedline* pRedl : rTable) { if( pRedl->IsVisible() ) - pRedl->InvalidateRange(); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); } // #TODO - add 'SwExtraRedlineTable' also ? diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx index fa7b749d4c06..da79c099b14e 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -1166,7 +1166,7 @@ void SwRangeRedline::Show(sal_uInt16 nLoop, size_t nMyPos) case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified - InvalidateRange(); + InvalidateRange(Invalidation::Add); break; default: break; @@ -1203,7 +1203,7 @@ void SwRangeRedline::Hide(sal_uInt16 nLoop, size_t nMyPos) case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified if( 1 <= nLoop ) - InvalidateRange(); + InvalidateRange(Invalidation::Remove); break; default: break; @@ -1245,7 +1245,7 @@ void SwRangeRedline::ShowOriginal(sal_uInt16 nLoop, size_t nMyPos) case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified if( 1 <= nLoop ) - InvalidateRange(); + InvalidateRange(Invalidation::Remove); break; default: break; @@ -1253,7 +1253,8 @@ void SwRangeRedline::ShowOriginal(sal_uInt16 nLoop, size_t nMyPos) pDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld ); } -void SwRangeRedline::InvalidateRange() // trigger the Layout +// trigger the Layout +void SwRangeRedline::InvalidateRange(Invalidation const eWhy) { sal_uLong nSttNd = GetMark()->nNode.GetIndex(), nEndNd = GetPoint()->nNode.GetIndex(); @@ -1286,9 +1287,17 @@ void SwRangeRedline::InvalidateRange() // trigger the Layout if (GetType() == nsRedlineType_t::REDLINE_DELETE) { sal_Int32 const nStart(n == nSttNd ? nSttCnt : 0); - sw::RedlineDelText const hint(nStart, - (n == nEndNd ? nEndCnt : pNd->GetText().getLength()) - nStart); - pNd->CallSwClientNotify(hint); + sal_Int32 const nLen((n == nEndNd ? nEndCnt : pNd->GetText().getLength()) - nStart); + if (eWhy == Invalidation::Add) + { + sw::RedlineDelText const hint(nStart, nLen); + pNd->CallSwClientNotify(hint); + } + else + { + sw::RedlineUnDelText const hint(nStart, nLen); + pNd->CallSwClientNotify(hint); + } } } } @@ -1400,7 +1409,7 @@ void SwRangeRedline::MoveToSection() DeleteMark(); } else - InvalidateRange(); + InvalidateRange(Invalidation::Remove); } void SwRangeRedline::CopyToSection() @@ -1680,7 +1689,7 @@ void SwRangeRedline::MoveFromSection(size_t nMyPos) *pItem = *End(); } else - InvalidateRange(); + InvalidateRange(Invalidation::Add); } // for Undo diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 28e1c7739e7c..57b6f698e0da 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -4466,7 +4466,7 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines) // trigger repaint of text frames to add/remove the redline color font if (pRedline->GetType() != nsRedlineType_t::REDLINE_DELETE) { - pRedline->InvalidateRange(); + pRedline->InvalidateRange(SwRangeRedline::Invalidation::Add); } } diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index 4a0ce81e2cb4..212fc0b40e28 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -722,15 +722,23 @@ SwTextFrame::~SwTextFrame() namespace sw { -static void UpdateMergedParaForInsert(MergedPara & rMerged, +// 1. if real insert => correct nStart/nEnd for full nLen +// 2. if rl un-delete => do not correct nStart/nEnd but just include un-deleted +static TextFrameIndex UpdateMergedParaForInsert(MergedPara & rMerged, + bool const isRealInsert, SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen) { - assert(nLen); // can 0 happen? + assert(!isRealInsert || nLen); // can 0 happen? yes, for redline in empty node assert(nIndex <= rNode.Len()); assert(nIndex + nLen <= rNode.Len()); assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex()); + if (!nLen) + { + return TextFrameIndex(0); + } OUStringBuffer text(rMerged.mergedText); sal_Int32 nTFIndex(0); + sal_Int32 nInserted(0); bool bInserted(false); bool bFoundNode(false); auto itInsert(rMerged.extents.end()); @@ -738,22 +746,75 @@ static void UpdateMergedParaForInsert(MergedPara & rMerged, { if (it->pNode == &rNode) { - bFoundNode = true; - if (it->nStart <= nIndex && nIndex <= it->nEnd) - { // note: this can happen only once - text.insert(nTFIndex + (nIndex - it->nStart), - rNode.GetText().copy(nIndex, nLen)); - it->nEnd += nLen; - bInserted = true; + if (isRealInsert) + { + bFoundNode = true; + if (it->nStart <= nIndex && nIndex <= it->nEnd) + { // note: this can happen only once + text.insert(nTFIndex + (nIndex - it->nStart), + rNode.GetText().copy(nIndex, nLen)); + it->nEnd += nLen; + nInserted = nLen; + assert(!bInserted); + bInserted = true; + } + else if (nIndex < it->nStart) + { + if (itInsert == rMerged.extents.end()) + { + itInsert = it; + } + it->nStart += nLen; + it->nEnd += nLen; + } } - else if (nIndex < it->nStart) + else { - if (itInsert == rMerged.extents.end()) + assert(it == rMerged.extents.begin() || (it-1)->pNode != &rNode || (it-1)->nEnd < nIndex); + if (nIndex + nLen < it->nStart) { itInsert = it; + break; + } + if (nIndex < it->nStart) + { + text.insert(nTFIndex, + rNode.GetText().copy(nIndex, it->nStart - nIndex)); + nInserted += it->nStart - nIndex; + it->nStart = nIndex; + bInserted = true; + } + assert(it->nStart <= nIndex); + if (nIndex <= it->nEnd) + { + nTFIndex += it->nEnd - it->nStart; + while (it->nEnd < nIndex + nLen) + { + auto *const pNext( + (it+1) != rMerged.extents.end() && (it+1)->pNode == it->pNode + ? &*(it+1) + : nullptr); + if (pNext && pNext->nStart <= nIndex + nLen) + { + text.insert(nTFIndex, + rNode.GetText().copy(it->nEnd, pNext->nStart - it->nEnd)); + nTFIndex += pNext->nStart - it->nEnd; + nInserted += pNext->nStart - it->nEnd; + pNext->nStart = it->nStart; + it = rMerged.extents.erase(it); + } + else + { + text.insert(nTFIndex, + rNode.GetText().copy(it->nEnd, nIndex + nLen - it->nEnd)); + nTFIndex += nIndex + nLen - it->nEnd; + nInserted += nIndex + nLen - it->nEnd; + it->nEnd = nIndex + nLen; + } + } + bInserted = true; + break; } - it->nStart += nLen; - it->nEnd += nLen; } } else if (rNode.GetIndex() < it->pNode->GetIndex() || bFoundNode) @@ -768,12 +829,14 @@ static void UpdateMergedParaForInsert(MergedPara & rMerged, { // must be in a gap rMerged.extents.emplace(itInsert, const_cast<SwTextNode*>(&rNode), nIndex, nIndex + nLen); text.insert(nTFIndex, rNode.GetText().copy(nIndex, nLen)); + nInserted = nLen; if (rNode.GetIndex() < rMerged.pParaPropsNode->GetIndex()) { // text inserted before current para-props node rMerged.pParaPropsNode = &rNode; } } rMerged.mergedText = text.makeStringAndClear(); + return TextFrameIndex(nInserted); } // 1. if real delete => correct nStart/nEnd for full nLen @@ -1621,6 +1684,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) SfxPoolItem const* pOld(nullptr); SfxPoolItem const* pNew(nullptr); sw::RedlineDelText const* pRedlineDelText(nullptr); + sw::RedlineUnDelText const* pRedlineUnDelText(nullptr); if (auto const pHint = dynamic_cast<sw::LegacyModifyHint const*>(&rHint)) { @@ -1631,6 +1695,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) { pRedlineDelText = pHynt; } + else if (auto const pHnt = dynamic_cast<sw::RedlineUnDelText const*>(&rHint)) + { + pRedlineUnDelText = pHnt; + } else { assert(!"unexpected hint"); @@ -1717,6 +1785,34 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) } } } + else if (pRedlineUnDelText) + { + if (m_pMergedPara) + { + sal_Int32 const nNPos = pRedlineUnDelText->nStart; + sal_Int32 const nNLen = pRedlineUnDelText->nLen; + nPos = MapModelToView(&rNode, nNPos); + nLen = UpdateMergedParaForInsert(*m_pMergedPara, false, rNode, nNPos, nNLen); + if (IsIdxInside(nPos, nLen)) + { + if (!nLen) + { + // Refresh NumPortions even when line is empty! + if (nPos) + InvalidateSize(); + else + Prepare(); + } + else + InvalidateRange_( SwCharRange( nPos, nLen ), nNLen ); + } + lcl_SetWrong( *this, rNode, nNPos, nNLen, false ); + lcl_SetScriptInval( *this, nPos ); + bSetFieldsDirty = true; + if (HasFollow()) + lcl_ModifyOfst( this, nPos, nLen ); + } + } else switch (nWhich) { case RES_LINENUMBER: @@ -1733,7 +1829,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) nLen = TextFrameIndex(nNLen); if (m_pMergedPara) { - UpdateMergedParaForInsert(*m_pMergedPara, rNode, nNPos, nNLen); + UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, nNPos, nNLen); } if( IsIdxInside( nPos, nLen ) ) { diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx index 147f9d5c731f..3866e55cfe11 100644 --- a/sw/source/core/undo/unredln.cxx +++ b/sw/source/core/undo/unredln.cxx @@ -485,7 +485,7 @@ void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext) { SwRangeRedline* pTmp = new SwRangeRedline(*pRedlData, rPam); rDoc.getIDocumentRedlineAccess().GetRedlineTable().Insert( pTmp ); - pTmp->InvalidateRange(); + pTmp->InvalidateRange(SwRangeRedline::Invalidation::Add); } else if( !( RedlineFlags::Ignore & GetRedlineFlags() ) && !rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() ) @@ -509,7 +509,7 @@ void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext) SwRangeRedline* pTmp = new SwRangeRedline(*pRedlData, rPam); rDoc.getIDocumentRedlineAccess().GetRedlineTable().Insert( pTmp ); - pTmp->InvalidateRange(); + pTmp->InvalidateRange(SwRangeRedline::Invalidation::Add); SetPaM(rPam, true); } |