-
Brad Payne (Vir Linden) authoredBrad Payne (Vir Linden) authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
llevent.cpp 7.41 KiB
/**
* @file llevent.cpp
* @brief LLEvent and LLEventListener base classes.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llevent.h"
using namespace LLOldEvents;
/************************************************
Events
************************************************/
// virtual
LLEvent::~LLEvent()
{
}
// virtual
bool LLEvent::accept(LLEventListener* listener)
{
return true;
}
// virtual
const std::string& LLEvent::desc()
{
return mDesc;
}
/************************************************
Observables
************************************************/
LLObservable::LLObservable()
: mDispatcher(new LLEventDispatcher())
{
}
// virtual
LLObservable::~LLObservable()
{
if (mDispatcher.notNull())
{
mDispatcher->disengage(this);
mDispatcher = NULL;
}
}
// virtual
bool LLObservable::setDispatcher(LLPointer<LLEventDispatcher> dispatcher)
{
if (mDispatcher.notNull())
{
mDispatcher->disengage(this);
mDispatcher = NULL;
}
if (dispatcher.notNull() || dispatcher->engage(this))
{
mDispatcher = dispatcher;
return true;
}
return false;
}
// Returns the current dispatcher pointer.
// virtual
LLEventDispatcher* LLObservable::getDispatcher()
{
return mDispatcher;
}
// Notifies the dispatcher of an event being fired.
void LLObservable::fireEvent(LLPointer<LLEvent> event, LLSD filter)
{
if (mDispatcher.notNull())
{
mDispatcher->fireEvent(event, filter);
}
}
/************************************************
Dispatchers
************************************************/
class LLEventDispatcher::Impl
{
public:
virtual ~Impl() { }
virtual bool engage(LLObservable* observable) { return true; }
virtual void disengage(LLObservable* observable) { }
virtual void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata) = 0;
virtual void removeListener(LLEventListener *listener) = 0;
virtual std::vector<LLListenerEntry> getListeners() const = 0;
virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter) = 0;
};
bool LLEventDispatcher::engage(LLObservable* observable)
{
return impl->engage(observable);
}
void LLEventDispatcher::disengage(LLObservable* observable)
{
impl->disengage(observable);
}
void LLEventDispatcher::addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata)
{
impl->addListener(listener, filter, userdata);
}
void LLEventDispatcher::removeListener(LLEventListener *listener)
{
impl->removeListener(listener);
}
std::vector<LLListenerEntry> LLEventDispatcher::getListeners() const
{
return impl->getListeners();
}
bool LLEventDispatcher::fireEvent(LLPointer<LLEvent> event, LLSD filter)
{
return impl->fireEvent(event, filter);
}
class LLSimpleDispatcher : public LLEventDispatcher::Impl
{
public:
LLSimpleDispatcher(LLEventDispatcher *parent) : mParent(parent) { }
virtual ~LLSimpleDispatcher();
virtual void addListener(LLEventListener* listener, LLSD filter, const LLSD& userdata);
virtual void removeListener(LLEventListener* listener);
virtual std::vector<LLListenerEntry> getListeners() const;
virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter);
protected:
std::vector<LLListenerEntry> mListeners;
LLEventDispatcher *mParent;
};
LLSimpleDispatcher::~LLSimpleDispatcher()
{
while (mListeners.size() > 0)
{
removeListener(mListeners.begin()->listener);
}
}
void LLSimpleDispatcher::addListener(LLEventListener* listener, LLSD filter, const LLSD& userdata)
{
if (listener == NULL) return;
removeListener(listener);
LLListenerEntry new_entry;
new_entry.listener = listener;
new_entry.filter = filter;
new_entry.userdata = userdata;
mListeners.push_back(new_entry);
listener->handleAttach(mParent);
}
void LLSimpleDispatcher::removeListener(LLEventListener* listener)
{
std::vector<LLListenerEntry>::iterator itor = mListeners.begin();
std::vector<LLListenerEntry>::iterator end = mListeners.end();
for (; itor != end; ++itor)
{
if ((*itor).listener == listener)
{
mListeners.erase(itor);
break;
}
}
listener->handleDetach(mParent);
}
std::vector<LLListenerEntry> LLSimpleDispatcher::getListeners() const
{
std::vector<LLListenerEntry> ret;
std::vector<LLListenerEntry>::const_iterator itor;
for (itor=mListeners.begin(); itor!=mListeners.end(); ++itor)
{
ret.push_back(*itor);
}
return ret;
}
// virtual
bool LLSimpleDispatcher::fireEvent(LLPointer<LLEvent> event, LLSD filter)
{
std::vector<LLListenerEntry>::iterator itor;
std::string filter_string = filter.asString();
for (itor=mListeners.begin(); itor!=mListeners.end(); ++itor)
{
LLListenerEntry& entry = *itor;
if (filter_string == "" || entry.filter.asString() == filter_string)
{
(entry.listener)->handleEvent(event, (*itor).userdata);
}
}
return true;
}
LLEventDispatcher::LLEventDispatcher()
{
impl = new LLSimpleDispatcher(this);
}
LLEventDispatcher::~LLEventDispatcher()
{
if (impl)
{
delete impl;
impl = NULL;
}
}
/************************************************
Listeners
************************************************/
LLEventListener::~LLEventListener()
{
}
LLSimpleListener::~LLSimpleListener()
{
clearDispatchers();
}
void LLSimpleListener::clearDispatchers()
{
// Remove myself from all listening dispatchers
std::vector<LLEventDispatcher *>::iterator itor;
while (mDispatchers.size() > 0)
{
itor = mDispatchers.begin();
LLEventDispatcher *dispatcher = *itor;
dispatcher->removeListener(this);
itor = mDispatchers.begin();
if (itor != mDispatchers.end() && (*itor) == dispatcher)
{
// Somehow, the dispatcher was not removed. Remove it forcibly
mDispatchers.erase(itor);
}
}
}
bool LLSimpleListener::handleAttach(LLEventDispatcher *dispatcher)
{
// Add dispatcher if it doesn't already exist
std::vector<LLEventDispatcher *>::iterator itor;
for (itor = mDispatchers.begin(); itor != mDispatchers.end(); ++itor)
{
if ((*itor) == dispatcher) return true;
}
mDispatchers.push_back(dispatcher);
return true;
}
bool LLSimpleListener::handleDetach(LLEventDispatcher *dispatcher)
{
// Remove dispatcher from list
std::vector<LLEventDispatcher *>::iterator itor;
for (itor = mDispatchers.begin(); itor != mDispatchers.end(); )
{
if ((*itor) == dispatcher)
{
itor = mDispatchers.erase(itor);
}
else
{
++itor;
}
}
return true;
}