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

Side by Side Diff: ui/views/controls/textfield/textfield.cc

Issue 2408623002: Views: Extract text selection code from Textfield. (Closed)
Patch Set: Rename [Starting/Ending]MouseAction. Created 4 years, 2 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/textfield/textfield.h" 5 #include "ui/views/controls/textfield/textfield.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
(...skipping 21 matching lines...) Expand all
32 #include "ui/gfx/selection_bound.h" 32 #include "ui/gfx/selection_bound.h"
33 #include "ui/native_theme/native_theme.h" 33 #include "ui/native_theme/native_theme.h"
34 #include "ui/strings/grit/ui_strings.h" 34 #include "ui/strings/grit/ui_strings.h"
35 #include "ui/views/background.h" 35 #include "ui/views/background.h"
36 #include "ui/views/controls/focusable_border.h" 36 #include "ui/views/controls/focusable_border.h"
37 #include "ui/views/controls/label.h" 37 #include "ui/views/controls/label.h"
38 #include "ui/views/controls/menu/menu_runner.h" 38 #include "ui/views/controls/menu/menu_runner.h"
39 #include "ui/views/controls/native/native_view_host.h" 39 #include "ui/views/controls/native/native_view_host.h"
40 #include "ui/views/controls/textfield/textfield_controller.h" 40 #include "ui/views/controls/textfield/textfield_controller.h"
41 #include "ui/views/drag_utils.h" 41 #include "ui/views/drag_utils.h"
42 #include "ui/views/metrics.h"
43 #include "ui/views/native_cursor.h" 42 #include "ui/views/native_cursor.h"
44 #include "ui/views/painter.h" 43 #include "ui/views/painter.h"
44 #include "ui/views/selection_controller.h"
45 #include "ui/views/style/platform_style.h" 45 #include "ui/views/style/platform_style.h"
46 #include "ui/views/views_delegate.h" 46 #include "ui/views/views_delegate.h"
47 #include "ui/views/widget/widget.h" 47 #include "ui/views/widget/widget.h"
48 48
49 #if defined(OS_WIN) 49 #if defined(OS_WIN)
50 #include "base/win/win_util.h" 50 #include "base/win/win_util.h"
51 #include "ui/base/win/osk_display_manager.h" 51 #include "ui/base/win/osk_display_manager.h"
52 #endif 52 #endif
53 53
54 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 54 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
(...skipping 22 matching lines...) Expand all
77 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY; 77 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
78 78
79 void ConvertRectToScreen(const View* src, gfx::Rect* r) { 79 void ConvertRectToScreen(const View* src, gfx::Rect* r) {
80 DCHECK(src); 80 DCHECK(src);
81 81
82 gfx::Point new_origin = r->origin(); 82 gfx::Point new_origin = r->origin();
83 View::ConvertPointToScreen(src, &new_origin); 83 View::ConvertPointToScreen(src, &new_origin);
84 r->set_origin(new_origin); 84 r->set_origin(new_origin);
85 } 85 }
86 86
87 // Get the drag selection timer delay, respecting animation scaling for testing.
88 int GetDragSelectionDelay() {
89 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) {
90 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: return 100;
91 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: return 25;
92 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: return 400;
93 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: return 1;
94 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: return 0;
95 }
96 return 100;
97 }
98
99 // Get the default command for a given key |event|. 87 // Get the default command for a given key |event|.
100 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) { 88 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) {
101 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) 89 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode())
102 return ui::TextEditCommand::INVALID_COMMAND; 90 return ui::TextEditCommand::INVALID_COMMAND;
103 91
104 const bool shift = event.IsShiftDown(); 92 const bool shift = event.IsShiftDown();
105 const bool control = event.IsControlDown(); 93 const bool control = event.IsControlDown();
106 const bool alt = event.IsAltDown() || event.IsAltGrDown(); 94 const bool alt = event.IsAltDown() || event.IsAltGrDown();
107 switch (event.key_code()) { 95 switch (event.key_code()) {
108 case ui::VKEY_Z: 96 case ui::VKEY_Z:
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 use_default_selection_text_color_(true), 235 use_default_selection_text_color_(true),
248 use_default_selection_background_color_(true), 236 use_default_selection_background_color_(true),
249 text_color_(SK_ColorBLACK), 237 text_color_(SK_ColorBLACK),
250 background_color_(SK_ColorWHITE), 238 background_color_(SK_ColorWHITE),
251 selection_text_color_(SK_ColorWHITE), 239 selection_text_color_(SK_ColorWHITE),
252 selection_background_color_(SK_ColorBLUE), 240 selection_background_color_(SK_ColorBLUE),
253 placeholder_text_color_(kDefaultPlaceholderTextColor), 241 placeholder_text_color_(kDefaultPlaceholderTextColor),
254 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), 242 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
255 text_input_flags_(0), 243 text_input_flags_(0),
256 performing_user_action_(false), 244 performing_user_action_(false),
245 performing_mouse_action_(false),
257 skip_input_method_cancel_composition_(false), 246 skip_input_method_cancel_composition_(false),
258 drop_cursor_visible_(false), 247 drop_cursor_visible_(false),
259 initiating_drag_(false), 248 initiating_drag_(false),
260 aggregated_clicks_(0), 249 selection_controller_(new SelectionController(this)),
261 drag_start_display_offset_(0), 250 drag_start_display_offset_(0),
262 touch_handles_hidden_due_to_scroll_(false), 251 touch_handles_hidden_due_to_scroll_(false),
263 weak_ptr_factory_(this) { 252 weak_ptr_factory_(this) {
264 set_context_menu_controller(this); 253 set_context_menu_controller(this);
265 set_drag_controller(this); 254 set_drag_controller(this);
266 GetRenderText()->SetFontList(GetDefaultFontList()); 255 GetRenderText()->SetFontList(GetDefaultFontList());
267 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); 256 SetBorder(std::unique_ptr<Border>(new FocusableBorder()));
268 SetFocusBehavior(FocusBehavior::ALWAYS); 257 SetFocusBehavior(FocusBehavior::ALWAYS);
269 258
270 // These allow BrowserView to pass edit commands from the Chrome menu to us 259 // These allow BrowserView to pass edit commands from the Chrome menu to us
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 return; 313 return;
325 model_->InsertText(new_text); 314 model_->InsertText(new_text);
326 OnCaretBoundsChanged(); 315 OnCaretBoundsChanged();
327 SchedulePaint(); 316 SchedulePaint();
328 } 317 }
329 318
330 base::string16 Textfield::GetSelectedText() const { 319 base::string16 Textfield::GetSelectedText() const {
331 return model_->GetSelectedText(); 320 return model_->GetSelectedText();
332 } 321 }
333 322
334 void Textfield::SelectAll(bool reversed) {
335 model_->SelectAll(reversed);
336 UpdateSelectionClipboard();
337 UpdateAfterChange(false, true);
338 }
339
340 void Textfield::SelectWordAt(const gfx::Point& point) {
341 model_->MoveCursorTo(point, false);
342 model_->SelectWord();
343 UpdateAfterChange(false, true);
344 }
345
346 void Textfield::ClearSelection() {
347 model_->ClearSelection();
348 UpdateAfterChange(false, true);
349 }
350
351 bool Textfield::HasSelection() const { 323 bool Textfield::HasSelection() const {
352 return !GetSelectedRange().is_empty(); 324 return !GetSelectedRange().is_empty();
353 } 325 }
354 326
355 SkColor Textfield::GetTextColor() const { 327 SkColor Textfield::GetTextColor() const {
356 if (!use_default_text_color_) 328 if (!use_default_text_color_)
357 return text_color_; 329 return text_color_;
358 330
359 return GetNativeTheme()->GetSystemColor(read_only() || !enabled() ? 331 return GetNativeTheme()->GetSystemColor(read_only() || !enabled() ?
360 ui::NativeTheme::kColorId_TextfieldReadOnlyColor : 332 ui::NativeTheme::kColorId_TextfieldReadOnlyColor :
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 } 447 }
476 448
477 bool Textfield::IsIMEComposing() const { 449 bool Textfield::IsIMEComposing() const {
478 return model_->HasCompositionText(); 450 return model_->HasCompositionText();
479 } 451 }
480 452
481 const gfx::Range& Textfield::GetSelectedRange() const { 453 const gfx::Range& Textfield::GetSelectedRange() const {
482 return GetRenderText()->selection(); 454 return GetRenderText()->selection();
483 } 455 }
484 456
485 void Textfield::SelectRange(const gfx::Range& range) {
486 model_->SelectRange(range);
487 UpdateAfterChange(false, true);
488 }
489
490 const gfx::SelectionModel& Textfield::GetSelectionModel() const { 457 const gfx::SelectionModel& Textfield::GetSelectionModel() const {
491 return GetRenderText()->selection_model(); 458 return GetRenderText()->selection_model();
492 } 459 }
493 460
494 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) { 461 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) {
495 model_->SelectSelectionModel(sel); 462 model_->SelectSelectionModel(sel);
496 UpdateAfterChange(false, true); 463 UpdateAfterChange(false, true);
497 } 464 }
498 465
499 size_t Textfield::GetCursorPosition() const { 466 size_t Textfield::GetCursorPosition() const {
(...skipping 23 matching lines...) Expand all
523 } 490 }
524 491
525 void Textfield::ClearEditHistory() { 492 void Textfield::ClearEditHistory() {
526 model_->ClearEditHistory(); 493 model_->ClearEditHistory();
527 } 494 }
528 495
529 void Textfield::SetAccessibleName(const base::string16& name) { 496 void Textfield::SetAccessibleName(const base::string16& name) {
530 accessible_name_ = name; 497 accessible_name_ = name;
531 } 498 }
532 499
533 bool Textfield::HasTextBeingDragged() {
534 return initiating_drag_;
535 }
536
537 //////////////////////////////////////////////////////////////////////////////// 500 ////////////////////////////////////////////////////////////////////////////////
538 // Textfield, View overrides: 501 // Textfield, View overrides:
539 502
540 gfx::Insets Textfield::GetInsets() const { 503 gfx::Insets Textfield::GetInsets() const {
541 gfx::Insets insets = View::GetInsets(); 504 gfx::Insets insets = View::GetInsets();
542 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); 505 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding);
543 return insets; 506 return insets;
544 } 507 }
545 508
546 int Textfield::GetBaseline() const { 509 int Textfield::GetBaseline() const {
(...skipping 11 matching lines...) Expand all
558 } 521 }
559 522
560 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { 523 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) {
561 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); 524 bool in_selection = GetRenderText()->IsPointInSelection(event.location());
562 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; 525 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
563 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); 526 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
564 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; 527 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor;
565 } 528 }
566 529
567 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { 530 bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
568 TrackMouseClicks(event); 531 bool handled = controller_ && controller_->HandleMouseEvent(this, event);
569 532 if (!handled &&
570 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { 533 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())) {
571 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { 534 RequestFocus();
572 RequestFocus(); 535 ShowImeIfNeeded();
573 ShowImeIfNeeded();
574 }
575
576 if (event.IsOnlyLeftMouseButton()) {
577 OnBeforeUserAction();
578 initiating_drag_ = false;
579 switch (aggregated_clicks_) {
580 case 0:
581 if (GetRenderText()->IsPointInSelection(event.location()))
582 initiating_drag_ = true;
583 else
584 MoveCursorTo(event.location(), event.IsShiftDown());
585 break;
586 case 1:
587 SelectWordAt(event.location());
588 double_click_word_ = GetRenderText()->selection();
589 break;
590 case 2:
591 SelectAll(false);
592 break;
593 default:
594 NOTREACHED();
595 }
596 OnAfterUserAction();
597 }
598
599 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
600 if (event.IsOnlyMiddleMouseButton()) {
601 if (GetRenderText()->IsPointInSelection(event.location())) {
602 OnBeforeUserAction();
603 ClearSelection();
604 ui::ScopedClipboardWriter(
605 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
606 OnAfterUserAction();
607 } else if (!read_only()) {
608 PasteSelectionClipboard(event);
609 }
610 }
611 #endif
612 } 536 }
613 537
614 return true; 538 return handled | selection_controller_->OnMousePressed(event, handled);
615 } 539 }
616 540
617 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { 541 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
618 last_drag_location_ = event.location(); 542 return selection_controller_->OnMouseDragged(event);
619
620 // Don't adjust the cursor on a potential drag and drop.
621 if (initiating_drag_ || !event.IsOnlyLeftMouseButton())
622 return true;
623
624 // A timer is used to continuously scroll while selecting beyond side edges.
625 const int x = event.location().x();
626 if ((x >= 0 && x <= width()) || GetDragSelectionDelay() == 0) {
627 drag_selection_timer_.Stop();
628 SelectThroughLastDragLocation();
629 } else if (!drag_selection_timer_.IsRunning()) {
630 // Select through the edge of the visible text, then start the scroll timer.
631 last_drag_location_.set_x(std::min(std::max(0, x), width()));
632 SelectThroughLastDragLocation();
633 drag_selection_timer_.Start(
634 FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()),
635 this, &Textfield::SelectThroughLastDragLocation);
636 }
637
638 return true;
639 } 543 }
640 544
641 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { 545 void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
642 OnBeforeUserAction(); 546 selection_controller_->OnMouseReleased(event);
643 drag_selection_timer_.Stop();
644 // Cancel suspected drag initiations, the user was clicking in the selection.
645 if (initiating_drag_)
646 MoveCursorTo(event.location(), false);
647 initiating_drag_ = false;
648 UpdateSelectionClipboard();
649 OnAfterUserAction();
650 } 547 }
651 548
652 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { 549 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
653 ui::TextEditCommand edit_command = scheduled_text_edit_command_; 550 ui::TextEditCommand edit_command = scheduled_text_edit_command_;
654 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; 551 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND;
655 552
656 // Since HandleKeyEvent() might destroy |this|, get a weak pointer and verify 553 // Since HandleKeyEvent() might destroy |this|, get a weak pointer and verify
657 // it isn't null before proceeding. 554 // it isn't null before proceeding.
658 base::WeakPtr<Textfield> textfield(weak_ptr_factory_.GetWeakPtr()); 555 base::WeakPtr<Textfield> textfield(weak_ptr_factory_.GetWeakPtr());
659 556
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 return drag_operations; 987 return drag_operations;
1091 } 988 }
1092 989
1093 bool Textfield::CanStartDragForView(View* sender, 990 bool Textfield::CanStartDragForView(View* sender,
1094 const gfx::Point& press_pt, 991 const gfx::Point& press_pt,
1095 const gfx::Point& p) { 992 const gfx::Point& p) {
1096 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt); 993 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
1097 } 994 }
1098 995
1099 //////////////////////////////////////////////////////////////////////////////// 996 ////////////////////////////////////////////////////////////////////////////////
997 // Textfield, SelectionControllerHost overrides:
998
999 bool Textfield::HasTextBeingDragged() const {
1000 return initiating_drag_;
1001 }
1002
1003 void Textfield::SelectAll(bool reversed) {
1004 model_->SelectAll(reversed);
1005 if (HasSelection())
1006 UpdateSelectionClipboard();
tapted 2016/10/11 04:42:09 this feels like something the SelectionController
karandeepb 2016/10/14 09:27:34 Not sure if this is still relevant. Also, it seems
1007 UpdateAfterChange(false, true);
1008 }
1009
1010 void Textfield::SelectRange(const gfx::Range& range) {
1011 model_->SelectRange(range);
1012 UpdateAfterChange(false, true);
1013 }
1014
1015 void Textfield::ClearSelection() {
1016 model_->ClearSelection();
1017 UpdateAfterChange(false, true);
1018 }
1019
1020 ////////////////////////////////////////////////////////////////////////////////
1100 // Textfield, ui::TouchEditable overrides: 1021 // Textfield, ui::TouchEditable overrides:
1101 1022
1102 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { 1023 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) {
1103 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) 1024 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
1104 return; 1025 return;
1105 1026
1106 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); 1027 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
1107 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); 1028 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
1108 gfx::SelectionModel selection( 1029 gfx::SelectionModel selection(
1109 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), 1030 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 break; 1674 break;
1754 case ui::TextEditCommand::INSERT_TEXT: 1675 case ui::TextEditCommand::INSERT_TEXT:
1755 case ui::TextEditCommand::SET_MARK: 1676 case ui::TextEditCommand::SET_MARK:
1756 case ui::TextEditCommand::UNSELECT: 1677 case ui::TextEditCommand::UNSELECT:
1757 case ui::TextEditCommand::INVALID_COMMAND: 1678 case ui::TextEditCommand::INVALID_COMMAND:
1758 NOTREACHED(); 1679 NOTREACHED();
1759 break; 1680 break;
1760 } 1681 }
1761 1682
1762 cursor_changed |= GetSelectionModel() != selection_model; 1683 cursor_changed |= GetSelectionModel() != selection_model;
1763 if (cursor_changed) 1684 if (cursor_changed && HasSelection())
1764 UpdateSelectionClipboard(); 1685 UpdateSelectionClipboard();
1765 UpdateAfterChange(text_changed, cursor_changed); 1686 UpdateAfterChange(text_changed, cursor_changed);
1766 OnAfterUserAction(); 1687 OnAfterUserAction();
1767 } 1688 }
1768 1689
1769 //////////////////////////////////////////////////////////////////////////////// 1690 ////////////////////////////////////////////////////////////////////////////////
1770 // Textfield, private: 1691 // Textfield, private:
1771 1692
1693 ////////////////////////////////////////////////////////////////////////////////
1694 // Textfield, SelectionControllerHost overrides:
1695
1696 gfx::RenderText* Textfield::GetRenderTextForSelection() {
1697 return GetRenderText();
1698 }
1699
1700 bool Textfield::IsReadOnly() const {
1701 return false;
1702 }
1703
1704 void Textfield::SetTextBeingDragged(bool value) {
1705 initiating_drag_ = value;
1706 }
1707
1708 int Textfield::GetViewHeight() const {
1709 return height();
1710 }
1711
1712 int Textfield::GetViewWidth() const {
1713 return width();
1714 }
1715
1716 int Textfield::GetDragSelectionDelay() const {
1717 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) {
1718 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION:
1719 return 100;
1720 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION:
1721 return 25;
1722 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION:
1723 return 400;
1724 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION:
1725 return 1;
1726 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION:
1727 return 0;
1728 }
1729 return 100;
1730 }
1731
1732 void Textfield::OnBeforeMouseAction() {
1733 OnBeforeUserAction();
1734 DCHECK(!performing_mouse_action_);
1735 performing_mouse_action_ = true;
1736 }
1737
1738 void Textfield::OnAfterMouseAction(bool text_changed, bool selection_changed) {
1739 OnAfterUserAction();
1740 DCHECK(performing_mouse_action_);
1741 performing_mouse_action_ = false;
1742 UpdateAfterChange(text_changed, selection_changed);
1743 }
1744
1745 void Textfield::SelectWordAt(const gfx::Point& point) {
1746 model_->MoveCursorTo(point, false);
1747 SelectWord();
1748 }
1749
1750 void Textfield::SelectWord() {
1751 model_->SelectWord();
1752 UpdateAfterChange(false, true);
tapted 2016/10/11 04:42:09 yeah if these can move into TextfieldModel (or som
karandeepb 2016/10/14 09:27:34 Have updated SelectionController and narrowed down
1753 }
1754
1755 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
1756 if (model_->MoveCursorTo(point, select))
1757 UpdateAfterChange(false, true);
1758 }
1759
1760 void Textfield::SelectTillEdge(gfx::VisualCursorDirection direction) {
1761 GetRenderText()->MoveCursor(gfx::LINE_BREAK, direction,
1762 gfx::SELECTION_RETAIN);
1763 UpdateAfterChange(false, true);
1764 }
1765
1766 void Textfield::PasteSelectionClipboard() {
1767 if (read_only())
1768 return;
1769 const base::string16 selection_clipboard_text = GetSelectionClipboardText();
1770 if (!HasFocus())
1771 RequestFocus();
1772 if (!selection_clipboard_text.empty()) {
1773 model_->InsertText(selection_clipboard_text);
1774 UpdateAfterChange(true, true);
1775 }
1776 }
1777
1778 void Textfield::UpdateSelectionClipboard() {
1779 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1780 if (performing_user_action_ &&
1781 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
1782 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION)
1783 .WriteText(GetSelectedText());
1784 if (controller_)
1785 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
1786 }
1787 #endif
1788 }
1789
1772 void Textfield::AccessibilitySetValue(const base::string16& new_value) { 1790 void Textfield::AccessibilitySetValue(const base::string16& new_value) {
1773 if (!read_only()) { 1791 if (!read_only()) {
1774 SetText(new_value); 1792 SetText(new_value);
1775 ClearSelection(); 1793 ClearSelection();
1776 } 1794 }
1777 } 1795 }
1778 1796
1779 void Textfield::UpdateBackgroundColor() { 1797 void Textfield::UpdateBackgroundColor() {
1780 const SkColor color = GetBackgroundColor(); 1798 const SkColor color = GetBackgroundColor();
1781 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { 1799 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
1782 set_background(Background::CreateBackgroundPainter( 1800 set_background(Background::CreateBackgroundPainter(
1783 true, Painter::CreateSolidRoundRectPainter( 1801 true, Painter::CreateSolidRoundRectPainter(
1784 color, FocusableBorder::kCornerRadiusDp))); 1802 color, FocusableBorder::kCornerRadiusDp)));
1785 } else { 1803 } else {
1786 set_background(Background::CreateSolidBackground(color)); 1804 set_background(Background::CreateSolidBackground(color));
1787 } 1805 }
1788 // Disable subpixel rendering when the background color is transparent 1806 // Disable subpixel rendering when the background color is transparent
1789 // because it draws incorrect colors around the glyphs in that case. 1807 // because it draws incorrect colors around the glyphs in that case.
1790 // See crbug.com/115198 1808 // See crbug.com/115198
1791 GetRenderText()->set_subpixel_rendering_suppressed( 1809 GetRenderText()->set_subpixel_rendering_suppressed(
1792 SkColorGetA(color) != SK_AlphaOPAQUE); 1810 SkColorGetA(color) != SK_AlphaOPAQUE);
1793 SchedulePaint(); 1811 SchedulePaint();
1794 } 1812 }
1795 1813
1796 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { 1814 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) {
1815 if (performing_mouse_action_)
1816 return;
1797 if (text_changed) { 1817 if (text_changed) {
1798 if (controller_) 1818 if (controller_)
1799 controller_->ContentsChanged(this, text()); 1819 controller_->ContentsChanged(this, text());
1800 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); 1820 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
1801 } 1821 }
1802 if (cursor_changed) { 1822 if (cursor_changed) {
1803 GetRenderText()->set_cursor_visible(ShouldShowCursor()); 1823 GetRenderText()->set_cursor_visible(ShouldShowCursor());
1804 RepaintCursor(); 1824 RepaintCursor();
1805 if (ShouldBlinkCursor()) 1825 if (ShouldBlinkCursor())
1806 StartBlinkingCursor(); 1826 StartBlinkingCursor();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1840 1860
1841 render_text->Draw(canvas); 1861 render_text->Draw(canvas);
1842 1862
1843 // Draw the detached drop cursor that marks where the text will be dropped. 1863 // Draw the detached drop cursor that marks where the text will be dropped.
1844 if (drop_cursor_visible_) 1864 if (drop_cursor_visible_)
1845 render_text->DrawCursor(canvas, drop_cursor_position_); 1865 render_text->DrawCursor(canvas, drop_cursor_position_);
1846 1866
1847 canvas->Restore(); 1867 canvas->Restore();
1848 } 1868 }
1849 1869
1850 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
1851 if (model_->MoveCursorTo(point, select))
1852 UpdateAfterChange(false, true);
1853 }
1854
1855 void Textfield::SelectThroughLastDragLocation() {
1856 OnBeforeUserAction();
1857
1858 const bool drags_to_end = PlatformStyle::kTextfieldDragVerticallyDragsToEnd;
1859 if (drags_to_end && last_drag_location_.y() < 0) {
1860 model_->MoveCursor(gfx::BreakType::LINE_BREAK,
1861 gfx::VisualCursorDirection::CURSOR_LEFT,
1862 gfx::SELECTION_RETAIN);
1863 } else if (drags_to_end && last_drag_location_.y() > height()) {
1864 model_->MoveCursor(gfx::BreakType::LINE_BREAK,
1865 gfx::VisualCursorDirection::CURSOR_RIGHT,
1866 gfx::SELECTION_RETAIN);
1867 } else {
1868 model_->MoveCursorTo(last_drag_location_, true);
1869 }
1870
1871 if (aggregated_clicks_ == 1) {
1872 model_->SelectWord();
1873 // Expand the selection so the initially selected word remains selected.
1874 gfx::Range selection = GetRenderText()->selection();
1875 const size_t min = std::min(selection.GetMin(),
1876 double_click_word_.GetMin());
1877 const size_t max = std::max(selection.GetMax(),
1878 double_click_word_.GetMax());
1879 const bool reversed = selection.is_reversed();
1880 selection.set_start(reversed ? max : min);
1881 selection.set_end(reversed ? min : max);
1882 model_->SelectRange(selection);
1883 }
1884 UpdateAfterChange(false, true);
1885 OnAfterUserAction();
1886 }
1887
1888 void Textfield::OnCaretBoundsChanged() { 1870 void Textfield::OnCaretBoundsChanged() {
1889 if (GetInputMethod()) 1871 if (GetInputMethod())
1890 GetInputMethod()->OnCaretBoundsChanged(this); 1872 GetInputMethod()->OnCaretBoundsChanged(this);
1891 if (touch_selection_controller_) 1873 if (touch_selection_controller_)
1892 touch_selection_controller_->SelectionChanged(); 1874 touch_selection_controller_->SelectionChanged();
1893 } 1875 }
1894 1876
1895 void Textfield::OnBeforeUserAction() { 1877 void Textfield::OnBeforeUserAction() {
1896 DCHECK(!performing_user_action_); 1878 DCHECK(!performing_user_action_);
1897 performing_user_action_ = true; 1879 performing_user_action_ = true;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1951 // IsCommandIdEnabled() as appropriate, for the commands added. 1933 // IsCommandIdEnabled() as appropriate, for the commands added.
1952 if (controller_) 1934 if (controller_)
1953 controller_->UpdateContextMenu(context_menu_contents_.get()); 1935 controller_->UpdateContextMenu(context_menu_contents_.get());
1954 } 1936 }
1955 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), 1937 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(),
1956 MenuRunner::HAS_MNEMONICS | 1938 MenuRunner::HAS_MNEMONICS |
1957 MenuRunner::CONTEXT_MENU | 1939 MenuRunner::CONTEXT_MENU |
1958 MenuRunner::ASYNC)); 1940 MenuRunner::ASYNC));
1959 } 1941 }
1960 1942
1961 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) {
1962 if (event.IsOnlyLeftMouseButton()) {
1963 base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
1964 if (!last_click_time_.is_null() &&
1965 time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
1966 !ExceededDragThreshold(event.location() - last_click_location_)) {
1967 // Upon clicking after a triple click, the count should go back to double
1968 // click and alternate between double and triple. This assignment maps
1969 // 0 to 1, 1 to 2, 2 to 1.
1970 aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
1971 } else {
1972 aggregated_clicks_ = 0;
1973 }
1974 last_click_time_ = event.time_stamp();
1975 last_click_location_ = event.location();
1976 }
1977 }
1978
1979 bool Textfield::ImeEditingAllowed() const { 1943 bool Textfield::ImeEditingAllowed() const {
1980 // Disallow input method editing of password fields. 1944 // Disallow input method editing of password fields.
1981 ui::TextInputType t = GetTextInputType(); 1945 ui::TextInputType t = GetTextInputType();
1982 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); 1946 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
1983 } 1947 }
1984 1948
1985 void Textfield::RevealPasswordChar(int index) { 1949 void Textfield::RevealPasswordChar(int index) {
1986 GetRenderText()->SetObscuredRevealIndex(index); 1950 GetRenderText()->SetObscuredRevealIndex(index);
1987 SchedulePaint(); 1951 SchedulePaint();
1988 1952
1989 if (index != -1) { 1953 if (index != -1) {
1990 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), 1954 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(),
1991 base::Bind(&Textfield::RevealPasswordChar, 1955 base::Bind(&Textfield::RevealPasswordChar,
1992 weak_ptr_factory_.GetWeakPtr(), -1)); 1956 weak_ptr_factory_.GetWeakPtr(), -1));
1993 } 1957 }
1994 } 1958 }
1995 1959
1996 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { 1960 void Textfield::CreateTouchSelectionControllerAndNotifyIt() {
1997 if (!HasFocus()) 1961 if (!HasFocus())
1998 return; 1962 return;
1999 1963
2000 if (!touch_selection_controller_) { 1964 if (!touch_selection_controller_) {
2001 touch_selection_controller_.reset( 1965 touch_selection_controller_.reset(
2002 ui::TouchEditingControllerDeprecated::Create(this)); 1966 ui::TouchEditingControllerDeprecated::Create(this));
2003 } 1967 }
2004 if (touch_selection_controller_) 1968 if (touch_selection_controller_)
2005 touch_selection_controller_->SelectionChanged(); 1969 touch_selection_controller_->SelectionChanged();
2006 } 1970 }
2007 1971
2008 void Textfield::UpdateSelectionClipboard() const {
2009 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2010 if (performing_user_action_ && HasSelection() &&
2011 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
2012 ui::ScopedClipboardWriter(
2013 ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
2014 if (controller_)
2015 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
2016 }
2017 #endif
2018 }
2019
2020 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
2021 DCHECK(event.IsOnlyMiddleMouseButton());
2022 DCHECK(!read_only());
2023 base::string16 selection_clipboard_text = GetSelectionClipboardText();
2024 OnBeforeUserAction();
2025 const gfx::SelectionModel mouse =
2026 GetRenderText()->FindCursorPosition(event.location());
2027 if (!HasFocus())
2028 RequestFocus();
2029 model_->MoveCursorTo(mouse);
2030 if (!selection_clipboard_text.empty()) {
2031 model_->InsertText(selection_clipboard_text);
2032 UpdateAfterChange(true, true);
2033 }
2034 OnAfterUserAction();
2035 }
2036
2037 void Textfield::OnKeypressUnhandled() { 1972 void Textfield::OnKeypressUnhandled() {
2038 PlatformStyle::OnTextfieldKeypressUnhandled(); 1973 PlatformStyle::OnTextfieldKeypressUnhandled();
2039 } 1974 }
2040 1975
2041 bool Textfield::ShouldShowCursor() const { 1976 bool Textfield::ShouldShowCursor() const {
2042 return HasFocus() && !HasSelection() && enabled() && !read_only() && 1977 return HasFocus() && !HasSelection() && enabled() && !read_only() &&
2043 !drop_cursor_visible_; 1978 !drop_cursor_visible_;
2044 } 1979 }
2045 1980
2046 bool Textfield::ShouldBlinkCursor() const { 1981 bool Textfield::ShouldBlinkCursor() const {
(...skipping 11 matching lines...) Expand all
2058 cursor_blink_timer_.Stop(); 1993 cursor_blink_timer_.Stop();
2059 } 1994 }
2060 1995
2061 void Textfield::OnCursorBlinkTimerFired() { 1996 void Textfield::OnCursorBlinkTimerFired() {
2062 DCHECK(ShouldBlinkCursor()); 1997 DCHECK(ShouldBlinkCursor());
2063 gfx::RenderText* render_text = GetRenderText(); 1998 gfx::RenderText* render_text = GetRenderText();
2064 render_text->set_cursor_visible(!render_text->cursor_visible()); 1999 render_text->set_cursor_visible(!render_text->cursor_visible());
2065 RepaintCursor(); 2000 RepaintCursor();
2066 } 2001 }
2067 2002
2003 gfx::Point Textfield::last_click_location() const {
2004 return selection_controller_->last_click_location();
2005 }
2006
2068 } // namespace views 2007 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698