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

Generated by: LCOV version 1.10