Kaydet (Commit) 18d07b2a authored tarafından Kohei Yoshida's avatar Kohei Yoshida

Rework SvtListener and SvtBroadcaster internals.

The old code was simply awkward.

Change-Id: I1a58a9af86c100be238d306570b40f70c5100314
üst d7867b28
......@@ -20,36 +20,41 @@
#define INCLUDED_SVL_BROADCAST_HXX
#include <svl/svldllapi.h>
#include <tools/rtti.hxx>
#include <boost/unordered_set.hpp>
class SvtListener;
class SfxHint;
class SvtListenerBase;
//-------------------------------------------------------------------------
class SVL_DLLPUBLIC SvtBroadcaster
{
friend class SvtListener;
friend class SvtListenerBase;
friend class SvtListenerIter;
SvtListenerBase* pRoot;
public:
friend class SvtListener;
typedef boost::unordered_set<SvtListener*> ListenersType;
private:
const SvtBroadcaster& operator=(const SvtBroadcaster &); // verboten
void Add( SvtListener* p );
void Remove( SvtListener* p );
protected:
virtual void ListenersGone();
public:
TYPEINFO();
SvtBroadcaster();
SvtBroadcaster( const SvtBroadcaster &rBC );
virtual ~SvtBroadcaster();
void Broadcast( const SfxHint &rHint );
sal_Bool HasListeners() const { return 0 != pRoot; }
ListenersType& GetAllListeners();
bool HasListeners() const;
private:
ListenersType maListeners;
};
......
......@@ -20,34 +20,30 @@
#define INCLUDED_SVL_LISTENER_HXX
#include <svl/svldllapi.h>
#include <tools/rtti.hxx>
#include <boost/unordered_set.hpp>
class SvtBroadcaster;
class SfxHint;
class SvtListenerBase;
//-------------------------------------------------------------------------
class SVL_DLLPUBLIC SvtListener
{
friend class SvtListenerBase;
SvtListenerBase *pBrdCastLst;
typedef boost::unordered_set<SvtBroadcaster*> BroadcastersType;
BroadcastersType maBroadcasters;
const SvtListener& operator=(const SvtListener &); // n.i., ist verboten
public:
TYPEINFO();
SvtListener();
SvtListener( const SvtListener &rCopy );
virtual ~SvtListener();
SvtListener();
SvtListener( const SvtListener &r );
virtual ~SvtListener();
sal_Bool StartListening( SvtBroadcaster& rBroadcaster );
sal_Bool EndListening( SvtBroadcaster& rBroadcaster );
void EndListeningAll();
sal_Bool IsListening( SvtBroadcaster& rBroadcaster ) const;
bool StartListening( SvtBroadcaster& rBroadcaster );
bool EndListening( SvtBroadcaster& rBroadcaster );
void EndListeningAll();
bool IsListening( SvtBroadcaster& rBroadcaster ) const;
sal_Bool HasBroadcaster() const { return 0 != pBrdCastLst; }
bool HasBroadcaster() const;
virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
};
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_SVL_LISTENERITER_HXX
#define INCLUDED_SVL_LISTENERITER_HXX
#include <svl/svldllapi.h>
#include <tools/rtti.hxx>
class SvtListener;
class SvtListenerBase;
class SvtBroadcaster;
//-------------------------------------------------------------------------
class SVL_DLLPUBLIC SvtListenerIter
{
friend class SvtListenerBase;
SvtBroadcaster& rRoot;
SvtListenerBase *pAkt, *pDelNext;
// for the update of all iterator's, if a listener is added or removed
// at the same time.
static SvtListenerIter *pListenerIters;
SvtListenerIter *pNxtIter;
SVL_DLLPRIVATE static void RemoveListener( SvtListenerBase& rDel,
SvtListenerBase* pNext );
public:
SvtListenerIter( SvtBroadcaster& );
~SvtListenerIter();
const SvtBroadcaster& GetBroadcaster() const { return rRoot; }
SvtBroadcaster& GetBroadcaster() { return rRoot; }
SvtListener* GoNext(); // to the next
SvtListener* GoStart(); // to the start of the list
SvtListener* GetCurr() const; // returns the current
int IsChanged() const { return pDelNext != pAkt; }
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -711,7 +711,6 @@
#include <svl/itemset.hxx>
#include <svl/languageoptions.hxx>
#include <svl/listener.hxx>
#include <svl/listeneriter.hxx>
#include <svl/macitem.hxx>
#include <svl/numuno.hxx>
#include <svl/poolcach.hxx>
......
......@@ -19,7 +19,6 @@
#include <sfx2/objsh.hxx>
#include <svl/listener.hxx>
#include <svl/listeneriter.hxx>
#include "document.hxx"
#include "brdcst.hxx"
......@@ -419,11 +418,12 @@ void ScBroadcastAreaSlot::UpdateInsert( ScBroadcastArea* pArea )
if (pArea != pTarget)
{
SvtBroadcaster& rTarget = pTarget->GetBroadcaster();
SvtListenerIter it( pArea->GetBroadcaster());
for (SvtListener* pListener = it.GetCurr(); pListener;
pListener = it.GoNext())
SvtBroadcaster::ListenersType& rListeners = pArea->GetBroadcaster().GetAllListeners();
SvtBroadcaster::ListenersType::iterator it = rListeners.begin(), itEnd = rListeners.end();
for (; it != itEnd; ++it)
{
pListener->StartListening( rTarget);
SvtListener& rListener = **it;
rListener.StartListening(rTarget);
}
}
}
......
......@@ -60,7 +60,6 @@
#include <editeng/justifyitem.hxx>
#include <svl/zforlist.hxx>
#include <svl/broadcast.hxx>
#include <svl/listeneriter.hxx>
#include <vcl/outdev.hxx>
#include "formula/errorcodes.hxx"
#include "formula/vectortoken.hxx"
......@@ -3075,11 +3074,13 @@ void ScColumn::MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow )
maBroadcasters.set(nDestRow, pBC);
}
SvtListenerIter aIter(rSource);
for (SvtListener* pLst = aIter.GoStart(); pLst; pLst = aIter.GoNext())
SvtBroadcaster::ListenersType& rListeners = rSource.GetAllListeners();
SvtBroadcaster::ListenersType::iterator it = rListeners.begin(), itEnd = rListeners.end();
for (; it != itEnd; ++it)
{
pLst->StartListening(*pBC);
pLst->EndListening(rSource);
SvtListener& rLst = **it;
rLst.StartListening(*pBC);
rLst.EndListening(rSource);
}
}
......
......@@ -119,8 +119,6 @@ $(eval $(call gb_Library_add_exception_objects,svl,\
svl/source/notify/hint \
svl/source/notify/isethint \
svl/source/notify/listener \
svl/source/notify/listenerbase \
svl/source/notify/listeneriter \
svl/source/notify/lstner \
svl/source/notify/smplhint \
svl/source/numbers/numfmuno \
......
......@@ -17,85 +17,94 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <svl/listener.hxx>
#include <svl/listeneriter.hxx>
#include <svl/broadcast.hxx>
#include <svl/listener.hxx>
#include <svl/smplhint.hxx>
namespace {
TYPEINIT0(SvtBroadcaster);
class StartListeningHandler : std::unary_function<SvtListener*, void>
{
SvtBroadcaster& mrBC;
public:
StartListeningHandler( SvtBroadcaster& rBC ) : mrBC(rBC) {}
void operator() ( SvtListener* p )
{
p->StartListening(mrBC);
}
};
// simple ctor of class SvtBroadcaster
class EndListeningHandler : std::unary_function<SvtListener*, void>
{
SvtBroadcaster& mrBC;
public:
EndListeningHandler( SvtBroadcaster& rBC ) : mrBC(rBC) {}
SvtBroadcaster::SvtBroadcaster()
: pRoot( 0 )
void operator() ( SvtListener* p )
{
p->EndListening(mrBC);
}
};
class NotifyHandler : std::unary_function<SvtListener*, void>
{
}
SvtBroadcaster& mrBC;
const SfxHint& mrHint;
public:
NotifyHandler( SvtBroadcaster& rBC, const SfxHint& rHint ) : mrBC(rBC), mrHint(rHint) {}
void operator() ( SvtListener* p )
{
p->Notify(mrBC, mrHint);
}
};
}
// copy ctor of class SvtBroadcaster
void SvtBroadcaster::Add( SvtListener* p )
{
maListeners.insert(p);
}
SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC )
: pRoot( 0 )
void SvtBroadcaster::Remove( SvtListener* p )
{
SvtListenerIter aIter( (SvtBroadcaster&)rBC );
SvtListener* pLast = aIter.GoStart();
if( pLast )
do {
pLast->StartListening( *this );
} while( 0 != ( pLast = aIter.GoNext() ));
maListeners.erase(p);
if (maListeners.empty())
ListenersGone();
}
SvtBroadcaster::SvtBroadcaster() {}
// unregister all listeners
SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
maListeners(rBC.maListeners)
{
std::for_each(maListeners.begin(), maListeners.end(), StartListeningHandler(*this));
}
SvtBroadcaster::~SvtBroadcaster()
{
Broadcast( SfxSimpleHint(SFX_HINT_DYING) );
SvtListenerIter aIter( *this );
SvtListener* pLast = aIter.GoStart();
if( pLast )
do {
pLast->EndListening( *this );
if( !HasListeners() ) // all gone ??
break;
} while( 0 != ( pLast = aIter.GoNext() ));
// unregister all listeners.
std::for_each(maListeners.begin(), maListeners.end(), EndListeningHandler(*this));
}
// broadcast immedeately
void SvtBroadcaster::Broadcast( const SfxHint &rHint )
{
// is anybody to notify?
if( HasListeners() /* && !IsModifyLocked()*/ )
{
// LockModify();
// bInModify = sal_True;
SvtListenerIter aIter( *this );
SvtListener* pLast = aIter.GoStart();
if( pLast )
do {
pLast->Notify( *this, rHint );
if( !HasListeners() ) // all gone ??
break;
} while( 0 != ( pLast = aIter.GoNext() ));
// bInModify = sal_False;
// UnlockModify();
}
std::for_each(maListeners.begin(), maListeners.end(), NotifyHandler(*this, rHint));
}
void SvtBroadcaster::ListenersGone() {}
SvtBroadcaster::ListenersType& SvtBroadcaster::GetAllListeners()
{
return maListeners;
}
// called, if no more listeners exists
void SvtBroadcaster::ListenersGone()
bool SvtBroadcaster::HasListeners() const
{
return !maListeners.empty();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -17,117 +17,68 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <tools/debug.hxx>
#include <svl/broadcast.hxx>
#include <svl/listener.hxx>
#include "listenerbase.hxx"
#include <svl/listeneriter.hxx>
TYPEINIT0(SvtListener);
// simple ctor of class SvtListener
SvtListener::SvtListener()
: pBrdCastLst( 0 )
{
}
// copy ctor of class SvtListener
#include <svl/broadcast.hxx>
#include <tools/debug.hxx>
SvtListener::SvtListener( const SvtListener &rListener )
: pBrdCastLst( 0 )
{
SvtListenerBase* pLst = rListener.pBrdCastLst;
while( pLst )
{
new SvtListenerBase( *this, *pLst->GetBroadcaster() );
pLst = pLst->GetNext();
}
}
SvtListener::SvtListener() {}
// unregisteres the SvtListener from its SvtBroadcasters
SvtListener::SvtListener( const SvtListener &r ) :
maBroadcasters(r.maBroadcasters) {}
SvtListener::~SvtListener()
{
// Unregister itself from all broadcasters it's listening to.
EndListeningAll();
}
// registeres at a specific SvtBroadcaster
sal_Bool SvtListener::StartListening( SvtBroadcaster& rBroadcaster )
bool SvtListener::StartListening( SvtBroadcaster& rBroadcaster )
{
const SvtListenerBase* pLst = pBrdCastLst;
while( pLst )
std::pair<BroadcastersType::iterator, bool> r =
maBroadcasters.insert(&rBroadcaster);
if (r.second)
{
if( &rBroadcaster == pLst->GetBroadcaster() )
{
// double, than return
return sal_False;
}
pLst = pLst->GetNext();
// This is a new broadcaster.
rBroadcaster.Add(this);
}
new SvtListenerBase( *this, rBroadcaster );
return sal_True;
return r.second;
}
// unregisteres at a specific SvtBroadcaster
sal_Bool SvtListener::EndListening( SvtBroadcaster& rBroadcaster )
bool SvtListener::EndListening( SvtBroadcaster& rBroadcaster )
{
SvtListenerBase *pLst = pBrdCastLst, *pPrev = pLst;
while( pLst )
{
if( &rBroadcaster == pLst->GetBroadcaster() )
{
if( pBrdCastLst == pLst )
pBrdCastLst = pLst->GetNext();
else
pPrev->SetNext( pLst->GetNext() );
delete pLst;
return sal_True;
}
pPrev = pLst;
pLst = pLst->GetNext();
}
return sal_False;
BroadcastersType::iterator it = maBroadcasters.find(&rBroadcaster);
if (it == maBroadcasters.end())
// Not listening to this broadcaster.
return false;
rBroadcaster.Remove(this);
maBroadcasters.erase(it);
return true;
}
// unregisteres all Broadcasters
void SvtListener::EndListeningAll()
{
SvtListenerBase *pLst = pBrdCastLst;
while( pLst )
BroadcastersType::iterator it = maBroadcasters.begin(), itEnd = maBroadcasters.end();
for (; it != itEnd; ++it)
{
SvtListenerBase *pDel = pLst;
pLst = pLst->GetNext();
delete pDel;
SvtBroadcaster& rBC = **it;
rBC.Remove(this);
}
pBrdCastLst = 0;
maBroadcasters.clear();
}
sal_Bool SvtListener::IsListening( SvtBroadcaster& rBroadcaster ) const
bool SvtListener::IsListening( SvtBroadcaster& rBroadcaster ) const
{
const SvtListenerBase *pLst = pBrdCastLst;
while( pLst )
{
if( &rBroadcaster == pLst->GetBroadcaster() )
break;
pLst = pLst->GetNext();
}
return 0 != pLst;
return maBroadcasters.count(&rBroadcaster) > 0;
}
// base implementation of notification handler
bool SvtListener::HasBroadcaster() const
{
return !maBroadcasters.empty();
}
void SvtListener::Notify( SvtBroadcaster&
#ifdef DBG_UTIL
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "listenerbase.hxx"
#include <svl/listeneriter.hxx>
#include <svl/listener.hxx>
#include <svl/broadcast.hxx>
SvtListenerBase::SvtListenerBase( SvtListener& rLst,
SvtBroadcaster& rBroadcaster )
: pLeft( 0 ), pRight( 0 ),
pBroadcaster( &rBroadcaster ), pListener( &rLst )
{
pNext = rLst.pBrdCastLst;
rLst.pBrdCastLst = this;
if( pBroadcaster->pRoot )
{
// set ever behind the root
pRight = pBroadcaster->pRoot->pRight;
pBroadcaster->pRoot->pRight = this;
this->pLeft = pBroadcaster->pRoot;
if( pRight )
pRight->pLeft = this;
}
else
pBroadcaster->pRoot = this;
}
SvtListenerBase::~SvtListenerBase()
{
SvtListenerBase *pR = pRight, *pL = pLeft;
if( pBroadcaster->pRoot )
pBroadcaster->pRoot = pL ? pL : pR;
if( pL )
pL->pRight = pR;
if( pR )
pR->pLeft = pL;
SvtListenerIter::RemoveListener( *this, pR );
if( !pBroadcaster->pRoot )
pBroadcaster->ListenersGone();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_SVL_SOURCE_NOTIFY_LISTENERBASE_HXX
#define INCLUDED_SVL_SOURCE_NOTIFY_LISTENERBASE_HXX
class SvtBroadcaster;
class SvtListener;
class SvtListenerBase
{
SvtListenerBase *pNext;
SvtListenerBase *pLeft, *pRight;
SvtBroadcaster *pBroadcaster;
SvtListener *pListener;
public:
SvtListenerBase( SvtListener& rLst, SvtBroadcaster& rBroadcaster );
~SvtListenerBase();
SvtListenerBase* GetNext() const { return pNext; }
void SetNext( SvtListenerBase* p ) { pNext = p; }
SvtBroadcaster* GetBroadcaster() const { return pBroadcaster; }
SvtListener* GetListener() const { return pListener; }
SvtListenerBase* GetLeft() const { return pLeft; }
SvtListenerBase* GetRight() const { return pRight; }
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "listenerbase.hxx"
#include <svl/listeneriter.hxx>
#include <svl/broadcast.hxx>
#include <svl/listener.hxx>
SvtListenerIter* SvtListenerIter::pListenerIters = 0;
SvtListenerIter::SvtListenerIter( SvtBroadcaster& rBrdcst )
: rRoot( rBrdcst )
{
// hinten einketten!
pNxtIter = 0;
if( pListenerIters )
{
SvtListenerIter* pTmp = pListenerIters;
while( pTmp->pNxtIter )
pTmp = pTmp->pNxtIter;
pTmp->pNxtIter = this;
}
else
pListenerIters = this;
pAkt = rRoot.pRoot;
pDelNext = pAkt;
}
SvtListenerIter::~SvtListenerIter()
{
if( pListenerIters )
{
if( pListenerIters == this )
pListenerIters = pNxtIter;
else
{
SvtListenerIter* pTmp = pListenerIters;
while( pTmp->pNxtIter != this )
if( 0 == ( pTmp = pTmp->pNxtIter ) )
return ;
pTmp->pNxtIter = pNxtIter;
}
}
}
void SvtListenerIter::RemoveListener( SvtListenerBase& rDel,
SvtListenerBase* pNext )
{
// Update the ListenerIter
SvtListenerIter* pTmp = pListenerIters;
while( pTmp )
{
if( pTmp->pAkt == &rDel || pTmp->pDelNext == &rDel )
pTmp->pDelNext = pNext;
pTmp = pTmp->pNxtIter;
}
}
SvtListener* SvtListenerIter::GoNext()
{
if( pDelNext == pAkt )
{
pAkt = pAkt->GetRight();
pDelNext = pAkt;
}
else
pAkt = pDelNext;
return pAkt ? pAkt->GetListener() : 0;
}
SvtListener* SvtListenerIter::GoStart() // zum Anfang des Baums
{
pAkt = rRoot.pRoot;
if( pAkt )
while( pAkt->GetLeft() )
pAkt = pAkt->GetLeft();
pDelNext = pAkt;
return pAkt ? pAkt->GetListener() : 0;
}
SvtListener* SvtListenerIter::GetCurr() const // returns the current
{
return pDelNext ? pDelNext->GetListener() : 0;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment