| OLD | NEW |
| 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 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "grit/ui_strings.h" | 10 #include "grit/ui_strings.h" |
| 11 #include "ui/accessibility/ax_view_state.h" | 11 #include "ui/accessibility/ax_view_state.h" |
| 12 #include "ui/base/clipboard/scoped_clipboard_writer.h" | 12 #include "ui/base/clipboard/scoped_clipboard_writer.h" |
| 13 #include "ui/base/cursor/cursor.h" | 13 #include "ui/base/cursor/cursor.h" |
| 14 #include "ui/base/dragdrop/drag_drop_types.h" | 14 #include "ui/base/dragdrop/drag_drop_types.h" |
| 15 #include "ui/base/dragdrop/drag_utils.h" | 15 #include "ui/base/dragdrop/drag_utils.h" |
| 16 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
| 17 #include "ui/base/ui_base_switches_util.h" | 17 #include "ui/base/ui_base_switches_util.h" |
| 18 #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| 18 #include "ui/events/event.h" | 19 #include "ui/events/event.h" |
| 19 #include "ui/events/keycodes/keyboard_codes.h" | 20 #include "ui/events/keycodes/keyboard_codes.h" |
| 20 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
| 21 #include "ui/gfx/display.h" | 22 #include "ui/gfx/display.h" |
| 22 #include "ui/gfx/insets.h" | 23 #include "ui/gfx/insets.h" |
| 23 #include "ui/gfx/screen.h" | 24 #include "ui/gfx/screen.h" |
| 24 #include "ui/native_theme/native_theme.h" | 25 #include "ui/native_theme/native_theme.h" |
| 25 #include "ui/views/background.h" | 26 #include "ui/views/background.h" |
| 26 #include "ui/views/controls/focusable_border.h" | 27 #include "ui/views/controls/focusable_border.h" |
| 27 #include "ui/views/controls/label.h" | 28 #include "ui/views/controls/label.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 56 const int kNoCommand = 0; | 57 const int kNoCommand = 0; |
| 57 | 58 |
| 58 void ConvertRectToScreen(const View* src, gfx::Rect* r) { | 59 void ConvertRectToScreen(const View* src, gfx::Rect* r) { |
| 59 DCHECK(src); | 60 DCHECK(src); |
| 60 | 61 |
| 61 gfx::Point new_origin = r->origin(); | 62 gfx::Point new_origin = r->origin(); |
| 62 View::ConvertPointToScreen(src, &new_origin); | 63 View::ConvertPointToScreen(src, &new_origin); |
| 63 r->set_origin(new_origin); | 64 r->set_origin(new_origin); |
| 64 } | 65 } |
| 65 | 66 |
| 67 // Get the drag selection timer delay, respecting animation scaling for testing. |
| 68 int GetDragSelectionDelay() { |
| 69 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) { |
| 70 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: return 100; |
| 71 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: return 25; |
| 72 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: return 400; |
| 73 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: return 0; |
| 74 } |
| 75 return 100; |
| 76 } |
| 77 |
| 66 int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) { | 78 int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) { |
| 67 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) | 79 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) |
| 68 return kNoCommand; | 80 return kNoCommand; |
| 69 | 81 |
| 70 const bool shift = event.IsShiftDown(); | 82 const bool shift = event.IsShiftDown(); |
| 71 const bool control = event.IsControlDown(); | 83 const bool control = event.IsControlDown(); |
| 72 const bool alt = event.IsAltDown() || event.IsAltGrDown(); | 84 const bool alt = event.IsAltDown() || event.IsAltGrDown(); |
| 73 switch (event.key_code()) { | 85 switch (event.key_code()) { |
| 74 case ui::VKEY_Z: | 86 case ui::VKEY_Z: |
| 75 if (control && !shift && !alt) | 87 if (control && !shift && !alt) |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 return; | 317 return; |
| 306 model_->InsertText(new_text); | 318 model_->InsertText(new_text); |
| 307 OnCaretBoundsChanged(); | 319 OnCaretBoundsChanged(); |
| 308 SchedulePaint(); | 320 SchedulePaint(); |
| 309 } | 321 } |
| 310 | 322 |
| 311 base::i18n::TextDirection Textfield::GetTextDirection() const { | 323 base::i18n::TextDirection Textfield::GetTextDirection() const { |
| 312 return GetRenderText()->GetTextDirection(); | 324 return GetRenderText()->GetTextDirection(); |
| 313 } | 325 } |
| 314 | 326 |
| 327 base::string16 Textfield::GetSelectedText() const { |
| 328 return model_->GetSelectedText(); |
| 329 } |
| 330 |
| 315 void Textfield::SelectAll(bool reversed) { | 331 void Textfield::SelectAll(bool reversed) { |
| 316 model_->SelectAll(reversed); | 332 model_->SelectAll(reversed); |
| 317 UpdateSelectionClipboard(); | 333 UpdateSelectionClipboard(); |
| 318 UpdateAfterChange(false, true); | 334 UpdateAfterChange(false, true); |
| 319 } | 335 } |
| 320 | 336 |
| 321 base::string16 Textfield::GetSelectedText() const { | |
| 322 return model_->GetSelectedText(); | |
| 323 } | |
| 324 | |
| 325 void Textfield::ClearSelection() { | 337 void Textfield::ClearSelection() { |
| 326 model_->ClearSelection(); | 338 model_->ClearSelection(); |
| 327 UpdateAfterChange(false, true); | 339 UpdateAfterChange(false, true); |
| 328 } | 340 } |
| 329 | 341 |
| 330 bool Textfield::HasSelection() const { | 342 bool Textfield::HasSelection() const { |
| 331 return !GetSelectedRange().is_empty(); | 343 return !GetSelectedRange().is_empty(); |
| 332 } | 344 } |
| 333 | 345 |
| 334 SkColor Textfield::GetTextColor() const { | 346 SkColor Textfield::GetTextColor() const { |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 PasteSelectionClipboard(event); | 557 PasteSelectionClipboard(event); |
| 546 } | 558 } |
| 547 } | 559 } |
| 548 #endif | 560 #endif |
| 549 } | 561 } |
| 550 | 562 |
| 551 return true; | 563 return true; |
| 552 } | 564 } |
| 553 | 565 |
| 554 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { | 566 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { |
| 567 last_drag_location_ = event.location(); |
| 568 |
| 555 // Don't adjust the cursor on a potential drag and drop, or if the mouse | 569 // Don't adjust the cursor on a potential drag and drop, or if the mouse |
| 556 // movement from the last mouse click does not exceed the drag threshold. | 570 // movement from the last mouse click does not exceed the drag threshold. |
| 557 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() || | 571 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() || |
| 558 !ExceededDragThreshold(event.location() - last_click_location_)) { | 572 !ExceededDragThreshold(last_drag_location_ - last_click_location_)) { |
| 559 return true; | 573 return true; |
| 560 } | 574 } |
| 561 | 575 |
| 562 OnBeforeUserAction(); | 576 // A timer is used to continuously scroll while selecting beyond side edges. |
| 563 model_->MoveCursorTo(event.location(), true); | 577 if ((event.location().x() > 0 && event.location().x() < size().width()) || |
| 564 if (aggregated_clicks_ == 1) { | 578 GetDragSelectionDelay() == 0) { |
| 565 model_->SelectWord(); | 579 drag_selection_timer_.Stop(); |
| 566 // Expand the selection so the initially selected word remains selected. | 580 SelectThroughLastDragLocation(); |
| 567 gfx::Range selection = GetRenderText()->selection(); | 581 } else if (!drag_selection_timer_.IsRunning()) { |
| 568 const size_t min = std::min(selection.GetMin(), | 582 drag_selection_timer_.Start( |
| 569 double_click_word_.GetMin()); | 583 FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()), |
| 570 const size_t max = std::max(selection.GetMax(), | 584 this, &Textfield::SelectThroughLastDragLocation); |
| 571 double_click_word_.GetMax()); | |
| 572 const bool reversed = selection.is_reversed(); | |
| 573 selection.set_start(reversed ? max : min); | |
| 574 selection.set_end(reversed ? min : max); | |
| 575 model_->SelectRange(selection); | |
| 576 } | 585 } |
| 577 UpdateAfterChange(false, true); | 586 |
| 578 OnAfterUserAction(); | |
| 579 return true; | 587 return true; |
| 580 } | 588 } |
| 581 | 589 |
| 582 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { | 590 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { |
| 583 OnBeforeUserAction(); | 591 OnBeforeUserAction(); |
| 592 drag_selection_timer_.Stop(); |
| 584 // Cancel suspected drag initiations, the user was clicking in the selection. | 593 // Cancel suspected drag initiations, the user was clicking in the selection. |
| 585 if (initiating_drag_) | 594 if (initiating_drag_) |
| 586 MoveCursorTo(event.location(), false); | 595 MoveCursorTo(event.location(), false); |
| 587 initiating_drag_ = false; | 596 initiating_drag_ = false; |
| 588 UpdateSelectionClipboard(); | 597 UpdateSelectionClipboard(); |
| 589 OnAfterUserAction(); | 598 OnAfterUserAction(); |
| 590 } | 599 } |
| 591 | 600 |
| 592 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { | 601 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { |
| 593 bool handled = controller_ && controller_->HandleKeyEvent(this, event); | 602 bool handled = controller_ && controller_->HandleKeyEvent(this, event); |
| (...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 render_text->DrawCursor(canvas, drop_cursor_position_); | 1544 render_text->DrawCursor(canvas, drop_cursor_position_); |
| 1536 | 1545 |
| 1537 canvas->Restore(); | 1546 canvas->Restore(); |
| 1538 } | 1547 } |
| 1539 | 1548 |
| 1540 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { | 1549 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { |
| 1541 if (model_->MoveCursorTo(point, select)) | 1550 if (model_->MoveCursorTo(point, select)) |
| 1542 UpdateAfterChange(false, true); | 1551 UpdateAfterChange(false, true); |
| 1543 } | 1552 } |
| 1544 | 1553 |
| 1554 void Textfield::SelectThroughLastDragLocation() { |
| 1555 OnBeforeUserAction(); |
| 1556 model_->MoveCursorTo(last_drag_location_, true); |
| 1557 if (aggregated_clicks_ == 1) { |
| 1558 model_->SelectWord(); |
| 1559 // Expand the selection so the initially selected word remains selected. |
| 1560 gfx::Range selection = GetRenderText()->selection(); |
| 1561 const size_t min = std::min(selection.GetMin(), |
| 1562 double_click_word_.GetMin()); |
| 1563 const size_t max = std::max(selection.GetMax(), |
| 1564 double_click_word_.GetMax()); |
| 1565 const bool reversed = selection.is_reversed(); |
| 1566 selection.set_start(reversed ? max : min); |
| 1567 selection.set_end(reversed ? min : max); |
| 1568 model_->SelectRange(selection); |
| 1569 } |
| 1570 UpdateAfterChange(false, true); |
| 1571 OnAfterUserAction(); |
| 1572 } |
| 1573 |
| 1545 void Textfield::OnCaretBoundsChanged() { | 1574 void Textfield::OnCaretBoundsChanged() { |
| 1546 if (GetInputMethod()) | 1575 if (GetInputMethod()) |
| 1547 GetInputMethod()->OnCaretBoundsChanged(this); | 1576 GetInputMethod()->OnCaretBoundsChanged(this); |
| 1548 if (touch_selection_controller_) | 1577 if (touch_selection_controller_) |
| 1549 touch_selection_controller_->SelectionChanged(); | 1578 touch_selection_controller_->SelectionChanged(); |
| 1550 } | 1579 } |
| 1551 | 1580 |
| 1552 void Textfield::OnBeforeUserAction() { | 1581 void Textfield::OnBeforeUserAction() { |
| 1553 DCHECK(!performing_user_action_); | 1582 DCHECK(!performing_user_action_); |
| 1554 performing_user_action_ = true; | 1583 performing_user_action_ = true; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 const size_t length = selection_clipboard_text.length(); | 1710 const size_t length = selection_clipboard_text.length(); |
| 1682 range = gfx::Range(range.start() + length, range.end() + length); | 1711 range = gfx::Range(range.start() + length, range.end() + length); |
| 1683 } | 1712 } |
| 1684 model_->MoveCursorTo(gfx::SelectionModel(range, affinity)); | 1713 model_->MoveCursorTo(gfx::SelectionModel(range, affinity)); |
| 1685 UpdateAfterChange(true, true); | 1714 UpdateAfterChange(true, true); |
| 1686 OnAfterUserAction(); | 1715 OnAfterUserAction(); |
| 1687 } | 1716 } |
| 1688 } | 1717 } |
| 1689 | 1718 |
| 1690 } // namespace views | 1719 } // namespace views |
| OLD | NEW |