summaryrefslogtreecommitdiff
path: root/indra/llcommon/llevent.h
blob: 8cd682b8bf492e017c18006ad51f6bc603260b90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/** 
 * @file llevent.h
 * @author Tom Yedwab
 * @brief LLEvent and LLEventListener base classes.
 *
 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef LL_EVENT_H
#define LL_EVENT_H

#include "llsd.h"
#include "llpointer.h"
#include "llthread.h"

namespace LLOldEvents
{

class LLEventListener;
class LLEvent;
class LLEventDispatcher;
class LLObservable;

// Abstract event. All events derive from LLEvent
class LL_COMMON_API LLEvent : public LLThreadSafeRefCount
{
protected:
	virtual ~LLEvent();
	
public:
	LLEvent(LLObservable* source, const std::string& desc = "") : mSource(source), mDesc(desc) { }

	LLObservable* getSource() { return mSource; }
	virtual LLSD		getValue() { return LLSD(); }
	// Determines whether this particular listener
	//   should be notified of this event.
	// If this function returns true, handleEvent is
	//   called on the listener with this event as the
	//   argument.
	// Defaults to handling all events. Override this
	//   if associated with an Observable with many different listeners
	virtual bool accept(LLEventListener* listener);

	// return a string describing the event
	virtual const std::string& desc();

private:
	LLObservable* mSource;
	std::string mDesc;
};

// Abstract listener. All listeners derive from LLEventListener
class LL_COMMON_API LLEventListener : public LLThreadSafeRefCount
{
protected:
	virtual ~LLEventListener();
	
public:

	// Processes the event.
	// TODO: Make the return value less ambiguous?
	virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) = 0;

	// Called when an dispatcher starts/stops listening
	virtual bool handleAttach(LLEventDispatcher *dispatcher) = 0;
	virtual bool handleDetach(LLEventDispatcher *dispatcher) = 0;
};

// A listener which tracks references to it and cleans up when it's deallocated
class LL_COMMON_API LLSimpleListener : public LLEventListener
{
public:
	void clearDispatchers();
	virtual bool handleAttach(LLEventDispatcher *dispatcher);
	virtual bool handleDetach(LLEventDispatcher *dispatcher);

protected:
	~LLSimpleListener();
	std::vector<LLEventDispatcher *> mDispatchers;
};

class LLObservable; // defined below

// A structure which stores a Listener and its metadata
struct LLListenerEntry
{
	LLEventListener* listener;
	LLSD filter;
	LLSD userdata;
};

// Base class for a dispatcher - an object which listens
// to events being fired and relays them to their
// appropriate destinations.
class LL_COMMON_API LLEventDispatcher : public LLThreadSafeRefCount
{
protected:
	virtual ~LLEventDispatcher();
	
public:
	// The default constructor creates a default simple dispatcher implementation.
	// The simple implementation has an array of listeners and fires every event to
	// all of them.
	LLEventDispatcher();
	
	// This dispatcher is being attached to an observable object.
	// If we return false, the attach fails.
	bool engage(LLObservable* observable);

	// This dispatcher is being detached from an observable object.
	void disengage(LLObservable* observable);

	// Adds a listener to this dispatcher, with a given user data
	// that will be passed to the listener when an event is fired.
	// Duplicate pointers are removed on addtion.
	void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata);

	// Removes a listener from this dispatcher
	void removeListener(LLEventListener *listener);

	// Gets a list of interested listeners
	std::vector<LLListenerEntry> getListeners() const;

	// Handle an event that has just been fired by communicating it
	// to listeners, passing it across a network, etc.
	bool fireEvent(LLPointer<LLEvent> event, LLSD filter);

public:
	class Impl;
private:
	Impl* impl;
};

// Interface for observable data (data that fires events)
// In order for this class to work properly, it needs
// an instance of an LLEventDispatcher to route events to their
// listeners.
class LL_COMMON_API LLObservable
{
public:
	// Initialize with the default Dispatcher
	LLObservable();
	virtual ~LLObservable();

	// Replaces the existing dispatcher pointer to the new one,
	// informing the dispatcher of the change.
	virtual bool setDispatcher(LLPointer<LLEventDispatcher> dispatcher);

	// Returns the current dispatcher pointer.
	virtual LLEventDispatcher* getDispatcher();

	void addListener(LLEventListener *listener, LLSD filter = "", const LLSD& userdata = "")
	{
		if (mDispatcher.notNull()) mDispatcher->addListener(listener, filter, userdata);
	}
	void removeListener(LLEventListener *listener)
	{
		if (mDispatcher.notNull()) mDispatcher->removeListener(listener);
	}
	// Notifies the dispatcher of an event being fired.
	void fireEvent(LLPointer<LLEvent> event, LLSD filter = LLSD());

protected:
	LLPointer<LLEventDispatcher> mDispatcher;
};

class LLValueChangedEvent : public LLEvent
{
public:
	LLValueChangedEvent(LLObservable* source, LLSD value) : LLEvent(source, "value_changed"), mValue(value) { }
	LLSD getValue() { return mValue; }
	LLSD mValue;
};

} // LLOldEvents

#endif // LL_EVENT_H