PageRenderTime 40ms CodeModel.GetById 18ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llevent.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 304 lines | 215 code | 39 blank | 50 comment | 32 complexity | d7d49374ffe239722416d82fbd24e409 MD5 | raw file
  1/** 
  2 * @file llevent.cpp
  3 * @brief LLEvent and LLEventListener base classes.
  4 *
  5 * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include "llevent.h"
 30
 31using namespace LLOldEvents;
 32
 33/************************************************
 34    Events
 35************************************************/
 36
 37// virtual
 38LLEvent::~LLEvent()
 39{
 40}
 41
 42// virtual
 43bool LLEvent::accept(LLEventListener* listener)
 44{
 45	return true;
 46}
 47
 48// virtual
 49const std::string& LLEvent::desc()
 50{
 51	return mDesc;
 52}
 53
 54/************************************************
 55    Observables
 56************************************************/
 57
 58LLObservable::LLObservable()
 59	: mDispatcher(new LLEventDispatcher())
 60{
 61}
 62
 63// virtual
 64LLObservable::~LLObservable()
 65{
 66	if (mDispatcher.notNull())
 67	{
 68		mDispatcher->disengage(this);
 69		mDispatcher = NULL;
 70	}
 71}
 72
 73// virtual
 74bool LLObservable::setDispatcher(LLPointer<LLEventDispatcher> dispatcher)
 75{
 76	if (mDispatcher.notNull())
 77	{
 78		mDispatcher->disengage(this);
 79		mDispatcher = NULL;
 80	}
 81	if (dispatcher.notNull() || dispatcher->engage(this))
 82	{
 83		mDispatcher = dispatcher;
 84		return true;
 85	}
 86	return false;
 87}
 88
 89// Returns the current dispatcher pointer.
 90// virtual
 91LLEventDispatcher* LLObservable::getDispatcher()
 92{
 93	return mDispatcher;
 94}
 95
 96// Notifies the dispatcher of an event being fired.
 97void LLObservable::fireEvent(LLPointer<LLEvent> event, LLSD filter)
 98{
 99	if (mDispatcher.notNull())
100	{
101		mDispatcher->fireEvent(event, filter);
102	}
103}
104
105/************************************************
106    Dispatchers
107************************************************/
108
109class LLEventDispatcher::Impl
110{
111public:
112	virtual ~Impl()												{				}
113	virtual bool engage(LLObservable* observable)				{ return true;	}
114	virtual void disengage(LLObservable* observable)			{				}
115
116	virtual void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata) = 0;
117	virtual void removeListener(LLEventListener *listener) = 0;
118	virtual std::vector<LLListenerEntry> getListeners() const = 0;
119	virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter) = 0;
120};
121
122bool LLEventDispatcher::engage(LLObservable* observable)
123{
124	return impl->engage(observable);
125}
126
127void LLEventDispatcher::disengage(LLObservable* observable)
128{
129	impl->disengage(observable);
130}
131
132void LLEventDispatcher::addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata)
133{
134	impl->addListener(listener, filter, userdata);
135}
136
137void LLEventDispatcher::removeListener(LLEventListener *listener)
138{
139	impl->removeListener(listener);
140}
141
142std::vector<LLListenerEntry> LLEventDispatcher::getListeners() const
143{
144	return impl->getListeners();
145}
146
147
148bool LLEventDispatcher::fireEvent(LLPointer<LLEvent> event, LLSD filter)
149{
150	return impl->fireEvent(event, filter);
151}
152
153class LLSimpleDispatcher : public LLEventDispatcher::Impl
154{
155public:
156	LLSimpleDispatcher(LLEventDispatcher *parent) : mParent(parent) { }
157	virtual ~LLSimpleDispatcher();
158	virtual void addListener(LLEventListener* listener, LLSD filter, const LLSD& userdata);
159	virtual void removeListener(LLEventListener* listener);
160	virtual std::vector<LLListenerEntry> getListeners() const;
161	virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter);
162
163protected:
164	std::vector<LLListenerEntry> mListeners;
165	LLEventDispatcher *mParent;
166};
167
168LLSimpleDispatcher::~LLSimpleDispatcher()
169{
170	while (mListeners.size() > 0)
171	{
172		removeListener(mListeners.begin()->listener);
173	}
174}
175
176void LLSimpleDispatcher::addListener(LLEventListener* listener, LLSD filter, const LLSD& userdata)
177{
178	if (listener == NULL) return;
179	removeListener(listener);
180	LLListenerEntry new_entry;
181	new_entry.listener = listener;
182	new_entry.filter = filter;
183	new_entry.userdata = userdata;
184	mListeners.push_back(new_entry);
185	listener->handleAttach(mParent);
186}
187
188void LLSimpleDispatcher::removeListener(LLEventListener* listener)
189{
190	std::vector<LLListenerEntry>::iterator itor = mListeners.begin();
191	std::vector<LLListenerEntry>::iterator end = mListeners.end();
192	for (; itor != end; ++itor)
193	{
194		if ((*itor).listener == listener)
195		{
196			mListeners.erase(itor);
197			break;
198		}
199	}
200	listener->handleDetach(mParent);
201}
202
203std::vector<LLListenerEntry> LLSimpleDispatcher::getListeners() const
204{
205	std::vector<LLListenerEntry> ret;
206	std::vector<LLListenerEntry>::const_iterator itor;
207	for (itor=mListeners.begin(); itor!=mListeners.end(); ++itor)
208	{
209		ret.push_back(*itor);
210	}
211	
212	return ret;
213}
214
215// virtual
216bool LLSimpleDispatcher::fireEvent(LLPointer<LLEvent> event, LLSD filter)
217{
218	std::vector<LLListenerEntry>::iterator itor;
219	std::string filter_string = filter.asString();
220	for (itor=mListeners.begin(); itor!=mListeners.end(); ++itor)
221	{
222		LLListenerEntry& entry = *itor;
223		if (filter_string == "" || entry.filter.asString() == filter_string)
224		{
225			(entry.listener)->handleEvent(event, (*itor).userdata);
226		}
227	}
228	return true;
229}
230
231LLEventDispatcher::LLEventDispatcher()
232{
233	impl = new LLSimpleDispatcher(this);
234}
235
236LLEventDispatcher::~LLEventDispatcher()
237{
238	if (impl)
239	{
240		delete impl;
241		impl = NULL;
242	}
243}
244
245/************************************************
246    Listeners
247************************************************/
248
249LLEventListener::~LLEventListener()
250{
251}
252
253LLSimpleListener::~LLSimpleListener()
254{
255	clearDispatchers();
256}
257
258void LLSimpleListener::clearDispatchers()
259{
260	// Remove myself from all listening dispatchers
261	std::vector<LLEventDispatcher *>::iterator itor;
262	while (mDispatchers.size() > 0)
263	{
264		itor = mDispatchers.begin();
265		LLEventDispatcher *dispatcher = *itor;
266		dispatcher->removeListener(this);
267		itor = mDispatchers.begin();
268		if (itor != mDispatchers.end() && (*itor) == dispatcher)
269		{
270			// Somehow, the dispatcher was not removed. Remove it forcibly
271			mDispatchers.erase(itor);
272		}
273	}
274}
275
276bool LLSimpleListener::handleAttach(LLEventDispatcher *dispatcher)
277{
278	// Add dispatcher if it doesn't already exist
279	std::vector<LLEventDispatcher *>::iterator itor;
280	for (itor = mDispatchers.begin(); itor != mDispatchers.end(); ++itor)
281	{
282		if ((*itor) == dispatcher) return true;
283	}
284	mDispatchers.push_back(dispatcher);
285	return true;
286}
287
288bool LLSimpleListener::handleDetach(LLEventDispatcher *dispatcher)
289{
290	// Remove dispatcher from list
291	std::vector<LLEventDispatcher *>::iterator itor;
292	for (itor = mDispatchers.begin(); itor != mDispatchers.end(); )
293	{
294		if ((*itor) == dispatcher)
295		{
296			itor = mDispatchers.erase(itor);
297		}
298		else
299		{
300			++itor;
301		}
302	}
303	return true;
304}