aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/rlvevent.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/rlvevent.h224
1 files changed, 224 insertions, 0 deletions
diff --git a/linden/indra/newview/rlvevent.h b/linden/indra/newview/rlvevent.h
new file mode 100644
index 0000000..c3d9c45
--- /dev/null
+++ b/linden/indra/newview/rlvevent.h
@@ -0,0 +1,224 @@
1#ifndef RLV_EVENTEMITTER_H
2#define RLV_EVENTEMITTER_H
3
4#include <algorithm>
5#include <typeinfo>
6#include <list>
7
8#include "lluuid.h"
9
10#include "rlvhelper.h"
11
12// ============================================================================
13/*
14 * RlvEvent
15 * ========
16 * Passed to observer event handlers (contains the same paramaters as RlvHandler::processXXXCommand)
17 */
18
19class RlvEvent
20{
21public:
22 RlvEvent(const LLUUID& uuid, const RlvCommand& rlvCmd) : m_UUID(uuid), m_rlvCmd(rlvCmd) {}
23 virtual ~RlvEvent() {}
24
25 const LLUUID& getSenderID() const { return m_UUID; };
26 const RlvCommand& getCommand() const { return m_rlvCmd; };
27
28protected:
29 LLUUID m_UUID;
30 RlvCommand m_rlvCmd;
31};
32
33// ============================================================================
34/*
35 * RlvObserver
36 * ===========
37 * Provides a way to extend the existing command set without changing the main RlvHandler class
38 *
39 * Steps:
40 * - derive your class from RlvObserver
41 * - override any of the event functions you need
42 * - add it as an observer: gRlvHandler.addObserver(new RlbObserverDerivedClass());
43 * - done
44 *
45 * Notes:
46 * - as long as you don't call gRlvHandler.remObserver() your class will be cleaned up from
47 * RlvEventEmitter destructor (see below)
48 * - event handlers are called only if RlvHandler didn't handle it so while you can
49 * add a new command @foobar=n, you won't get called for @detach=n
50 * - event handlers are called *after* the command is added so a call to
51 * RlvHandler::hasBehaviour("foobar") would return TRUE
52 * - return TRUE if you handled the command (won't get passed on to the next observer)
53 * return FALSE if you didn't handle the command (gets passed on to the next observer)
54 *
55 */
56
57class RlvObserver
58{
59public:
60 virtual ~RlvObserver() {}
61
62 typedef RlvEvent EventType;
63
64 virtual BOOL onAddCommand(const EventType& rlvEvent) { return FALSE; }
65 virtual BOOL onRemoveCommand(const EventType& rlvEvent) { return FALSE; }
66 virtual BOOL onReplyCommand(const EventType& rlvEvent) { return FALSE; }
67 virtual BOOL onForceCommand(const EventType& rlvEvent) { return FALSE; }
68};
69
70// ============================================================================
71/*
72 * RlvEventEmitter
73 * ===============
74 * Essentially a slightly modified eventEmitter (see lleventemitter.h)
75 *
76 * Changes:
77 * - if an event handler returns TRUE then no further observers are notified
78 * - cleans up the (remaining) observers in the destructor
79 */
80
81template < class T >
82class RlvEventEmitter
83{
84 public:
85 typedef typename T::EventType EventType;
86 typedef std::list< T* > ObserverContainer;
87 typedef BOOL ( T::*observerMethod )( const EventType& );
88
89 protected:
90 ObserverContainer observers;
91
92 public:
93 RlvEventEmitter() { };
94
95 ~RlvEventEmitter()
96 {
97 clearObservers();
98 }
99
100 BOOL addObserver ( T* observerIn )
101 {
102 if ( ! observerIn )
103 return FALSE;
104
105 // check if observer already exists
106 if ( std::find ( observers.begin (), observers.end (), observerIn ) != observers.end () )
107 return FALSE;
108
109 // save it
110 observers.push_back ( observerIn );
111
112 return true;
113 }
114
115 BOOL remObserver ( T* observerIn )
116 {
117 if ( ! observerIn )
118 return FALSE;
119
120 observers.remove ( observerIn );
121
122 return TRUE;
123 }
124
125 void clearObservers()
126 {
127 typename std::list< T* >::iterator iter = observers.begin ();
128
129 while (iter != observers.end ())
130 {
131 delete *iter;
132 ++iter;
133 };
134
135 observers.clear();
136 }
137
138 BOOL update ( observerMethod method, const EventType& msgIn )
139 {
140 typename std::list< T* >::iterator iter = observers.begin ();
141
142 BOOL fContinue = TRUE;
143 while ( (iter != observers.end ()) && (fContinue) )
144 {
145 fContinue = !( ( ( *iter )->*method ) ( msgIn ) );
146 ++iter;
147 };
148
149 return !fContinue;
150 }
151};
152
153// ============================================================================
154
155class RlvBehaviourObserver
156{
157public:
158 virtual ~RlvBehaviourObserver() {}
159 virtual void changed(const RlvCommand& rlvCmd, bool fInternal) = 0;
160};
161
162// ============================================================================
163
164class RlvBehaviourNotifyObserver : public RlvBehaviourObserver
165{
166public:
167 virtual ~RlvBehaviourNotifyObserver() { }
168
169 void changed(const RlvCommand& rlvCmd, bool fInternal)
170 {
171 if ( (fInternal) || ((RLV_TYPE_ADD != rlvCmd.getParamType()) && (RLV_TYPE_REMOVE != rlvCmd.getParamType())) )
172 return;
173
174 std::string strCmd = rlvCmd.asString();
175 std::string strNotify = llformat("/%s=%c", strCmd.c_str(), (RLV_TYPE_ADD == rlvCmd.getParamType()) ? 'n' : 'y');
176
177 for (std::multimap<LLUUID, notifyData>::const_iterator itNotify = m_Notifications.begin();
178 itNotify != m_Notifications.end(); ++itNotify)
179 {
180 if ( (itNotify->second.strFilter.empty()) || (std::string::npos != strCmd.find(itNotify->second.strFilter)) )
181 rlvSendChatReply(itNotify->second.nChannel, strNotify);
182 }
183 }
184
185 void addNotify(const LLUUID& idObj, S32 nChannel, const std::string& strFilter)
186 {
187 m_Notifications.insert(std::pair<LLUUID, notifyData>(idObj, notifyData(nChannel, strFilter)));
188 }
189
190 void clearNotify(const LLUUID& idObj)
191 {
192 m_Notifications.erase(idObj);
193 }
194
195 bool hasNotify()
196 {
197 return (m_Notifications.size() != 0);
198 }
199
200 void removeNotify(const LLUUID& idObj, S32 nChannel, const std::string& strFilter)
201 {
202 for (std::multimap<LLUUID, notifyData>::iterator itNotify = m_Notifications.lower_bound(idObj),
203 endNotify = m_Notifications.upper_bound(idObj); itNotify != endNotify; ++itNotify)
204 {
205 if ( (itNotify->second.nChannel == nChannel) && (itNotify->second.strFilter == strFilter) )
206 {
207 m_Notifications.erase(itNotify);
208 break;
209 }
210 }
211 }
212protected:
213 struct notifyData
214 {
215 S32 nChannel;
216 std::string strFilter;
217 notifyData(S32 channel, const std::string& filter) : nChannel(channel), strFilter(filter) {}
218 };
219 std::multimap<LLUUID, notifyData> m_Notifications;
220};
221
222// ============================================================================
223
224#endif // RLV_EVENTEMITTER_H