Allow for event handlers to have separate (optional) destructors.

git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5868 4a71c877-e1ca-e34f-864e-861f7616d084
master
Freddie Witherden 2008-08-24 16:58:27 +00:00
parent fd0084951e
commit cc94bc2818
2 changed files with 49 additions and 33 deletions

View File

@ -668,7 +668,7 @@ void widgetRemoveChildImpl(widget *self, widget *child)
}
int widgetAddEventHandlerImpl(widget *self, eventType type, callback handler,
void *userData)
callback destructor, void *userData)
{
eventTableEntry *entry = malloc(sizeof(eventTableEntry));
eventTableEntry *lastEntry = vectorHead(self->eventVtbl);
@ -677,10 +677,11 @@ int widgetAddEventHandlerImpl(widget *self, eventType type, callback handler,
assert(type != EVT_TIMER_SINGLE_SHOT && type != EVT_TIMER_PERSISTENT);
// Assign the handler an id which is one higher than the current highest
entry->id = (lastEntry) ? lastEntry->id + 1 : 1;
entry->type = type;
entry->callback = handler;
entry->userData = userData;
entry->id = (lastEntry) ? lastEntry->id + 1 : 1;
entry->type = type;
entry->callback = handler;
entry->destructor = destructor;
entry->userData = userData;
entry->lastCalled = 0; // We have never been called
entry->interval = -1; // We are not a timer event
@ -693,7 +694,8 @@ int widgetAddEventHandlerImpl(widget *self, eventType type, callback handler,
}
int widgetAddTimerEventHandlerImpl(widget *self, eventType type, int interval,
callback handler, void *userData)
callback handler, callback destructor,
void *userData)
{
eventTableEntry *entry = malloc(sizeof(eventTableEntry));
eventTableEntry *lastEntry = vectorHead(self->eventVtbl);
@ -701,10 +703,11 @@ int widgetAddTimerEventHandlerImpl(widget *self, eventType type, int interval,
// We should only be used to add timer events
assert(type == EVT_TIMER_SINGLE_SHOT || type == EVT_TIMER_PERSISTENT);
entry->id = (lastEntry) ? lastEntry->id + 1 : 1;
entry->type = type;
entry->callback = handler;
entry->userData = userData;
entry->id = (lastEntry) ? lastEntry->id + 1 : 1;
entry->type = type;
entry->callback = handler;
entry->destructor = destructor;
entry->userData = userData;
entry->lastCalled = 0;
entry->interval = interval;
@ -728,12 +731,16 @@ void widgetRemoveEventHandlerImpl(widget *self, int id)
// If the handler matches, remove it
if (handler->id == id)
{
// Generate an EVT_DESTRUCT event to allow the handler to clean-up
eventMisc evtDestruct;
evtDestruct.event.type = EVT_DESTRUCT;
handler->callback(self, (event *) &evtDestruct, handler->id,
handler->userData);
// If there is a destructor; call it
if (handler->destructor)
{
// Generate an EVT_DESTRUCT event
eventMisc evtDestruct;
evtDestruct.event.type = EVT_DESTRUCT;
handler->destructor(self, (event *) &evtDestruct, -1,
handler->userData);
}
// Release the handler
free(handler);
@ -813,6 +820,7 @@ int widgetAddAnimation(widget *self, int nframes,
// Install the animation timer event handler
return widgetAddTimerEventHandler(self, EVT_TIMER_PERSISTENT, 10,
widgetAnimationTimerCallback,
widgetAnimationTimerCallback, ourFrames);
}
@ -1493,17 +1501,20 @@ void widgetRemoveChild(widget *self, widget *child)
WIDGET_GET_VTBL(self)->removeChild(self, child);
}
int widgetAddEventHandler(widget *self, eventType type,
callback handler, void *userData)
int widgetAddEventHandler(widget *self, eventType type, callback handler,
callback destructor, void *userData)
{
return WIDGET_GET_VTBL(self)->addEventHandler(self, type, handler, userData);
return WIDGET_GET_VTBL(self)->addEventHandler(self, type, handler,
destructor, userData);
}
int widgetAddTimerEventHandler(widget *self, eventType type, int interval,
callback handler, void *userData)
callback handler, callback destructor,
void *userData)
{
return WIDGET_GET_VTBL(self)->addTimerEventHandler(self, type, interval,
handler, userData);
handler, destructor,
userData);
}
void widgetRemoveEventHandler(widget *self, int id)

View File

@ -67,12 +67,6 @@ typedef struct _eventMisc eventMisc;
* @param evt A pointer to the event structure. Depending on the value of
* evt->type it may be necessary to cast this to derived event
* structure (e.g., evtMouse or evtMisc).
*
* All callback functions must be able to handle EVT_DESTRUCT
* events, which are generated when either self is destroyed or the
* event handler removed (widgetRemoveEventHandler). This allows
* for the callback to free any memory which it has allocated/is
* responsible for (e.g. userData).
* @param handlerId The (unique) id of this event handler. This can be used to:
* - Remove the event handler from the widgets event table;
* which can be done by calling widgetRemoveEventHandler. It
@ -270,6 +264,9 @@ struct _eventTableEntry
/// The method to call
callback callback;
/// The method to call when removing the event handler
callback destructor;
/// Pointer to user supplied data to pass to callback
void *userData;
@ -334,9 +331,12 @@ struct _widgetVtbl
bool (*fireTimerCallbacks) (widget *self, const event *evt);
int (*addEventHandler) (widget *self, eventType type,
callback handler, void *userData);
callback handler,
callback destructor,
void *userData);
int (*addTimerEventHandler) (widget *self, eventType type,
int interval, callback handler,
callback destructor,
void *userData);
void (*removeEventHandler) (widget *self, int id);
@ -537,9 +537,11 @@ void widgetRemoveChildImpl(widget *self, widget *child);
bool widgetFireCallbacksImpl(widget *self, const event *evt);
bool widgetFireTimerCallbacksImpl(widget *self, const event *evt);
int widgetAddEventHandlerImpl(widget *self, eventType type,
callback handler, void *userData);
callback handler, callback destructor,
void *userData);
int widgetAddTimerEventHandlerImpl(widget *self, eventType type, int interval,
callback handler, void *userData);
callback handler, callback destructor,
void *userData);
void widgetRemoveEventHandlerImpl(widget *self, int id);
point widgetAnimationInterpolateTranslateImpl(widget *self, animationFrame k1,
animationFrame k2, int time);
@ -698,11 +700,12 @@ void widgetRemoveChild(widget *self, widget *child);
* @param self The widget to add the event handler to.
* @param type The type of event that handler should respond to.
* @param handler The function to call when the event type fires.
* @param destructor The function to call when the event handler is removed.
* @param userData User specified data pointer to pass to handler.
* @return The id of the newly added event.
*/
int widgetAddEventHandler(widget *self, eventType type,
callback handler, void *userData);
int widgetAddEventHandler(widget *self, eventType type, callback handler,
callback destructor, void *userData);
/**
* Similar to widgetAddEventHandler in many respects, except that it is designed
@ -712,11 +715,13 @@ int widgetAddEventHandler(widget *self, eventType type,
* @param type The type of the timer to register the handler for.
* @param interval The duration in ms to wait.
* @param handler The function to call when the event fires.
* @param destructor The function to call when the event handler is removed.
* @param userData User specified data pointer to pass to handler.
* @return The id of the newly added event.
*/
int widgetAddTimerEventHandler(widget *self, eventType type, int interval,
callback handler, void *userData);
callback handler, callback destructor,
void *userData);
/**
* Removes the event from the events table at offset id.