blob: 227a7a1b23b06d0395c784e9e8a099ab376b1ad6 [file] [log] [blame]
/*
* Copyright (C) 2007 Holger Hans Peter Freyther
* Copyright (C) 2010 Igalia S.L
* Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "ContextMenuItem.h"
#include "ContextMenu.h"
#include "GOwnPtr.h"
#include "GRefPtr.h"
#include <gtk/gtk.h>
#include <wtf/text/CString.h>
#define WEBKIT_CONTEXT_MENU_ACTION "webkit-context-menu"
namespace WebCore {
static const char* gtkStockIDFromContextMenuAction(const ContextMenuAction& action)
{
switch (action) {
case ContextMenuItemTagCopyLinkToClipboard:
case ContextMenuItemTagCopyImageToClipboard:
case ContextMenuItemTagCopyMediaLinkToClipboard:
case ContextMenuItemTagCopy:
return GTK_STOCK_COPY;
case ContextMenuItemTagOpenLinkInNewWindow:
case ContextMenuItemTagOpenImageInNewWindow:
case ContextMenuItemTagOpenFrameInNewWindow:
case ContextMenuItemTagOpenMediaInNewWindow:
return GTK_STOCK_OPEN;
case ContextMenuItemTagDownloadLinkToDisk:
case ContextMenuItemTagDownloadImageToDisk:
return GTK_STOCK_SAVE;
case ContextMenuItemTagGoBack:
return GTK_STOCK_GO_BACK;
case ContextMenuItemTagGoForward:
return GTK_STOCK_GO_FORWARD;
case ContextMenuItemTagStop:
return GTK_STOCK_STOP;
case ContextMenuItemTagReload:
return GTK_STOCK_REFRESH;
case ContextMenuItemTagCut:
return GTK_STOCK_CUT;
case ContextMenuItemTagPaste:
return GTK_STOCK_PASTE;
case ContextMenuItemTagDelete:
return GTK_STOCK_DELETE;
case ContextMenuItemTagSelectAll:
return GTK_STOCK_SELECT_ALL;
case ContextMenuItemTagSpellingGuess:
return 0;
case ContextMenuItemTagIgnoreSpelling:
return GTK_STOCK_NO;
case ContextMenuItemTagLearnSpelling:
return GTK_STOCK_OK;
case ContextMenuItemTagOther:
return GTK_STOCK_MISSING_IMAGE;
case ContextMenuItemTagSearchInSpotlight:
return GTK_STOCK_FIND;
case ContextMenuItemTagSearchWeb:
return GTK_STOCK_FIND;
case ContextMenuItemTagOpenWithDefaultApplication:
return GTK_STOCK_OPEN;
case ContextMenuItemPDFZoomIn:
return GTK_STOCK_ZOOM_IN;
case ContextMenuItemPDFZoomOut:
return GTK_STOCK_ZOOM_OUT;
case ContextMenuItemPDFAutoSize:
return GTK_STOCK_ZOOM_FIT;
case ContextMenuItemPDFNextPage:
return GTK_STOCK_GO_FORWARD;
case ContextMenuItemPDFPreviousPage:
return GTK_STOCK_GO_BACK;
// New tags, not part of API
case ContextMenuItemTagOpenLink:
return GTK_STOCK_OPEN;
case ContextMenuItemTagCheckSpelling:
return GTK_STOCK_SPELL_CHECK;
case ContextMenuItemTagFontMenu:
return GTK_STOCK_SELECT_FONT;
case ContextMenuItemTagShowFonts:
return GTK_STOCK_SELECT_FONT;
case ContextMenuItemTagBold:
return GTK_STOCK_BOLD;
case ContextMenuItemTagItalic:
return GTK_STOCK_ITALIC;
case ContextMenuItemTagUnderline:
return GTK_STOCK_UNDERLINE;
case ContextMenuItemTagShowColors:
return GTK_STOCK_SELECT_COLOR;
case ContextMenuItemTagToggleMediaControls:
case ContextMenuItemTagToggleMediaLoop:
case ContextMenuItemTagCopyImageUrlToClipboard:
// No icon for this.
return 0;
case ContextMenuItemTagEnterVideoFullscreen:
return GTK_STOCK_FULLSCREEN;
default:
return 0;
}
}
static PlatformMenuItemDescription createPlatformMenuItemDescription(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
{
if (type == SeparatorType)
return GTK_MENU_ITEM(gtk_separator_menu_item_new());
GOwnPtr<char> actionName(g_strdup_printf("context-menu-action-%d", action));
GRefPtr<GtkAction> platformAction;
if (type == CheckableActionType) {
platformAction = adoptGRef(GTK_ACTION(gtk_toggle_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action))));
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(platformAction.get()), checked);
} else
platformAction = adoptGRef(gtk_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action)));
gtk_action_set_sensitive(platformAction.get(), enabled);
GtkMenuItem* item = GTK_MENU_ITEM(gtk_action_create_menu_item(platformAction.get()));
g_object_set_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
return item;
}
// Extract the ActionType from the menu item
ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
: m_platformDescription(item)
{
}
ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
{
m_platformDescription = GTK_MENU_ITEM(gtk_menu_item_new());
if (subMenu)
setSubMenu(subMenu);
}
ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
{
m_platformDescription = createPlatformMenuItemDescription(type, action, title, true, false);
if (subMenu)
setSubMenu(subMenu);
}
ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
{
m_platformDescription = createPlatformMenuItemDescription(type, action, title, enabled, checked);
}
ContextMenuItem::ContextMenuItem(ContextMenuAction action, const String& title, bool enabled, bool checked, Vector<ContextMenuItem>& subMenuItems)
{
m_platformDescription = createPlatformMenuItemDescription(SubmenuType, action, title, enabled, checked);
setSubMenu(subMenuItems);
}
ContextMenuItem::~ContextMenuItem()
{
}
PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
{
PlatformMenuItemDescription platformDescription = m_platformDescription;
m_platformDescription = 0;
return platformDescription;
}
ContextMenuItemType ContextMenuItem::type() const
{
if (GTK_IS_SEPARATOR_MENU_ITEM(m_platformDescription))
return SeparatorType;
if (GTK_IS_CHECK_MENU_ITEM(m_platformDescription))
return CheckableActionType;
if (gtk_menu_item_get_submenu(m_platformDescription))
return SubmenuType;
return ActionType;
}
void ContextMenuItem::setType(ContextMenuItemType type)
{
if (type == SeparatorType)
m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
}
ContextMenuAction ContextMenuItem::action() const
{
return static_cast<ContextMenuAction>(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION)));
}
void ContextMenuItem::setAction(ContextMenuAction action)
{
g_object_set_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
}
String ContextMenuItem::title() const
{
GtkAction* action = gtkAction();
return action ? String::fromUTF8(gtk_action_get_label(action)) : String();
}
void ContextMenuItem::setTitle(const String& title)
{
GtkAction* action = gtkAction();
if (action)
gtk_action_set_label(action, title.utf8().data());
}
PlatformMenuDescription ContextMenuItem::platformSubMenu() const
{
GtkWidget* subMenu = gtk_menu_item_get_submenu(m_platformDescription);
return subMenu ? GTK_MENU(subMenu) : 0;
}
void ContextMenuItem::setSubMenu(ContextMenu* menu)
{
gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->releasePlatformDescription()));
}
void ContextMenuItem::setSubMenu(Vector<ContextMenuItem>& subMenuItems)
{
ContextMenu menu(platformMenuDescription(subMenuItems));
setSubMenu(&menu);
}
void ContextMenuItem::setChecked(bool shouldCheck)
{
GtkAction* action = gtkAction();
if (action && GTK_IS_TOGGLE_ACTION(action))
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), shouldCheck);
}
bool ContextMenuItem::checked() const
{
GtkAction* action = gtkAction();
if (action && GTK_IS_TOGGLE_ACTION(action))
return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
return false;
}
bool ContextMenuItem::enabled() const
{
GtkAction* action = gtkAction();
return action ? gtk_action_get_sensitive(action) : false;
}
void ContextMenuItem::setEnabled(bool shouldEnable)
{
GtkAction* action = gtkAction();
if (action)
gtk_action_set_sensitive(action, shouldEnable);
}
GtkAction* ContextMenuItem::gtkAction() const
{
return gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
}
}