Home | History | Annotate | Download | only in ewk
      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  */
     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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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