1 /*
2 Copyright (C) 2010 ProFUSION embedded systems
3 Copyright (C) 2010 Samsung Electronics
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include "ewk_contextmenu.h"
23
24 #include "ContextMenu.h"
25 #include "ContextMenuController.h"
26 #include "ContextMenuItem.h"
27 #include "EWebKit.h"
28 #include "ewk_private.h"
29
30 #include <Eina.h>
31 #include <eina_safety_checks.h>
32 #include <wtf/text/CString.h>
33
34 /**
35 * \struct _Ewk_Context_Menu
36 * @brief Contains the context menu data.
37 */
38 struct _Ewk_Context_Menu {
39 unsigned int __ref; /**< the reference count of the object */
40 #if ENABLE(CONTEXT_MENUS)
41 WebCore::ContextMenuController* controller; /**< the WebCore's object which is responsible for the context menu */
42 #endif
43 Evas_Object* view; /**< the view object */
44
45 Eina_List* items; /**< the list of items */
46 };
47
48 /**
49 * \struct _Ewk_Context_Menu_Item
50 * @brief Represents one item of the context menu object.
51 */
52 struct _Ewk_Context_Menu_Item {
53 Ewk_Context_Menu_Item_Type type; /**< contains the type of the item */
54 Ewk_Context_Menu_Action action; /**< contains the action of the item */
55
56 const char* title; /**< contains the title of the item */
57 Ewk_Context_Menu* submenu; /**< contains the pointer to the submenu of the item */
58
59 Eina_Bool checked:1;
60 Eina_Bool enabled:1;
61 };
62
63 /**
64 * Increases the reference count of the given object.
65 *
66 * @param menu the context menu object to increase the reference count
67 */
ewk_context_menu_ref(Ewk_Context_Menu * menu)68 void ewk_context_menu_ref(Ewk_Context_Menu* menu)
69 {
70 EINA_SAFETY_ON_NULL_RETURN(menu);
71 menu->__ref++;
72 }
73
74 /**
75 * Decreases the reference count of the given object, possibly freeing it.
76 *
77 * When the reference count it's reached 0, the menu with all items are freed.
78 *
79 * @param menu the context menu object to decrease the reference count
80 */
ewk_context_menu_unref(Ewk_Context_Menu * menu)81 void ewk_context_menu_unref(Ewk_Context_Menu* menu)
82 {
83 EINA_SAFETY_ON_NULL_RETURN(menu);
84 void* item;
85
86 if (--menu->__ref)
87 return;
88
89 EINA_LIST_FREE(menu->items, item)
90 ewk_context_menu_item_free(static_cast<Ewk_Context_Menu_Item*>(item));
91
92 free(menu);
93 }
94
95 /**
96 * Destroys the context menu object.
97 *
98 * @param menu the context menu object to destroy
99 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure
100 *
101 * @see ewk_context_menu_item_free
102 */
ewk_context_menu_destroy(Ewk_Context_Menu * menu)103 Eina_Bool ewk_context_menu_destroy(Ewk_Context_Menu* menu)
104 {
105 EINA_SAFETY_ON_NULL_RETURN_VAL(menu, EINA_FALSE);
106 #if ENABLE(CONTEXT_MENUS)
107 EINA_SAFETY_ON_NULL_RETURN_VAL(menu->controller, EINA_FALSE);
108
109 menu->controller->clearContextMenu();
110 #endif
111
112 return EINA_TRUE;
113 }
114
115 /**
116 * Gets the list of items.
117 *
118 * @param o the context menu object to get list of the items
119 * @return the list of the items on success or @c 0 on failure
120 */
ewk_context_menu_item_list_get(Ewk_Context_Menu * o)121 const Eina_List* ewk_context_menu_item_list_get(Ewk_Context_Menu* o)
122 {
123 EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0);
124
125 return o->items;
126 }
127
128 /**
129 * Creates a new item of the context menu.
130 *
131 * @param type specifies a type of the item
132 * @param action specifies a action of the item
133 * @param submenu specifies a submenu of the item
134 * @param title specifies a title of the item
135 * @param checked
136 * @param enabled @c EINA_TRUE to enable the item or @c EINA_FALSE to disable
137 * @return the pointer to the new item on success or @c 0 on failure
138 *
139 * @note The return value @b should @b be freed after use.
140 */
ewk_context_menu_item_new(Ewk_Context_Menu_Item_Type type,Ewk_Context_Menu_Action action,Ewk_Context_Menu * submenu,const char * title,Eina_Bool checked,Eina_Bool enabled)141 Ewk_Context_Menu_Item* ewk_context_menu_item_new(Ewk_Context_Menu_Item_Type type,
142 Ewk_Context_Menu_Action action, Ewk_Context_Menu* submenu,
143 const char* title, Eina_Bool checked, Eina_Bool enabled)
144 {
145 Ewk_Context_Menu_Item* item = (Ewk_Context_Menu_Item*) malloc(sizeof(*item));
146 if (!item)
147 return 0;
148
149 item->type = type;
150 item->action = action;
151 item->title = eina_stringshare_add(title);
152 item->submenu = submenu;
153 item->checked = checked;
154 item->enabled = enabled;
155
156 return item;
157 }
158
159 /**
160 * Selects the item from the context menu object.
161 *
162 * @param menu the context menu object
163 * @param item the item is selected
164 * @return @c EINA_TRUE on success or @c EINA_FALSE on failure
165 */
ewk_context_menu_item_select(Ewk_Context_Menu * menu,Ewk_Context_Menu_Item * item)166 Eina_Bool ewk_context_menu_item_select(Ewk_Context_Menu* menu, Ewk_Context_Menu_Item* item)
167 {
168 #if ENABLE(CONTEXT_MENUS)
169 EINA_SAFETY_ON_NULL_RETURN_VAL(menu, EINA_FALSE);
170 EINA_SAFETY_ON_NULL_RETURN_VAL(item, EINA_FALSE);
171 WebCore::ContextMenuAction action = static_cast<WebCore::ContextMenuAction>(item->action);
172 WebCore::ContextMenuItemType type = static_cast<WebCore::ContextMenuItemType>(item->type);
173
174 // Don't care about title and submenu as they're not used after this point.
175 WebCore::ContextMenuItem core(type, action, WTF::String());
176 menu->controller->contextMenuItemSelected(&core);
177 return EINA_TRUE;
178 #else
179 return EINA_FALSE;
180 #endif
181 }
182
183 /**
184 * Destroys the item of the context menu object.
185 *
186 * @param item the item to destroy
187 *
188 * @see ewk_context_menu_destroy
189 * @see ewk_context_menu_unref
190 */
ewk_context_menu_item_free(Ewk_Context_Menu_Item * item)191 void ewk_context_menu_item_free(Ewk_Context_Menu_Item* item)
192 {
193 EINA_SAFETY_ON_NULL_RETURN(item);
194
195 eina_stringshare_del(item->title);
196 free(item);
197 }
198
199 /**
200 * Gets type of the item.
201 *
202 * @param o the item to get the type
203 * @return type of the item on success or @c EWK_ACTION_TYPE on failure
204 *
205 * @see ewk_context_menu_item_type_set
206 */
ewk_context_menu_item_type_get(Ewk_Context_Menu_Item * o)207 Ewk_Context_Menu_Item_Type ewk_context_menu_item_type_get(Ewk_Context_Menu_Item* o)
208 {
209 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EWK_ACTION_TYPE);
210 return o->type;
211 }
212
213 /**
214 * Sets the type of item.
215 *
216 * @param o the item to set the type
217 * @param type a new type for the item object
218 * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure
219 *
220 * @see ewk_context_menu_item_type_get
221 */
ewk_context_menu_item_type_set(Ewk_Context_Menu_Item * o,Ewk_Context_Menu_Item_Type type)222 Eina_Bool ewk_context_menu_item_type_set(Ewk_Context_Menu_Item* o, Ewk_Context_Menu_Item_Type type)
223 {
224 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
225 o->type = type;
226 return EINA_TRUE;
227 }
228
229 /**
230 * Gets an action of the item.
231 *
232 * @param o the item to get the action
233 * @return an action of the item on success or @c EWK_CONTEXT_MENU_ITEM_TAG_NO_ACTION on failure
234 *
235 * @see ewk_context_menu_item_action_set
236 */
ewk_context_menu_item_action_get(Ewk_Context_Menu_Item * o)237 Ewk_Context_Menu_Action ewk_context_menu_item_action_get(Ewk_Context_Menu_Item* o)
238 {
239 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EWK_CONTEXT_MENU_ITEM_TAG_NO_ACTION);
240 return o->action;
241 }
242
243 /**
244 * Sets an action of the item.
245 *
246 * @param o the item to set the action
247 * @param action a new action for the item object
248 * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure
249 *
250 * @see ewk_context_menu_item_action_get
251 */
ewk_context_menu_item_action_set(Ewk_Context_Menu_Item * o,Ewk_Context_Menu_Action action)252 Eina_Bool ewk_context_menu_item_action_set(Ewk_Context_Menu_Item* o, Ewk_Context_Menu_Action action)
253 {
254 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
255 o->action = action;
256 return EINA_TRUE;
257 }
258
259 /**
260 * Gets a title of the item.
261 *
262 * @param o the item to get the title
263 * @return a title of the item on success, or @c 0 on failure
264 *
265 * @see ewk_context_menu_item_title_set
266 */
ewk_context_menu_item_title_get(Ewk_Context_Menu_Item * o)267 const char* ewk_context_menu_item_title_get(Ewk_Context_Menu_Item* o)
268 {
269 EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0);
270 return o->title;
271 }
272
273 /**
274 * Sets a title of the item.
275 *
276 * @param o the item to set the title
277 * @param title a new title for the item object
278 * @return a new title of the item on success or @c 0 on failure
279 *
280 * @see ewk_context_menu_item_title_get
281 */
ewk_context_menu_item_title_set(Ewk_Context_Menu_Item * o,const char * title)282 const char* ewk_context_menu_item_title_set(Ewk_Context_Menu_Item* o, const char* title)
283 {
284 EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0);
285 eina_stringshare_replace(&o->title, title);
286 return o->title;
287 }
288
ewk_context_menu_item_checked_get(Ewk_Context_Menu_Item * o)289 Eina_Bool ewk_context_menu_item_checked_get(Ewk_Context_Menu_Item* o)
290 {
291 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
292 return o->checked;
293 }
294
ewk_context_menu_item_checked_set(Ewk_Context_Menu_Item * o,Eina_Bool checked)295 Eina_Bool ewk_context_menu_item_checked_set(Ewk_Context_Menu_Item* o, Eina_Bool checked)
296 {
297 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
298 o->checked = checked;
299 return EINA_TRUE;
300 }
301
302 /**
303 * Gets if the item is enabled.
304 *
305 * @param o the item to get enabled state
306 * @return @c EINA_TRUE if it's enabled, @c EINA_FALSE if not or on failure
307 *
308 * @see ewk_context_menu_item_enabled_set
309 */
ewk_context_menu_item_enabled_get(Ewk_Context_Menu_Item * o)310 Eina_Bool ewk_context_menu_item_enabled_get(Ewk_Context_Menu_Item* o)
311 {
312 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
313 return o->enabled;
314 }
315
316 /**
317 * Enables/disables the item.
318 *
319 * @param o the item to enable/disable
320 * @param enabled @c EINA_TRUE to enable the item or @c EINA_FALSE to disable
321 * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure
322 *
323 * @see ewk_context_menu_item_enabled_get
324 */
ewk_context_menu_item_enabled_set(Ewk_Context_Menu_Item * o,Eina_Bool enabled)325 Eina_Bool ewk_context_menu_item_enabled_set(Ewk_Context_Menu_Item *o, Eina_Bool enabled)
326 {
327 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
328 o->enabled = enabled;
329 return EINA_TRUE;
330 }
331
332
333 /* internal methods ****************************************************/
334
335 #if ENABLE(CONTEXT_MENUS)
336 /**
337 * @internal
338 *
339 * Creates an empty context menu on view.
340 *
341 * @param view the view object
342 * @param controller the WebCore's context menu controller
343 * @return newly allocated the context menu on success or @c 0 on errors
344 *
345 * @note emits a signal "contextmenu,new"
346 */
ewk_context_menu_new(Evas_Object * view,WebCore::ContextMenuController * controller)347 Ewk_Context_Menu* ewk_context_menu_new(Evas_Object* view, WebCore::ContextMenuController* controller)
348 {
349 Ewk_Context_Menu* menu;
350 EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0);
351 EINA_SAFETY_ON_NULL_RETURN_VAL(controller, 0);
352
353 menu = static_cast<Ewk_Context_Menu*>(malloc(sizeof(*menu)));
354 if (!menu) {
355 CRITICAL("Could not allocate context menu memory.");
356 return 0;
357 }
358
359 menu->__ref = 1;
360 menu->view = view;
361 menu->controller = controller;
362 menu->items = 0;
363 evas_object_smart_callback_call(menu->view, "contextmenu,new", menu);
364
365 return menu;
366 }
367
368 /**
369 * @internal
370 *
371 * Frees the context menu.
372 *
373 * @param o the view object
374 * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure
375 *
376 * @note emits a signal "contextmenu,free"
377 *
378 * @see ewk_context_menu_unref
379 * @see ewk_context_menu_destroy
380 */
ewk_context_menu_free(Ewk_Context_Menu * o)381 Eina_Bool ewk_context_menu_free(Ewk_Context_Menu* o)
382 {
383 EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
384 evas_object_smart_callback_call(o->view, "contextmenu,free", o);
385 ewk_context_menu_unref(o);
386 return EINA_TRUE;
387 }
388
389 /**
390 * @internal
391 *
392 * Appends the WebCore's item to the context menu object.
393 *
394 * @param o the context menu object
395 * @param core the WebCore's context menu item that will be added to the context menu
396 * @note emits a signal "contextmenu,item,appended"
397 *
398 * @see ewk_context_menu_item_new
399 */
ewk_context_menu_item_append(Ewk_Context_Menu * o,WebCore::ContextMenuItem & core)400 void ewk_context_menu_item_append(Ewk_Context_Menu* o, WebCore::ContextMenuItem& core)
401 {
402 Ewk_Context_Menu_Item_Type type = static_cast<Ewk_Context_Menu_Item_Type>(core.type());
403 Ewk_Context_Menu_Action action = static_cast<Ewk_Context_Menu_Action>(core.action());
404
405 Ewk_Context_Menu_Item* menu_item = ewk_context_menu_item_new
406 (type, action, 0, core.title().utf8().data(), core.checked(),
407 core.enabled());
408 EINA_SAFETY_ON_NULL_RETURN(menu_item);
409
410 o->items = eina_list_append(o->items, menu_item);
411 evas_object_smart_callback_call(o->view, "contextmenu,item,appended", o);
412 }
413
414 /**
415 * @internal
416 *
417 * Emits a signal with the items of the context menu.
418 *
419 * @param o the context menu object
420 * @return the same context menu object that was given through parameter
421 *
422 * @note emits a signal "contextmenu,customize"
423 *
424 * @see ewk_context_menu_item_list_get
425 */
ewk_context_menu_custom_get(Ewk_Context_Menu * o)426 Ewk_Context_Menu* ewk_context_menu_custom_get(Ewk_Context_Menu* o)
427 {
428 EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0);
429
430 evas_object_smart_callback_call(o->view, "contextmenu,customize", o->items);
431 return o;
432 }
433
434 /**
435 * @internal
436 *
437 * Emits a signal "contextmenu,show"
438 *
439 * @param o the context menu object
440 */
ewk_context_menu_show(Ewk_Context_Menu * o)441 void ewk_context_menu_show(Ewk_Context_Menu* o)
442 {
443 EINA_SAFETY_ON_NULL_RETURN(o);
444
445 evas_object_smart_callback_call(o->view, "contextmenu,show", o);
446 }
447
448 #endif
449