• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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