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