render_view_context_menu_views.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h" 6 7#include "base/logging.h" 8#include "base/strings/utf_string_conversions.h" 9#include "chrome/app/chrome_command_ids.h" 10#include "content/public/browser/render_view_host.h" 11#include "content/public/browser/render_widget_host_view.h" 12#include "content/public/browser/web_contents.h" 13#include "grit/generated_resources.h" 14#include "ui/base/accelerators/accelerator.h" 15#include "ui/base/l10n/l10n_util.h" 16#include "ui/events/keycodes/keyboard_codes.h" 17#include "ui/gfx/point.h" 18#include "ui/views/controls/menu/menu_item_view.h" 19#include "ui/views/controls/menu/menu_model_adapter.h" 20#include "ui/views/controls/menu/menu_runner.h" 21 22using content::WebContents; 23 24//////////////////////////////////////////////////////////////////////////////// 25// RenderViewContextMenuViews, public: 26 27RenderViewContextMenuViews::RenderViewContextMenuViews( 28 content::RenderFrameHost* render_frame_host, 29 const content::ContextMenuParams& params) 30 : RenderViewContextMenu(render_frame_host, params), 31 bidi_submenu_model_(this), 32 menu_view_(NULL) { 33} 34 35RenderViewContextMenuViews::~RenderViewContextMenuViews() { 36} 37 38// static 39RenderViewContextMenuViews* RenderViewContextMenuViews::Create( 40 content::RenderFrameHost* render_frame_host, 41 const content::ContextMenuParams& params) { 42 return new RenderViewContextMenuViews(render_frame_host, params); 43} 44 45void RenderViewContextMenuViews::RunMenuAt(views::Widget* parent, 46 const gfx::Point& point, 47 ui::MenuSourceType type) { 48 views::MenuAnchorPosition anchor_position = 49 (type == ui::MENU_SOURCE_TOUCH || type == ui::MENU_SOURCE_TOUCH_EDIT_MENU) 50 ? views::MENU_ANCHOR_BOTTOMCENTER 51 : views::MENU_ANCHOR_TOPLEFT; 52 53 if (menu_runner_->RunMenuAt( 54 parent, NULL, gfx::Rect(point, gfx::Size()), anchor_position, type) == 55 views::MenuRunner::MENU_DELETED) 56 return; 57} 58 59//////////////////////////////////////////////////////////////////////////////// 60// RenderViewContextMenuViews, protected: 61 62void RenderViewContextMenuViews::PlatformInit() { 63 menu_adapter_.reset(new views::MenuModelAdapter(&menu_model_)); 64 menu_view_ = menu_adapter_->CreateMenu(); 65 menu_runner_.reset(new views::MenuRunner( 66 menu_view_, 67 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU)); 68} 69 70void RenderViewContextMenuViews::PlatformCancel() { 71 DCHECK(menu_runner_.get()); 72 menu_runner_->Cancel(); 73} 74 75bool RenderViewContextMenuViews::GetAcceleratorForCommandId( 76 int command_id, 77 ui::Accelerator* accel) { 78 // There are no formally defined accelerators we can query so we assume 79 // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do. 80 switch (command_id) { 81 case IDC_CONTENT_CONTEXT_UNDO: 82 *accel = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN); 83 return true; 84 85 case IDC_CONTENT_CONTEXT_REDO: 86 // TODO(jcampan): should it be Ctrl-Y? 87 *accel = ui::Accelerator(ui::VKEY_Z, 88 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); 89 return true; 90 91 case IDC_CONTENT_CONTEXT_CUT: 92 *accel = ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN); 93 return true; 94 95 case IDC_CONTENT_CONTEXT_COPY: 96 *accel = ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN); 97 return true; 98 99 case IDC_CONTENT_CONTEXT_PASTE: 100 *accel = ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN); 101 return true; 102 103 case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE: 104 *accel = ui::Accelerator(ui::VKEY_V, 105 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); 106 return true; 107 108 case IDC_CONTENT_CONTEXT_SELECTALL: 109 *accel = ui::Accelerator(ui::VKEY_A, ui::EF_CONTROL_DOWN); 110 return true; 111 112 default: 113 return false; 114 } 115} 116 117void RenderViewContextMenuViews::ExecuteCommand(int command_id, 118 int event_flags) { 119 switch (command_id) { 120 case IDC_WRITING_DIRECTION_DEFAULT: 121 // WebKit's current behavior is for this menu item to always be disabled. 122 NOTREACHED(); 123 break; 124 125 case IDC_WRITING_DIRECTION_RTL: 126 case IDC_WRITING_DIRECTION_LTR: { 127 content::RenderViewHost* view_host = GetRenderViewHost(); 128 view_host->UpdateTextDirection((command_id == IDC_WRITING_DIRECTION_RTL) ? 129 blink::WebTextDirectionRightToLeft : 130 blink::WebTextDirectionLeftToRight); 131 view_host->NotifyTextDirection(); 132 break; 133 } 134 135 default: 136 RenderViewContextMenu::ExecuteCommand(command_id, event_flags); 137 break; 138 } 139} 140 141bool RenderViewContextMenuViews::IsCommandIdChecked(int command_id) const { 142 switch (command_id) { 143 case IDC_WRITING_DIRECTION_DEFAULT: 144 return (params_.writing_direction_default & 145 blink::WebContextMenuData::CheckableMenuItemChecked) != 0; 146 case IDC_WRITING_DIRECTION_RTL: 147 return (params_.writing_direction_right_to_left & 148 blink::WebContextMenuData::CheckableMenuItemChecked) != 0; 149 case IDC_WRITING_DIRECTION_LTR: 150 return (params_.writing_direction_left_to_right & 151 blink::WebContextMenuData::CheckableMenuItemChecked) != 0; 152 153 default: 154 return RenderViewContextMenu::IsCommandIdChecked(command_id); 155 } 156} 157 158bool RenderViewContextMenuViews::IsCommandIdEnabled(int command_id) const { 159 switch (command_id) { 160 case IDC_WRITING_DIRECTION_MENU: 161 return true; 162 case IDC_WRITING_DIRECTION_DEFAULT: // Provided to match OS defaults. 163 return params_.writing_direction_default & 164 blink::WebContextMenuData::CheckableMenuItemEnabled; 165 case IDC_WRITING_DIRECTION_RTL: 166 return params_.writing_direction_right_to_left & 167 blink::WebContextMenuData::CheckableMenuItemEnabled; 168 case IDC_WRITING_DIRECTION_LTR: 169 return params_.writing_direction_left_to_right & 170 blink::WebContextMenuData::CheckableMenuItemEnabled; 171 172 default: 173 return RenderViewContextMenu::IsCommandIdEnabled(command_id); 174 } 175} 176 177void RenderViewContextMenuViews::AppendPlatformEditableItems() { 178 bidi_submenu_model_.AddCheckItem( 179 IDC_WRITING_DIRECTION_DEFAULT, 180 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT)); 181 bidi_submenu_model_.AddCheckItem( 182 IDC_WRITING_DIRECTION_LTR, 183 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR)); 184 bidi_submenu_model_.AddCheckItem( 185 IDC_WRITING_DIRECTION_RTL, 186 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL)); 187 188 menu_model_.AddSubMenu( 189 IDC_WRITING_DIRECTION_MENU, 190 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU), 191 &bidi_submenu_model_); 192} 193 194void RenderViewContextMenuViews::UpdateMenuItem(int command_id, 195 bool enabled, 196 bool hidden, 197 const base::string16& title) { 198 views::MenuItemView* item = menu_view_->GetMenuItemByID(command_id); 199 if (!item) 200 return; 201 202 item->SetEnabled(enabled); 203 item->SetTitle(title); 204 item->SetVisible(!hidden); 205 206 views::MenuItemView* parent = item->GetParentMenuItem(); 207 if (!parent) 208 return; 209 210 parent->ChildrenChanged(); 211} 212