aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-popup.h
blob: 65c51ce65f2ad4e49e7e48c6f1010c596b98f86b (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
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
 *
 * 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)
 *
 */

#ifndef __E_POPUP_H__
#define __E_POPUP_H__

#include <glib-object.h>
#include "libedataserver/e-msgport.h"

#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */

/* This is an abstract popup menu management/merging class.

   To implement your own popup menu system, just create your own
   target types and implement the target free method. */

typedef struct _EPopup EPopup;
typedef struct _EPopupClass EPopupClass;

typedef struct _EPopupItem EPopupItem;
typedef struct _EPopupFactory EPopupFactory; /* anonymous type */
typedef struct _EPopupTarget EPopupTarget;

typedef void (*EPopupActivateFunc)(EPopup *ep, EPopupItem *item, void *data);
typedef void (*EPopupFactoryFunc)(EPopup *emp, void *data);
typedef void (*EPopupItemsFunc)(EPopup *ep, GSList *items, void *data);

/**
 * enum _e_popup_t - Popup item type enumeration.
 * @E_POPUP_ITEM: A simple menu item.
 * @E_POPUP_TOGGLE: A toggle menu item. If struct _EPopupItem::image is
 * not NULL, then it points to GtkImage directly and there is a toggle
 * with an image and caption shown in the popup menu.
 * @E_POPUP_RADIO: A radio menu item.  Note that the radio group is
 * global for the entire (sub) menu.  i.e. submenu's must be used to
 * separate radio button menu items.
 * @E_POPUP_IMAGE: A &GtkImage menu item.  In this case the @image
 * field of &struct _EPopupItem points to the &GtkImage directly.
 * @E_POPUP_SUBMENU: A sub-menu header.  It is up to the application
 * to define the @path properly so that the submenu comes before the
 * submenu items.
 * @E_POPUP_BAR: A menu separator bar.
 * @E_POPUP_TYPE_MASK: Mask used to separate item type from option bits.
 * @E_POPUP_ACTIVE: An option bit to signify that the radio button or
 * toggle button is active.
 * @E_POPUP_INCONSISTENT: An option to toggle only, if set, the toggle
 * is shown in inconsistent state. This is used before E_POPUP_ACTIVE.
 */
enum _e_popup_t {
    E_POPUP_ITEM = 0,
    E_POPUP_TOGGLE,
    E_POPUP_RADIO,
    E_POPUP_IMAGE,
    E_POPUP_SUBMENU,
    E_POPUP_BAR,
    E_POPUP_TYPE_MASK = 0xffff,
    E_POPUP_ACTIVE = 0x10000,
    E_POPUP_INCONSISTENT = 0x20000
};

/* FIXME: activate passes back no context data apart from that provided.
   FIXME: It should pass the target at the least.  The menu widget is
   useless */

/**
 * struct _EPopupItem - A popup menu item definition.
 * @type: The type of the popup.  See the &enum _epopup_t definition
 * for possible values.
 * @path: An absolute path, which when sorted using a simple ASCII
 * sort, will put the menu item in the right place in the menu
 * heirarchy.  '/' is used to separate menus from submenu items.
 * @label: The text of the menyu item.
 * @activate: A function conforming to &EPopupActivateFunc which will
 * be called when the menu item is activated.
 * @user_data: Extra per-item user-data available to the
 * application.  This is not passed to the @data field of @activate.
 * @image: For most types, the name of the icon in the icon theme to
 * display next to the menu item, if required.  For the %E_POPUP_IMAGE
 * type, it is a pointer to the &GtkWidget instead.
 * @visible: Visibility mask.  Used together with the &EPopupTarget mask
 * to determine if the item should be part of the menu or not.
 * @enable: Sensitivity mask. Similar to the visibility mask, but
 * currently unimplemented.
 * @popup: Used by e-popup to reference the parent object from
 * callbacks.
 *
 * The EPopupItem defines a single popup menu item, or submenu item,
 * or menu separator based on the @type.  Any number of these are
 * merged at popup display type to form the popup menu.
 *
 * The application may extend this structure using simple C structure
 * containers to add any additional fields it may require.
 */
struct _EPopupItem {
    enum _e_popup_t type;
    char *path;     /* absolute path! must sort ascii-lexographically into the right spot */
    char *label;
    EPopupActivateFunc activate;
    void *user_data;    /* user data, not passed directly to @activate */
    void *image;        /* char* for item type, GtkWidget * for image type */
    guint32 visible;    /* visibility mask */
    guint32 enable;     /* sensitivity mask */
};

/**
 * struct EPopupTarget - A popup menu target definition.
 *
 * @popup: The parent popup object, used for virtual methods on the target.
 * @widget: The parent widget, where available.  In some cases the
 * type of this object is part of the published api for the target.
 * @type: The target type.  This will be defined by the
 * implementation.
 * @mask: Target mask. This is used to sensitise and show items
 * based on their definition in EPopupItem.
 *
 * An EPopupTarget defines the context for a specific popup menu
 * instance.  The root target object is abstract, and it is up to
 * sub-classes of &EPopup to define the additional fields required to
 * make it usable.
 */
