1 /* 2 * Copyright (C) 2007 Holger Hans Peter Freyther 3 * Copyright (C) 2010 Igalia S.L 4 * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "config.h" 22 23 #include "ContextMenuItem.h" 24 25 #include "ContextMenu.h" 26 #include "GOwnPtr.h" 27 #include "NotImplemented.h" 28 #include <gtk/gtk.h> 29 #include <wtf/text/CString.h> 30 31 #define WEBKIT_CONTEXT_MENU_ACTION "webkit-context-menu" 32 33 namespace WebCore { 34 35 static const char* gtkStockIDFromContextMenuAction(const ContextMenuAction& action) 36 { 37 switch (action) { 38 case ContextMenuItemTagCopyLinkToClipboard: 39 case ContextMenuItemTagCopyImageToClipboard: 40 case ContextMenuItemTagCopyMediaLinkToClipboard: 41 case ContextMenuItemTagCopy: 42 return GTK_STOCK_COPY; 43 case ContextMenuItemTagOpenLinkInNewWindow: 44 case ContextMenuItemTagOpenImageInNewWindow: 45 case ContextMenuItemTagOpenFrameInNewWindow: 46 case ContextMenuItemTagOpenMediaInNewWindow: 47 return GTK_STOCK_OPEN; 48 case ContextMenuItemTagDownloadLinkToDisk: 49 case ContextMenuItemTagDownloadImageToDisk: 50 return GTK_STOCK_SAVE; 51 case ContextMenuItemTagGoBack: 52 return GTK_STOCK_GO_BACK; 53 case ContextMenuItemTagGoForward: 54 return GTK_STOCK_GO_FORWARD; 55 case ContextMenuItemTagStop: 56 return GTK_STOCK_STOP; 57 case ContextMenuItemTagReload: 58 return GTK_STOCK_REFRESH; 59 case ContextMenuItemTagCut: 60 return GTK_STOCK_CUT; 61 case ContextMenuItemTagPaste: 62 return GTK_STOCK_PASTE; 63 case ContextMenuItemTagDelete: 64 return GTK_STOCK_DELETE; 65 case ContextMenuItemTagSelectAll: 66 return GTK_STOCK_SELECT_ALL; 67 case ContextMenuItemTagSpellingGuess: 68 return 0; 69 case ContextMenuItemTagIgnoreSpelling: 70 return GTK_STOCK_NO; 71 case ContextMenuItemTagLearnSpelling: 72 return GTK_STOCK_OK; 73 case ContextMenuItemTagOther: 74 return GTK_STOCK_MISSING_IMAGE; 75 case ContextMenuItemTagSearchInSpotlight: 76 return GTK_STOCK_FIND; 77 case ContextMenuItemTagSearchWeb: 78 return GTK_STOCK_FIND; 79 case ContextMenuItemTagOpenWithDefaultApplication: 80 return GTK_STOCK_OPEN; 81 case ContextMenuItemPDFZoomIn: 82 return GTK_STOCK_ZOOM_IN; 83 case ContextMenuItemPDFZoomOut: 84 return GTK_STOCK_ZOOM_OUT; 85 case ContextMenuItemPDFAutoSize: 86 return GTK_STOCK_ZOOM_FIT; 87 case ContextMenuItemPDFNextPage: 88 return GTK_STOCK_GO_FORWARD; 89 case ContextMenuItemPDFPreviousPage: 90 return GTK_STOCK_GO_BACK; 91 // New tags, not part of API 92 case ContextMenuItemTagOpenLink: 93 return GTK_STOCK_OPEN; 94 case ContextMenuItemTagCheckSpelling: 95 return GTK_STOCK_SPELL_CHECK; 96 case ContextMenuItemTagFontMenu: 97 return GTK_STOCK_SELECT_FONT; 98 case ContextMenuItemTagShowFonts: 99 return GTK_STOCK_SELECT_FONT; 100 case ContextMenuItemTagBold: 101 return GTK_STOCK_BOLD; 102 case ContextMenuItemTagItalic: 103 return GTK_STOCK_ITALIC; 104 case ContextMenuItemTagUnderline: 105 return GTK_STOCK_UNDERLINE; 106 case ContextMenuItemTagShowColors: 107 return GTK_STOCK_SELECT_COLOR; 108 case ContextMenuItemTagToggleMediaControls: 109 case ContextMenuItemTagToggleMediaLoop: 110 case ContextMenuItemTagCopyImageUrlToClipboard: 111 // No icon for this. 112 return 0; 113 case ContextMenuItemTagEnterVideoFullscreen: 114 return GTK_STOCK_FULLSCREEN; 115 default: 116 return 0; 117 } 118 } 119 120 // Extract the ActionType from the menu item 121 ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item) 122 : m_platformDescription(item) 123 { 124 } 125 126 ContextMenuItem::ContextMenuItem(ContextMenu*) 127 { 128 notImplemented(); 129 } 130 131 ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu) 132 { 133 if (type == SeparatorType) { 134 m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new()); 135 return; 136 } 137 138 GOwnPtr<char> actionName(g_strdup_printf("context-menu-action-%d", action)); 139 GtkAction* platformAction = 0; 140 141 if (type == CheckableActionType) 142 platformAction = GTK_ACTION(gtk_toggle_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action))); 143 else 144 platformAction = gtk_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action)); 145 146 m_platformDescription = GTK_MENU_ITEM(gtk_action_create_menu_item(platformAction)); 147 g_object_unref(platformAction); 148 149 g_object_set_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action)); 150 151 if (subMenu) 152 setSubMenu(subMenu); 153 } 154 155 ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool, bool) 156 { 157 // FIXME: Implement with WebKit2 ContextMenu changes. 158 notImplemented(); 159 } 160 161 ContextMenuItem::ContextMenuItem(ContextMenuAction, const String&, bool, bool, Vector<ContextMenuItem>&) 162 { 163 // FIXME: Implement with WebKit2 ContextMenu changes. 164 notImplemented(); 165 } 166 167 ContextMenuItem::~ContextMenuItem() 168 { 169 } 170 171 PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription() 172 { 173 PlatformMenuItemDescription platformDescription = m_platformDescription; 174 m_platformDescription = 0; 175 return platformDescription; 176 } 177 178 ContextMenuItemType ContextMenuItem::type() const 179 { 180 if (GTK_IS_SEPARATOR_MENU_ITEM(m_platformDescription)) 181 return SeparatorType; 182 if (GTK_IS_CHECK_MENU_ITEM(m_platformDescription)) 183 return CheckableActionType; 184 if (gtk_menu_item_get_submenu(m_platformDescription)) 185 return SubmenuType; 186 return ActionType; 187 } 188 189 void ContextMenuItem::setType(ContextMenuItemType type) 190 { 191 if (type == SeparatorType) 192 m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new()); 193 } 194 195 ContextMenuAction ContextMenuItem::action() const 196 { 197 return static_cast<ContextMenuAction>(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION))); 198 } 199 200 void ContextMenuItem::setAction(ContextMenuAction action) 201 { 202 g_object_set_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action)); 203 } 204 205 String ContextMenuItem::title() const 206 { 207 GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription)); 208 return action ? String(gtk_action_get_label(action)) : String(); 209 } 210 211 void ContextMenuItem::setTitle(const String& title) 212 { 213 GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription)); 214 if (action) 215 gtk_action_set_label(action, title.utf8().data()); 216 } 217 218 PlatformMenuDescription ContextMenuItem::platformSubMenu() const 219 { 220 GtkWidget* subMenu = gtk_menu_item_get_submenu(m_platformDescription); 221 return subMenu ? GTK_MENU(subMenu) : 0; 222 } 223 224 void ContextMenuItem::setSubMenu(ContextMenu* menu) 225 { 226 gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->platformDescription())); 227 } 228 229 void ContextMenuItem::setChecked(bool shouldCheck) 230 { 231 GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription)); 232 if (action && GTK_IS_TOGGLE_ACTION(action)) 233 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), shouldCheck); 234 } 235 236 bool ContextMenuItem::checked() const 237 { 238 // FIXME: Implement with WebKit2 ContextMenu changes. 239 notImplemented(); 240 return false; 241 } 242 243 bool ContextMenuItem::enabled() const 244 { 245 // FIXME: Implement with WebKit2 ContextMenu changes. 246 notImplemented(); 247 return false; 248 } 249 250 void ContextMenuItem::setEnabled(bool shouldEnable) 251 { 252 GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription)); 253 if (action) 254 gtk_action_set_sensitive(action, shouldEnable); 255 } 256 257 } 258