Chromium Code Reviews| Index: ui/views/controls/views_text_services_context_menu_mac.mm |
| diff --git a/ui/views/controls/views_text_services_context_menu_mac.mm b/ui/views/controls/views_text_services_context_menu_mac.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..eaed9dad31595450a3a050ad014587f299c110e0 |
| --- /dev/null |
| +++ b/ui/views/controls/views_text_services_context_menu_mac.mm |
| @@ -0,0 +1,167 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| +#include "ui/views/controls/views_text_services_context_menu.h" |
| + |
| +#import <Cocoa/Cocoa.h> |
| + |
| +#include "base/memory/ptr_util.h" |
| +#include "ui/base/cocoa/text_services_context_menu.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| +#include "ui/base/models/simple_menu_model.h" |
| +#include "ui/gfx/decorated_text.h" |
| +#import "ui/gfx/decorated_text_mac.h" |
| +#include "ui/strings/grit/ui_strings.h" |
| +#include "ui/views/controls/textfield/textfield.h" |
| +#include "ui/views/view.h" |
| +#include "ui/views/widget/widget.h" |
| + |
| +namespace views { |
| + |
| +namespace { |
| + |
| +// The menu index for "Look Up". |
| +const int kLookupMenuIndex = 0; |
|
tapted
2017/01/13 21:37:33
nit: constexpr
spqchan
2017/01/26 18:27:01
Done.
|
| + |
| +// This class serves as a bridge to TextServicesContextMenu to add and handle |
| +// text service items in the context menu. The items include Speech, Look Up |
| +// and BiDi. |
| +class ViewsTextServicesContextMenuMac |
| + : public ViewsTextServicesContextMenu, |
| + public ui::TextServicesContextMenu::Delegate { |
| + public: |
| + ViewsTextServicesContextMenuMac(ui::SimpleMenuModel* menu, Textfield* client); |
| + ~ViewsTextServicesContextMenuMac() override; |
| + |
| + // Handler for the "Look Up" menu item. |
| + void LookUpInDictionary(); |
| + |
| + // ViewTextServicesContextMenu: |
| + bool HandlesCommandId(int command_id) const override; |
| + bool IsCommandIdChecked(int command_id) const override; |
| + bool IsCommandIdEnabled(int command_id) const override; |
| + void ExecuteCommand(int command_id, int event_flags) override; |
| + bool IsTextDirectionItemChecked( |
| + base::i18n::TextDirection direction) const override; |
| + |
| + // TextServicesContextMenu::Delegate: |
| + base::string16 GetSelectedText() const override; |
| + bool IsTextDirectionEnabled( |
| + base::i18n::TextDirection direction) const override; |
| + bool IsTextDirectionChecked( |
| + base::i18n::TextDirection direction) const override; |
| + void UpdateTextDirection(base::i18n::TextDirection direction) override; |
| + |
| + private: |
| + // Appends and handles the text service menu. |
| + ui::TextServicesContextMenu menu_; |
| + |
| + // The view associated with the menu. Weak. Owns |this|. |
| + Textfield* client_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ViewsTextServicesContextMenuMac); |
| +}; |
| + |
| +ViewsTextServicesContextMenuMac::ViewsTextServicesContextMenuMac( |
| + ui::SimpleMenuModel* menu, |
| + Textfield* client) |
| + : menu_(this), client_(client) { |
| + base::string16 text = GetSelectedText(); |
| + if (!text.empty()) { |
| + menu->InsertItemAt( |
| + kLookupMenuIndex, IDS_CONTENT_CONTEXT_LOOK_UP, |
| + l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_LOOK_UP, text)); |
| + menu->InsertSeparatorAt(kLookupMenuIndex + 1, ui::NORMAL_SEPARATOR); |
| + } |
| + menu_.AppendToContextMenu(menu); |
| +} |
| + |
| +ViewsTextServicesContextMenuMac::~ViewsTextServicesContextMenuMac() {} |
| + |
| +void ViewsTextServicesContextMenuMac::LookUpInDictionary() { |
| + gfx::Point baseline_point; |
| + gfx::DecoratedText text; |
| + if (client_->GetDecoratedTextAndBaselineFromSelection(&text, |
| + &baseline_point)) { |
| + Widget* widget = client_->GetWidget(); |
| + gfx::NativeView view = widget->GetNativeView(); |
| + views::View::ConvertPointToTarget(client_, widget->GetRootView(), |
| + &baseline_point); |
| + |
| + NSPoint lookup_point = NSMakePoint( |
| + baseline_point.x(), NSHeight([view frame]) - baseline_point.y()); |
| + [view showDefinitionForAttributedString: |
| + gfx::GetAttributedStringFromDecoratedText(text) |
| + atPoint:lookup_point]; |
| + } |
| +} |
| + |
| +bool ViewsTextServicesContextMenuMac::HandlesCommandId(int command_id) const { |
| + return command_id == IDS_CONTENT_CONTEXT_LOOK_UP; |
| +} |
| + |
| +bool ViewsTextServicesContextMenuMac::IsCommandIdChecked(int command_id) const { |
| + DCHECK_EQ(IDS_CONTENT_CONTEXT_LOOK_UP, command_id); |
| + return false; |
| +} |
| + |
| +bool ViewsTextServicesContextMenuMac::IsCommandIdEnabled(int command_id) const { |
| + DCHECK_EQ(IDS_CONTENT_CONTEXT_LOOK_UP, command_id); |
| + return true; |
| +} |
| + |
| +void ViewsTextServicesContextMenuMac::ExecuteCommand(int command_id, |
| + int event_flags) { |
| + DCHECK_EQ(IDS_CONTENT_CONTEXT_LOOK_UP, command_id); |
| + LookUpInDictionary(); |
| +} |
| + |
| +bool ViewsTextServicesContextMenuMac::IsTextDirectionItemChecked( |
| + base::i18n::TextDirection direction) const { |
| + return IsTextDirectionChecked(direction); |
| +} |
| + |
| +base::string16 ViewsTextServicesContextMenuMac::GetSelectedText() const { |
| + return client_->GetSelectedText(); |
| +} |
| + |
| +bool ViewsTextServicesContextMenuMac::IsTextDirectionEnabled( |
| + base::i18n::TextDirection direction) const { |
| + return direction != base::i18n::UNKNOWN_DIRECTION; |
| +} |
| + |
| +bool ViewsTextServicesContextMenuMac::IsTextDirectionChecked( |
| + base::i18n::TextDirection direction) const { |
| + switch (direction) { |
| + case base::i18n::UNKNOWN_DIRECTION: |
| + return false; |
| + case base::i18n::RIGHT_TO_LEFT: |
| + return client_->GetTextDirection() == base::i18n::RIGHT_TO_LEFT; |
| + case base::i18n::LEFT_TO_RIGHT: |
| + return client_->GetTextDirection() == base::i18n::LEFT_TO_RIGHT; |
| + case base::i18n::TEXT_DIRECTION_NUM_DIRECTIONS: |
| + NOTREACHED(); |
| + return false; |
| + } |
| +} |
| + |
| +void ViewsTextServicesContextMenuMac::UpdateTextDirection( |
| + base::i18n::TextDirection direction) { |
| + DCHECK_NE(direction, base::i18n::UNKNOWN_DIRECTION); |
| + |
| + base::i18n::TextDirection text_direction = |
| + direction == base::i18n::LEFT_TO_RIGHT ? base::i18n::LEFT_TO_RIGHT |
| + : base::i18n::RIGHT_TO_LEFT; |
| + client_->ChangeTextDirectionAndLayoutAlignment(text_direction); |
| +} |
| + |
| +} // namespace |
| + |
| +// static |
| +std::unique_ptr<ViewsTextServicesContextMenu> |
| +ViewsTextServicesContextMenu::Create(ui::SimpleMenuModel* menu, |
| + Textfield* client) { |
| + return base::MakeUnique<ViewsTextServicesContextMenuMac>(menu, client); |
| +} |
| + |
| +} // namespace views |