struct _EPopupTarget {
    struct _EPopup *popup;  /* used for virtual methods */

    struct _GtkWidget *widget;  /* used if you need a parent toplevel, if available */
    guint32 type;       /* targe type, for implementors */

    guint32 mask;       /* depends on type, visibility mask */

    /* implementation fields follow */
};

/**
 * struct _EPopup - A Popup menu manager.
 *
 * @object: Superclass, GObject.
 * @priv: Private data.
 * @menuid: The id of this menu instance.
 * @target: The current target during the display of the popup menu.
 *
 * The EPopup manager object.  Each popup menu is built using this
 * one-off object which is created each time the popup is invoked.
 */
struct _EPopup {
    GObject object;

    struct _EPopupPrivate *priv;

    char *menuid;

    EPopupTarget *target;
};

/**
 * struct _EPopupClass -
 *
 * @object_class: Superclass type.
 * @factories: A list of factories for this particular class of popup
 * menu.
 * @target_free: Virtual method to free the popup target.  The base
 * class frees the allocation and unrefs the popup pointer
 * structure.
 *
 * The EPopup class definition.  This should be sub-classed for each
 * component that wants to provide hookable popup menus.  The
 * sub-class only needs to know how to allocate and free the various target
 * types it supports.
 */
struct _EPopupClass {
    GObjectClass object_class;

    EDList factories;

    void (*target_free)(EPopup *ep, EPopupTarget *t);
};

GType e_popup_get_type(void);

EPopup *e_popup_new(const char *menuid);

/* Static class methods */
EPopupFactory *e_popup_class_add_factory(EPopupClass *klass, const char *menuid, EPopupFactoryFunc func, void *data);
void e_popup_class_remove_factory(EPopupClass *klass, EPopupFactory *f);

EPopup *e_popup_construct(EPopup *, const char *menuid);

void e_popup_add_items(EPopup *, GSList *items, const char *domain, EPopupItemsFunc freefunc, void *data);

void e_popup_add_static_items(EPopup *emp, EPopupTarget *target);
/* do not call e_popup_create_menu, it can leak structures if not used right */
struct _GtkMenu *e_popup_create_menu(EPopup *, EPopupTarget *, guint32 mask);
struct _GtkMenu *e_popup_create_menu_once(EPopup *emp, EPopupTarget *, guint32 mask);

void *e_popup_target_new(EPopup *, int type, size_t size);
void e_popup_target_free(EPopup *, void *);

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

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

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

#include "e-util/e-plugin.h"

typedef struct _EPopupHookMenu EPopupHookMenu;
typedef struct _EPopupHook EPopupHook;
typedef struct _EPopupHookClass EPopupHookClass;

typedef struct _EPluginHookTargetMap EPopupHookTargetMap;
typedef struct _EPluginHookTargetKey EPopupHookTargetMask;

typedef void (*EPopupHookFunc)(struct _EPlugin *plugin, EPopupTarget *target);

/**
 * struct _EPopupHookMenu -
 *
 * @hook: Parent pointer.
 * @id: The identifier of the menu to which these items belong.
 * @target_type: The target number of the type of target these menu
 * items expect. It will generally also be defined by the menu id.
 * @items: A list of EPopupItems.
 * @factory: If supplied, a function to call
 *
 * The structure used to keep track of all of the items that a plugin
 * wishes to add to a given menu. This is used internally by a factory
 * method set on EPlugin to add the right menu items to a given menu.
 */
struct _EPopupHookMenu {
    struct _EPopupHook *hook; /* parent pointer */
    char *id;       /* target menu id for these menu items */
    int target_type;    /* target type of this menu */
    GSList *items;      /* items to add to menu */
    char *factory;      /* optional factory to call for adding menu items */
};

/**
 * struct _EPopupHook - A popup menu hook.
 *
 * @hook: Superclass.
 * @menus: A list of EPopupHookMenus, for all menus registered on
 * this hook type.
 *
 * The EPopupHook class loads and manages the meta-data required to
 * map plugin definitions to physical menus.
 */
struct _EPopupHook {
    EPluginHook hook;

    GSList *menus;
};

/**
 * struct _EPopupHookClass -
 *
 * @hook_class: Superclass.
 * @target_map: Table of EPluginHookTargetMaps which enumerate the
 * target types and enable bits of the implementing class.
 * @popup_class: The EPopupClass of the corresponding popup manager
 * for the implementing class.
 *
 * The EPopupHookClass is a concrete class, however it is empty on its
 * own.  It needs to be sub-classed and initialised appropriately.
 *
 * The EPluginHookClass.id must be set to the name and version of the
 * hook handler itself.  The @target_map must be initialised with the
 * data required to enumerate the target types and enable flags
 * supported by the implementing class.
 */
struct _EPopupHookClass {
    EPluginHookClass hook_class;

    /* EPopupHookTargetMap by .type */
    GHashTable *target_map;
    /* the popup class these popups belong to */
    EPopupClass *popup_class;
};

GType e_popup_hook_get_type(void);

/* for implementors */
void e_popup_hook_class_add_target_map(EPopupHookClass *klass, const EPopupHookTargetMap *);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __E_POPUP_H__ */