diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-12 22:18:49 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-18 08:31:55 -0500 |
commit | 2030b9ac6c68ba6f15b0283e0b4e57ae49bd67b0 (patch) | |
tree | dc7ad2b2f890ea0ac614d7820c2e655c84327c3f /sc/source/core/data | |
parent | 192f6a41444b62feae03185975c120f770e2938f (diff) |
Dedicated listener type tailored for formula groups.
Right now, it's only used when loading an xlsx file. But eventually
this one should be used everywhere.
Change-Id: I216c3a9a33c4b8040e8284d59299e0637471fb50
Diffstat (limited to 'sc/source/core/data')
-rw-r--r-- | sc/source/core/data/bcaslot.cxx | 116 | ||||
-rw-r--r-- | sc/source/core/data/colorscale.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/documen2.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/documen7.cxx | 17 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 52 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 8 |
6 files changed, 156 insertions, 43 deletions
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx index 8229d6846bdb..9af7c19e2304 100644 --- a/sc/source/core/data/bcaslot.cxx +++ b/sc/source/core/data/bcaslot.cxx @@ -27,6 +27,7 @@ #include "docoptio.hxx" #include "refupdat.hxx" #include "table.hxx" +#include <bulkdatahint.hxx> #if DEBUG_AREA_BROADCASTER #include <formulacell.hxx> @@ -107,6 +108,13 @@ static SCSIZE nBcaSlots = initSlotDistribution( aSlotDistribution, nBcaSlotsRow) // Ensure that all static variables are initialized with this one call. #endif +ScBroadcastArea::ScBroadcastArea( const ScRange& rRange ) : + pUpdateChainNext(NULL), + aRange(rRange), + nRefCount(0), + mbInUpdateChain(false), + mbGroupListening(false) {} + ScBroadcastAreaSlot::ScBroadcastAreaSlot( ScDocument* pDocument, ScBroadcastAreaSlotMachine* pBASMa ) : aTmpSeekBroadcastArea( ScRange()), @@ -155,8 +163,8 @@ bool ScBroadcastAreaSlot::CheckHardRecalcStateCondition() const return false; } -bool ScBroadcastAreaSlot::StartListeningArea( const ScRange& rRange, - SvtListener* pListener, ScBroadcastArea*& rpArea ) +bool ScBroadcastAreaSlot::StartListeningArea( + const ScRange& rRange, bool bGroupListening, SvtListener* pListener, ScBroadcastArea*& rpArea ) { bool bNewArea = false; OSL_ENSURE(pListener, "StartListeningArea: pListener Null"); @@ -168,12 +176,13 @@ bool ScBroadcastAreaSlot::StartListeningArea( const ScRange& rRange, // to new and insert it would save an attempt to find it, on mass // operations like identical large [HV]LOOKUP() areas the new/delete // would add quite some penalty for all but the first formula cell. - ScBroadcastAreas::const_iterator aIter( FindBroadcastArea( rRange)); + ScBroadcastAreas::const_iterator aIter( FindBroadcastArea( rRange, bGroupListening)); if (aIter != aBroadcastAreaTbl.end()) rpArea = (*aIter).mpArea; else { rpArea = new ScBroadcastArea( rRange); + rpArea->SetGroupListening(bGroupListening); if (aBroadcastAreaTbl.insert( rpArea).second) { rpArea->IncRef(); @@ -208,13 +217,13 @@ void ScBroadcastAreaSlot::InsertListeningArea( ScBroadcastArea* pArea ) // If rpArea != NULL then no listeners are stopped, only the area is removed // and the reference count decremented. -void ScBroadcastAreaSlot::EndListeningArea( const ScRange& rRange, - SvtListener* pListener, ScBroadcastArea*& rpArea ) +void ScBroadcastAreaSlot::EndListeningArea( + const ScRange& rRange, bool bGroupListening, SvtListener* pListener, ScBroadcastArea*& rpArea ) { OSL_ENSURE(pListener, "EndListeningArea: pListener Null"); if ( !rpArea ) { - ScBroadcastAreas::const_iterator aIter( FindBroadcastArea( rRange)); + ScBroadcastAreas::const_iterator aIter( FindBroadcastArea( rRange, bGroupListening)); if (aIter == aBroadcastAreaTbl.end() || isMarkedErased( aIter)) return; rpArea = (*aIter).mpArea; @@ -230,7 +239,7 @@ void ScBroadcastAreaSlot::EndListeningArea( const ScRange& rRange, { if (rpArea && !rpArea->GetBroadcaster().HasListeners()) { - ScBroadcastAreas::const_iterator aIter( FindBroadcastArea( rRange)); + ScBroadcastAreas::const_iterator aIter( FindBroadcastArea( rRange, bGroupListening)); if (aIter == aBroadcastAreaTbl.end() || isMarkedErased( aIter)) return; OSL_ENSURE( (*aIter).mpArea == rpArea, "EndListeningArea: area pointer mismatch"); @@ -242,9 +251,10 @@ void ScBroadcastAreaSlot::EndListeningArea( const ScRange& rRange, } ScBroadcastAreas::const_iterator ScBroadcastAreaSlot::FindBroadcastArea( - const ScRange& rRange ) const + const ScRange& rRange, bool bGroupListening ) const { aTmpSeekBroadcastArea.UpdateRange( rRange); + aTmpSeekBroadcastArea.SetGroupListening(bGroupListening); return aBroadcastAreaTbl.find( &aTmpSeekBroadcastArea); } @@ -270,7 +280,19 @@ bool ScBroadcastAreaSlot::AreaBroadcast( const ScHint& rHint) const ScRange& rAreaRange = pArea->GetRange(); if (rAreaRange.In( rAddress)) { - if (!pBASM->IsInBulkBroadcast() || pBASM->InsertBulkArea( pArea)) + if (pArea->IsGroupListening()) + { + if (pBASM->IsInBulkBroadcast()) + { + pBASM->InsertBulkGroupArea(pArea, rAddress); + } + else + { + pArea->GetBroadcaster().Broadcast( rHint); + bIsBroadcasted = true; + } + } + else if (!pBASM->IsInBulkBroadcast() || pBASM->InsertBulkArea( pArea)) { pArea->GetBroadcaster().Broadcast( rHint); bIsBroadcasted = true; @@ -296,27 +318,46 @@ bool ScBroadcastAreaSlot::AreaBroadcastInRange( const ScRange& rRange, bool bInBroadcast = mbInBroadcastIteration; mbInBroadcastIteration = true; bool bIsBroadcasted = false; + + mbHasErasedArea = false; + for (ScBroadcastAreas::const_iterator aIter( aBroadcastAreaTbl.begin()), aIterEnd( aBroadcastAreaTbl.end()); aIter != aIterEnd; ++aIter ) { - if (isMarkedErased( aIter)) + if (mbHasErasedArea && isMarkedErased( aIter)) continue; + ScBroadcastArea* pArea = (*aIter).mpArea; const ScRange& rAreaRange = pArea->GetRange(); if (rAreaRange.Intersects( rRange )) { - if (!pBASM->IsInBulkBroadcast() || pBASM->InsertBulkArea( pArea)) + if (pArea->IsGroupListening()) + { + if (pBASM->IsInBulkBroadcast()) + { + pBASM->InsertBulkGroupArea(pArea, rRange); + } + else + { + pArea->GetBroadcaster().Broadcast( rHint); + bIsBroadcasted = true; + } + } + else if (!pBASM->IsInBulkBroadcast() || pBASM->InsertBulkArea( pArea)) { pArea->GetBroadcaster().Broadcast( rHint); bIsBroadcasted = true; } } } + mbInBroadcastIteration = bInBroadcast; + // A Notify() during broadcast may call EndListeningArea() and thus dispose // an area if it was the last listener, which would invalidate an iterator // pointing to it, hence the real erase is done afterwards. FinallyEraseAreas(); + return bIsBroadcasted; } @@ -487,6 +528,7 @@ void ScBroadcastAreaSlot::GetAllListeners( { sc::AreaListener aEntry; aEntry.maArea = rAreaRange; + aEntry.mbGroupListening = pArea->IsGroupListening(); aEntry.mpListener = *itLst; rListeners.push_back(aEntry); } @@ -617,8 +659,8 @@ inline void ComputeNextSlot( SCSIZE & nOff, SCSIZE & nBreak, ScBroadcastAreaSlot } } -void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange& rRange, - SvtListener* pListener ) +void ScBroadcastAreaSlotMachine::StartListeningArea( + const ScRange& rRange, bool bGroupListening, SvtListener* pListener ) { if ( rRange == BCA_LISTEN_ALWAYS ) { @@ -653,7 +695,7 @@ void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange& rRange, // ScBroadcastArea, listeners were added to an already // existing identical area that doesn't need to be inserted // to slots again. - if (!(*pp)->StartListeningArea( rRange, pListener, pArea)) + if (!(*pp)->StartListeningArea( rRange, bGroupListening, pListener, pArea)) bDone = true; } else @@ -664,8 +706,8 @@ void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange& rRange, } } -void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange& rRange, - SvtListener* pListener ) +void ScBroadcastAreaSlotMachine::EndListeningArea( + const ScRange& rRange, bool bGroupListening, SvtListener* pListener ) { if ( rRange == BCA_LISTEN_ALWAYS ) { @@ -700,7 +742,7 @@ void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange& rRange, do { if ( *pp ) - (*pp)->EndListeningArea( rRange, pListener, pArea ); + (*pp)->EndListeningArea( rRange, bGroupListening, pListener, pArea); } while (++pp < pStop); } else @@ -708,7 +750,7 @@ void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange& rRange, while ( nOff <= nEnd ) { if ( *pp ) - (*pp)->EndListeningArea( rRange, pListener, pArea ); + (*pp)->EndListeningArea( rRange, bGroupListening, pListener, pArea); ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak); } } @@ -988,7 +1030,10 @@ void ScBroadcastAreaSlotMachine::LeaveBulkBroadcast() if (nInBulkBroadcast > 0) { if (--nInBulkBroadcast == 0) + { ScBroadcastAreasBulk().swap( aBulkBroadcastAreas); + BulkBroadcastGroupAreas(); + } } } @@ -997,6 +1042,41 @@ bool ScBroadcastAreaSlotMachine::InsertBulkArea( const ScBroadcastArea* pArea ) return aBulkBroadcastAreas.insert( pArea ).second; } +void ScBroadcastAreaSlotMachine::InsertBulkGroupArea( ScBroadcastArea* pArea, const ScRange& rRange ) +{ + BulkGroupAreasType::iterator it = maBulkGroupAreas.lower_bound(pArea); + if (it == maBulkGroupAreas.end() || maBulkGroupAreas.key_comp()(pArea, it->first)) + { + // Insert a new one. + it = maBulkGroupAreas.insert(it, pArea, new sc::ColumnSpanSet(false)); + } + + sc::ColumnSpanSet* pSet = it->second; + assert(pSet); + pSet->set(rRange, true); +} + +void ScBroadcastAreaSlotMachine::BulkBroadcastGroupAreas() +{ + if (maBulkGroupAreas.empty()) + return; + + sc::BulkDataHint aHint(*pDoc, NULL); + + BulkGroupAreasType::iterator it = maBulkGroupAreas.begin(), itEnd = maBulkGroupAreas.end(); + for (; it != itEnd; ++it) + { + ScBroadcastArea* pArea = it->first; + const sc::ColumnSpanSet* pSpans = it->second; + assert(pArea); + assert(pSpans); + aHint.setSpans(pSpans); + pArea->GetBroadcaster().Broadcast(aHint); + } + + maBulkGroupAreas.clear(); +} + size_t ScBroadcastAreaSlotMachine::RemoveBulkArea( const ScBroadcastArea* pArea ) { return aBulkBroadcastAreas.erase( pArea ); diff --git a/sc/source/core/data/colorscale.cxx b/sc/source/core/data/colorscale.cxx index b915e25b13af..9de8919294b2 100644 --- a/sc/source/core/data/colorscale.cxx +++ b/sc/source/core/data/colorscale.cxx @@ -81,7 +81,7 @@ void ScFormulaListener::startListening(ScTokenArray* pArr, const ScAddress& rPos aCell2.SetCol(MAXCOL); } } - mpDoc->StartListeningArea(ScRange(aCell1, aCell2), this); + mpDoc->StartListeningArea(ScRange(aCell1, aCell2), false, this); maCells.push_back(ScRange(aCell1, aCell2)); } } diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 1693ad7e54d3..89389251012e 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -1187,7 +1187,7 @@ void ScDocument::AddLookupCache( ScLookupCache & rCache ) OSL_FAIL( "ScDocument::AddLookupCache: couldn't add to hash map"); } else - StartListeningArea( rCache.getRange(), &rCache); + StartListeningArea( rCache.getRange(), false, &rCache); } void ScDocument::RemoveLookupCache( ScLookupCache & rCache ) @@ -1202,7 +1202,7 @@ void ScDocument::RemoveLookupCache( ScLookupCache & rCache ) { ScLookupCache* pCache = (*it).second; pLookupCacheMapImpl->aCacheMap.erase( it); - EndListeningArea( pCache->getRange(), &rCache); + EndListeningArea( pCache->getRange(), false, &rCache); } } diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx index af09c83ce084..5ea4ce59f338 100644 --- a/sc/source/core/data/documen7.cxx +++ b/sc/source/core/data/documen7.cxx @@ -45,20 +45,17 @@ extern const ScFormulaCell* pLastFormulaTreeTop; // cellform.cxx Err527 WorkA // STATIC DATA ----------------------------------------------------------- -void ScDocument::StartListeningArea( const ScRange& rRange, - SvtListener* pListener - ) +void ScDocument::StartListeningArea( + const ScRange& rRange, bool bGroupListening, SvtListener* pListener ) { if ( pBASM ) - pBASM->StartListeningArea( rRange, pListener ); + pBASM->StartListeningArea(rRange, bGroupListening, pListener); } -void ScDocument::EndListeningArea( const ScRange& rRange, - SvtListener* pListener - ) +void ScDocument::EndListeningArea( const ScRange& rRange, bool bGroupListening, SvtListener* pListener ) { if ( pBASM ) - pBASM->EndListeningArea( rRange, pListener ); + pBASM->EndListeningArea(rRange, bGroupListening, pListener); } void ScDocument::Broadcast( const ScHint& rHint ) @@ -155,7 +152,7 @@ void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint ) std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end(); for (; it != itEnd; ++it) { - pBASM->EndListeningArea(it->maArea, it->mpListener); + pBASM->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener); it->mpListener->Notify(rHint); // Adjust the references. } } @@ -206,7 +203,7 @@ void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint ) { ScRange aNewRange = it->maArea; aNewRange.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab()); - pBASM->StartListeningArea(aNewRange, it->mpListener); + pBASM->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener); } } } diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 1d9b20fb0d9e..6b3cbe46ba28 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -58,6 +58,7 @@ #include <refhint.hxx> #include <listenerquery.hxx> #include <listenerqueryids.hxx> +#include <grouparealistener.hxx> #include <boost/scoped_ptr.hpp> @@ -508,6 +509,29 @@ void ScFormulaCellGroup::compileOpenCLKernel() meKernelState = sc::OpenCLKernelBinaryCreated; } +sc::FormulaGroupAreaListener* ScFormulaCellGroup::getAreaListener( + ScFormulaCell** ppTopCell, const ScRange& rRange, bool bStartFixed, bool bEndFixed ) +{ + // TODO : Find existing one with the same criteria. + maAreaListeners.push_back(new sc::FormulaGroupAreaListener(rRange, ppTopCell, mnLength, bStartFixed, bEndFixed)); + return &maAreaListeners.back(); +} + +void ScFormulaCellGroup::endAllGroupListening( ScDocument& rDoc ) +{ + AreaListenersType::iterator it = maAreaListeners.begin(), itEnd = maAreaListeners.end(); + for (; it != itEnd; ++it) + { + sc::FormulaGroupAreaListener* pListener = &(*it); + ScRange aListenRange = pListener->getListeningRange(); + // This "always listen" special range is never grouped. + bool bGroupListening = (aListenRange != BCA_LISTEN_ALWAYS); + rDoc.EndListeningArea(aListenRange, bGroupListening, pListener); + } + + maAreaListeners.clear(); +} + ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos ) : eTempGrammar(formula::FormulaGrammar::GRAM_DEFAULT), pCode(new ScTokenArray), @@ -1854,14 +1878,14 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) if (pCode->IsRecalcModeAlways()) { // The formula was previously volatile, but no more. - pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, this); + pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, false, this); pCode->SetExclusiveRecalcModeNormal(); } else { // non-volatile formula. End listening to the area in case // it's listening due to macro module change. - pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, this); + pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, false, this); } pDocument->RemoveFromFormulaTree(this); break; @@ -3799,7 +3823,7 @@ void startListeningArea( aCell2.SetCol(MAXCOL); } } - rDoc.StartListeningArea(ScRange(aCell1, aCell2), pCell); + rDoc.StartListeningArea(ScRange(aCell1, aCell2), false, pCell); } } @@ -3807,6 +3831,9 @@ void startListeningArea( void ScFormulaCell::StartListeningTo( ScDocument* pDoc ) { + if (mxGroup) + mxGroup->endAllGroupListening(*pDoc); + if (pDoc->IsClipOrUndo() || pDoc->GetNoListening() || IsInChangeTrack()) return; @@ -3815,7 +3842,7 @@ void ScFormulaCell::StartListeningTo( ScDocument* pDoc ) ScTokenArray* pArr = GetCode(); if( pArr->IsRecalcModeAlways() ) { - pDoc->StartListeningArea(BCA_LISTEN_ALWAYS, this); + pDoc->StartListeningArea(BCA_LISTEN_ALWAYS, false, this); } pArr->Reset(); @@ -3845,6 +3872,9 @@ void ScFormulaCell::StartListeningTo( sc::StartListeningContext& rCxt ) { ScDocument& rDoc = rCxt.getDoc(); + if (mxGroup) + mxGroup->endAllGroupListening(rDoc); + if (rDoc.IsClipOrUndo() || rDoc.GetNoListening() || IsInChangeTrack()) return; @@ -3853,7 +3883,7 @@ void ScFormulaCell::StartListeningTo( sc::StartListeningContext& rCxt ) ScTokenArray* pArr = GetCode(); if( pArr->IsRecalcModeAlways() ) { - rDoc.StartListeningArea(BCA_LISTEN_ALWAYS, this); + rDoc.StartListeningArea(BCA_LISTEN_ALWAYS, false, this); } pArr->Reset(); @@ -3902,7 +3932,7 @@ void endListeningArea( } } - rDoc.EndListeningArea(ScRange(aCell1, aCell2), pCell); + rDoc.EndListeningArea(ScRange(aCell1, aCell2), false, pCell); } } @@ -3911,6 +3941,9 @@ void endListeningArea( void ScFormulaCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr, ScAddress aCellPos ) { + if (mxGroup) + mxGroup->endAllGroupListening(*pDoc); + if (pDoc->IsClipOrUndo() || IsInChangeTrack()) return; @@ -3918,7 +3951,7 @@ void ScFormulaCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr, if ( GetCode()->IsRecalcModeAlways() ) { - pDoc->EndListeningArea( BCA_LISTEN_ALWAYS, this ); + pDoc->EndListeningArea(BCA_LISTEN_ALWAYS, false, this); } if (!pArr) @@ -3950,6 +3983,9 @@ void ScFormulaCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr, void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt ) { + if (mxGroup) + mxGroup->endAllGroupListening(rCxt.getDoc()); + if (rCxt.getDoc().IsClipOrUndo() || IsInChangeTrack()) return; @@ -3963,7 +3999,7 @@ void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt ) if (pArr->IsRecalcModeAlways()) { - rDoc.EndListeningArea(BCA_LISTEN_ALWAYS, this); + rDoc.EndListeningArea(BCA_LISTEN_ALWAYS, false, this); } pArr->Reset(); diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index f7c61184fecd..c42f777912af 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -739,7 +739,7 @@ void ScTable::SortReorderByColumn( std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end(); for (; it != itEnd; ++it) { - pDocument->EndListeningArea(it->maArea, it->mpListener); + pDocument->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener); aListeners.push_back( it->mpListener); } } @@ -770,7 +770,7 @@ void ScTable::SortReorderByColumn( aNewRange.aStart.SetCol( itCol->second); aNewRange.aEnd.SetCol( itCol->second); } - pDocument->StartListeningArea(aNewRange, it->mpListener); + pDocument->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener); } } @@ -1020,7 +1020,7 @@ void ScTable::SortReorderByRow( std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end(); for (; it != itEnd; ++it) { - pDocument->EndListeningArea(it->maArea, it->mpListener); + pDocument->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener); aListeners.push_back( it->mpListener); } } @@ -1082,7 +1082,7 @@ void ScTable::SortReorderByRow( aNewRange.aStart.SetRow( itRow->second); aNewRange.aEnd.SetRow( itRow->second); } - pDocument->StartListeningArea(aNewRange, it->mpListener); + pDocument->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener); } } |