| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "views/controls/textfield/textfield_views_model.h" | 5 #include "views/controls/textfield/textfield_views_model.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/i18n/break_iterator.h" | 9 #include "base/i18n/break_iterator.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 if (HasCompositionText()) | 383 if (HasCompositionText()) |
| 384 ConfirmCompositionText(); | 384 ConfirmCompositionText(); |
| 385 render_text_->MoveCursorRight(break_type, select); | 385 render_text_->MoveCursorRight(break_type, select); |
| 386 } | 386 } |
| 387 | 387 |
| 388 bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& selection) { | 388 bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& selection) { |
| 389 if (HasCompositionText()) { | 389 if (HasCompositionText()) { |
| 390 ConfirmCompositionText(); | 390 ConfirmCompositionText(); |
| 391 // ConfirmCompositionText() updates cursor position. Need to reflect it in | 391 // ConfirmCompositionText() updates cursor position. Need to reflect it in |
| 392 // the SelectionModel parameter of MoveCursorTo(). | 392 // the SelectionModel parameter of MoveCursorTo(). |
| 393 gfx::SelectionModel sel(selection); | 393 gfx::SelectionModel sel(render_text_->GetSelectionStart(), |
| 394 sel.set_selection_start(render_text_->GetSelectionStart()); | 394 selection.selection_end(), |
| 395 selection.caret_pos(), |
| 396 selection.caret_placement()); |
| 395 return render_text_->MoveCursorTo(sel); | 397 return render_text_->MoveCursorTo(sel); |
| 396 } | 398 } |
| 397 return render_text_->MoveCursorTo(selection); | 399 return render_text_->MoveCursorTo(selection); |
| 398 } | 400 } |
| 399 | 401 |
| 400 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) { | 402 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) { |
| 401 if (HasCompositionText()) | 403 if (HasCompositionText()) |
| 402 ConfirmCompositionText(); | 404 ConfirmCompositionText(); |
| 403 return render_text_->MoveCursorTo(point, select); | 405 return render_text_->MoveCursorTo(point, select); |
| 404 } | 406 } |
| 405 | 407 |
| 406 string16 TextfieldViewsModel::GetSelectedText() const { | 408 string16 TextfieldViewsModel::GetSelectedText() const { |
| 407 return GetText().substr(render_text_->MinOfSelection(), | 409 return GetText().substr(render_text_->MinOfSelection(), |
| 408 (render_text_->MaxOfSelection() - render_text_->MinOfSelection())); | 410 (render_text_->MaxOfSelection() - render_text_->MinOfSelection())); |
| 409 } | 411 } |
| 410 | 412 |
| 413 void TextfieldViewsModel::GetSelectedRange(ui::Range* range) const { |
| 414 range->set_start(render_text_->GetSelectionStart()); |
| 415 range->set_end(render_text_->GetCursorPosition()); |
| 416 } |
| 417 |
| 418 void TextfieldViewsModel::SelectRange(const ui::Range& range) { |
| 419 if (HasCompositionText()) |
| 420 ConfirmCompositionText(); |
| 421 render_text_->SelectRange(range); |
| 422 } |
| 423 |
| 411 void TextfieldViewsModel::GetSelectionModel(gfx::SelectionModel* sel) const { | 424 void TextfieldViewsModel::GetSelectionModel(gfx::SelectionModel* sel) const { |
| 412 *sel = render_text_->selection_model(); | 425 *sel = render_text_->selection_model(); |
| 413 } | 426 } |
| 414 | 427 |
| 415 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) { | 428 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) { |
| 416 if (HasCompositionText()) | 429 if (HasCompositionText()) |
| 417 ConfirmCompositionText(); | 430 ConfirmCompositionText(); |
| 418 render_text_->MoveCursorTo(sel); | 431 render_text_->MoveCursorTo(sel); |
| 419 } | 432 } |
| 420 | 433 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 | 505 |
| 493 bool TextfieldViewsModel::Cut() { | 506 bool TextfieldViewsModel::Cut() { |
| 494 if (!HasCompositionText() && HasSelection()) { | 507 if (!HasCompositionText() && HasSelection()) { |
| 495 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate | 508 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate |
| 496 ->GetClipboard()).WriteText(GetSelectedText()); | 509 ->GetClipboard()).WriteText(GetSelectedText()); |
| 497 // A trick to let undo/redo handle cursor correctly. | 510 // A trick to let undo/redo handle cursor correctly. |
| 498 // Undoing CUT moves the cursor to the end of the change rather | 511 // Undoing CUT moves the cursor to the end of the change rather |
| 499 // than beginning, unlike Delete/Backspace. | 512 // than beginning, unlike Delete/Backspace. |
| 500 // TODO(oshima): Change Delete/Backspace to use DeleteSelection, | 513 // TODO(oshima): Change Delete/Backspace to use DeleteSelection, |
| 501 // update DeleteEdit and remove this trick. | 514 // update DeleteEdit and remove this trick. |
| 502 gfx::SelectionModel sel(render_text_->GetCursorPosition(), | 515 render_text_->SelectRange(ui::Range(render_text_->GetCursorPosition(), |
| 503 render_text_->GetSelectionStart(), | 516 render_text_->GetSelectionStart())); |
| 504 render_text_->GetSelectionStart(), | |
| 505 gfx::SelectionModel::LEADING); | |
| 506 render_text_->MoveCursorTo(sel); | |
| 507 DeleteSelection(); | 517 DeleteSelection(); |
| 508 return true; | 518 return true; |
| 509 } | 519 } |
| 510 return false; | 520 return false; |
| 511 } | 521 } |
| 512 | 522 |
| 513 void TextfieldViewsModel::Copy() { | 523 void TextfieldViewsModel::Copy() { |
| 514 if (!HasCompositionText() && HasSelection()) { | 524 if (!HasCompositionText() && HasSelection()) { |
| 515 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate | 525 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate |
| 516 ->GetClipboard()).WriteText(GetSelectedText()); | 526 ->GetClipboard()).WriteText(GetSelectedText()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 render_text_->SetText(new_text.insert(cursor, composition.text)); | 585 render_text_->SetText(new_text.insert(cursor, composition.text)); |
| 576 ui::Range range(cursor, cursor + composition.text.length()); | 586 ui::Range range(cursor, cursor + composition.text.length()); |
| 577 render_text_->SetCompositionRange(range); | 587 render_text_->SetCompositionRange(range); |
| 578 // TODO(msw): Support multiple composition underline ranges. | 588 // TODO(msw): Support multiple composition underline ranges. |
| 579 | 589 |
| 580 if (composition.selection.IsValid()) { | 590 if (composition.selection.IsValid()) { |
| 581 size_t start = | 591 size_t start = |
| 582 std::min(range.start() + composition.selection.start(), range.end()); | 592 std::min(range.start() + composition.selection.start(), range.end()); |
| 583 size_t end = | 593 size_t end = |
| 584 std::min(range.start() + composition.selection.end(), range.end()); | 594 std::min(range.start() + composition.selection.end(), range.end()); |
| 585 gfx::SelectionModel sel(start, end); | 595 render_text_->SelectRange(ui::Range(start, end)); |
| 586 render_text_->MoveCursorTo(sel); | |
| 587 } else { | 596 } else { |
| 588 render_text_->SetCursorPosition(range.end()); | 597 render_text_->SetCursorPosition(range.end()); |
| 589 } | 598 } |
| 590 } | 599 } |
| 591 | 600 |
| 592 void TextfieldViewsModel::ConfirmCompositionText() { | 601 void TextfieldViewsModel::ConfirmCompositionText() { |
| 593 DCHECK(HasCompositionText()); | 602 DCHECK(HasCompositionText()); |
| 594 ui::Range range = render_text_->GetCompositionRange(); | 603 ui::Range range = render_text_->GetCompositionRange(); |
| 595 string16 text = GetText().substr(range.start(), range.length()); | 604 string16 text = GetText().substr(range.start(), range.length()); |
| 596 // TODO(oshima): current behavior on ChromeOS is a bit weird and not | 605 // TODO(oshima): current behavior on ChromeOS is a bit weird and not |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 ExecuteAndRecordInsert(text, mergeable); | 656 ExecuteAndRecordInsert(text, mergeable); |
| 648 } | 657 } |
| 649 } | 658 } |
| 650 | 659 |
| 651 void TextfieldViewsModel::ReplaceTextInternal(const string16& text, | 660 void TextfieldViewsModel::ReplaceTextInternal(const string16& text, |
| 652 bool mergeable) { | 661 bool mergeable) { |
| 653 if (HasCompositionText()) { | 662 if (HasCompositionText()) { |
| 654 CancelCompositionText(); | 663 CancelCompositionText(); |
| 655 } else if (!HasSelection()) { | 664 } else if (!HasSelection()) { |
| 656 size_t cursor = GetCursorPosition(); | 665 size_t cursor = GetCursorPosition(); |
| 657 gfx::SelectionModel sel(render_text_->selection_model()); | 666 const gfx::SelectionModel& model = render_text_->selection_model(); |
| 658 sel.set_selection_start(render_text_->GetIndexOfNextGrapheme(cursor)); | 667 gfx::SelectionModel sel(render_text_->GetIndexOfNextGrapheme(cursor), |
| 668 model.selection_end(), |
| 669 model.caret_pos(), |
| 670 model.caret_placement()); |
| 659 render_text_->MoveCursorTo(sel); | 671 render_text_->MoveCursorTo(sel); |
| 660 } | 672 } |
| 661 // Edit history is recorded in InsertText. | 673 // Edit history is recorded in InsertText. |
| 662 InsertTextInternal(text, mergeable); | 674 InsertTextInternal(text, mergeable); |
| 663 } | 675 } |
| 664 | 676 |
| 665 void TextfieldViewsModel::ClearEditHistory() { | 677 void TextfieldViewsModel::ClearEditHistory() { |
| 666 STLDeleteContainerPointers(edit_history_.begin(), | 678 STLDeleteContainerPointers(edit_history_.begin(), |
| 667 edit_history_.end()); | 679 edit_history_.end()); |
| 668 edit_history_.clear(); | 680 edit_history_.clear(); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 if (delete_from != delete_to) | 782 if (delete_from != delete_to) |
| 771 render_text_->SetText(text.erase(delete_from, delete_to - delete_from)); | 783 render_text_->SetText(text.erase(delete_from, delete_to - delete_from)); |
| 772 if (!new_text.empty()) | 784 if (!new_text.empty()) |
| 773 render_text_->SetText(text.insert(new_text_insert_at, new_text)); | 785 render_text_->SetText(text.insert(new_text_insert_at, new_text)); |
| 774 render_text_->SetCursorPosition(new_cursor_pos); | 786 render_text_->SetCursorPosition(new_cursor_pos); |
| 775 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't). | 787 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't). |
| 776 // This looks fine feature and we may want to do the same. | 788 // This looks fine feature and we may want to do the same. |
| 777 } | 789 } |
| 778 | 790 |
| 779 } // namespace views | 791 } // namespace views |
| OLD | NEW |