1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef SC_BCASLOT_HXX 25 #define SC_BCASLOT_HXX 26 27 #include <set> 28 #include <hash_set> 29 #include <functional> 30 #include <svl/broadcast.hxx> 31 #include <svl/svarray.hxx> 32 33 #include "global.hxx" 34 #include "brdcst.hxx" 35 36 /** 37 Used in a Unique Associative Container. 38 */ 39 40 class ScBroadcastArea 41 { 42 private: 43 ScBroadcastArea* pUpdateChainNext; 44 SvtBroadcaster aBroadcaster; 45 ScRange aRange; 46 sal_uLong nRefCount; 47 sal_Bool bInUpdateChain; 48 49 public: 50 ScBroadcastArea( const ScRange& rRange ) 51 : pUpdateChainNext( NULL ), aRange( rRange ), 52 nRefCount( 0 ), bInUpdateChain( sal_False ) {} 53 inline SvtBroadcaster& GetBroadcaster() { return aBroadcaster; } 54 inline const SvtBroadcaster& GetBroadcaster() const { return aBroadcaster; } 55 inline void UpdateRange( const ScRange& rNewRange ) 56 { aRange = rNewRange; } 57 inline const ScRange& GetRange() const { return aRange; } 58 inline const ScAddress& GetStart() const { return aRange.aStart; } 59 inline const ScAddress& GetEnd() const { return aRange.aEnd; } 60 inline void IncRef() { ++nRefCount; } 61 inline sal_uLong DecRef() { return nRefCount ? --nRefCount : 0; } 62 inline sal_uLong GetRef() { return nRefCount; } 63 inline ScBroadcastArea* GetUpdateChainNext() const { return pUpdateChainNext; } 64 inline void SetUpdateChainNext( ScBroadcastArea* p ) { pUpdateChainNext = p; } 65 inline sal_Bool IsInUpdateChain() const { return bInUpdateChain; } 66 inline void SetInUpdateChain( sal_Bool b ) { bInUpdateChain = b; } 67 68 /** Equalness of this or range. */ 69 inline bool operator==( const ScBroadcastArea & rArea ) const; 70 }; 71 72 inline bool ScBroadcastArea::operator==( const ScBroadcastArea & rArea ) const 73 { 74 return aRange == rArea.aRange; 75 } 76 77 //============================================================================= 78 79 struct ScBroadcastAreaHash 80 { 81 size_t operator()( const ScBroadcastArea* p ) const 82 { 83 return p->GetRange().hashArea(); 84 } 85 }; 86 87 struct ScBroadcastAreaEqual 88 { 89 bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const 90 { 91 return *p1 == *p2; 92 } 93 }; 94 95 typedef ::std::hash_set< ScBroadcastArea*, ScBroadcastAreaHash, ScBroadcastAreaEqual > ScBroadcastAreas; 96 97 //============================================================================= 98 99 struct ScBroadcastAreaBulkHash 100 { 101 size_t operator()( const ScBroadcastArea* p ) const 102 { 103 return reinterpret_cast<size_t>(p); 104 } 105 }; 106 107 struct ScBroadcastAreaBulkEqual 108 { 109 bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const 110 { 111 return p1 == p2; 112 } 113 }; 114 115 typedef ::std::hash_set< const ScBroadcastArea*, ScBroadcastAreaBulkHash, 116 ScBroadcastAreaBulkEqual > ScBroadcastAreasBulk; 117 118 //============================================================================= 119 120 class ScBroadcastAreaSlotMachine; 121 122 /// Collection of BroadcastAreas 123 class ScBroadcastAreaSlot 124 { 125 private: 126 ScBroadcastAreas aBroadcastAreaTbl; 127 mutable ScBroadcastArea aTmpSeekBroadcastArea; // for FindBroadcastArea() 128 ScDocument* pDoc; 129 ScBroadcastAreaSlotMachine* pBASM; 130 131 ScBroadcastAreas::iterator FindBroadcastArea( const ScRange& rRange ) const; 132 133 /** 134 More hypothetical (memory would probably be doomed anyway) check 135 whether there would be an overflow when adding an area, setting the 136 proper state if so. 137 138 @return sal_True if a HardRecalcState is effective and area is not to be 139 added. 140 */ 141 bool CheckHardRecalcStateCondition() const; 142 143 public: 144 ScBroadcastAreaSlot( ScDocument* pDoc, 145 ScBroadcastAreaSlotMachine* pBASM ); 146 ~ScBroadcastAreaSlot(); 147 const ScBroadcastAreas& GetBroadcastAreas() const 148 { return aBroadcastAreaTbl; } 149 150 /** 151 Only here new ScBroadcastArea objects are created, prevention of dupes. 152 153 @param rpArea 154 If NULL, a new ScBroadcastArea is created and assigned ton the 155 reference if a matching area wasn't found. If a matching area was 156 found, that is assigned. In any case, the SvtListener is added to 157 the broadcaster. 158 159 If not NULL then no listeners are startet, only the area is 160 inserted and the reference count incremented. Effectively the same 161 as InsertListeningArea(), so use that instead. 162 163 @return 164 sal_True if rpArea passed was NULL and ScBroadcastArea is newly 165 created. 166 */ 167 bool StartListeningArea( const ScRange& rRange, 168 SvtListener* pListener, 169 ScBroadcastArea*& rpArea ); 170 171 /** 172 Insert a ScBroadcastArea obtained via StartListeningArea() to 173 subsequent slots. 174 */ 175 void InsertListeningArea( ScBroadcastArea* pArea ); 176 177 void EndListeningArea( const ScRange& rRange, 178 SvtListener* pListener, 179 ScBroadcastArea*& rpArea ); 180 sal_Bool AreaBroadcast( const ScHint& rHint ) const; 181 /// @return sal_True if at least one broadcast occurred. 182 sal_Bool AreaBroadcastInRange( const ScRange& rRange, 183 const ScHint& rHint ) const; 184 void DelBroadcastAreasInRange( const ScRange& rRange ); 185 void UpdateRemove( UpdateRefMode eUpdateRefMode, 186 const ScRange& rRange, 187 SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); 188 void UpdateRemoveArea( ScBroadcastArea* pArea ); 189 void UpdateInsert( ScBroadcastArea* pArea ); 190 }; 191 192 193 /** 194 BroadcastAreaSlots and their management, once per document. 195 */ 196 197 class ScBroadcastAreaSlotMachine 198 { 199 private: 200 201 /** 202 Slot offset arrangement of columns and rows, once per sheet. 203 204 +---+---+ 205 | 0 | 3 | 206 +---+---+ 207 | 1 | 4 | 208 +---+---+ 209 | 2 | 5 | 210 +---+---+ 211 */ 212 213 class TableSlots 214 { 215 public: 216 TableSlots(); 217 ~TableSlots(); 218 inline ScBroadcastAreaSlot** getSlots() { return ppSlots; } 219 220 /** 221 Obtain slot pointer, no check on validity! It is assumed that 222 all calls are made with the results of ComputeSlotOffset(), 223 ComputeAreaPoints() and ComputeNextSlot() 224 */ 225 inline ScBroadcastAreaSlot* getAreaSlot( SCSIZE nOff ) { return *(ppSlots + nOff); } 226 227 private: 228 ScBroadcastAreaSlot** ppSlots; 229 230 // prevent usage 231 TableSlots( const TableSlots& ); 232 TableSlots& operator=( const TableSlots& ); 233 }; 234 235 typedef ::std::map< SCTAB, TableSlots* > TableSlotsMap; 236 237 private: 238 ScBroadcastAreasBulk aBulkBroadcastAreas; 239 TableSlotsMap aTableSlotsMap; 240 SvtBroadcaster *pBCAlways; // for the RC_ALWAYS special range 241 ScDocument *pDoc; 242 ScBroadcastArea *pUpdateChain; 243 ScBroadcastArea *pEOUpdateChain; 244 sal_uLong nInBulkBroadcast; 245 246 inline SCSIZE ComputeSlotOffset( const ScAddress& rAddress ) const; 247 void ComputeAreaPoints( const ScRange& rRange, 248 SCSIZE& nStart, SCSIZE& nEnd, 249 SCSIZE& nRowBreak ) const; 250 251 public: 252 ScBroadcastAreaSlotMachine( ScDocument* pDoc ); 253 ~ScBroadcastAreaSlotMachine(); 254 void StartListeningArea( const ScRange& rRange, 255 SvtListener* pListener ); 256 void EndListeningArea( const ScRange& rRange, 257 SvtListener* pListener ); 258 sal_Bool AreaBroadcast( const ScHint& rHint ) const; 259 // return: at least one broadcast occurred 260 sal_Bool AreaBroadcastInRange( const ScRange& rRange, const ScHint& rHint ) const; 261 void DelBroadcastAreasInRange( const ScRange& rRange ); 262 void UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode, 263 const ScRange& rRange, 264 SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); 265 void EnterBulkBroadcast(); 266 void LeaveBulkBroadcast(); 267 bool InsertBulkArea( const ScBroadcastArea* p ); 268 /// @return: how many removed 269 size_t RemoveBulkArea( const ScBroadcastArea* p ); 270 inline ScBroadcastArea* GetUpdateChain() const { return pUpdateChain; } 271 inline void SetUpdateChain( ScBroadcastArea* p ) { pUpdateChain = p; } 272 inline ScBroadcastArea* GetEOUpdateChain() const { return pEOUpdateChain; } 273 inline void SetEOUpdateChain( ScBroadcastArea* p ) { pEOUpdateChain = p; } 274 inline bool IsInBulkBroadcast() const { return nInBulkBroadcast > 0; } 275 }; 276 277 278 class ScBulkBroadcast 279 { 280 ScBroadcastAreaSlotMachine* pBASM; 281 public: 282 explicit ScBulkBroadcast( ScBroadcastAreaSlotMachine* p ) : pBASM(p) 283 { 284 if (pBASM) 285 pBASM->EnterBulkBroadcast(); 286 } 287 ~ScBulkBroadcast() 288 { 289 if (pBASM) 290 pBASM->LeaveBulkBroadcast(); 291 } 292 void LeaveBulkBroadcast() 293 { 294 if (pBASM) 295 { 296 pBASM->LeaveBulkBroadcast(); 297 pBASM = NULL; 298 } 299 } 300 }; 301 302 #endif 303