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/gfx/render_text.h" | 5 #include "ui/gfx/render_text.h" |
6 | 6 |
7 #include <limits.h> | 7 #include <limits.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <climits> | 10 #include <climits> |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 } | 606 } |
607 } | 607 } |
608 } | 608 } |
609 | 609 |
610 void RenderText::SetCursorPosition(size_t position) { | 610 void RenderText::SetCursorPosition(size_t position) { |
611 MoveCursorTo(position, false); | 611 MoveCursorTo(position, false); |
612 } | 612 } |
613 | 613 |
614 void RenderText::MoveCursor(BreakType break_type, | 614 void RenderText::MoveCursor(BreakType break_type, |
615 VisualCursorDirection direction, | 615 VisualCursorDirection direction, |
616 bool select) { | 616 SelectionBehavior selection_behavior) { |
617 SelectionModel cursor(cursor_position(), selection_model_.caret_affinity()); | 617 SelectionModel cursor(cursor_position(), selection_model_.caret_affinity()); |
618 // Cancelling a selection moves to the edge of the selection. | 618 // Cancelling a selection moves to the edge of the selection. |
619 if (break_type != LINE_BREAK && !selection().is_empty() && !select) { | 619 if (break_type != LINE_BREAK && !selection().is_empty() && |
| 620 selection_behavior == SELECTION_NONE) { |
620 SelectionModel selection_start = GetSelectionModelForSelectionStart(); | 621 SelectionModel selection_start = GetSelectionModelForSelectionStart(); |
621 int start_x = GetCursorBounds(selection_start, true).x(); | 622 int start_x = GetCursorBounds(selection_start, true).x(); |
622 int cursor_x = GetCursorBounds(cursor, true).x(); | 623 int cursor_x = GetCursorBounds(cursor, true).x(); |
623 // Use the selection start if it is left (when |direction| is CURSOR_LEFT) | 624 // Use the selection start if it is left (when |direction| is CURSOR_LEFT) |
624 // or right (when |direction| is CURSOR_RIGHT) of the selection end. | 625 // or right (when |direction| is CURSOR_RIGHT) of the selection end. |
625 if (direction == CURSOR_RIGHT ? start_x > cursor_x : start_x < cursor_x) | 626 if (direction == CURSOR_RIGHT ? start_x > cursor_x : start_x < cursor_x) |
626 cursor = selection_start; | 627 cursor = selection_start; |
627 // Use the nearest word boundary in the proper |direction| for word breaks. | 628 // Use the nearest word boundary in the proper |direction| for word breaks. |
628 if (break_type == WORD_BREAK) | 629 if (break_type == WORD_BREAK) |
629 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); | 630 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); |
630 // Use an adjacent selection model if the cursor is not at a valid position. | 631 // Use an adjacent selection model if the cursor is not at a valid position. |
631 if (!IsValidCursorIndex(cursor.caret_pos())) | 632 if (!IsValidCursorIndex(cursor.caret_pos())) |
632 cursor = GetAdjacentSelectionModel(cursor, CHARACTER_BREAK, direction); | 633 cursor = GetAdjacentSelectionModel(cursor, CHARACTER_BREAK, direction); |
633 } else { | 634 } else { |
634 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); | 635 cursor = GetAdjacentSelectionModel(cursor, break_type, direction); |
635 } | 636 } |
636 if (select) | 637 |
637 cursor.set_selection_start(selection().start()); | 638 // |cursor| corresponds to the tentative end point of the new selection. The |
| 639 // selection direction is reversed iff the current selection is non-empty and |
| 640 // the old selection end point and |cursor| are at the opposite ends of the |
| 641 // old selection start point. |
| 642 uint32_t min_end = std::min(selection().end(), cursor.selection().end()); |
| 643 uint32_t max_end = std::max(selection().end(), cursor.selection().end()); |
| 644 uint32_t current_start = selection().start(); |
| 645 |
| 646 bool selection_reversed = !selection().is_empty() && |
| 647 min_end <= current_start && |
| 648 current_start <= max_end; |
| 649 |
| 650 // Take |selection_behavior| into account. |
| 651 switch (selection_behavior) { |
| 652 case SELECTION_RETAIN: |
| 653 cursor.set_selection_start(current_start); |
| 654 break; |
| 655 case SELECTION_EXTEND: |
| 656 cursor.set_selection_start(selection_reversed ? selection().end() |
| 657 : current_start); |
| 658 break; |
| 659 case SELECTION_CARET: |
| 660 if (selection_reversed) { |
| 661 cursor = |
| 662 SelectionModel(current_start, selection_model_.caret_affinity()); |
| 663 } else { |
| 664 cursor.set_selection_start(current_start); |
| 665 } |
| 666 break; |
| 667 case SELECTION_NONE: |
| 668 // Do nothing. |
| 669 break; |
| 670 } |
| 671 |
638 MoveCursorTo(cursor); | 672 MoveCursorTo(cursor); |
639 } | 673 } |
640 | 674 |
641 bool RenderText::MoveCursorTo(const SelectionModel& model) { | 675 bool RenderText::MoveCursorTo(const SelectionModel& model) { |
642 // Enforce valid selection model components. | 676 // Enforce valid selection model components. |
643 size_t text_length = text().length(); | 677 size_t text_length = text().length(); |
644 Range range(std::min(model.selection().start(), | 678 Range range(std::min(model.selection().start(), |
645 static_cast<uint32_t>(text_length)), | 679 static_cast<uint32_t>(text_length)), |
646 std::min(model.caret_pos(), text_length)); | 680 std::min(model.caret_pos(), text_length)); |
647 // The current model only supports caret positions at valid cursor indices. | 681 // The current model only supports caret positions at valid cursor indices. |
(...skipping 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 | 1621 |
1588 SetDisplayOffset(display_offset_.x() + delta_x); | 1622 SetDisplayOffset(display_offset_.x() + delta_x); |
1589 } | 1623 } |
1590 | 1624 |
1591 void RenderText::DrawSelection(Canvas* canvas) { | 1625 void RenderText::DrawSelection(Canvas* canvas) { |
1592 for (const Rect& s : GetSubstringBounds(selection())) | 1626 for (const Rect& s : GetSubstringBounds(selection())) |
1593 canvas->FillRect(s, selection_background_focused_color_); | 1627 canvas->FillRect(s, selection_background_focused_color_); |
1594 } | 1628 } |
1595 | 1629 |
1596 } // namespace gfx | 1630 } // namespace gfx |
OLD | NEW |