2011-06-13 Carlos Garcia Campos <cgarcia@igalia.com>
[WebKit-https.git] / Source / WebCore / platform / gtk / ContextMenuItemGtk.cpp
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 "GRefPtr.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 static PlatformMenuItemDescription createPlatformMenuItemDescription(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
121 {
122     if (type == SeparatorType)
123         return GTK_MENU_ITEM(gtk_separator_menu_item_new());
124
125     GOwnPtr<char> actionName(g_strdup_printf("context-menu-action-%d", action));
126     GRefPtr<GtkAction> platformAction;
127
128     if (type == CheckableActionType) {
129         platformAction = adoptGRef(GTK_ACTION(gtk_toggle_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action))));
130         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(platformAction.get()), checked);
131     } else
132         platformAction = adoptGRef(gtk_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action)));
133     gtk_action_set_sensitive(platformAction.get(), enabled);
134
135     GtkMenuItem* item = GTK_MENU_ITEM(gtk_action_create_menu_item(platformAction.get()));
136     g_object_set_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
137
138     return item;
139 }
140
141 // Extract the ActionType from the menu item
142 ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
143     : m_platformDescription(item)
144 {
145 }
146
147 ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
148 {
149     m_platformDescription = GTK_MENU_ITEM(gtk_menu_item_new());
150     if (subMenu)
151         setSubMenu(subMenu);
152 }
153
154 ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
155 {
156     m_platformDescription = createPlatformMenuItemDescription(type, action, title, true, false);
157     if (subMenu)
158         setSubMenu(subMenu);
159 }
160
161 ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
162 {
163     m_platformDescription = createPlatformMenuItemDescription(type, action, title, enabled, checked);
164 }
165
166 ContextMenuItem::ContextMenuItem(ContextMenuAction action, const String& title, bool enabled, bool checked, Vector<ContextMenuItem>& subMenuItems)
167 {
168     m_platformDescription = createPlatformMenuItemDescription(SubmenuType, action, title, enabled, checked);
169     setSubMenu(subMenuItems);
170 }
171
172 ContextMenuItem::~ContextMenuItem()
173 {
174 }
175
176 PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
177 {
178     PlatformMenuItemDescription platformDescription = m_platformDescription;
179     m_platformDescription = 0;
180     return platformDescription;
181 }
182
183 ContextMenuItemType ContextMenuItem::type() const
184 {
185     if (GTK_IS_SEPARATOR_MENU_ITEM(m_platformDescription))
186         return SeparatorType;
187     if (GTK_IS_CHECK_MENU_ITEM(m_platformDescription))
188         return CheckableActionType;
189     if (gtk_menu_item_get_submenu(m_platformDescription))
190         return SubmenuType;
191     return ActionType;
192 }
193
194 void ContextMenuItem::setType(ContextMenuItemType type)
195 {
196     if (type == SeparatorType)
197         m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
198 }
199
200 ContextMenuAction ContextMenuItem::action() const
201 {
202     return static_cast<ContextMenuAction>(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION)));
203 }
204
205 void ContextMenuItem::setAction(ContextMenuAction action)
206 {
207     g_object_set_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
208 }
209
210 String ContextMenuItem::title() const
211 {
212     GtkAction* action = gtkAction();
213     return action ? String::fromUTF8(gtk_action_get_label(action)) : String();
214 }
215
216 void ContextMenuItem::setTitle(const String& title)
217 {
218     GtkAction* action = gtkAction();
219     if (action)
220         gtk_action_set_label(action, title.utf8().data());
221 }
222
223 PlatformMenuDescription ContextMenuItem::platformSubMenu() const
224 {
225     GtkWidget* subMenu = gtk_menu_item_get_submenu(m_platformDescription);
226     return subMenu ? GTK_MENU(subMenu) : 0;
227 }
228
229 void ContextMenuItem::setSubMenu(ContextMenu* menu)
230 {
231     gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->releasePlatformDescription()));
232 }
233
234 void ContextMenuItem::setSubMenu(Vector<ContextMenuItem>& subMenuItems)
235 {
236     ContextMenu menu(platformMenuDescription(subMenuItems));
237     setSubMenu(&menu);
238 }
239
240 void ContextMenuItem::setChecked(bool shouldCheck)
241 {
242     GtkAction* action = gtkAction();
243     if (action && GTK_IS_TOGGLE_ACTION(action))
244         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), shouldCheck);
245 }
246
247 bool ContextMenuItem::checked() const
248 {
249     GtkAction* action = gtkAction();
250     if (action && GTK_IS_TOGGLE_ACTION(action))
251         return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
252     return false;
253 }
254
255 bool ContextMenuItem::enabled() const
256 {
257     GtkAction* action = gtkAction();
258     return action ? gtk_action_get_sensitive(action) : false;
259 }
260
261 void ContextMenuItem::setEnabled(bool shouldEnable)
262 {
263     GtkAction* action = gtkAction();
264     if (action)
265         gtk_action_set_sensitive(action, shouldEnable);
266 }
267
268 GtkAction* ContextMenuItem::gtkAction() const
269 {
270     return gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
271 }
272
273 }