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