LCOV - code coverage report
Current view: top level - sc/source/core/tool - chartlis.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 223 366 60.9 %
Date: 2014-11-03 Functions: 54 73 74.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10