Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Unified Diff: ui/views/controls/textfield/textfield.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | ui/views/controls/textfield/textfield_controller.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/controls/textfield/textfield.cc
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
deleted file mode 100644
index cd4c7e43313a66ed55ea6539e52a6cc17f2984b9..0000000000000000000000000000000000000000
--- a/ui/views/controls/textfield/textfield.cc
+++ /dev/null
@@ -1,1823 +0,0 @@
-// Copyright (c) 2012 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/textfield/textfield.h"
-
-#include <string>
-
-#include "base/debug/trace_event.h"
-#include "ui/accessibility/ax_view_state.h"
-#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/base/cursor/cursor.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/base/dragdrop/drag_utils.h"
-#include "ui/base/ui_base_switches_util.h"
-#include "ui/compositor/scoped_animation_duration_scale_mode.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/screen.h"
-#include "ui/native_theme/native_theme.h"
-#include "ui/strings/grit/ui_strings.h"
-#include "ui/views/background.h"
-#include "ui/views/controls/focusable_border.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/controls/native/native_view_host.h"
-#include "ui/views/controls/textfield/textfield_controller.h"
-#include "ui/views/drag_utils.h"
-#include "ui/views/ime/input_method.h"
-#include "ui/views/metrics.h"
-#include "ui/views/native_cursor.h"
-#include "ui/views/painter.h"
-#include "ui/views/views_delegate.h"
-#include "ui/views/widget/widget.h"
-
-#if defined(OS_WIN)
-#include "base/win/win_util.h"
-#endif
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-#include "base/strings/utf_string_conversions.h"
-#include "ui/events/linux/text_edit_command_auralinux.h"
-#include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
-#endif
-
-namespace views {
-
-namespace {
-
-// Default placeholder text color.
-const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
-
-const int kNoCommand = 0;
-
-void ConvertRectToScreen(const View* src, gfx::Rect* r) {
- DCHECK(src);
-
- gfx::Point new_origin = r->origin();
- View::ConvertPointToScreen(src, &new_origin);
- r->set_origin(new_origin);
-}
-
-// Get the drag selection timer delay, respecting animation scaling for testing.
-int GetDragSelectionDelay() {
- switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) {
- case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: return 100;
- case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: return 25;
- case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: return 400;
- case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: return 1;
- case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: return 0;
- }
- return 100;
-}
-
-// Get the default command for a given key |event| and selection state.
-int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) {
- if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode())
- return kNoCommand;
-
- const bool shift = event.IsShiftDown();
- const bool control = event.IsControlDown();
- const bool alt = event.IsAltDown() || event.IsAltGrDown();
- switch (event.key_code()) {
- case ui::VKEY_Z:
- if (control && !shift && !alt)
- return IDS_APP_UNDO;
- return (control && shift && !alt) ? IDS_APP_REDO : kNoCommand;
- case ui::VKEY_Y:
- return (control && !alt) ? IDS_APP_REDO : kNoCommand;
- case ui::VKEY_A:
- return (control && !alt) ? IDS_APP_SELECT_ALL : kNoCommand;
- case ui::VKEY_X:
- return (control && !alt) ? IDS_APP_CUT : kNoCommand;
- case ui::VKEY_C:
- return (control && !alt) ? IDS_APP_COPY : kNoCommand;
- case ui::VKEY_V:
- return (control && !alt) ? IDS_APP_PASTE : kNoCommand;
- case ui::VKEY_RIGHT:
- // Ignore alt+right, which may be a browser navigation shortcut.
- if (alt)
- return kNoCommand;
- if (!shift)
- return control ? IDS_MOVE_WORD_RIGHT : IDS_MOVE_RIGHT;
- return control ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
- IDS_MOVE_RIGHT_AND_MODIFY_SELECTION;
- case ui::VKEY_LEFT:
- // Ignore alt+left, which may be a browser navigation shortcut.
- if (alt)
- return kNoCommand;
- if (!shift)
- return control ? IDS_MOVE_WORD_LEFT : IDS_MOVE_LEFT;
- return control ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
- IDS_MOVE_LEFT_AND_MODIFY_SELECTION;
- case ui::VKEY_HOME:
- return shift ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
- IDS_MOVE_TO_BEGINNING_OF_LINE;
- case ui::VKEY_END:
- return shift ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
- IDS_MOVE_TO_END_OF_LINE;
- case ui::VKEY_BACK:
- if (!control || has_selection)
- return IDS_DELETE_BACKWARD;
-#if defined(OS_LINUX)
- // Only erase by line break on Linux and ChromeOS.
- if (shift)
- return IDS_DELETE_TO_BEGINNING_OF_LINE;
-#endif
- return IDS_DELETE_WORD_BACKWARD;
- case ui::VKEY_DELETE:
- if (!control || has_selection)
- return (shift && has_selection) ? IDS_APP_CUT : IDS_DELETE_FORWARD;
-#if defined(OS_LINUX)
- // Only erase by line break on Linux and ChromeOS.
- if (shift)
- return IDS_DELETE_TO_END_OF_LINE;
-#endif
- return IDS_DELETE_WORD_FORWARD;
- case ui::VKEY_INSERT:
- if (control && !shift)
- return IDS_APP_COPY;
- return (shift && !control) ? IDS_APP_PASTE : kNoCommand;
- default:
- return kNoCommand;
- }
-}
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-// Convert a custom text edit |command| to the equivalent views command ID.
-int GetViewsCommand(const ui::TextEditCommandAuraLinux& command, bool rtl) {
- const bool select = command.extend_selection();
- switch (command.command_id()) {
- case ui::TextEditCommandAuraLinux::COPY:
- return IDS_APP_COPY;
- case ui::TextEditCommandAuraLinux::CUT:
- return IDS_APP_CUT;
- case ui::TextEditCommandAuraLinux::DELETE_BACKWARD:
- return IDS_DELETE_BACKWARD;
- case ui::TextEditCommandAuraLinux::DELETE_FORWARD:
- return IDS_DELETE_FORWARD;
- case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_LINE:
- case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_PARAGRAPH:
- return IDS_DELETE_TO_BEGINNING_OF_LINE;
- case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_LINE:
- case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_PARAGRAPH:
- return IDS_DELETE_TO_END_OF_LINE;
- case ui::TextEditCommandAuraLinux::DELETE_WORD_BACKWARD:
- return IDS_DELETE_WORD_BACKWARD;
- case ui::TextEditCommandAuraLinux::DELETE_WORD_FORWARD:
- return IDS_DELETE_WORD_FORWARD;
- case ui::TextEditCommandAuraLinux::INSERT_TEXT:
- return kNoCommand;
- case ui::TextEditCommandAuraLinux::MOVE_BACKWARD:
- if (rtl)
- return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
- return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
- case ui::TextEditCommandAuraLinux::MOVE_DOWN:
- return IDS_MOVE_DOWN;
- case ui::TextEditCommandAuraLinux::MOVE_FORWARD:
- if (rtl)
- return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
- return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
- case ui::TextEditCommandAuraLinux::MOVE_LEFT:
- return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
- case ui::TextEditCommandAuraLinux::MOVE_PAGE_DOWN:
- case ui::TextEditCommandAuraLinux::MOVE_PAGE_UP:
- return kNoCommand;
- case ui::TextEditCommandAuraLinux::MOVE_RIGHT:
- return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
- case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_DOCUMENT:
- case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_LINE:
- case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_PARAGRAPH:
- return select ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
- IDS_MOVE_TO_BEGINNING_OF_LINE;
- case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_DOCUMENT:
- case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_LINE:
- case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_PARAGRAPH:
- return select ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
- IDS_MOVE_TO_END_OF_LINE;
- case ui::TextEditCommandAuraLinux::MOVE_UP:
- return IDS_MOVE_UP;
- case ui::TextEditCommandAuraLinux::MOVE_WORD_BACKWARD:
- if (rtl) {
- return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
- IDS_MOVE_WORD_RIGHT;
- }
- return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
- IDS_MOVE_WORD_LEFT;
- case ui::TextEditCommandAuraLinux::MOVE_WORD_FORWARD:
- if (rtl) {
- return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
- IDS_MOVE_WORD_LEFT;
- }
- return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
- IDS_MOVE_WORD_RIGHT;
- case ui::TextEditCommandAuraLinux::MOVE_WORD_LEFT:
- return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
- IDS_MOVE_WORD_LEFT;
- case ui::TextEditCommandAuraLinux::MOVE_WORD_RIGHT:
- return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
- IDS_MOVE_WORD_RIGHT;
- case ui::TextEditCommandAuraLinux::PASTE:
- return IDS_APP_PASTE;
- case ui::TextEditCommandAuraLinux::SELECT_ALL:
- return IDS_APP_SELECT_ALL;
- case ui::TextEditCommandAuraLinux::SET_MARK:
- case ui::TextEditCommandAuraLinux::UNSELECT:
- case ui::TextEditCommandAuraLinux::INVALID_COMMAND:
- return kNoCommand;
- }
- return kNoCommand;
-}
-#endif
-
-} // namespace
-
-// static
-const char Textfield::kViewClassName[] = "Textfield";
-const int Textfield::kTextPadding = 3;
-
-// static
-size_t Textfield::GetCaretBlinkMs() {
- static const size_t default_value = 500;
-#if defined(OS_WIN)
- static const size_t system_value = ::GetCaretBlinkTime();
- if (system_value != 0)
- return (system_value == INFINITE) ? 0 : system_value;
-#endif
- return default_value;
-}
-
-Textfield::Textfield()
- : model_(new TextfieldModel(this)),
- controller_(NULL),
- read_only_(false),
- default_width_in_chars_(0),
- use_default_text_color_(true),
- use_default_background_color_(true),
- use_default_selection_text_color_(true),
- use_default_selection_background_color_(true),
- text_color_(SK_ColorBLACK),
- background_color_(SK_ColorWHITE),
- selection_text_color_(SK_ColorWHITE),
- selection_background_color_(SK_ColorBLUE),
- placeholder_text_color_(kDefaultPlaceholderTextColor),
- text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
- performing_user_action_(false),
- skip_input_method_cancel_composition_(false),
- cursor_visible_(false),
- drop_cursor_visible_(false),
- initiating_drag_(false),
- aggregated_clicks_(0),
- drag_start_display_offset_(0),
- touch_handles_hidden_due_to_scroll_(false),
- weak_ptr_factory_(this) {
- set_context_menu_controller(this);
- set_drag_controller(this);
- SetBorder(scoped_ptr<Border>(new FocusableBorder()));
- SetFocusable(true);
-
- if (ViewsDelegate::views_delegate) {
- password_reveal_duration_ = ViewsDelegate::views_delegate->
- GetDefaultTextfieldObscuredRevealDuration();
- }
-}
-
-Textfield::~Textfield() {}
-
-void Textfield::SetReadOnly(bool read_only) {
- // Update read-only without changing the focusable state (or active, etc.).
- read_only_ = read_only;
- if (GetInputMethod())
- GetInputMethod()->OnTextInputTypeChanged(this);
- SetColor(GetTextColor());
- UpdateBackgroundColor();
-}
-
-void Textfield::SetTextInputType(ui::TextInputType type) {
- GetRenderText()->SetObscured(type == ui::TEXT_INPUT_TYPE_PASSWORD);
- text_input_type_ = type;
- OnCaretBoundsChanged();
- if (GetInputMethod())
- GetInputMethod()->OnTextInputTypeChanged(this);
- SchedulePaint();
-}
-
-void Textfield::SetText(const base::string16& new_text) {
- model_->SetText(new_text);
- OnCaretBoundsChanged();
- SchedulePaint();
- NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
-}
-
-void Textfield::AppendText(const base::string16& new_text) {
- if (new_text.empty())
- return;
- model_->Append(new_text);
- OnCaretBoundsChanged();
- SchedulePaint();
-}
-
-void Textfield::InsertOrReplaceText(const base::string16& new_text) {
- if (new_text.empty())
- return;
- model_->InsertText(new_text);
- OnCaretBoundsChanged();
- SchedulePaint();
-}
-
-base::i18n::TextDirection Textfield::GetTextDirection() const {
- return GetRenderText()->GetTextDirection();
-}
-
-base::string16 Textfield::GetSelectedText() const {
- return model_->GetSelectedText();
-}
-
-void Textfield::SelectAll(bool reversed) {
- model_->SelectAll(reversed);
- UpdateSelectionClipboard();
- UpdateAfterChange(false, true);
-}
-
-void Textfield::SelectWordAt(const gfx::Point& point) {
- model_->MoveCursorTo(point, false);
- model_->SelectWord();
- UpdateAfterChange(false, true);
-}
-
-void Textfield::ClearSelection() {
- model_->ClearSelection();
- UpdateAfterChange(false, true);
-}
-
-bool Textfield::HasSelection() const {
- return !GetSelectedRange().is_empty();
-}
-
-SkColor Textfield::GetTextColor() const {
- if (!use_default_text_color_)
- return text_color_;
-
- return GetNativeTheme()->GetSystemColor(read_only() ?
- ui::NativeTheme::kColorId_TextfieldReadOnlyColor :
- ui::NativeTheme::kColorId_TextfieldDefaultColor);
-}
-
-void Textfield::SetTextColor(SkColor color) {
- text_color_ = color;
- use_default_text_color_ = false;
- SetColor(color);
-}
-
-void Textfield::UseDefaultTextColor() {
- use_default_text_color_ = true;
- SetColor(GetTextColor());
-}
-
-SkColor Textfield::GetBackgroundColor() const {
- if (!use_default_background_color_)
- return background_color_;
-
- return GetNativeTheme()->GetSystemColor(read_only() ?
- ui::NativeTheme::kColorId_TextfieldReadOnlyBackground :
- ui::NativeTheme::kColorId_TextfieldDefaultBackground);
-}
-
-void Textfield::SetBackgroundColor(SkColor color) {
- background_color_ = color;
- use_default_background_color_ = false;
- UpdateBackgroundColor();
-}
-
-void Textfield::UseDefaultBackgroundColor() {
- use_default_background_color_ = true;
- UpdateBackgroundColor();
-}
-
-SkColor Textfield::GetSelectionTextColor() const {
- return use_default_selection_text_color_ ?
- GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_TextfieldSelectionColor) :
- selection_text_color_;
-}
-
-void Textfield::SetSelectionTextColor(SkColor color) {
- selection_text_color_ = color;
- use_default_selection_text_color_ = false;
- GetRenderText()->set_selection_color(GetSelectionTextColor());
- SchedulePaint();
-}
-
-void Textfield::UseDefaultSelectionTextColor() {
- use_default_selection_text_color_ = true;
- GetRenderText()->set_selection_color(GetSelectionTextColor());
- SchedulePaint();
-}
-
-void Textfield::SetShadows(const gfx::ShadowValues& shadows) {
- GetRenderText()->set_shadows(shadows);
- SchedulePaint();
-}
-
-SkColor Textfield::GetSelectionBackgroundColor() const {
- return use_default_selection_background_color_ ?
- GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused) :
- selection_background_color_;
-}
-
-void Textfield::SetSelectionBackgroundColor(SkColor color) {
- selection_background_color_ = color;
- use_default_selection_background_color_ = false;
- GetRenderText()->set_selection_background_focused_color(
- GetSelectionBackgroundColor());
- SchedulePaint();
-}
-
-void Textfield::UseDefaultSelectionBackgroundColor() {
- use_default_selection_background_color_ = true;
- GetRenderText()->set_selection_background_focused_color(
- GetSelectionBackgroundColor());
- SchedulePaint();
-}
-
-bool Textfield::GetCursorEnabled() const {
- return GetRenderText()->cursor_enabled();
-}
-
-void Textfield::SetCursorEnabled(bool enabled) {
- GetRenderText()->SetCursorEnabled(enabled);
-}
-
-const gfx::FontList& Textfield::GetFontList() const {
- return GetRenderText()->font_list();
-}
-
-void Textfield::SetFontList(const gfx::FontList& font_list) {
- GetRenderText()->SetFontList(font_list);
- OnCaretBoundsChanged();
- PreferredSizeChanged();
-}
-
-base::string16 Textfield::GetPlaceholderText() const {
- return placeholder_text_;
-}
-
-gfx::HorizontalAlignment Textfield::GetHorizontalAlignment() const {
- return GetRenderText()->horizontal_alignment();
-}
-
-void Textfield::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
- GetRenderText()->SetHorizontalAlignment(alignment);
-}
-
-void Textfield::ShowImeIfNeeded() {
- if (enabled() && !read_only())
- GetInputMethod()->ShowImeIfNeeded();
-}
-
-bool Textfield::IsIMEComposing() const {
- return model_->HasCompositionText();
-}
-
-const gfx::Range& Textfield::GetSelectedRange() const {
- return GetRenderText()->selection();
-}
-
-void Textfield::SelectRange(const gfx::Range& range) {
- model_->SelectRange(range);
- UpdateAfterChange(false, true);
-}
-
-const gfx::SelectionModel& Textfield::GetSelectionModel() const {
- return GetRenderText()->selection_model();
-}
-
-void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) {
- model_->SelectSelectionModel(sel);
- UpdateAfterChange(false, true);
-}
-
-size_t Textfield::GetCursorPosition() const {
- return model_->GetCursorPosition();
-}
-
-void Textfield::SetColor(SkColor value) {
- GetRenderText()->SetColor(value);
- SchedulePaint();
-}
-
-void Textfield::ApplyColor(SkColor value, const gfx::Range& range) {
- GetRenderText()->ApplyColor(value, range);
- SchedulePaint();
-}
-
-void Textfield::SetStyle(gfx::TextStyle style, bool value) {
- GetRenderText()->SetStyle(style, value);
- SchedulePaint();
-}
-
-void Textfield::ApplyStyle(gfx::TextStyle style,
- bool value,
- const gfx::Range& range) {
- GetRenderText()->ApplyStyle(style, value, range);
- SchedulePaint();
-}
-
-void Textfield::ClearEditHistory() {
- model_->ClearEditHistory();
-}
-
-void Textfield::SetAccessibleName(const base::string16& name) {
- accessible_name_ = name;
-}
-
-void Textfield::ExecuteCommand(int command_id) {
- ExecuteCommand(command_id, ui::EF_NONE);
-}
-
-void Textfield::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
- focus_painter_ = focus_painter.Pass();
-}
-
-bool Textfield::HasTextBeingDragged() {
- return initiating_drag_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, View overrides:
-
-gfx::Insets Textfield::GetInsets() const {
- gfx::Insets insets = View::GetInsets();
- insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding);
- return insets;
-}
-
-int Textfield::GetBaseline() const {
- return GetInsets().top() + GetRenderText()->GetBaseline();
-}
-
-gfx::Size Textfield::GetPreferredSize() const {
- const gfx::Insets& insets = GetInsets();
- return gfx::Size(GetFontList().GetExpectedTextWidth(default_width_in_chars_) +
- insets.width(), GetFontList().GetHeight() + insets.height());
-}
-
-const char* Textfield::GetClassName() const {
- return kViewClassName;
-}
-
-gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) {
- bool in_selection = GetRenderText()->IsPointInSelection(event.location());
- bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
- bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
- return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor;
-}
-
-bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
- TrackMouseClicks(event);
-
- if (!controller_ || !controller_->HandleMouseEvent(this, event)) {
- if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) {
- RequestFocus();
- ShowImeIfNeeded();
- }
-
- if (event.IsOnlyLeftMouseButton()) {
- OnBeforeUserAction();
- initiating_drag_ = false;
- switch (aggregated_clicks_) {
- case 0:
- if (GetRenderText()->IsPointInSelection(event.location()))
- initiating_drag_ = true;
- else
- MoveCursorTo(event.location(), event.IsShiftDown());
- break;
- case 1:
- SelectWordAt(event.location());
- double_click_word_ = GetRenderText()->selection();
- break;
- case 2:
- SelectAll(false);
- break;
- default:
- NOTREACHED();
- }
- OnAfterUserAction();
- }
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- if (event.IsOnlyMiddleMouseButton()) {
- if (GetRenderText()->IsPointInSelection(event.location())) {
- OnBeforeUserAction();
- ClearSelection();
- ui::ScopedClipboardWriter(
- ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
- OnAfterUserAction();
- } else if (!read_only()) {
- PasteSelectionClipboard(event);
- }
- }
-#endif
- }
-
- return true;
-}
-
-bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
- last_drag_location_ = event.location();
-
- // Don't adjust the cursor on a potential drag and drop, or if the mouse
- // movement from the last mouse click does not exceed the drag threshold.
- if (initiating_drag_ || !event.IsOnlyLeftMouseButton() ||
- !ExceededDragThreshold(last_drag_location_ - last_click_location_)) {
- return true;
- }
-
- // A timer is used to continuously scroll while selecting beyond side edges.
- if ((event.location().x() > 0 && event.location().x() < size().width()) ||
- GetDragSelectionDelay() == 0) {
- drag_selection_timer_.Stop();
- SelectThroughLastDragLocation();
- } else if (!drag_selection_timer_.IsRunning()) {
- drag_selection_timer_.Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()),
- this, &Textfield::SelectThroughLastDragLocation);
- }
-
- return true;
-}
-
-void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
- OnBeforeUserAction();
- drag_selection_timer_.Stop();
- // Cancel suspected drag initiations, the user was clicking in the selection.
- if (initiating_drag_)
- MoveCursorTo(event.location(), false);
- initiating_drag_ = false;
- UpdateSelectionClipboard();
- OnAfterUserAction();
-}
-
-bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
- // Since HandleKeyEvent() might destroy |this|, get a weak pointer and verify
- // it isn't null before proceeding.
- base::WeakPtr<Textfield> textfield(weak_ptr_factory_.GetWeakPtr());
-
- bool handled = controller_ && controller_->HandleKeyEvent(this, event);
-
- if (!textfield)
- return handled;
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
- ui::GetTextEditKeyBindingsDelegate();
- std::vector<ui::TextEditCommandAuraLinux> commands;
- if (!handled && delegate && delegate->MatchEvent(event, &commands)) {
- const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
- for (size_t i = 0; i < commands.size(); ++i) {
- const int command = GetViewsCommand(commands[i], rtl);
- if (IsCommandIdEnabled(command)) {
- ExecuteCommand(command);
- handled = true;
- }
- }
- return handled;
- }
-#endif
-
- const int command = GetCommandForKeyEvent(event, HasSelection());
- if (!handled && IsCommandIdEnabled(command)) {
- ExecuteCommand(command);
- handled = true;
- }
- return handled;
-}
-
-ui::TextInputClient* Textfield::GetTextInputClient() {
- return read_only_ ? NULL : this;
-}
-
-void Textfield::OnGestureEvent(ui::GestureEvent* event) {
- switch (event->type()) {
- case ui::ET_GESTURE_TAP_DOWN:
- RequestFocus();
- ShowImeIfNeeded();
- event->SetHandled();
- break;
- case ui::ET_GESTURE_TAP:
- if (event->details().tap_count() == 1) {
- if (!GetRenderText()->IsPointInSelection(event->location())) {
- OnBeforeUserAction();
- MoveCursorTo(event->location(), false);
- OnAfterUserAction();
- }
- } else if (event->details().tap_count() == 2) {
- OnBeforeUserAction();
- SelectWordAt(event->location());
- OnAfterUserAction();
- } else {
- OnBeforeUserAction();
- SelectAll(false);
- OnAfterUserAction();
- }
- CreateTouchSelectionControllerAndNotifyIt();
-#if defined(OS_WIN)
- if (!read_only())
- base::win::DisplayVirtualKeyboard();
-#endif
- event->SetHandled();
- break;
- case ui::ET_GESTURE_LONG_PRESS:
- if (!GetRenderText()->IsPointInSelection(event->location())) {
- // If long-press happens outside selection, select word and try to
- // activate touch selection.
- OnBeforeUserAction();
- SelectWordAt(event->location());
- OnAfterUserAction();
- CreateTouchSelectionControllerAndNotifyIt();
- // If touch selection activated successfully, mark event as handled so
- // that the regular context menu is not shown.
- if (touch_selection_controller_)
- event->SetHandled();
- } else {
- // If long-press happens on the selection, deactivate touch selection
- // and try to initiate drag-drop. If drag-drop is not enabled, context
- // menu will be shown. Event is not marked as handled to let Views
- // handle drag-drop or context menu.
- DestroyTouchSelection();
- initiating_drag_ = switches::IsTouchDragDropEnabled();
- }
- break;
- case ui::ET_GESTURE_LONG_TAP:
- // If touch selection is enabled, the context menu on long tap will be
- // shown by the |touch_selection_controller_|, hence we mark the event
- // handled so Views does not try to show context menu on it.
- if (touch_selection_controller_)
- event->SetHandled();
- break;
- case ui::ET_GESTURE_SCROLL_BEGIN:
- touch_handles_hidden_due_to_scroll_ = touch_selection_controller_ != NULL;
- DestroyTouchSelection();
- drag_start_location_ = event->location();
- drag_start_display_offset_ =
- GetRenderText()->GetUpdatedDisplayOffset().x();
- event->SetHandled();
- break;
- case ui::ET_GESTURE_SCROLL_UPDATE: {
- int new_offset = drag_start_display_offset_ + event->location().x() -
- drag_start_location_.x();
- GetRenderText()->SetDisplayOffset(new_offset);
- SchedulePaint();
- event->SetHandled();
- break;
- }
- case ui::ET_GESTURE_SCROLL_END:
- case ui::ET_SCROLL_FLING_START:
- if (touch_handles_hidden_due_to_scroll_) {
- CreateTouchSelectionControllerAndNotifyIt();
- touch_handles_hidden_due_to_scroll_ = false;
- }
- event->SetHandled();
- break;
- default:
- return;
- }
-}
-
-void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
- SelectAll(false);
-}
-
-bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- // Skip any accelerator handling that conflicts with custom keybindings.
- ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
- ui::GetTextEditKeyBindingsDelegate();
- std::vector<ui::TextEditCommandAuraLinux> commands;
- if (delegate && delegate->MatchEvent(event, &commands)) {
- const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
- for (size_t i = 0; i < commands.size(); ++i)
- if (IsCommandIdEnabled(GetViewsCommand(commands[i], rtl)))
- return true;
- }
-#endif
-
- // Skip backspace accelerator handling; editable textfields handle this key.
- // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes.
- const bool is_backspace = event.key_code() == ui::VKEY_BACK;
- return (is_backspace && !read_only()) || event.IsUnicodeKeyCode();
-}
-
-bool Textfield::GetDropFormats(
- int* formats,
- std::set<OSExchangeData::CustomFormat>* custom_formats) {
- if (!enabled() || read_only())
- return false;
- // TODO(msw): Can we support URL, FILENAME, etc.?
- *formats = ui::OSExchangeData::STRING;
- if (controller_)
- controller_->AppendDropFormats(formats, custom_formats);
- return true;
-}
-
-bool Textfield::CanDrop(const OSExchangeData& data) {
- int formats;
- std::set<OSExchangeData::CustomFormat> custom_formats;
- GetDropFormats(&formats, &custom_formats);
- return enabled() && !read_only() &&
- data.HasAnyFormat(formats, custom_formats);
-}
-
-int Textfield::OnDragUpdated(const ui::DropTargetEvent& event) {
- DCHECK(CanDrop(event.data()));
- gfx::RenderText* render_text = GetRenderText();
- const gfx::Range& selection = render_text->selection();
- drop_cursor_position_ = render_text->FindCursorPosition(event.location());
- bool in_selection = !selection.is_empty() &&
- selection.Contains(gfx::Range(drop_cursor_position_.caret_pos()));
- drop_cursor_visible_ = !in_selection;
- // TODO(msw): Pan over text when the user drags to the visible text edge.
- OnCaretBoundsChanged();
- SchedulePaint();
-
- if (initiating_drag_) {
- if (in_selection)
- return ui::DragDropTypes::DRAG_NONE;
- return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
- ui::DragDropTypes::DRAG_MOVE;
- }
- return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
-}
-
-void Textfield::OnDragExited() {
- drop_cursor_visible_ = false;
- SchedulePaint();
-}
-
-int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) {
- DCHECK(CanDrop(event.data()));
- drop_cursor_visible_ = false;
-
- if (controller_) {
- int drag_operation = controller_->OnDrop(event.data());
- if (drag_operation != ui::DragDropTypes::DRAG_NONE)
- return drag_operation;
- }
-
- gfx::RenderText* render_text = GetRenderText();
- DCHECK(!initiating_drag_ ||
- !render_text->IsPointInSelection(event.location()));
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
-
- gfx::SelectionModel drop_destination_model =
- render_text->FindCursorPosition(event.location());
- base::string16 new_text;
- event.data().GetString(&new_text);
-
- // Delete the current selection for a drag and drop within this view.
- const bool move = initiating_drag_ && !event.IsControlDown() &&
- event.source_operations() & ui::DragDropTypes::DRAG_MOVE;
- if (move) {
- // Adjust the drop destination if it is on or after the current selection.
- size_t pos = drop_destination_model.caret_pos();
- pos -= render_text->selection().Intersect(gfx::Range(0, pos)).length();
- model_->DeleteSelectionAndInsertTextAt(new_text, pos);
- } else {
- model_->MoveCursorTo(drop_destination_model);
- // Drop always inserts text even if the textfield is not in insert mode.
- model_->InsertText(new_text);
- }
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
- return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY;
-}
-
-void Textfield::OnDragDone() {
- initiating_drag_ = false;
- drop_cursor_visible_ = false;
-}
-
-void Textfield::GetAccessibleState(ui::AXViewState* state) {
- state->role = ui::AX_ROLE_TEXT_FIELD;
- state->name = accessible_name_;
- if (read_only())
- state->AddStateFlag(ui::AX_STATE_READ_ONLY);
- if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
- state->AddStateFlag(ui::AX_STATE_PROTECTED);
- state->value = text();
-
- const gfx::Range range = GetSelectedRange();
- state->selection_start = range.start();
- state->selection_end = range.end();
-
- if (!read_only()) {
- state->set_value_callback =
- base::Bind(&Textfield::AccessibilitySetValue,
- weak_ptr_factory_.GetWeakPtr());
- }
-}
-
-void Textfield::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- // Textfield insets include a reasonable amount of whitespace on all sides of
- // the default font list. Fallback fonts with larger heights may paint over
- // the vertical whitespace as needed. Alternate solutions involve undesirable
- // behavior like changing the default font size, shrinking some fallback fonts
- // beyond their legibility, or enlarging controls dynamically with content.
- gfx::Rect bounds = GetContentsBounds();
- // GetContentsBounds() does not actually use the local GetInsets() override.
- bounds.Inset(gfx::Insets(0, kTextPadding, 0, kTextPadding));
- GetRenderText()->SetDisplayRect(bounds);
- OnCaretBoundsChanged();
-}
-
-bool Textfield::GetNeedsNotificationWhenVisibleBoundsChange() const {
- return true;
-}
-
-void Textfield::OnVisibleBoundsChanged() {
- if (touch_selection_controller_)
- touch_selection_controller_->SelectionChanged();
-}
-
-void Textfield::OnEnabledChanged() {
- View::OnEnabledChanged();
- if (GetInputMethod())
- GetInputMethod()->OnTextInputTypeChanged(this);
- SchedulePaint();
-}
-
-void Textfield::OnPaint(gfx::Canvas* canvas) {
- OnPaintBackground(canvas);
- PaintTextAndCursor(canvas);
- OnPaintBorder(canvas);
-}
-
-void Textfield::OnFocus() {
- GetRenderText()->set_focused(true);
- cursor_visible_ = true;
- SchedulePaint();
- GetInputMethod()->OnFocus();
- OnCaretBoundsChanged();
-
- const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
- if (caret_blink_ms != 0) {
- cursor_repaint_timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(caret_blink_ms), this,
- &Textfield::UpdateCursor);
- }
-
- View::OnFocus();
- SchedulePaint();
-}
-
-void Textfield::OnBlur() {
- GetRenderText()->set_focused(false);
- GetInputMethod()->OnBlur();
- cursor_repaint_timer_.Stop();
- if (cursor_visible_) {
- cursor_visible_ = false;
- RepaintCursor();
- }
-
- DestroyTouchSelection();
-
- // Border typically draws focus indicator.
- SchedulePaint();
-}
-
-gfx::Point Textfield::GetKeyboardContextMenuLocation() {
- return GetCaretBounds().bottom_right();
-}
-
-void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) {
- gfx::RenderText* render_text = GetRenderText();
- render_text->SetColor(GetTextColor());
- UpdateBackgroundColor();
- render_text->set_cursor_color(GetTextColor());
- render_text->set_selection_color(GetSelectionTextColor());
- render_text->set_selection_background_focused_color(
- GetSelectionBackgroundColor());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, TextfieldModel::Delegate overrides:
-
-void Textfield::OnCompositionTextConfirmedOrCleared() {
- if (!skip_input_method_cancel_composition_)
- GetInputMethod()->CancelComposition(this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, ContextMenuController overrides:
-
-void Textfield::ShowContextMenuForView(View* source,
- const gfx::Point& point,
- ui::MenuSourceType source_type) {
- UpdateContextMenu();
- ignore_result(context_menu_runner_->RunMenuAt(GetWidget(),
- NULL,
- gfx::Rect(point, gfx::Size()),
- MENU_ANCHOR_TOPLEFT,
- source_type));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, DragController overrides:
-
-void Textfield::WriteDragDataForView(View* sender,
- const gfx::Point& press_pt,
- OSExchangeData* data) {
- const base::string16& selected_text(GetSelectedText());
- data->SetString(selected_text);
- Label label(selected_text, GetFontList());
- label.SetBackgroundColor(GetBackgroundColor());
- label.SetSubpixelRenderingEnabled(false);
- gfx::Size size(label.GetPreferredSize());
- gfx::NativeView native_view = GetWidget()->GetNativeView();
- gfx::Display display = gfx::Screen::GetScreenFor(native_view)->
- GetDisplayNearestWindow(native_view);
- size.SetToMin(gfx::Size(display.size().width(), height()));
- label.SetBoundsRect(gfx::Rect(size));
- scoped_ptr<gfx::Canvas> canvas(
- GetCanvasForDragImage(GetWidget(), label.size()));
- label.SetEnabledColor(GetTextColor());
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- // Desktop Linux Aura does not yet support transparency in drag images.
- canvas->DrawColor(GetBackgroundColor());
-#endif
- label.Paint(canvas.get(), views::CullSet());
- const gfx::Vector2d kOffset(-15, 0);
- drag_utils::SetDragImageOnDataObject(*canvas, kOffset, data);
- if (controller_)
- controller_->OnWriteDragData(data);
-}
-
-int Textfield::GetDragOperationsForView(View* sender, const gfx::Point& p) {
- int drag_operations = ui::DragDropTypes::DRAG_COPY;
- if (!enabled() || text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD ||
- !GetRenderText()->IsPointInSelection(p)) {
- drag_operations = ui::DragDropTypes::DRAG_NONE;
- } else if (sender == this && !read_only()) {
- drag_operations =
- ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY;
- }
- if (controller_)
- controller_->OnGetDragOperationsForTextfield(&drag_operations);
- return drag_operations;
-}
-
-bool Textfield::CanStartDragForView(View* sender,
- const gfx::Point& press_pt,
- const gfx::Point& p) {
- return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, ui::TouchEditable overrides:
-
-void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) {
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
- return;
-
- gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
- gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
- gfx::SelectionModel selection(
- gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
- end_caret.caret_affinity());
-
- OnBeforeUserAction();
- SelectSelectionModel(selection);
- OnAfterUserAction();
-}
-
-void Textfield::MoveCaretTo(const gfx::Point& point) {
- SelectRect(point, point);
-}
-
-void Textfield::GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) {
- gfx::RenderText* render_text = GetRenderText();
- const gfx::SelectionModel& sel = render_text->selection_model();
- gfx::SelectionModel start_sel =
- render_text->GetSelectionModelForSelectionStart();
- *p1 = render_text->GetCursorBounds(start_sel, true);
- *p2 = render_text->GetCursorBounds(sel, true);
-}
-
-gfx::Rect Textfield::GetBounds() {
- return GetLocalBounds();
-}
-
-gfx::NativeView Textfield::GetNativeView() const {
- return GetWidget()->GetNativeView();
-}
-
-void Textfield::ConvertPointToScreen(gfx::Point* point) {
- View::ConvertPointToScreen(this, point);
-}
-
-void Textfield::ConvertPointFromScreen(gfx::Point* point) {
- View::ConvertPointFromScreen(this, point);
-}
-
-bool Textfield::DrawsHandles() {
- return false;
-}
-
-void Textfield::OpenContextMenu(const gfx::Point& anchor) {
- DestroyTouchSelection();
- ShowContextMenu(anchor, ui::MENU_SOURCE_TOUCH_EDIT_MENU);
-}
-
-void Textfield::DestroyTouchSelection() {
- touch_selection_controller_.reset();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, ui::SimpleMenuModel::Delegate overrides:
-
-bool Textfield::IsCommandIdChecked(int command_id) const {
- return true;
-}
-
-bool Textfield::IsCommandIdEnabled(int command_id) const {
- base::string16 result;
- bool editable = !read_only();
- bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
- switch (command_id) {
- case IDS_APP_UNDO:
- return editable && model_->CanUndo();
- case IDS_APP_REDO:
- return editable && model_->CanRedo();
- case IDS_APP_CUT:
- return editable && readable && model_->HasSelection();
- case IDS_APP_COPY:
- return readable && model_->HasSelection();
- case IDS_APP_PASTE:
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
- return editable && !result.empty();
- case IDS_APP_DELETE:
- return editable && model_->HasSelection();
- case IDS_APP_SELECT_ALL:
- return !text().empty();
- case IDS_DELETE_FORWARD:
- case IDS_DELETE_BACKWARD:
- case IDS_DELETE_TO_BEGINNING_OF_LINE:
- case IDS_DELETE_TO_END_OF_LINE:
- case IDS_DELETE_WORD_BACKWARD:
- case IDS_DELETE_WORD_FORWARD:
- return editable;
- case IDS_MOVE_LEFT:
- case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
- case IDS_MOVE_RIGHT:
- case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
- case IDS_MOVE_WORD_LEFT:
- case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
- case IDS_MOVE_WORD_RIGHT:
- case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
- case IDS_MOVE_TO_BEGINNING_OF_LINE:
- case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
- case IDS_MOVE_TO_END_OF_LINE:
- case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
- return true;
- default:
- return false;
- }
-}
-
-bool Textfield::GetAcceleratorForCommandId(int command_id,
- ui::Accelerator* accelerator) {
- return false;
-}
-
-void Textfield::ExecuteCommand(int command_id, int event_flags) {
- DestroyTouchSelection();
- if (!IsCommandIdEnabled(command_id))
- return;
-
- bool text_changed = false;
- bool cursor_changed = false;
- bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
- gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
- gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
- gfx::SelectionModel selection_model = GetSelectionModel();
-
- OnBeforeUserAction();
- switch (command_id) {
- case IDS_APP_UNDO:
- text_changed = cursor_changed = model_->Undo();
- break;
- case IDS_APP_REDO:
- text_changed = cursor_changed = model_->Redo();
- break;
- case IDS_APP_CUT:
- text_changed = cursor_changed = Cut();
- break;
- case IDS_APP_COPY:
- Copy();
- break;
- case IDS_APP_PASTE:
- text_changed = cursor_changed = Paste();
- break;
- case IDS_APP_DELETE:
- text_changed = cursor_changed = model_->Delete();
- break;
- case IDS_APP_SELECT_ALL:
- SelectAll(false);
- break;
- case IDS_DELETE_BACKWARD:
- text_changed = cursor_changed = model_->Backspace();
- break;
- case IDS_DELETE_FORWARD:
- text_changed = cursor_changed = model_->Delete();
- break;
- case IDS_DELETE_TO_END_OF_LINE:
- model_->MoveCursor(gfx::LINE_BREAK, end, true);
- text_changed = cursor_changed = model_->Delete();
- break;
- case IDS_DELETE_TO_BEGINNING_OF_LINE:
- model_->MoveCursor(gfx::LINE_BREAK, begin, true);
- text_changed = cursor_changed = model_->Backspace();
- break;
- case IDS_DELETE_WORD_BACKWARD:
- model_->MoveCursor(gfx::WORD_BREAK, begin, true);
- text_changed = cursor_changed = model_->Backspace();
- break;
- case IDS_DELETE_WORD_FORWARD:
- model_->MoveCursor(gfx::WORD_BREAK, end, true);
- text_changed = cursor_changed = model_->Delete();
- break;
- case IDS_MOVE_LEFT:
- model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
- break;
- case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
- model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
- break;
- case IDS_MOVE_RIGHT:
- model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
- break;
- case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
- model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
- break;
- case IDS_MOVE_WORD_LEFT:
- model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
- break;
- case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
- model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
- break;
- case IDS_MOVE_WORD_RIGHT:
- model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
- break;
- case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
- model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
- break;
- case IDS_MOVE_TO_BEGINNING_OF_LINE:
- model_->MoveCursor(gfx::LINE_BREAK, begin, false);
- break;
- case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
- model_->MoveCursor(gfx::LINE_BREAK, begin, true);
- break;
- case IDS_MOVE_TO_END_OF_LINE:
- model_->MoveCursor(gfx::LINE_BREAK, end, false);
- break;
- case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
- model_->MoveCursor(gfx::LINE_BREAK, end, true);
- break;
- default:
- NOTREACHED();
- break;
- }
-
- cursor_changed |= GetSelectionModel() != selection_model;
- if (cursor_changed)
- UpdateSelectionClipboard();
- UpdateAfterChange(text_changed, cursor_changed);
- OnAfterUserAction();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, ui::TextInputClient overrides:
-
-void Textfield::SetCompositionText(const ui::CompositionText& composition) {
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- model_->SetCompositionText(composition);
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void Textfield::ConfirmCompositionText() {
- if (!model_->HasCompositionText())
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- model_->ConfirmCompositionText();
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void Textfield::ClearCompositionText() {
- if (!model_->HasCompositionText())
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- model_->CancelCompositionText();
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void Textfield::InsertText(const base::string16& new_text) {
- // TODO(suzhe): Filter invalid characters.
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || new_text.empty())
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- if (GetRenderText()->insert_mode())
- model_->InsertText(new_text);
- else
- model_->ReplaceText(new_text);
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void Textfield::InsertChar(base::char16 ch, int flags) {
- const int kControlModifierMask = ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
- ui::EF_COMMAND_DOWN | ui::EF_ALTGR_DOWN |
- ui::EF_MOD3_DOWN;
-
- // Filter out all control characters, including tab and new line characters,
- // and all characters with Alt modifier. But allow characters with the AltGr
- // modifier. On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a
- // different flag that we don't care about.
- const bool should_insert_char =
- ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) &&
- (flags & kControlModifierMask) != ui::EF_ALT_DOWN;
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || !should_insert_char)
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- if (GetRenderText()->insert_mode())
- model_->InsertChar(ch);
- else
- model_->ReplaceChar(ch);
- skip_input_method_cancel_composition_ = false;
-
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-
- if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD &&
- password_reveal_duration_ != base::TimeDelta()) {
- const size_t change_offset = model_->GetCursorPosition();
- DCHECK_GT(change_offset, 0u);
- RevealPasswordChar(change_offset - 1);
- }
-}
-
-gfx::NativeWindow Textfield::GetAttachedWindow() const {
- // Imagine the following hierarchy.
- // [NativeWidget A] - FocusManager
- // [View]
- // [NativeWidget B]
- // [View]
- // [View X]
- // An important thing is that [NativeWidget A] owns Win32 input focus even
- // when [View X] is logically focused by FocusManager. As a result, an Win32
- // IME may want to interact with the native view of [NativeWidget A] rather
- // than that of [NativeWidget B]. This is why we need to call
- // GetTopLevelWidget() here.
- return GetWidget()->GetTopLevelWidget()->GetNativeWindow();
-}
-
-ui::TextInputType Textfield::GetTextInputType() const {
- if (read_only() || !enabled())
- return ui::TEXT_INPUT_TYPE_NONE;
- return text_input_type_;
-}
-
-ui::TextInputMode Textfield::GetTextInputMode() const {
- return ui::TEXT_INPUT_MODE_DEFAULT;
-}
-
-bool Textfield::CanComposeInline() const {
- return true;
-}
-
-gfx::Rect Textfield::GetCaretBounds() const {
- gfx::Rect rect = GetRenderText()->GetUpdatedCursorBounds();
- ConvertRectToScreen(this, &rect);
- return rect;
-}
-
-bool Textfield::GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) const {
- DCHECK(rect);
- if (!HasCompositionText())
- return false;
- gfx::RenderText* render_text = GetRenderText();
- const gfx::Range& composition_range = render_text->GetCompositionRange();
- DCHECK(!composition_range.is_empty());
-
- size_t text_index = composition_range.start() + index;
- if (composition_range.end() <= text_index)
- return false;
- if (!render_text->IsValidCursorIndex(text_index)) {
- text_index = render_text->IndexOfAdjacentGrapheme(
- text_index, gfx::CURSOR_BACKWARD);
- }
- if (text_index < composition_range.start())
- return false;
- const gfx::SelectionModel caret(text_index, gfx::CURSOR_BACKWARD);
- *rect = render_text->GetCursorBounds(caret, false);
- ConvertRectToScreen(this, rect);
- return true;
-}
-
-bool Textfield::HasCompositionText() const {
- return model_->HasCompositionText();
-}
-
-bool Textfield::GetTextRange(gfx::Range* range) const {
- if (!ImeEditingAllowed())
- return false;
-
- model_->GetTextRange(range);
- return true;
-}
-
-bool Textfield::GetCompositionTextRange(gfx::Range* range) const {
- if (!ImeEditingAllowed())
- return false;
-
- model_->GetCompositionTextRange(range);
- return true;
-}
-
-bool Textfield::GetSelectionRange(gfx::Range* range) const {
- if (!ImeEditingAllowed())
- return false;
- *range = GetRenderText()->selection();
- return true;
-}
-
-bool Textfield::SetSelectionRange(const gfx::Range& range) {
- if (!ImeEditingAllowed() || !range.IsValid())
- return false;
- OnBeforeUserAction();
- SelectRange(range);
- OnAfterUserAction();
- return true;
-}
-
-bool Textfield::DeleteRange(const gfx::Range& range) {
- if (!ImeEditingAllowed() || range.is_empty())
- return false;
-
- OnBeforeUserAction();
- model_->SelectRange(range);
- if (model_->HasSelection()) {
- model_->DeleteSelection();
- UpdateAfterChange(true, true);
- }
- OnAfterUserAction();
- return true;
-}
-
-bool Textfield::GetTextFromRange(const gfx::Range& range,
- base::string16* range_text) const {
- if (!ImeEditingAllowed() || !range.IsValid())
- return false;
-
- gfx::Range text_range;
- if (!GetTextRange(&text_range) || !text_range.Contains(range))
- return false;
-
- *range_text = model_->GetTextFromRange(range);
- return true;
-}
-
-void Textfield::OnInputMethodChanged() {}
-
-bool Textfield::ChangeTextDirectionAndLayoutAlignment(
- base::i18n::TextDirection direction) {
- // Restore text directionality mode when the indicated direction matches the
- // current forced mode; otherwise, force the mode indicated. This helps users
- // manage BiDi text layout without getting stuck in forced LTR or RTL modes.
- const gfx::DirectionalityMode mode = direction == base::i18n::RIGHT_TO_LEFT ?
- gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR;
- if (mode == GetRenderText()->directionality_mode())
- GetRenderText()->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT);
- else
- GetRenderText()->SetDirectionalityMode(mode);
- SchedulePaint();
- return true;
-}
-
-void Textfield::ExtendSelectionAndDelete(size_t before, size_t after) {
- gfx::Range range = GetRenderText()->selection();
- DCHECK_GE(range.start(), before);
-
- range.set_start(range.start() - before);
- range.set_end(range.end() + after);
- gfx::Range text_range;
- if (GetTextRange(&text_range) && text_range.Contains(range))
- DeleteRange(range);
-}
-
-void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {}
-
-void Textfield::OnCandidateWindowShown() {}
-
-void Textfield::OnCandidateWindowUpdated() {}
-
-void Textfield::OnCandidateWindowHidden() {}
-
-bool Textfield::IsEditingCommandEnabled(int command_id) {
- return IsCommandIdEnabled(command_id);
-}
-
-void Textfield::ExecuteEditingCommand(int command_id) {
- ExecuteCommand(command_id);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, protected:
-
-gfx::RenderText* Textfield::GetRenderText() const {
- return model_->render_text();
-}
-
-base::string16 Textfield::GetSelectionClipboardText() const {
- base::string16 selection_clipboard_text;
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
- return selection_clipboard_text;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Textfield, private:
-
-void Textfield::AccessibilitySetValue(const base::string16& new_value) {
- if (!read_only()) {
- SetText(new_value);
- ClearSelection();
- }
-}
-
-void Textfield::UpdateBackgroundColor() {
- const SkColor color = GetBackgroundColor();
- set_background(Background::CreateSolidBackground(color));
- GetRenderText()->set_background_is_transparent(SkColorGetA(color) != 0xFF);
- SchedulePaint();
-}
-
-void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) {
- if (text_changed) {
- if (controller_)
- controller_->ContentsChanged(this, text());
- NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
- }
- if (cursor_changed) {
- cursor_visible_ = true;
- RepaintCursor();
- if (cursor_repaint_timer_.IsRunning())
- cursor_repaint_timer_.Reset();
- if (!text_changed) {
- // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire
- // this if only the selection changed.
- NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true);
- }
- }
- if (text_changed || cursor_changed) {
- OnCaretBoundsChanged();
- SchedulePaint();
- }
-}
-
-void Textfield::UpdateCursor() {
- const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
- cursor_visible_ = !cursor_visible_ || (caret_blink_ms == 0);
- RepaintCursor();
-}
-
-void Textfield::RepaintCursor() {
- gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
- r.Inset(-1, -1, -1, -1);
- SchedulePaintInRect(r);
-}
-
-void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) {
- TRACE_EVENT0("views", "Textfield::PaintTextAndCursor");
- canvas->Save();
-
- // Draw placeholder text if needed.
- gfx::RenderText* render_text = GetRenderText();
- if (text().empty() && !GetPlaceholderText().empty()) {
- canvas->DrawStringRect(GetPlaceholderText(), GetFontList(),
- placeholder_text_color(), render_text->display_rect());
- }
-
- // Draw the text, cursor, and selection.
- render_text->set_cursor_visible(cursor_visible_ && !drop_cursor_visible_ &&
- !HasSelection());
- render_text->Draw(canvas);
-
- // Draw the detached drop cursor that marks where the text will be dropped.
- if (drop_cursor_visible_)
- render_text->DrawCursor(canvas, drop_cursor_position_);
-
- canvas->Restore();
-}
-
-void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
- if (model_->MoveCursorTo(point, select))
- UpdateAfterChange(false, true);
-}
-
-void Textfield::SelectThroughLastDragLocation() {
- OnBeforeUserAction();
- model_->MoveCursorTo(last_drag_location_, true);
- if (aggregated_clicks_ == 1) {
- model_->SelectWord();
- // Expand the selection so the initially selected word remains selected.
- gfx::Range selection = GetRenderText()->selection();
- const size_t min = std::min(selection.GetMin(),
- double_click_word_.GetMin());
- const size_t max = std::max(selection.GetMax(),
- double_click_word_.GetMax());
- const bool reversed = selection.is_reversed();
- selection.set_start(reversed ? max : min);
- selection.set_end(reversed ? min : max);
- model_->SelectRange(selection);
- }
- UpdateAfterChange(false, true);
- OnAfterUserAction();
-}
-
-void Textfield::OnCaretBoundsChanged() {
- if (GetInputMethod())
- GetInputMethod()->OnCaretBoundsChanged(this);
- if (touch_selection_controller_)
- touch_selection_controller_->SelectionChanged();
-}
-
-void Textfield::OnBeforeUserAction() {
- DCHECK(!performing_user_action_);
- performing_user_action_ = true;
- if (controller_)
- controller_->OnBeforeUserAction(this);
-}
-
-void Textfield::OnAfterUserAction() {
- if (controller_)
- controller_->OnAfterUserAction(this);
- DCHECK(performing_user_action_);
- performing_user_action_ = false;
-}
-
-bool Textfield::Cut() {
- if (!read_only() && text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD &&
- model_->Cut()) {
- if (controller_)
- controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
- return true;
- }
- return false;
-}
-
-bool Textfield::Copy() {
- if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD && model_->Copy()) {
- if (controller_)
- controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
- return true;
- }
- return false;
-}
-
-bool Textfield::Paste() {
- if (!read_only() && model_->Paste()) {
- if (controller_)
- controller_->OnAfterPaste();
- return true;
- }
- return false;
-}
-
-void Textfield::UpdateContextMenu() {
- if (!context_menu_contents_.get()) {
- context_menu_contents_.reset(new ui::SimpleMenuModel(this));
- context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
- context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
- context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
- context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
- context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
- context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
- context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
- context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
- IDS_APP_SELECT_ALL);
- if (controller_)
- controller_->UpdateContextMenu(context_menu_contents_.get());
- }
- context_menu_runner_.reset(
- new MenuRunner(context_menu_contents_.get(),
- MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU));
-}
-
-void Textfield::TrackMouseClicks(const ui::MouseEvent& event) {
- if (event.IsOnlyLeftMouseButton()) {
- base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
- if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
- !ExceededDragThreshold(event.location() - last_click_location_)) {
- // Upon clicking after a triple click, the count should go back to double
- // click and alternate between double and triple. This assignment maps
- // 0 to 1, 1 to 2, 2 to 1.
- aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
- } else {
- aggregated_clicks_ = 0;
- }
- last_click_time_ = event.time_stamp();
- last_click_location_ = event.location();
- }
-}
-
-bool Textfield::ImeEditingAllowed() const {
- // Disallow input method editing of password fields.
- ui::TextInputType t = GetTextInputType();
- return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
-}
-
-void Textfield::RevealPasswordChar(int index) {
- GetRenderText()->SetObscuredRevealIndex(index);
- SchedulePaint();
-
- if (index != -1) {
- password_reveal_timer_.Start(FROM_HERE, password_reveal_duration_,
- base::Bind(&Textfield::RevealPasswordChar,
- weak_ptr_factory_.GetWeakPtr(), -1));
- }
-}
-
-void Textfield::CreateTouchSelectionControllerAndNotifyIt() {
- if (!HasFocus())
- return;
-
- if (!touch_selection_controller_) {
- touch_selection_controller_.reset(
- ui::TouchSelectionController::create(this));
- }
- if (touch_selection_controller_)
- touch_selection_controller_->SelectionChanged();
-}
-
-void Textfield::UpdateSelectionClipboard() const {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- if (performing_user_action_ && HasSelection()) {
- ui::ScopedClipboardWriter(
- ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
- if (controller_)
- controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
- }
-#endif
-}
-
-void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
- DCHECK(event.IsOnlyMiddleMouseButton());
- DCHECK(!read_only());
- base::string16 selection_clipboard_text = GetSelectionClipboardText();
- if (!selection_clipboard_text.empty()) {
- OnBeforeUserAction();
- gfx::Range range = GetSelectionModel().selection();
- gfx::LogicalCursorDirection affinity = GetSelectionModel().caret_affinity();
- const gfx::SelectionModel mouse =
- GetRenderText()->FindCursorPosition(event.location());
- model_->MoveCursorTo(mouse);
- model_->InsertText(selection_clipboard_text);
- // Update the new selection range as needed.
- if (range.GetMin() >= mouse.caret_pos()) {
- const size_t length = selection_clipboard_text.length();
- range = gfx::Range(range.start() + length, range.end() + length);
- }
- model_->MoveCursorTo(gfx::SelectionModel(range, affinity));
- UpdateAfterChange(true, true);
- OnAfterUserAction();
- }
-}
-
-} // namespace views
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | ui/views/controls/textfield/textfield_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698