diff options
Diffstat (limited to 'sc/source/core/inc/bcaslot.hxx')
-rw-r--r-- | sc/source/core/inc/bcaslot.hxx | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx new file mode 100644 index 000000000000..1ecbefe4a9b1 --- /dev/null +++ b/sc/source/core/inc/bcaslot.hxx @@ -0,0 +1,309 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SC_BCASLOT_HXX +#define SC_BCASLOT_HXX + +#include <set> +#include <hash_set> +#include <functional> +#include <svl/broadcast.hxx> +#include <svl/svarray.hxx> + +#include "global.hxx" +#include "brdcst.hxx" + +/** + Used in a Unique Associative Container. + */ + +class ScBroadcastArea +{ +private: + ScBroadcastArea* pUpdateChainNext; + SvtBroadcaster aBroadcaster; + ScRange aRange; + ULONG nRefCount; + BOOL bInUpdateChain; + +public: + ScBroadcastArea( const ScRange& rRange ) + : pUpdateChainNext( NULL ), aRange( rRange ), + nRefCount( 0 ), bInUpdateChain( FALSE ) {} + inline SvtBroadcaster& GetBroadcaster() { return aBroadcaster; } + inline const SvtBroadcaster& GetBroadcaster() const { return aBroadcaster; } + inline void UpdateRange( const ScRange& rNewRange ) + { aRange = rNewRange; } + inline const ScRange& GetRange() const { return aRange; } + inline const ScAddress& GetStart() const { return aRange.aStart; } + inline const ScAddress& GetEnd() const { return aRange.aEnd; } + inline void IncRef() { ++nRefCount; } + inline ULONG DecRef() { return nRefCount ? --nRefCount : 0; } + inline ULONG GetRef() { return nRefCount; } + inline ScBroadcastArea* GetUpdateChainNext() const { return pUpdateChainNext; } + inline void SetUpdateChainNext( ScBroadcastArea* p ) { pUpdateChainNext = p; } + inline BOOL IsInUpdateChain() const { return bInUpdateChain; } + inline void SetInUpdateChain( BOOL b ) { bInUpdateChain = b; } + + /** Equalness of this or range. */ + inline bool operator==( const ScBroadcastArea & rArea ) const; +}; + +inline bool ScBroadcastArea::operator==( const ScBroadcastArea & rArea ) const +{ + return aRange == rArea.aRange; +} + +//============================================================================= + +struct ScBroadcastAreaHash +{ + size_t operator()( const ScBroadcastArea* p ) const + { + return p->GetRange().hashArea(); + } +}; + +struct ScBroadcastAreaEqual +{ + bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const + { + return *p1 == *p2; + } +}; + +typedef ::std::hash_set< ScBroadcastArea*, ScBroadcastAreaHash, ScBroadcastAreaEqual > ScBroadcastAreas; + +//============================================================================= + +struct ScBroadcastAreaBulkHash +{ + size_t operator()( const ScBroadcastArea* p ) const + { + return reinterpret_cast<size_t>(p); + } +}; + +struct ScBroadcastAreaBulkEqual +{ + bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const + { + return p1 == p2; + } +}; + +typedef ::std::hash_set< const ScBroadcastArea*, ScBroadcastAreaBulkHash, + ScBroadcastAreaBulkEqual > ScBroadcastAreasBulk; + +//============================================================================= + +class ScBroadcastAreaSlotMachine; + +/// Collection of BroadcastAreas +class ScBroadcastAreaSlot +{ +private: + ScBroadcastAreas aBroadcastAreaTbl; + mutable ScBroadcastArea aTmpSeekBroadcastArea; // for FindBroadcastArea() + ScDocument* pDoc; + ScBroadcastAreaSlotMachine* pBASM; + + ScBroadcastAreas::iterator FindBroadcastArea( const ScRange& rRange ) const; + + /** + More hypothetical (memory would probably be doomed anyway) check + whether there would be an overflow when adding an area, setting the + proper state if so. + + @return TRUE if a HardRecalcState is effective and area is not to be + added. + */ + bool CheckHardRecalcStateCondition() const; + +public: + ScBroadcastAreaSlot( ScDocument* pDoc, + ScBroadcastAreaSlotMachine* pBASM ); + ~ScBroadcastAreaSlot(); + const ScBroadcastAreas& GetBroadcastAreas() const + { return aBroadcastAreaTbl; } + + /** + Only here new ScBroadcastArea objects are created, prevention of dupes. + + @param rpArea + If NULL, a new ScBroadcastArea is created and assigned ton the + reference if a matching area wasn't found. If a matching area was + found, that is assigned. In any case, the SvtListener is added to + the broadcaster. + + If not NULL then no listeners are startet, only the area is + inserted and the reference count incremented. Effectively the same + as InsertListeningArea(), so use that instead. + + @return + TRUE if rpArea passed was NULL and ScBroadcastArea is newly + created. + */ + bool StartListeningArea( const ScRange& rRange, + SvtListener* pListener, + ScBroadcastArea*& rpArea ); + + /** + Insert a ScBroadcastArea obtained via StartListeningArea() to + subsequent slots. + */ + void InsertListeningArea( ScBroadcastArea* pArea ); + + void EndListeningArea( const ScRange& rRange, + SvtListener* pListener, + ScBroadcastArea*& rpArea ); + BOOL AreaBroadcast( const ScHint& rHint ) const; + /// @return TRUE if at least one broadcast occurred. + BOOL AreaBroadcastInRange( const ScRange& rRange, + const ScHint& rHint ) const; + void DelBroadcastAreasInRange( const ScRange& rRange ); + void UpdateRemove( UpdateRefMode eUpdateRefMode, + const ScRange& rRange, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); + void UpdateRemoveArea( ScBroadcastArea* pArea ); + void UpdateInsert( ScBroadcastArea* pArea ); +}; + + +/** + BroadcastAreaSlots and their management, once per document. + */ + +class ScBroadcastAreaSlotMachine +{ +private: + + /** + Slot offset arrangement of columns and rows, once per sheet. + + +---+---+ + | 0 | 3 | + +---+---+ + | 1 | 4 | + +---+---+ + | 2 | 5 | + +---+---+ + */ + + /* TODO: When going for 1M rows this will definitely need some change, or + * with lots of referred sheets even the reservation of NULL pointers would + * be a memory hog. */ + + class TableSlots + { + public: + TableSlots(); + ~TableSlots(); + inline ScBroadcastAreaSlot** getSlots() { return ppSlots; } + + /** + Obtain slot pointer, no check on validity! It is assumed that + all calls are made with the result of ComputeSlotOfsset() + */ + inline ScBroadcastAreaSlot* getAreaSlot( SCSIZE nOff ) { return *(ppSlots + nOff); } + + private: + ScBroadcastAreaSlot** ppSlots; + + // prevent usage + TableSlots( const TableSlots& ); + TableSlots& operator=( const TableSlots& ); + }; + + typedef ::std::map< SCTAB, TableSlots* > TableSlotsMap; + +private: + ScBroadcastAreasBulk aBulkBroadcastAreas; + TableSlotsMap aTableSlotsMap; + SvtBroadcaster *pBCAlways; // for the RC_ALWAYS special range + ScDocument *pDoc; + ScBroadcastArea *pUpdateChain; + ScBroadcastArea *pEOUpdateChain; + ULONG nInBulkBroadcast; + + inline SCSIZE ComputeSlotOffset( const ScAddress& rAddress ) const; + void ComputeAreaPoints( const ScRange& rRange, + SCSIZE& nStart, SCSIZE& nEnd, + SCSIZE& nRowBreak ) const; + +public: + ScBroadcastAreaSlotMachine( ScDocument* pDoc ); + ~ScBroadcastAreaSlotMachine(); + void StartListeningArea( const ScRange& rRange, + SvtListener* pListener ); + void EndListeningArea( const ScRange& rRange, + SvtListener* pListener ); + BOOL AreaBroadcast( const ScHint& rHint ) const; + // return: at least one broadcast occurred + BOOL AreaBroadcastInRange( const ScRange& rRange, const ScHint& rHint ) const; + void DelBroadcastAreasInRange( const ScRange& rRange ); + void UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode, + const ScRange& rRange, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); + void EnterBulkBroadcast(); + void LeaveBulkBroadcast(); + bool InsertBulkArea( const ScBroadcastArea* p ); + /// @return: how many removed + size_t RemoveBulkArea( const ScBroadcastArea* p ); + inline ScBroadcastArea* GetUpdateChain() const { return pUpdateChain; } + inline void SetUpdateChain( ScBroadcastArea* p ) { pUpdateChain = p; } + inline ScBroadcastArea* GetEOUpdateChain() const { return pEOUpdateChain; } + inline void SetEOUpdateChain( ScBroadcastArea* p ) { pEOUpdateChain = p; } + inline bool IsInBulkBroadcast() const { return nInBulkBroadcast > 0; } +}; + + +class ScBulkBroadcast +{ + ScBroadcastAreaSlotMachine* pBASM; +public: + explicit ScBulkBroadcast( ScBroadcastAreaSlotMachine* p ) : pBASM(p) + { + if (pBASM) + pBASM->EnterBulkBroadcast(); + } + ~ScBulkBroadcast() + { + if (pBASM) + pBASM->LeaveBulkBroadcast(); + } + void LeaveBulkBroadcast() + { + if (pBASM) + { + pBASM->LeaveBulkBroadcast(); + pBASM = NULL; + } + } +}; + +#endif |