1 |
/* |
/* |
2 |
$Id$ |
$Id$ |
3 |
|
|
4 |
Copyright (C) 2004 Kai Sterker <kaisterker@linuxgames.com> |
Copyright (C) 2004/2005 Kai Sterker <kaisterker@linuxgames.com> |
5 |
Part of the Adonthell Project http://adonthell.linuxgames.com |
Part of the Adonthell Project http://adonthell.linuxgames.com |
6 |
|
|
7 |
Adonthell is free software; you can redistribute it and/or modify |
Adonthell is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
(at your option) any later version. |
11 |
|
|
12 |
Adonthell is distributed in the hope that it will be useful, |
Adonthell is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
GNU General Public License for more details. |
16 |
|
|
17 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
18 |
along with Adonthell; if not, write to the Free Software |
along with Adonthell; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 |
*/ |
*/ |
21 |
|
|
22 |
/** |
/** |
23 |
* @file event/listener.h |
* @file event/listener.h |
24 |
* @author Kai Sterker <kaisterker@linuxgames.com> |
* @author Kai Sterker <kaisterker@linuxgames.com> |
25 |
* |
* |
26 |
* @brief Declares the %listener class. |
* @brief Declares the %listener class. |
27 |
* |
* |
28 |
*/ |
*/ |
29 |
|
|
30 |
#ifndef EVENT_LISTENER_H |
#ifndef EVENT_LISTENER_H |
31 |
#define EVENT_LISTENER_H |
#define EVENT_LISTENER_H |
32 |
|
|
33 |
#include "python/method.h" |
#include "python/method.h" |
34 |
#include "event/event.h" |
#include "event/event.h" |
35 |
|
|
36 |
#ifndef SWIG |
namespace events |
37 |
/** |
{ |
38 |
* Pointer to a function returning a newly allocated %event |
class factory; |
39 |
*/ |
|
40 |
typedef events::event* (*new_event)(); |
/** |
41 |
#endif // SWIG |
* An %event %listener contains a callback to a %python %method that it |
42 |
|
* will execute when the event occurs that the %listener is waiting |
43 |
namespace events |
* for. A %listener is usually created by a certain %event %factory and will |
44 |
{ |
* be destroyed if the %factory is destroyed. That way, it's not neccessary |
45 |
class factory; |
* to keep track of every single %listener. Instead, a few factories can |
46 |
|
* be used to create groups of listeners that can be disposed together. |
47 |
/** |
*/ |
48 |
* An %event %listener contains a callback to a %python %method that it |
class listener |
49 |
* will execute when the event occurs that the %listener is waiting |
{ |
50 |
* for. A %listener is usually created by a certain %event %factory and will |
public: |
51 |
* be destroyed if the %factory is destroyed. That way, it's not neccessary |
/** |
52 |
* to keep track of every single %listener. Instead, a few factories can |
* Create a new listener, which listens to the given event. |
53 |
* be used to create groups of listeners that can be disposed together. |
*/ |
54 |
*/ |
listener (factory *f, event *e); |
55 |
class listener |
|
56 |
{ |
/** |
57 |
public: |
* Destroy the %listener. Automatically removes it from |
58 |
/** |
* the %event %manager and %factory if required. |
59 |
* Create a new listener, which listens to the given event. |
*/ |
60 |
*/ |
~listener (); |
61 |
listener (factory *f, event *e); |
|
62 |
|
/** |
63 |
/** |
* @name Member access |
64 |
* Destroy the %listener. Automatically removes it from |
*/ |
65 |
* the %event %manager and %factory if required. |
//@{ |
66 |
*/ |
/** |
67 |
~listener (); |
* Get type of associated %event. |
68 |
|
* @return type of associated %event |
69 |
/** |
*/ |
70 |
* @name Member access |
u_int8 type () const |
71 |
*/ |
{ |
72 |
//@{ |
return Event->type (); |
73 |
/** |
} |
74 |
* Get type of associated %event. |
|
75 |
* @return type of associated %event |
/** |
76 |
*/ |
* Get the %event this 5listener waits for. |
77 |
u_int8 type () const |
* @return %event attached to the %listener. |
78 |
{ |
*/ |
79 |
return Event->type (); |
const event * get_event () const |
80 |
} |
{ |
81 |
|
return Event; |
82 |
/** |
} |
83 |
* Get the %event this 5listener waits for. |
|
84 |
* @return %event attached to the %listener. |
/** |
85 |
*/ |
* Get the event's id. |
86 |
const event * get_event () const |
* @return id of the %event. |
87 |
{ |
*/ |
88 |
return Event; |
const string & id () const |
89 |
} |
{ |
90 |
|
return Id; |
91 |
/** |
} |
92 |
* Get the event's id. |
|
93 |
* @return id of the %event. |
/** |
94 |
*/ |
* Assign an id to the %event, so it may be retrieved from an |
95 |
const string & id () const |
* event_list later on, without having a pointer to it. |
96 |
{ |
* |
97 |
return Id; |
* @param id a string to identify the %event. |
98 |
} |
*/ |
99 |
|
void set_id (const string & id) |
100 |
/** |
{ |
101 |
* Assign an id to the %event, so it may be retrieved from an |
Id = id; |
102 |
* event_list later on, without having a pointer to it. |
} |
103 |
* |
|
104 |
* @param id a string to identify the %event. |
/** |
105 |
*/ |
* Deleting a %listener from Python side can cause problems. |
106 |
void set_id (const string & id) |
* Instead, it should be marked as deletable with this method. |
107 |
{ |
* It will then be deleted on C++ side as soon as possible. |
108 |
Id = id; |
*/ |
109 |
} |
void destroy () |
110 |
|
{ |
111 |
/** |
Event->set_repeat (0); |
112 |
* Deleting a %listener from Python side can cause problems. |
} |
113 |
* Instead, it should be marked as deletable with this method. |
|
114 |
* It will then be deleted on C++ side as soon as possible. |
/** |
115 |
*/ |
* Check whether the %listener is marked for deletion. |
116 |
void destroy () |
*/ |
117 |
{ |
bool is_destroyed () const |
118 |
Event->set_repeat (0); |
{ |
119 |
} |
return Event->repeat () == 0; |
120 |
|
} |
121 |
/** |
|
122 |
* Check whether the %listener is marked for deletion. |
// these are internal methods that shouldn't be exported by SWIG! |
123 |
*/ |
#ifndef SWIG |
124 |
bool is_destroyed () const |
/** |
125 |
{ |
* Return whether the %listener is registered with the %event %manager. |
126 |
return Event->repeat () == 0; |
* @return \c true if this is the case, \c false otherwise. |
127 |
} |
*/ |
128 |
|
bool is_registered () const |
129 |
// these are internal methods that shouldn't be exported by SWIG! |
{ |
130 |
#ifndef SWIG |
return Registered; |
131 |
/** |
} |
132 |
* Return whether the %listener is registered with the %event %manager. |
|
133 |
* @return \c true if this is the case, \c false otherwise. |
/** |
134 |
*/ |
* This method is called by the %event %manager when the %listerner |
135 |
bool is_registered () const |
* is added to or removed from it. If the %listener is still added |
136 |
{ |
* when it is being destroyed, it will be automatically removed from |
137 |
return Registered; |
* the %manager. |
138 |
} |
* |
139 |
|
* @param state pass \c true if %listener is being connected, \c false otherwise |
140 |
/** |
*/ |
141 |
* This method is called by the %event %manager when the %listerner |
void set_registered (bool state) |
142 |
* is added to or removed from it. If the %listener is still added |
{ |
143 |
* when it is being destroyed, it will be automatically removed from |
Registered = state; |
144 |
* the %manager. |
} |
145 |
* |
#endif // SWIG |
146 |
* @param state pass \c true if %listener is being connected, \c false otherwise |
//@} |
147 |
*/ |
|
148 |
void set_registered (bool state) |
/** |
149 |
{ |
* Sets a python method to be executed whenever an |
150 |
Registered = state; |
* %event occurs that this listener listens to. |
151 |
} |
* |
152 |
#endif // SWIG |
* @param file Name of the script to load. |
153 |
//@} |
* @param classname Name of the class containing the callback. |
154 |
|
* @param callback Name of the method to call. |
155 |
/** |
* @param args Additional arguments to pass to the callback. |
156 |
* Sets a python method to be executed whenever an |
* @return \b false if connecting the callback failed, \b true otherwise. |
157 |
* %event occurs that this listener listens to. |
*/ |
158 |
* |
bool connect_callback (const string & file, const string & classname, |
159 |
* @param file Name of the script to load. |
const string & callback, PyObject *args = NULL); |
160 |
* @param classname Name of the class containing the callback. |
|
161 |
* @param callback Name of the method to call. |
/** |
162 |
* @param args Additional arguments to pass to the callback. |
* Execute the associated python script or callback. |
163 |
* @return \b false if connecting the callback failed, \b true otherwise. |
* |
164 |
*/ |
* @param evnt The %event that triggered the execution. |
165 |
bool connect_callback (const string & file, const string & classname, |
* @return The number of times the %event needs to be repeated. |
166 |
const string & callback, PyObject *args = NULL); |
*/ |
167 |
|
s_int32 raise_event (const event* evnt); |
168 |
/** |
|
169 |
* Execute the associated python script or callback. |
/** |
170 |
* |
* Check whether the given %event matches the %event attached to |
171 |
* @param evnt The %event that triggered the execution. |
* the %listener. |
172 |
* @return The number of times the %event needs to be repeated. |
* @param e %event to compare with the attached %event. |
173 |
*/ |
* @return \b true if events compare equal, \b false otherwise. |
174 |
s_int32 raise_event (const event* evnt); |
*/ |
175 |
|
bool equals (const event *e) const |
176 |
/** |
{ |
177 |
* Check whether the given %event matches the %event attached to |
return Event->equals (e); |
178 |
* the %listener. |
} |
179 |
* @param e %event to compare with the attached %event. |
|
180 |
* @return \b true if events compare equal, \b false otherwise. |
/** |
181 |
*/ |
* @name Pausing / Resuming execution |
182 |
bool equals (const event *e) const |
*/ |
183 |
{ |
//@{ |
184 |
return Event->equals (e); |
/** |
185 |
} |
* Disable the %event temporarily. As long as it in this state, the |
186 |
|
* event will neither be executed, nor will its repeat-count change. |
187 |
/** |
* As long as the %event is paused, it will be removed from its |
188 |
* @name Pausing / Resuming execution |
* %event handler. |
189 |
*/ |
*/ |
190 |
//@{ |
void pause (const u_int16 & level = 1); |
191 |
/** |
|
192 |
* Disable the %event temporarily. As long as it in this state, the |
/** |
193 |
* event will neither be executed, nor will its repeat-count change. |
* Re-enable an %event that has been paused. Re-registers it with |
194 |
* As long as the %event is paused, it will be removed from its |
* its %event handler. |
195 |
* %event handler. |
*/ |
196 |
*/ |
void resume (); |
197 |
void pause (const u_int16 & level = 1); |
|
198 |
|
/** |
199 |
/** |
* Check whether the %event is temporarily disabled or not. |
200 |
* Re-enable an %event that has been paused. Re-registers it with |
* @return \b true if it is paused, \b false otherwise. |
201 |
* its %event handler. |
*/ |
202 |
*/ |
bool is_paused () const |
203 |
void resume (); |
{ |
204 |
|
return (Paused > 0); |
205 |
/** |
} |
206 |
* Check whether the %event is temporarily disabled or not. |
//@} |
207 |
* @return \b true if it is paused, \b false otherwise. |
|
208 |
*/ |
/** |
209 |
bool is_paused () const |
* @name Loading / Saving |
210 |
{ |
*/ |
211 |
return (Paused > 0); |
//@{ |
212 |
} |
/** |
213 |
//@} |
* Flattens the %event %listener to the given stream. |
214 |
|
* |
215 |
/** |
* @param out stream where to add the %event %listener. |
216 |
* @name Loading / Saving |
*/ |
217 |
*/ |
void put_state (base::flat& out) const; |
218 |
//@{ |
|
219 |
/** |
/** |
220 |
* Flattens the %event %listener to the given stream. |
* Loads the %event %listener from given stream. |
221 |
* |
* |
222 |
* @param out stream where to add the %event %listener. |
* @param in stream to load the %event %listener from. |
223 |
*/ |
*/ |
224 |
void put_state (base::flat& out) const; |
bool get_state (base::flat& in); |
225 |
|
//@} |
226 |
/** |
|
227 |
* Loads the %event %listener from given stream. |
#ifndef SWIG |
228 |
* |
/** |
229 |
* @param in stream to load the %event %listener from. |
* Allow %listener to be passed as python argument |
230 |
*/ |
*/ |
231 |
bool get_state (base::flat& in); |
GET_TYPE_NAME(events::listener) |
232 |
//@} |
#endif // SWIG |
233 |
|
|
234 |
#ifndef SWIG |
private: |
235 |
/** |
/** |
236 |
* Register an %event for loading. Before the %event %factory can load |
* (Optional) Id of the event |
237 |
* an %event from file, it needs a callback function that returns |
*/ |
238 |
* a new instance of the %event of the given type. |
string Id; |
239 |
* |
|
240 |
* @param type the type of the %event to register |
/** |
241 |
* @param e a callback returning a new instance of an %event of the |
* Whether the %listener is registered with the %event %manager |
242 |
* given type. |
*/ |
243 |
* |
bool Registered; |
244 |
* @sa get_state () |
|
245 |
*/ |
/** |
246 |
static void register_event (u_int8 type, new_event e); |
* Whether the %listener is temporarily disabled or not |
247 |
|
*/ |
248 |
/** |
u_int16 Paused; |
249 |
* Allow %listener to be passed as python argument |
|
250 |
*/ |
/** |
251 |
GET_TYPE_NAME(event::listener) |
* The callback connected to this %listener |
252 |
#endif // SWIG |
*/ |
253 |
|
python::method *Method; |
254 |
private: |
|
255 |
/** |
/** |
256 |
* (Optional) Id of the event |
* Arguments to pass to the method |
257 |
*/ |
*/ |
258 |
string Id; |
PyObject *Args; |
259 |
|
|
260 |
/** |
/** |
261 |
* Whether the %listener is registered with the %event %manager |
* The %event this %listener will react to. |
262 |
*/ |
*/ |
263 |
bool Registered; |
event *Event; |
264 |
|
|
265 |
/** |
/** |
266 |
* Whether the %listener is temporarily disabled or not |
* The %event %factory that created this listener. |
267 |
*/ |
*/ |
268 |
u_int16 Paused; |
factory *Factory; |
269 |
|
}; |
270 |
/** |
} |
271 |
* The callback connected to this %listener |
|
272 |
*/ |
#endif // EVENT_LISTENER_H |
|
python::method *Method; |
|
|
|
|
|
/** |
|
|
* Arguments to pass to the method |
|
|
*/ |
|
|
PyObject *Args; |
|
|
|
|
|
/** |
|
|
* The %event this %listener will react to. |
|
|
*/ |
|
|
event *Event; |
|
|
|
|
|
/** |
|
|
* The %event %factory that created this listener. |
|
|
*/ |
|
|
factory *Factory; |
|
|
|
|
|
/** |
|
|
* Array with callbacks that return a newly allocated instance of an %event. |
|
|
* The event's type is the postion of the according callback in the array. |
|
|
*/ |
|
|
static new_event instanciate_event[MAX_EVENTS]; |
|
|
}; |
|
|
} |
|
|
|
|
|
#ifndef SWIG |
|
|
/** |
|
|
* Registers an %event with the %event %factory, allowing it to load this %event |
|
|
* without knowing about it at compile time. |
|
|
*/ |
|
|
#define REGISTER_EVENT(type,evt)\ |
|
|
listener::register_event (type, (new_event) &new_ ## evt); |
|
|
|
|
|
/** |
|
|
* A function that returns a new instance of an %event. |
|
|
*/ |
|
|
#define NEW_EVENT(evt)\ |
|
|
events::event* new_ ## evt () { return (events::event*) new events::evt; } |
|
|
|
|
|
#endif // SWIG |
|
|
#endif // EVENT_LISTENER_H |
|