| /* |
| Copyright (C) 2010 ProFUSION embedded systems |
| Copyright (C) 2010 Samsung Electronics |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Library General Public |
| License as published by the Free Software Foundation; either |
| version 2 of the License, or (at your option) any later version. |
| |
| This library 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 |
| Library General Public License for more details. |
| |
| You should have received a copy of the GNU Library General Public License |
| along with this library; see the file COPYING.LIB. If not, write to |
| the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "config.h" |
| #include "ewk_contextmenu.h" |
| |
| #include "ContextMenu.h" |
| #include "ContextMenuController.h" |
| #include "ContextMenuItem.h" |
| #include "EWebKit.h" |
| #include "ewk_private.h" |
| |
| #include <Eina.h> |
| #include <eina_safety_checks.h> |
| #include <wtf/text/CString.h> |
| |
| /** |
| * \struct _Ewk_Context_Menu |
| * @brief Contains the context menu data. |
| */ |
| struct _Ewk_Context_Menu { |
| unsigned int __ref; /**< the reference count of the object */ |
| #if ENABLE(CONTEXT_MENUS) |
| WebCore::ContextMenuController* controller; /**< the WebCore's object which is responsible for the context menu */ |
| #endif |
| Evas_Object* view; /**< the view object */ |
| |
| Eina_List* items; /**< the list of items */ |
| }; |
| |
| /** |
| * \struct _Ewk_Context_Menu_Item |
| * @brief Represents one item of the context menu object. |
| */ |
| struct _Ewk_Context_Menu_Item { |
| Ewk_Context_Menu_Item_Type type; /**< contains the type of the item */ |
| Ewk_Context_Menu_Action action; /**< contains the action of the item */ |
| |
| const char* title; /**< contains the title of the item */ |
| Ewk_Context_Menu* submenu; /**< contains the pointer to the submenu of the item */ |
| |
| Eina_Bool checked:1; |
| Eina_Bool enabled:1; |
| }; |
| |
| /** |
| * Increases the reference count of the given object. |
| * |
| * @param menu the context menu object to increase the reference count |
| */ |
| void ewk_context_menu_ref(Ewk_Context_Menu* menu) |
| { |
| EINA_SAFETY_ON_NULL_RETURN(menu); |
| menu->__ref++; |
| } |
| |
| /** |
| * Decreases the reference count of the given object, possibly freeing it. |
| * |
| * When the reference count it's reached 0, the menu with all items are freed. |
| * |
| * @param menu the context menu object to decrease the reference count |
| */ |
| void ewk_context_menu_unref(Ewk_Context_Menu* menu) |
| { |
| EINA_SAFETY_ON_NULL_RETURN(menu); |
| void* item; |
| |
| if (--menu->__ref) |
| return; |
| |
| EINA_LIST_FREE(menu->items, item) |
| ewk_context_menu_item_free(static_cast<Ewk_Context_Menu_Item*>(item)); |
| |
| free(menu); |
| } |
| |
| /** |
| * Destroys the context menu object. |
| * |
| * @param menu the context menu object to destroy |
| * @return @c EINA_TRUE on success, @c EINA_FALSE on failure |
| * |
| * @see ewk_context_menu_item_free |
| */ |
| Eina_Bool ewk_context_menu_destroy(Ewk_Context_Menu* menu) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(menu, EINA_FALSE); |
| #if ENABLE(CONTEXT_MENUS) |
| EINA_SAFETY_ON_NULL_RETURN_VAL(menu->controller, EINA_FALSE); |
| |
| menu->controller->clearContextMenu(); |
| #endif |
| |
| return EINA_TRUE; |
| } |
| |
| /** |
| * Gets the list of items. |
| * |
| * @param o the context menu object to get list of the items |
| * @return the list of the items on success or @c 0 on failure |
| */ |
| const Eina_List* ewk_context_menu_item_list_get(Ewk_Context_Menu* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0); |
| |
| return o->items; |
| } |
| |
| /** |
| * Creates a new item of the context menu. |
| * |
| * @param type specifies a type of the item |
| * @param action specifies a action of the item |
| * @param submenu specifies a submenu of the item |
| * @param title specifies a title of the item |
| * @param checked |
| * @param enabled @c EINA_TRUE to enable the item or @c EINA_FALSE to disable |
| * @return the pointer to the new item on success or @c 0 on failure |
| * |
| * @note The return value @b should @b be freed after use. |
| */ |
| Ewk_Context_Menu_Item* 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) |
| { |
| Ewk_Context_Menu_Item* item = (Ewk_Context_Menu_Item*) malloc(sizeof(*item)); |
| if (!item) |
| return 0; |
| |
| item->type = type; |
| item->action = action; |
| item->title = eina_stringshare_add(title); |
| item->submenu = submenu; |
| item->checked = checked; |
| item->enabled = enabled; |
| |
| return item; |
| } |
| |
| /** |
| * Selects the item from the context menu object. |
| * |
| * @param menu the context menu object |
| * @param item the item is selected |
| * @return @c EINA_TRUE on success or @c EINA_FALSE on failure |
| */ |
| Eina_Bool ewk_context_menu_item_select(Ewk_Context_Menu* menu, Ewk_Context_Menu_Item* item) |
| { |
| #if ENABLE(CONTEXT_MENUS) |
| EINA_SAFETY_ON_NULL_RETURN_VAL(menu, EINA_FALSE); |
| EINA_SAFETY_ON_NULL_RETURN_VAL(item, EINA_FALSE); |
| WebCore::ContextMenuAction action = static_cast<WebCore::ContextMenuAction>(item->action); |
| WebCore::ContextMenuItemType type = static_cast<WebCore::ContextMenuItemType>(item->type); |
| |
| // Don't care about title and submenu as they're not used after this point. |
| WebCore::ContextMenuItem core(type, action, WTF::String()); |
| menu->controller->contextMenuItemSelected(&core); |
| return EINA_TRUE; |
| #else |
| return EINA_FALSE; |
| #endif |
| } |
| |
| /** |
| * Destroys the item of the context menu object. |
| * |
| * @param item the item to destroy |
| * |
| * @see ewk_context_menu_destroy |
| * @see ewk_context_menu_unref |
| */ |
| void ewk_context_menu_item_free(Ewk_Context_Menu_Item* item) |
| { |
| EINA_SAFETY_ON_NULL_RETURN(item); |
| |
| eina_stringshare_del(item->title); |
| free(item); |
| } |
| |
| /** |
| * Gets type of the item. |
| * |
| * @param o the item to get the type |
| * @return type of the item on success or @c EWK_ACTION_TYPE on failure |
| * |
| * @see ewk_context_menu_item_type_set |
| */ |
| Ewk_Context_Menu_Item_Type ewk_context_menu_item_type_get(Ewk_Context_Menu_Item* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EWK_ACTION_TYPE); |
| return o->type; |
| } |
| |
| /** |
| * Sets the type of item. |
| * |
| * @param o the item to set the type |
| * @param type a new type for the item object |
| * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure |
| * |
| * @see ewk_context_menu_item_type_get |
| */ |
| Eina_Bool ewk_context_menu_item_type_set(Ewk_Context_Menu_Item* o, Ewk_Context_Menu_Item_Type type) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE); |
| o->type = type; |
| return EINA_TRUE; |
| } |
| |
| /** |
| * Gets an action of the item. |
| * |
| * @param o the item to get the action |
| * @return an action of the item on success or @c EWK_CONTEXT_MENU_ITEM_TAG_NO_ACTION on failure |
| * |
| * @see ewk_context_menu_item_action_set |
| */ |
| Ewk_Context_Menu_Action ewk_context_menu_item_action_get(Ewk_Context_Menu_Item* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EWK_CONTEXT_MENU_ITEM_TAG_NO_ACTION); |
| return o->action; |
| } |
| |
| /** |
| * Sets an action of the item. |
| * |
| * @param o the item to set the action |
| * @param action a new action for the item object |
| * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure |
| * |
| * @see ewk_context_menu_item_action_get |
| */ |
| Eina_Bool ewk_context_menu_item_action_set(Ewk_Context_Menu_Item* o, Ewk_Context_Menu_Action action) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE); |
| o->action = action; |
| return EINA_TRUE; |
| } |
| |
| /** |
| * Gets a title of the item. |
| * |
| * @param o the item to get the title |
| * @return a title of the item on success, or @c 0 on failure |
| * |
| * @see ewk_context_menu_item_title_set |
| */ |
| const char* ewk_context_menu_item_title_get(Ewk_Context_Menu_Item* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0); |
| return o->title; |
| } |
| |
| /** |
| * Sets a title of the item. |
| * |
| * @param o the item to set the title |
| * @param title a new title for the item object |
| * @return a new title of the item on success or @c 0 on failure |
| * |
| * @see ewk_context_menu_item_title_get |
| */ |
| const char* ewk_context_menu_item_title_set(Ewk_Context_Menu_Item* o, const char* title) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0); |
| eina_stringshare_replace(&o->title, title); |
| return o->title; |
| } |
| |
| Eina_Bool ewk_context_menu_item_checked_get(Ewk_Context_Menu_Item* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE); |
| return o->checked; |
| } |
| |
| Eina_Bool ewk_context_menu_item_checked_set(Ewk_Context_Menu_Item* o, Eina_Bool checked) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE); |
| o->checked = checked; |
| return EINA_TRUE; |
| } |
| |
| /** |
| * Gets if the item is enabled. |
| * |
| * @param o the item to get enabled state |
| * @return @c EINA_TRUE if it's enabled, @c EINA_FALSE if not or on failure |
| * |
| * @see ewk_context_menu_item_enabled_set |
| */ |
| Eina_Bool ewk_context_menu_item_enabled_get(Ewk_Context_Menu_Item* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE); |
| return o->enabled; |
| } |
| |
| /** |
| * Enables/disables the item. |
| * |
| * @param o the item to enable/disable |
| * @param enabled @c EINA_TRUE to enable the item or @c EINA_FALSE to disable |
| * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure |
| * |
| * @see ewk_context_menu_item_enabled_get |
| */ |
| Eina_Bool ewk_context_menu_item_enabled_set(Ewk_Context_Menu_Item *o, Eina_Bool enabled) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE); |
| o->enabled = enabled; |
| return EINA_TRUE; |
| } |
| |
| |
| /* internal methods ****************************************************/ |
| |
| #if ENABLE(CONTEXT_MENUS) |
| /** |
| * @internal |
| * |
| * Creates an empty context menu on view. |
| * |
| * @param view the view object |
| * @param controller the WebCore's context menu controller |
| * @return newly allocated the context menu on success or @c 0 on errors |
| * |
| * @note emits a signal "contextmenu,new" |
| */ |
| Ewk_Context_Menu* ewk_context_menu_new(Evas_Object* view, WebCore::ContextMenuController* controller) |
| { |
| Ewk_Context_Menu* menu; |
| EINA_SAFETY_ON_NULL_RETURN_VAL(view, 0); |
| EINA_SAFETY_ON_NULL_RETURN_VAL(controller, 0); |
| |
| menu = static_cast<Ewk_Context_Menu*>(malloc(sizeof(*menu))); |
| if (!menu) { |
| CRITICAL("Could not allocate context menu memory."); |
| return 0; |
| } |
| |
| menu->__ref = 1; |
| menu->view = view; |
| menu->controller = controller; |
| menu->items = 0; |
| evas_object_smart_callback_call(menu->view, "contextmenu,new", menu); |
| |
| return menu; |
| } |
| |
| /** |
| * @internal |
| * |
| * Frees the context menu. |
| * |
| * @param o the view object |
| * @return @c EINA_TRUE on success, or @c EINA_FALSE on failure |
| * |
| * @note emits a signal "contextmenu,free" |
| * |
| * @see ewk_context_menu_unref |
| * @see ewk_context_menu_destroy |
| */ |
| Eina_Bool ewk_context_menu_free(Ewk_Context_Menu* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE); |
| evas_object_smart_callback_call(o->view, "contextmenu,free", o); |
| ewk_context_menu_unref(o); |
| return EINA_TRUE; |
| } |
| |
| /** |
| * @internal |
| * |
| * Appends the WebCore's item to the context menu object. |
| * |
| * @param o the context menu object |
| * @param core the WebCore's context menu item that will be added to the context menu |
| * @note emits a signal "contextmenu,item,appended" |
| * |
| * @see ewk_context_menu_item_new |
| */ |
| void ewk_context_menu_item_append(Ewk_Context_Menu* o, WebCore::ContextMenuItem& core) |
| { |
| Ewk_Context_Menu_Item_Type type = static_cast<Ewk_Context_Menu_Item_Type>(core.type()); |
| Ewk_Context_Menu_Action action = static_cast<Ewk_Context_Menu_Action>(core.action()); |
| |
| Ewk_Context_Menu_Item* menu_item = ewk_context_menu_item_new |
| (type, action, 0, core.title().utf8().data(), core.checked(), |
| core.enabled()); |
| EINA_SAFETY_ON_NULL_RETURN(menu_item); |
| |
| o->items = eina_list_append(o->items, menu_item); |
| evas_object_smart_callback_call(o->view, "contextmenu,item,appended", o); |
| } |
| |
| /** |
| * @internal |
| * |
| * Emits a signal with the items of the context menu. |
| * |
| * @param o the context menu object |
| * @return the same context menu object that was given through parameter |
| * |
| * @note emits a signal "contextmenu,customize" |
| * |
| * @see ewk_context_menu_item_list_get |
| */ |
| Ewk_Context_Menu* ewk_context_menu_custom_get(Ewk_Context_Menu* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN_VAL(o, 0); |
| |
| evas_object_smart_callback_call(o->view, "contextmenu,customize", o->items); |
| return o; |
| } |
| |
| /** |
| * @internal |
| * |
| * Emits a signal "contextmenu,show" |
| * |
| * @param o the context menu object |
| */ |
| void ewk_context_menu_show(Ewk_Context_Menu* o) |
| { |
| EINA_SAFETY_ON_NULL_RETURN(o); |
| |
| evas_object_smart_callback_call(o->view, "contextmenu,show", o); |
| } |
| |
| #endif |