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 : : #include <vcl/svapp.hxx>
30 : :
31 : : #include "chartlis.hxx"
32 : : #include "brdcst.hxx"
33 : : #include "document.hxx"
34 : : #include "reftokenhelper.hxx"
35 : : #include "stlalgorithm.hxx"
36 : :
37 : : using namespace com::sun::star;
38 : : using ::std::vector;
39 : : using ::std::list;
40 : : using ::std::auto_ptr;
41 : : using ::std::unary_function;
42 : : using ::std::for_each;
43 : :
44 : : // Update chart listeners quickly, to get a similar behavior to loaded charts
45 : : // which register UNO listeners.
46 : : #define SC_CHARTTIMEOUT 10
47 : :
48 : :
49 : : // ====================================================================
50 : :
51 : 0 : class ScChartUnoData
52 : : {
53 : : uno::Reference< chart::XChartDataChangeEventListener > xListener;
54 : : uno::Reference< chart::XChartData > xSource;
55 : :
56 : : public:
57 : 4 : ScChartUnoData( const uno::Reference< chart::XChartDataChangeEventListener >& rL,
58 : : const uno::Reference< chart::XChartData >& rS ) :
59 : 4 : xListener( rL ), xSource( rS ) {}
60 : 4 : ~ScChartUnoData() {}
61 : :
62 : 12 : const uno::Reference< chart::XChartDataChangeEventListener >& GetListener() const { return xListener; }
63 : 16 : const uno::Reference< chart::XChartData >& GetSource() const { return xSource; }
64 : : };
65 : :
66 : :
67 : : // === ScChartListener ================================================
68 : :
69 : 0 : ScChartListener::ExternalRefListener::ExternalRefListener(ScChartListener& rParent, ScDocument* pDoc) :
70 [ # # ]: 0 : mrParent(rParent), mpDoc(pDoc)
71 : : {
72 : 0 : }
73 : :
74 [ # # ]: 0 : ScChartListener::ExternalRefListener::~ExternalRefListener()
75 : : {
76 [ # # ][ # # ]: 0 : if (!mpDoc || mpDoc->IsInDtorClear())
[ # # ]
77 : : // The document is being destroyed. Do nothing.
78 : : return;
79 : :
80 : : // Make sure to remove all pointers to this object.
81 [ # # ][ # # ]: 0 : mpDoc->GetExternalRefManager()->removeLinkListener(this);
[ # # ]
82 [ # # ]: 0 : }
83 : :
84 : 0 : void ScChartListener::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType)
85 : : {
86 [ # # # ]: 0 : switch (eType)
87 : : {
88 : : case ScExternalRefManager::LINK_MODIFIED:
89 : : {
90 [ # # ]: 0 : if (maFileIds.count(nFileId))
91 : : // We are listening to this external document. Send an update
92 : : // requst to the chart.
93 : 0 : mrParent.SetUpdateQueue();
94 : : }
95 : 0 : break;
96 : : case ScExternalRefManager::LINK_BROKEN:
97 : 0 : removeFileId(nFileId);
98 : 0 : break;
99 : : }
100 : 0 : }
101 : :
102 : 0 : void ScChartListener::ExternalRefListener::addFileId(sal_uInt16 nFileId)
103 : : {
104 : 0 : maFileIds.insert(nFileId);
105 : 0 : }
106 : :
107 : 0 : void ScChartListener::ExternalRefListener::removeFileId(sal_uInt16 nFileId)
108 : : {
109 : 0 : maFileIds.erase(nFileId);
110 : 0 : }
111 : :
112 : 0 : boost::unordered_set<sal_uInt16>& ScChartListener::ExternalRefListener::getAllFileIds()
113 : : {
114 : 0 : return maFileIds;
115 : : }
116 : :
117 : : // ----------------------------------------------------------------------------
118 : :
119 : 14 : ScChartListener::ScChartListener( const rtl::OUString& rName, ScDocument* pDocP,
120 : : const ScRangeListRef& rRangeList ) :
121 : : SvtListener(),
122 : : mpExtRefListener(NULL),
123 [ + - ]: 14 : mpTokens(new vector<ScTokenRef>),
124 : : maName(rName),
125 : : pUnoData( NULL ),
126 : : mpDoc( pDocP ),
127 : : bUsed( false ),
128 : : bDirty( false ),
129 [ + - ]: 28 : bSeriesRangesScheduled( false )
130 : : {
131 [ + - ]: 14 : ScRefTokenHelper::getTokensFromRangeList(*mpTokens, *rRangeList);
132 : 14 : }
133 : :
134 : 6 : ScChartListener::ScChartListener( const rtl::OUString& rName, ScDocument* pDocP, vector<ScTokenRef>* pTokens ) :
135 : : SvtListener(),
136 : : mpExtRefListener(NULL),
137 : : mpTokens(pTokens),
138 : : maName(rName),
139 : : pUnoData( NULL ),
140 : : mpDoc( pDocP ),
141 : : bUsed( false ),
142 : : bDirty( false ),
143 : 6 : bSeriesRangesScheduled( false )
144 : : {
145 : 6 : }
146 : :
147 : 0 : ScChartListener::ScChartListener( const ScChartListener& r ) :
148 : : SvtListener(),
149 : : mpExtRefListener(NULL),
150 [ # # ]: 0 : mpTokens(new vector<ScTokenRef>(*r.mpTokens)),
151 : : maName(r.maName),
152 : : pUnoData( NULL ),
153 : : mpDoc( r.mpDoc ),
154 : : bUsed( false ),
155 : : bDirty( r.bDirty ),
156 [ # # ]: 0 : bSeriesRangesScheduled( r.bSeriesRangesScheduled )
157 : : {
158 [ # # ]: 0 : if ( r.pUnoData )
159 [ # # ][ # # ]: 0 : pUnoData = new ScChartUnoData( *r.pUnoData );
160 : :
161 [ # # ]: 0 : if (r.mpExtRefListener.get())
162 : : {
163 : : // Re-register this new listener for the files that the old listener
164 : : // was listening to.
165 : :
166 [ # # ]: 0 : ScExternalRefManager* pRefMgr = mpDoc->GetExternalRefManager();
167 [ # # ]: 0 : const boost::unordered_set<sal_uInt16>& rFileIds = r.mpExtRefListener->getAllFileIds();
168 [ # # ][ # # ]: 0 : mpExtRefListener.reset(new ExternalRefListener(*this, mpDoc));
[ # # ]
169 [ # # ][ # # ]: 0 : boost::unordered_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
170 [ # # ]: 0 : for (; itr != itrEnd; ++itr)
171 : : {
172 [ # # ][ # # ]: 0 : pRefMgr->addLinkListener(*itr, mpExtRefListener.get());
173 [ # # ][ # # ]: 0 : mpExtRefListener->addFileId(*itr);
174 : : }
175 : : }
176 : 0 : }
177 : :
178 [ + - ][ + - ]: 20 : ScChartListener::~ScChartListener()
179 : : {
180 [ + - ]: 20 : if ( HasBroadcaster() )
181 [ + - ]: 20 : EndListeningTo();
182 [ + + ][ + - ]: 20 : delete pUnoData;
183 : :
184 [ - + ]: 20 : if (mpExtRefListener.get())
185 : : {
186 : : // Stop listening to all external files.
187 [ # # ]: 0 : ScExternalRefManager* pRefMgr = mpDoc->GetExternalRefManager();
188 [ # # ]: 0 : const boost::unordered_set<sal_uInt16>& rFileIds = mpExtRefListener->getAllFileIds();
189 [ # # ][ # # ]: 0 : boost::unordered_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
190 [ # # ]: 0 : for (; itr != itrEnd; ++itr)
191 [ # # ][ # # ]: 0 : pRefMgr->removeLinkListener(*itr, mpExtRefListener.get());
192 : : }
193 [ - + ]: 40 : }
194 : :
195 : 39 : const rtl::OUString& ScChartListener::GetName() const
196 : : {
197 : 39 : return maName;
198 : : }
199 : :
200 : 4 : void ScChartListener::SetUno(
201 : : const uno::Reference< chart::XChartDataChangeEventListener >& rListener,
202 : : const uno::Reference< chart::XChartData >& rSource )
203 : : {
204 [ - + ]: 4 : delete pUnoData;
205 [ + - ]: 4 : pUnoData = new ScChartUnoData( rListener, rSource );
206 : 4 : }
207 : :
208 : 6 : uno::Reference< chart::XChartDataChangeEventListener > ScChartListener::GetUnoListener() const
209 : : {
210 [ + - ]: 6 : if ( pUnoData )
211 : 6 : return pUnoData->GetListener();
212 : 6 : return uno::Reference< chart::XChartDataChangeEventListener >();
213 : : }
214 : :
215 : 10 : uno::Reference< chart::XChartData > ScChartListener::GetUnoSource() const
216 : : {
217 [ + - ]: 10 : if ( pUnoData )
218 : 10 : return pUnoData->GetSource();
219 : 10 : return uno::Reference< chart::XChartData >();
220 : : }
221 : :
222 : 63 : void ScChartListener::Notify( SvtBroadcaster&, const SfxHint& rHint )
223 : : {
224 [ - + ]: 63 : const ScHint* p = dynamic_cast<const ScHint*>(&rHint);
225 [ + - ][ + - ]: 63 : if (p && (p->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING)))
[ + - ]
226 : 63 : SetUpdateQueue();
227 : 63 : }
228 : :
229 : 6 : void ScChartListener::Update()
230 : : {
231 [ - + ]: 6 : if ( mpDoc->IsInInterpreter() )
232 : : { // If interpreting do nothing and restart timer so we don't
233 : : // interfere with interpreter and don't produce an Err522 or similar.
234 : : // This may happen if we are rescheduled via Basic function.
235 : 0 : mpDoc->GetChartListenerCollection()->StartTimer();
236 : 6 : return ;
237 : : }
238 [ + - ]: 6 : if ( pUnoData )
239 : : {
240 : 6 : bDirty = false;
241 : : //! irgendwann mal erkennen, was sich innerhalb des Charts geaendert hat
242 : 6 : chart::ChartDataChangeEvent aEvent( pUnoData->GetSource(),
243 : : chart::ChartDataChangeType_ALL,
244 [ + - ]: 6 : 0, 0, 0, 0 );
245 [ + - ][ + - ]: 6 : pUnoData->GetListener()->chartDataChanged( aEvent );
[ + - ]
246 : : }
247 [ # # ]: 0 : else if ( mpDoc->GetAutoCalc() )
248 : : {
249 : 0 : bDirty = false;
250 : 0 : mpDoc->UpdateChart(GetName());
251 : : }
252 : : }
253 : :
254 : 6 : ScRangeListRef ScChartListener::GetRangeList() const
255 : : {
256 [ + - ]: 6 : ScRangeListRef aRLRef(new ScRangeList);
257 [ + - ]: 6 : ScRefTokenHelper::getRangeListFromTokens(*aRLRef, *mpTokens);
258 : 6 : return aRLRef;
259 : : }
260 : :
261 : 12 : void ScChartListener::SetRangeList( const ScRangeListRef& rNew )
262 : : {
263 [ + - ]: 12 : vector<ScTokenRef> aTokens;
264 [ + - ]: 12 : ScRefTokenHelper::getTokensFromRangeList(aTokens, *rNew);
265 : 12 : mpTokens->swap(aTokens);
266 : 12 : }
267 : :
268 : : namespace {
269 : :
270 : : class StartEndListening : public unary_function<ScTokenRef, void>
271 : : {
272 : : public:
273 : 64 : StartEndListening(ScDocument* pDoc, ScChartListener& rParent, bool bStart) :
274 : 64 : mpDoc(pDoc), mrParent(rParent), mbStart(bStart) {}
275 : :
276 : 112 : void operator() (const ScTokenRef& pToken)
277 : : {
278 [ - + ]: 112 : if (!ScRefTokenHelper::isRef(pToken))
279 : 112 : return;
280 : :
281 : 112 : bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
282 [ - + ]: 112 : if (bExternal)
283 : : {
284 : 0 : sal_uInt16 nFileId = pToken->GetIndex();
285 : 0 : ScExternalRefManager* pRefMgr = mpDoc->GetExternalRefManager();
286 : 0 : ScChartListener::ExternalRefListener* pExtRefListener = mrParent.GetExtRefListener();
287 [ # # ]: 0 : if (mbStart)
288 : : {
289 : 0 : pRefMgr->addLinkListener(nFileId, pExtRefListener);
290 : 0 : pExtRefListener->addFileId(nFileId);
291 : : }
292 : : else
293 : : {
294 : 0 : pRefMgr->removeLinkListener(nFileId, pExtRefListener);
295 : 0 : pExtRefListener->removeFileId(nFileId);
296 : : }
297 : : }
298 : : else
299 : : {
300 : 112 : ScRange aRange;
301 [ + - ]: 112 : ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal);
302 [ + + ]: 112 : if (mbStart)
303 [ + - ]: 56 : startListening(aRange);
304 : : else
305 [ + - ]: 112 : endListening(aRange);
306 : : }
307 : : }
308 : : private:
309 : 56 : void startListening(const ScRange& rRange)
310 : : {
311 [ + + ]: 56 : if (rRange.aStart == rRange.aEnd)
312 : 14 : mpDoc->StartListeningCell(rRange.aStart, &mrParent);
313 : : else
314 : 42 : mpDoc->StartListeningArea(rRange, &mrParent);
315 : 56 : }
316 : :
317 : 56 : void endListening(const ScRange& rRange)
318 : : {
319 [ + + ]: 56 : if (rRange.aStart == rRange.aEnd)
320 : 14 : mpDoc->EndListeningCell(rRange.aStart, &mrParent);
321 : : else
322 : 42 : mpDoc->EndListeningArea(rRange, &mrParent);
323 : 56 : }
324 : : private:
325 : : ScDocument* mpDoc;
326 : : ScChartListener& mrParent;
327 : : bool mbStart;
328 : : };
329 : :
330 : : }
331 : :
332 : 32 : void ScChartListener::StartListeningTo()
333 : : {
334 [ + - ][ - + ]: 32 : if (!mpTokens.get() || mpTokens->empty())
[ - + ]
335 : : // no references to listen to.
336 : 32 : return;
337 : :
338 [ + - ]: 32 : for_each(mpTokens->begin(), mpTokens->end(), StartEndListening(mpDoc, *this, true));
339 : : }
340 : :
341 : 32 : void ScChartListener::EndListeningTo()
342 : : {
343 [ + - ][ - + ]: 32 : if (!mpTokens.get() || mpTokens->empty())
[ - + ]
344 : : // no references to listen to.
345 : 32 : return;
346 : :
347 [ + - ]: 32 : for_each(mpTokens->begin(), mpTokens->end(), StartEndListening(mpDoc, *this, false));
348 : : }
349 : :
350 : :
351 : 0 : void ScChartListener::ChangeListening( const ScRangeListRef& rRangeListRef,
352 : : bool bDirtyP )
353 : : {
354 : 0 : EndListeningTo();
355 : 0 : SetRangeList( rRangeListRef );
356 : 0 : StartListeningTo();
357 [ # # ]: 0 : if ( bDirtyP )
358 : 0 : SetDirty( true );
359 : 0 : }
360 : :
361 : :
362 : 0 : void ScChartListener::UpdateScheduledSeriesRanges()
363 : : {
364 [ # # ]: 0 : if ( bSeriesRangesScheduled )
365 : : {
366 : 0 : bSeriesRangesScheduled = false;
367 : 0 : UpdateSeriesRanges();
368 : : }
369 : 0 : }
370 : :
371 : :
372 : 0 : void ScChartListener::UpdateChartIntersecting( const ScRange& rRange )
373 : : {
374 : 0 : ScTokenRef pToken;
375 [ # # ]: 0 : ScRefTokenHelper::getTokenFromRange(pToken, rRange);
376 : :
377 [ # # ][ # # ]: 0 : if (ScRefTokenHelper::intersects(*mpTokens, pToken))
378 : : {
379 : : // force update (chart has to be loaded), don't use ScChartListener::Update
380 [ # # ][ # # ]: 0 : mpDoc->UpdateChart(GetName());
381 [ # # ]: 0 : }
382 : 0 : }
383 : :
384 : :
385 : 0 : void ScChartListener::UpdateSeriesRanges()
386 : : {
387 [ # # ][ # # ]: 0 : ScRangeListRef pRangeList(new ScRangeList);
388 [ # # ]: 0 : ScRefTokenHelper::getRangeListFromTokens(*pRangeList, *mpTokens);
389 [ # # ][ # # ]: 0 : mpDoc->SetChartRangeList(GetName(), pRangeList);
[ # # ]
390 : 0 : }
391 : :
392 : 0 : ScChartListener::ExternalRefListener* ScChartListener::GetExtRefListener()
393 : : {
394 [ # # ]: 0 : if (!mpExtRefListener.get())
395 [ # # ]: 0 : mpExtRefListener.reset(new ExternalRefListener(*this, mpDoc));
396 : :
397 : 0 : return mpExtRefListener.get();
398 : : }
399 : :
400 : 63 : void ScChartListener::SetUpdateQueue()
401 : : {
402 : 63 : bDirty = true;
403 : 63 : mpDoc->GetChartListenerCollection()->StartTimer();
404 : 63 : }
405 : :
406 : 0 : bool ScChartListener::operator==( const ScChartListener& r ) const
407 : : {
408 [ # # ][ # # ]: 0 : bool b1 = (mpTokens.get() && !mpTokens->empty());
409 [ # # ][ # # ]: 0 : bool b2 = (r.mpTokens.get() && !r.mpTokens->empty());
410 : :
411 [ # # ][ # # ]: 0 : if (mpDoc != r.mpDoc || bUsed != r.bUsed || bDirty != r.bDirty ||
[ # # ]
[ # # # # ]
[ # # ][ # # ]
412 : : bSeriesRangesScheduled != r.bSeriesRangesScheduled ||
413 : 0 : GetName() != r.GetName() || b1 != b2)
414 : 0 : return false;
415 : :
416 [ # # ][ # # ]: 0 : if (!b1 && !b2)
417 : : // both token list instances are empty.
418 : 0 : return true;
419 : :
420 : 0 : return *mpTokens == *r.mpTokens;
421 : : }
422 : :
423 : 0 : bool ScChartListener::operator!=( const ScChartListener& r ) const
424 : : {
425 : 0 : return !operator==(r);
426 : : }
427 : :
428 : : // ============================================================================
429 : :
430 : 4770 : ScChartHiddenRangeListener::ScChartHiddenRangeListener()
431 : : {
432 : 4770 : }
433 : :
434 : 4770 : ScChartHiddenRangeListener::~ScChartHiddenRangeListener()
435 : : {
436 : : // empty d'tor
437 [ - + ]: 4770 : }
438 : :
439 : : // === ScChartListenerCollection ======================================
440 : :
441 : 4770 : ScChartListenerCollection::RangeListenerItem::RangeListenerItem(const ScRange& rRange, ScChartHiddenRangeListener* p) :
442 : 4770 : maRange(rRange), mpListener(p)
443 : : {
444 : 4770 : }
445 : :
446 : 846 : ScChartListenerCollection::ScChartListenerCollection( ScDocument* pDocP ) :
447 [ + - ][ + - ]: 846 : pDoc( pDocP )
[ + - ]
448 : : {
449 [ + - ]: 846 : aTimer.SetTimeoutHdl( LINK( this, ScChartListenerCollection, TimerHdl ) );
450 : 846 : }
451 : :
452 : 36 : ScChartListenerCollection::ScChartListenerCollection(
453 : : const ScChartListenerCollection& rColl ) :
454 [ + - ][ + - ]: 36 : pDoc( rColl.pDoc )
[ + - ]
455 : : {
456 [ + - ]: 36 : aTimer.SetTimeoutHdl( LINK( this, ScChartListenerCollection, TimerHdl ) );
457 : 36 : }
458 : :
459 [ + - ][ + - ]: 731 : ScChartListenerCollection::~ScChartListenerCollection()
460 : : {
461 : : // remove ChartListener objects before aTimer dtor is called, because
462 : : // ScChartListener::EndListeningTo may cause ScChartListenerCollection::StartTimer
463 : : // to be called if an empty ScNoteCell is deleted
464 : :
465 [ + - ]: 731 : maListeners.clear();
466 : 731 : }
467 : :
468 : 0 : void ScChartListenerCollection::StartAllListeners()
469 : : {
470 [ # # ][ # # ]: 0 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
471 [ # # ][ # # ]: 0 : for (; it != itEnd; ++it)
[ # # ]
472 [ # # ][ # # ]: 0 : it->second->StartListeningTo();
473 : 0 : }
474 : :
475 : 20 : void ScChartListenerCollection::insert(ScChartListener* pListener)
476 : : {
477 [ + - ]: 20 : rtl::OUString aName = pListener->GetName();
478 [ + - ]: 20 : maListeners.insert(aName, pListener);
479 : 20 : }
480 : :
481 : 29 : ScChartListener* ScChartListenerCollection::findByName(const rtl::OUString& rName)
482 : : {
483 [ + - ]: 29 : ListenersType::iterator it = maListeners.find(rName);
484 [ + - ][ + - ]: 29 : return it == maListeners.end() ? NULL : it->second;
[ - + ][ + - ]
[ + - ][ # # ]
485 : : }
486 : :
487 : 0 : const ScChartListener* ScChartListenerCollection::findByName(const rtl::OUString& rName) const
488 : : {
489 [ # # ]: 0 : ListenersType::const_iterator it = maListeners.find(rName);
490 [ # # ][ # # ]: 0 : return it == maListeners.end() ? NULL : it->second;
[ # # ][ # # ]
[ # # ][ # # ]
491 : : }
492 : :
493 : 109 : bool ScChartListenerCollection::hasListeners() const
494 : : {
495 : 109 : return !maListeners.empty();
496 : : }
497 : :
498 : 0 : const ScChartListenerCollection::ListenersType& ScChartListenerCollection::getListeners() const
499 : : {
500 : 0 : return maListeners;
501 : : }
502 : :
503 : 170 : ScChartListenerCollection::ListenersType& ScChartListenerCollection::getListeners()
504 : : {
505 : 170 : return maListeners;
506 : : }
507 : :
508 : 821 : ScChartListenerCollection::StringSetType& ScChartListenerCollection::getNonOleObjectNames()
509 : : {
510 : 821 : return maNonOleObjectNames;
511 : : }
512 : :
513 : 4 : rtl::OUString ScChartListenerCollection::getUniqueName(const rtl::OUString& rPrefix) const
514 : : {
515 [ + - ]: 10 : for (sal_Int32 nNum = 1; nNum < 10000; ++nNum) // arbitrary limit to prevent infinite loop.
516 : : {
517 [ + - ]: 6 : rtl::OUStringBuffer aBuf(rPrefix);
518 [ + - ]: 6 : aBuf.append(nNum);
519 [ + - ]: 6 : rtl::OUString aTestName = aBuf.makeStringAndClear();
520 [ + - ][ + - ]: 6 : if (maListeners.find(aTestName) == maListeners.end())
[ + - ][ + + ]
521 : 6 : return aTestName;
522 [ + + ][ + + ]: 6 : }
523 : 4 : return rtl::OUString();
524 : : }
525 : :
526 : 12 : void ScChartListenerCollection::ChangeListening( const String& rName,
527 : : const ScRangeListRef& rRangeListRef, bool bDirty )
528 : : {
529 [ + - ]: 12 : ScChartListener* pCL = findByName(rName);
530 [ + - ]: 12 : if (pCL)
531 : : {
532 : 12 : pCL->EndListeningTo();
533 : 12 : pCL->SetRangeList( rRangeListRef );
534 : : }
535 : : else
536 : : {
537 [ # # ][ # # ]: 0 : pCL = new ScChartListener(rName, pDoc, rRangeListRef);
538 : 0 : insert(pCL);
539 : : }
540 : 12 : pCL->StartListeningTo();
541 [ - + ]: 12 : if ( bDirty )
542 : 0 : pCL->SetDirty( true );
543 : 12 : }
544 : :
545 : : namespace {
546 : :
547 : : class InsertChartListener : public std::unary_function<ScChartListener*, void>
548 : : {
549 : : ScChartListenerCollection::ListenersType& mrListeners;
550 : : public:
551 : 507 : InsertChartListener(ScChartListenerCollection::ListenersType& rListeners) :
552 : 507 : mrListeners(rListeners) {}
553 : :
554 : 19 : void operator() (ScChartListener* p)
555 : : {
556 [ + - ]: 19 : rtl::OUString aName = p->GetName();
557 [ + - ]: 19 : mrListeners.insert(aName, p);
558 : 19 : }
559 : : };
560 : :
561 : : }
562 : :
563 : 503 : void ScChartListenerCollection::FreeUnused()
564 : : {
565 [ + - ][ + - ]: 503 : std::vector<ScChartListener*> aUsed, aUnused;
566 : :
567 : : // First, filter each listener into 'used' and 'unused' categories.
568 : : {
569 [ + - ][ + - ]: 503 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
570 [ + - ][ + - ]: 520 : for (; it != itEnd; ++it)
[ + + ]
571 : : {
572 [ + - ]: 17 : ScChartListener* p = it->second;
573 [ - + ]: 17 : if (p->IsUno())
574 : : {
575 : : // We don't delete UNO charts; they are to be deleted separately via FreeUno().
576 [ # # ]: 0 : aUsed.push_back(p);
577 : 0 : continue;
578 : : }
579 : :
580 [ + - ]: 17 : if (p->IsUsed())
581 : : {
582 : 17 : p->SetUsed(false);
583 [ + - ]: 17 : aUsed.push_back(p);
584 : : }
585 : : else
586 [ # # ]: 17 : aUnused.push_back(p);
587 : : }
588 : : }
589 : :
590 : : // Release all pointers currently managed by the ptr_map container.
591 [ + - ][ + - ]: 503 : maListeners.release().release();
592 : :
593 : : // Re-insert the listeners we need to keep.
594 [ + - ]: 503 : std::for_each(aUsed.begin(), aUsed.end(), InsertChartListener(maListeners));
595 : :
596 : : // Now, delete the ones no longer needed.
597 [ + - ]: 503 : std::for_each(aUnused.begin(), aUnused.end(), ScDeleteObjectByPtr<ScChartListener>());
598 : 503 : }
599 : :
600 : 4 : void ScChartListenerCollection::FreeUno( const uno::Reference< chart::XChartDataChangeEventListener >& rListener,
601 : : const uno::Reference< chart::XChartData >& rSource )
602 : : {
603 [ + - ][ + - ]: 4 : std::vector<ScChartListener*> aUsed, aUnused;
604 : :
605 : : // First, filter each listener into 'used' and 'unused' categories.
606 : : {
607 [ + - ][ + - ]: 4 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
608 [ + - ][ + - ]: 10 : for (; it != itEnd; ++it)
[ + + ]
609 : : {
610 [ + - ]: 6 : ScChartListener* p = it->second;
611 [ + - ][ + - ]: 6 : if (p->IsUno() && p->GetUnoListener() == rListener && p->GetUnoSource() == rSource)
[ + + ][ + - ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + + # #
# # ][ + - ]
612 [ + - ]: 4 : aUnused.push_back(p);
613 : : else
614 [ + - ]: 2 : aUsed.push_back(p);
615 : : }
616 : : }
617 : :
618 : : // Release all pointers currently managed by the ptr_map container.
619 [ + - ][ + - ]: 4 : maListeners.release().release();
620 : :
621 : : // Re-insert the listeners we need to keep.
622 [ + - ]: 4 : std::for_each(aUsed.begin(), aUsed.end(), InsertChartListener(maListeners));
623 : :
624 : : // Now, delete the ones no longer needed.
625 [ + - ]: 4 : std::for_each(aUnused.begin(), aUnused.end(), ScDeleteObjectByPtr<ScChartListener>());
626 : 4 : }
627 : :
628 : 540 : void ScChartListenerCollection::StartTimer()
629 : : {
630 : 540 : aTimer.SetTimeout( SC_CHARTTIMEOUT );
631 : 540 : aTimer.Start();
632 : 540 : }
633 : :
634 : 52 : IMPL_LINK_NOARG(ScChartListenerCollection, TimerHdl)
635 : : {
636 [ - + ]: 52 : if ( Application::AnyInput( VCL_INPUT_KEYBOARD ) )
637 : : {
638 : 0 : aTimer.Start();
639 : 0 : return 0;
640 : : }
641 : 52 : UpdateDirtyCharts();
642 : 52 : return 0;
643 : : }
644 : :
645 : 190 : void ScChartListenerCollection::UpdateDirtyCharts()
646 : : {
647 [ + - ][ + - ]: 190 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
648 [ + - ][ + - ]: 193 : for (; it != itEnd; ++it)
[ + + ]
649 : : {
650 [ + - ]: 3 : ScChartListener* p = it->second;
651 [ - + ]: 3 : if (p->IsDirty())
652 [ # # ]: 0 : p->Update();
653 : :
654 [ - + ][ # # ]: 3 : if (aTimer.IsActive() && !pDoc->IsImportingXML())
[ - + ]
655 : 0 : break; // da kam einer dazwischen
656 : : }
657 : 190 : }
658 : :
659 : :
660 : 477 : void ScChartListenerCollection::SetDirty()
661 : : {
662 [ + - ][ + - ]: 477 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
663 [ # # ][ + - ]: 477 : for (; it != itEnd; ++it)
[ - + ]
664 [ # # ]: 0 : it->second->SetDirty(true);
665 : :
666 [ + - ]: 477 : StartTimer();
667 : 477 : }
668 : :
669 : :
670 : 0 : void ScChartListenerCollection::SetDiffDirty(
671 : : const ScChartListenerCollection& rCmp, bool bSetChartRangeLists )
672 : : {
673 : 0 : bool bDirty = false;
674 [ # # ][ # # ]: 0 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
675 [ # # ][ # # ]: 0 : for (; it != itEnd; ++it)
[ # # ]
676 : : {
677 [ # # ]: 0 : ScChartListener* pCL = it->second;
678 : : OSL_ASSERT(pCL);
679 [ # # ][ # # ]: 0 : const ScChartListener* pCLCmp = rCmp.findByName(pCL->GetName());
680 [ # # ][ # # ]: 0 : if (!pCLCmp || *pCL != *pCLCmp)
[ # # ][ # # ]
681 : : {
682 [ # # ]: 0 : if ( bSetChartRangeLists )
683 : : {
684 [ # # ]: 0 : if (pCLCmp)
685 : : {
686 [ # # ]: 0 : const ScRangeListRef& rList1 = pCL->GetRangeList();
687 [ # # ]: 0 : const ScRangeListRef& rList2 = pCLCmp->GetRangeList();
688 : 0 : bool b1 = rList1.Is();
689 : 0 : bool b2 = rList2.Is();
690 [ # # ][ # # ]: 0 : if ( b1 != b2 || (b1 && b2 && (*rList1 != *rList2)) )
[ # # ][ # # ]
[ # # ][ # # ]
691 [ # # ][ # # ]: 0 : pDoc->SetChartRangeList( pCL->GetName(), rList1 );
[ # # ][ # # ]
692 : : }
693 : : else
694 [ # # ][ # # ]: 0 : pDoc->SetChartRangeList( pCL->GetName(), pCL->GetRangeList() );
[ # # ][ # # ]
695 : : }
696 : 0 : bDirty = true;
697 : 0 : pCL->SetDirty( true );
698 : : }
699 : : }
700 [ # # ]: 0 : if ( bDirty )
701 [ # # ]: 0 : StartTimer();
702 : 0 : }
703 : :
704 : :
705 : 76 : void ScChartListenerCollection::SetRangeDirty( const ScRange& rRange )
706 : : {
707 : 76 : bool bDirty = false;
708 [ + - ][ + - ]: 76 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
709 [ # # ][ + - ]: 76 : for (; it != itEnd; ++it)
[ - + ]
710 : : {
711 [ # # ]: 0 : ScChartListener* pCL = it->second;
712 [ # # ]: 0 : const ScRangeListRef& rList = pCL->GetRangeList();
713 [ # # ][ # # ]: 0 : if ( rList.Is() && rList->Intersects( rRange ) )
[ # # ][ # # ]
714 : : {
715 : 0 : bDirty = true;
716 : 0 : pCL->SetDirty( true );
717 : : }
718 [ # # ]: 0 : }
719 [ - + ]: 76 : if ( bDirty )
720 [ # # ]: 0 : StartTimer();
721 : :
722 : : // New hidden range listener implementation
723 [ - + ]: 76 : for (list<RangeListenerItem>::iterator itr = maHiddenListeners.begin(), itrEnd = maHiddenListeners.end();
724 : : itr != itrEnd; ++itr)
725 : : {
726 [ # # ][ # # ]: 0 : if (itr->maRange.Intersects(rRange))
727 [ # # ]: 0 : itr->mpListener->notify();
728 : : }
729 : 76 : }
730 : :
731 : :
732 : 196 : void ScChartListenerCollection::UpdateScheduledSeriesRanges()
733 : : {
734 [ + - ][ + - ]: 196 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
735 [ # # ][ + - ]: 196 : for (; it != itEnd; ++it)
[ - + ]
736 [ # # ][ # # ]: 0 : it->second->UpdateScheduledSeriesRanges();
737 : 196 : }
738 : :
739 : :
740 : 177 : void ScChartListenerCollection::UpdateChartsContainingTab( SCTAB nTab )
741 : : {
742 : 177 : ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab );
743 [ + - ][ + - ]: 177 : ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end();
744 [ # # ][ + - ]: 177 : for (; it != itEnd; ++it)
[ - + ]
745 [ # # ][ # # ]: 0 : it->second->UpdateChartIntersecting(aRange);
746 : 177 : }
747 : :
748 : :
749 : 36 : bool ScChartListenerCollection::operator==( const ScChartListenerCollection& r ) const
750 : : {
751 : : // hier nicht ScStrCollection::operator==() verwenden, der umstaendlich via
752 : : // IsEqual und Compare laeuft, stattdessen ScChartListener::operator==()
753 [ + - ][ - + ]: 36 : if (pDoc != r.pDoc || maListeners.size() != r.maListeners.size())
[ - + ]
754 : 0 : return false;
755 : :
756 [ + - ][ + - ]: 36 : ListenersType::const_iterator it = maListeners.begin(), itEnd = maListeners.end();
757 [ + - ]: 36 : ListenersType::const_iterator it2 = r.maListeners.begin();
758 [ # # ][ # # ]: 36 : for (; it != itEnd; ++it, ++it2)
[ + - ][ - + ]
759 : : {
760 [ # # ][ # # ]: 0 : if (*it != *it2)
[ # # ][ # # ]
761 : 0 : return false;
762 : : }
763 : 36 : return true;
764 : : }
765 : :
766 : 0 : bool ScChartListenerCollection::operator!=( const ScChartListenerCollection& r ) const
767 : : {
768 : 0 : return !operator==(r);
769 : : }
770 : :
771 : 4770 : void ScChartListenerCollection::StartListeningHiddenRange( const ScRange& rRange, ScChartHiddenRangeListener* pListener )
772 : : {
773 : 4770 : RangeListenerItem aItem(rRange, pListener);
774 [ + - ]: 4770 : maHiddenListeners.push_back(aItem);
775 : 4770 : }
776 : :
777 : : namespace {
778 : :
779 : : struct MatchListener : public ::std::unary_function<
780 : : ScChartListenerCollection::RangeListenerItem, bool>
781 : : {
782 : 9188 : MatchListener(const ScChartHiddenRangeListener* pMatch) :
783 : 9188 : mpMatch(pMatch)
784 : : {
785 : 9188 : }
786 : :
787 : 249760 : bool operator() (const ScChartListenerCollection::RangeListenerItem& rItem) const
788 : : {
789 : 249760 : return mpMatch == rItem.mpListener;
790 : : }
791 : :
792 : : private:
793 : : const ScChartHiddenRangeListener* mpMatch;
794 : : };
795 : :
796 : : }
797 : 9188 : void ScChartListenerCollection::EndListeningHiddenRange( ScChartHiddenRangeListener* pListener )
798 : : {
799 [ + - ]: 9188 : maHiddenListeners.remove_if(MatchListener(pListener));
800 : 9188 : }
801 : :
802 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|