aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-event.h
blob: 28caded6fe9a70fc99d7d89dbc1fafcb576fb507 (plain) (blame)
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
 *
 * This program 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; either
 * version 2 of the License, or (at your option) version 3.
 *
 * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
 *
 *
 * Authors:
 *      Michel Zucchi <notzed@ximian.com>
 *
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 *
 */

#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION)
#error "Only <e-util/e-util.h> should be included directly."
#endif

/* This a bit 'whipped together', so is likely to change mid-term */

#ifndef E_EVENT_H
#define E_EVENT_H

#include <glib-object.h>

/* Standard GObject macros */
#define E_TYPE_EVENT \
    (e_event_get_type ())
#define E_EVENT(obj) \
    (G_TYPE_CHECK_INSTANCE_CAST \
    ((obj), E_TYPE_EVENT, EEvent))
#define E_EVENT_CLASS(cls) \
    (G_TYPE_CHECK_CLASS_CAST \
    ((cls), E_TYPE_EVENT, EEventClass))
#define E_IS_EVENT(obj) \
    (G_TYPE_CHECK_INSTANCE_TYPE \
    ((obj), E_TYPE_EVENT))
#define E_IS_EVENT_CLASS(cls) \
    (G_TYPE_CHECK_CLASS_TYPE \
    ((cls), E_TYPE_EVENT))
#define E_EVENT_GET_CLASS(obj) \
    (G_TYPE_INSTANCE_GET_CLASS \
    ((obj), E_TYPE_EVENT, EEventClass))

G_BEGIN_DECLS

/* This is an abstract event management class. */

typedef struct _EEvent EEvent;
typedef struct _EEventClass EEventClass;
typedef struct _EEventPrivate EEventPrivate;

typedef struct _EEventItem EEventItem;
typedef struct _EEventFactory EEventFactory; /* anonymous type */
typedef struct _EEventTarget EEventTarget;

typedef void (*EEventItemsFunc)(EEvent *ee, GSList *items, gpointer data);
typedef void (*EEventFunc)(EEvent *ee, EEventItem *item, gpointer data);
typedef void (*EEventFactoryFunc)(EEvent *ee, gpointer);

/**
 * enum _e_event_t - Event type.
 *
 * @E_EVENT_PASS: A passthrough event handler which only receives the event.
 * @E_EVENT_SINK: A sink event handler swallows all events it processes.
 *
 * The event type defines what type of event listener this is.
 *
 * Events should normally be @E_EVENT_PASS.
 **/
enum _e_event_t {
    E_EVENT_PASS,       /* passthrough */
    E_EVENT_SINK        /* sink events */
};

/**
 * struct _EEventItem - An event listener item.
 *
 * @type: The type of the event listener.
 * @priority: A signed number signifying the priority of the event
 * listener.  0 should be used normally.  This is used to order event
 * receipt when multiple listners are present.
 * @id: The name of the event to listen to.  By convention events are of the form
 * "component.subcomponent".  The target mask provides further
 * sub-event type qualification.
 * @target_type: Target type for this event.  This is implementation
 * specific.
 * @handle: Event handler callback.
 * @user_data: Callback data.
 * @enable: Target-specific mask to qualify the receipt of events.
 * This is target and implementation specific.
 *
 * An EEventItem defines a specific event listening point on a given
 * EEvent object.  When an event is broadcast onto an EEvent handler,
 * any matching EEventItems will be invoked in priority order.
 **/
struct _EEventItem {
    enum _e_event_t type;
    gint priority;      /* priority of event */
    const gchar *id;        /* event id */
    gint target_type;
    EEventFunc handle;
    gpointer user_data;
    guint32 enable;     /* enable mask */
};

/**
 * struct _EEventTarget - Base EventTarget.
 *
 * @event: Parent object.
 * @type: Target type.  Defined by the implementation.
 * @mask: Mask of this target.  This is defined by the implementation,
 * the type, and the actual content of the target.
 *
 * This defined a base EventTarget.  This must be subclassed by
 * implementations to provide contextual data for events, and define
 * the enablement qualifiers.
 *
 **/
struct _EEventTarget {
    EEvent *event;  /* used for virtual methods */

    guint32 type;       /* targe type, for implementors */
    guint32 mask;       /* depends on type, enable mask */

    /* implementation fields follow */
};

/**
 * struct _EEvent - An Event Manager.
 *
 * @object: Superclass.
 * @priv: Private data.
 * @id: Id of this event manager.
 * @target: The current target, only set during event emission.
 *
 * The EEvent manager object.  Each component which defines event
 * types supplies a single EEvent manager object.  This manager routes
 * all events invoked on this object to all registered listeners based
 * on their qualifiers.
 **/
struct _EEvent {
    GObject object;
    EEventPrivate *priv;
    gchar *id;
    EEventTarget *target;   /* current target during event emission */
};

/**
 * struct _EEventClass - Event management type.
 *
 * @object_class: Superclass.
 * @target_free: Virtual method to free the target.
 *
 * The EEvent class definition.  This must be sub-classed for each
 * component that wishes to provide hookable events.  The subclass
 * only needs to know how to allocate and free each target type it
 * supports.
 **/
struct _EEventClass {
    GObjectClass object_class;

    void        (*target_free)      (EEvent *event,
                         EEventTarget *target);
};

GType       e_event_get_type        (void);
EEvent *    e_event_construct       (EEvent *event,
                         const gchar *id);
gpointer    e_event_add_items       (EEvent *event,
                         GSList *items,
                         EEventItemsFunc freefunc,
                         gpointer data);
void        e_event_remove_items        (EEvent *event,
                         gpointer handle);
void        e_event_emit            (EEvent *event,
                         const gchar *id,
                         EEventTarget *target);
gpointer    e_event_target_new      (EEvent *event,
                         gint type,
                         gsize size);
void        e_event_target_free     (EEvent *event,
                         gpointer object);

/* ********************************************************************** */

/* event plugin target, they are closely integrated */

/* To implement a basic event menu plugin, you just need to subclass
 * this and initialise the class target type tables */

/* For events, the plugin item talks to a specific instance, rather than
 * a set of instances of the hook handler */

#include <e-util/e-plugin.h>

/* Standard GObject macros */
#define E_TYPE_EVENT_HOOK \
    (e_event_hook_get_type ())
#define E_EVENT_HOOK(obj) \
    (G_TYPE_CHECK_INSTANCE_CAST \
    ((obj), E_TYPE_EVENT_HOOK, EEventHook))
#define E_EVENT_HOOK_CLASS(cls) \
    (G_TYPE_CHECK_CLASS_CAST \
    ((cls), E_TYPE_EVENT_HOOK, EEventHookClass))
#define E_IS_EVENT_HOOK(obj) \
    (G_TYPE_CHECK_INSTANCE_TYPE \
    ((obj), E_TYPE_EVENT_HOOK))
#define E_IS_EVENT_HOOK_CLASS(cls) \
    (G_TYPE_CHECK_CLASS_TYPE \
    ((cls), E_TYPE_EVENT_HOOK))
#define E_EVENT_HOOK_GET_CLASS(obj) \
    (G_TYPE_INSTANCE_GET_CLASS \
    ((obj), E_TYPE_EVENT_HOOK, EEventHookClass))

typedef struct _EEventHook EEventHook;
typedef struct _EEventHookClass EEventHookClass;

typedef struct _EPluginHookTargetMap EEventHookTargetMap;
typedef struct _EPluginHookTargetKey EEventHookTargetMask;

typedef void (*EEventHookFunc)(EPlugin *plugin, EEventTarget *target);

/**
 * struct _EEventHook - An event hook.
 *
 * @hook: Superclass.
 *
 * The EEventHook class loads and manages the meta-data required to
 * track event listeners.  Unlike other hook types, there is a 1:1
 * match between an EEventHook instance class and its EEvent instance.
 *
 * When the hook is loaded, all of its event hooks are stored directly
 * on the corresponding EEvent which is stored in its class static area.
 **/
struct _EEventHook {
    EPluginHook hook;
};

/**
 * struct _EEventHookClass -
 *
 * @hook_class:
 * @target_map: Table of EPluginHookTargetMaps which enumerate the
 * target types and enable bits of the implementing class.
 * @event: The EEvent instance on which all loaded events must be registered.
 *
 * The EEventHookClass is an empty event hooking class, which must be
 * subclassed and initialised before use.
 *
 * The EPluginHookClass.id must be set to the name and version of the
 * hook handler itself, and then the type must be registered with the
 * EPlugin hook list before any plugins are loaded.
 **/
struct _EEventHookClass {
    EPluginHookClass hook_class;

    /* EEventHookTargetMap by .type */
    GHashTable *target_map;
    /* the event router these events's belong to */
    EEvent *event;
};

GType       e_event_hook_get_type   (void);
void        e_event_hook_class_add_target_map
                    (EEventHookClass *klass,
                     const EEventHookTargetMap *map);

G_END_DECLS

#endif /* E_EVENT_H */