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
gtkStockIDFromContextMenuAction(const ContextMenuAction & action)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
ContextMenuItem(PlatformMenuItemDescription item)121 ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
122 : m_platformDescription(item)
123 {
124 }
125
ContextMenuItem(ContextMenu *)126 ContextMenuItem::ContextMenuItem(ContextMenu*)
127 {
128 notImplemented();
129 }
130
ContextMenuItem(ContextMenuItemType type,ContextMenuAction action,const String & title,ContextMenu * subMenu)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
ContextMenuItem(ContextMenuItemType,ContextMenuAction,const String &,bool,bool)155 ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool, bool)
156 {
157 // FIXME: Implement with WebKit2 ContextMenu changes.
158 notImplemented();
159 }
160
ContextMenuItem(ContextMenuAction,const String &,bool,bool,Vector<ContextMenuItem> &)161 ContextMenuItem::ContextMenuItem(ContextMenuAction, const String&, bool, bool, Vector<ContextMenuItem>&)
162 {
163 // FIXME: Implement with WebKit2 ContextMenu changes.
164 notImplemented();
165 }
166
~ContextMenuItem()167 ContextMenuItem::~ContextMenuItem()
168 {
169 }
170
releasePlatformDescription()171 PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
172 {
173 PlatformMenuItemDescription platformDescription = m_platformDescription;
174 m_platformDescription = 0;
175 return platformDescription;
176 }
177
type() const178 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
setType(ContextMenuItemType type)189 void ContextMenuItem::setType(ContextMenuItemType type)
190 {
191 if (type == SeparatorType)
192 m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
193 }
194
action() const195 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
setAction(ContextMenuAction action)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
title() const205 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
setTitle(const String & title)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
platformSubMenu() const218 PlatformMenuDescription ContextMenuItem::platformSubMenu() const
219 {
220 GtkWidget* subMenu = gtk_menu_item_get_submenu(m_platformDescription);
221 return subMenu ? GTK_MENU(subMenu) : 0;
222 }
223
setSubMenu(ContextMenu * menu)224 void ContextMenuItem::setSubMenu(ContextMenu* menu)
225 {
226 gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->platformDescription()));
227 }
228
setChecked(bool shouldCheck)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
checked() const236 bool ContextMenuItem::checked() const
237 {
238 // FIXME: Implement with WebKit2 ContextMenu changes.
239 notImplemented();
240 return false;
241 }
242
enabled() const243 bool ContextMenuItem::enabled() const
244 {
245 // FIXME: Implement with WebKit2 ContextMenu changes.
246 notImplemented();
247 return false;
248 }
249
setEnabled(bool shouldEnable)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