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