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
33namespace WebCore {
34
35static 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
121ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
122    : m_platformDescription(item)
123{
124}
125
126ContextMenuItem::ContextMenuItem(ContextMenu*)
127{
128    notImplemented();
129}
130
131ContextMenuItem::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
155ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool, bool)
156{
157    // FIXME: Implement with WebKit2 ContextMenu changes.
158    notImplemented();
159}
160
161ContextMenuItem::ContextMenuItem(ContextMenuAction, const String&, bool, bool, Vector<ContextMenuItem>&)
162{
163    // FIXME: Implement with WebKit2 ContextMenu changes.
164    notImplemented();
165}
166
167ContextMenuItem::~ContextMenuItem()
168{
169}
170
171PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
172{
173    PlatformMenuItemDescription platformDescription = m_platformDescription;
174    m_platformDescription = 0;
175    return platformDescription;
176}
177
178ContextMenuItemType 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
189void ContextMenuItem::setType(ContextMenuItemType type)
190{
191    if (type == SeparatorType)
192        m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
193}
194
195ContextMenuAction 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
200void ContextMenuItem::setAction(ContextMenuAction action)
201{
202    g_object_set_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
203}
204
205String 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
211void 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
218PlatformMenuDescription ContextMenuItem::platformSubMenu() const
219{
220    GtkWidget* subMenu = gtk_menu_item_get_submenu(m_platformDescription);
221    return subMenu ? GTK_MENU(subMenu) : 0;
222}
223
224void ContextMenuItem::setSubMenu(ContextMenu* menu)
225{
226    gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->platformDescription()));
227}
228
229void 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
236bool ContextMenuItem::checked() const
237{
238    // FIXME: Implement with WebKit2 ContextMenu changes.
239    notImplemented();
240    return false;
241}
242
243bool ContextMenuItem::enabled() const
244{
245    // FIXME: Implement with WebKit2 ContextMenu changes.
246    notImplemented();
247    return false;
248}
249
250void 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