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

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

Issue 7461102: modification to RenderText for inheritance/SelectionModel (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: fix a lint error Created 9 years, 4 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 | Annotate | Revision Log
OLDNEW
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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 render_text_->MoveCursorLeft(break_type, select); 373 render_text_->MoveCursorLeft(break_type, select);
374 } 374 }
375 375
376 void TextfieldViewsModel::MoveCursorRight(gfx::BreakType break_type, 376 void TextfieldViewsModel::MoveCursorRight(gfx::BreakType break_type,
377 bool select) { 377 bool select) {
378 if (HasCompositionText()) 378 if (HasCompositionText())
379 ConfirmCompositionText(); 379 ConfirmCompositionText();
380 render_text_->MoveCursorRight(break_type, select); 380 render_text_->MoveCursorRight(break_type, select);
381 } 381 }
382 382
383 bool TextfieldViewsModel::MoveCursorTo(size_t pos, bool select) { 383 bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& selection) {
384 if (HasCompositionText()) 384 if (HasCompositionText()) {
385 ConfirmCompositionText(); 385 ConfirmCompositionText();
386 return render_text_->MoveCursorTo(pos, select); 386 // ConfirmCompositionText() updates cursor position. Need to reflect it in
387 // the SelectionModel parameter of MoveCursorTo().
388 gfx::SelectionModel sel(selection);
389 sel.set_selection_start(render_text_->GetSelectionStart());
390 return render_text_->MoveCursorTo(sel);
391 }
392 return render_text_->MoveCursorTo(selection);
387 } 393 }
388 394
389 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) { 395 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) {
390 if (HasCompositionText()) 396 if (HasCompositionText())
391 ConfirmCompositionText(); 397 ConfirmCompositionText();
392 return render_text_->MoveCursorTo(point, select); 398 return render_text_->MoveCursorTo(point, select);
393 } 399 }
394 400
395 std::vector<gfx::Rect> TextfieldViewsModel::GetSelectionBounds() const { 401 std::vector<gfx::Rect> TextfieldViewsModel::GetSelectionBounds() const {
396 return render_text_->GetSubstringBounds(render_text_->GetSelection()); 402 return render_text_->GetSubstringBounds(render_text_->GetSelectionStart(),
403 render_text_->GetCursorPosition());
397 } 404 }
398 405
399 string16 TextfieldViewsModel::GetSelectedText() const { 406 string16 TextfieldViewsModel::GetSelectedText() const {
400 ui::Range selection = render_text_->GetSelection(); 407 return GetText().substr(render_text_->MinOfSelection(),
401 return GetText().substr(selection.GetMin(), selection.length()); 408 std::abs(static_cast<long>(render_text_->GetCursorPosition() -
msw 2011/08/03 19:46:39 It just occurred to me, can't we safely use MaxOfS
xji 2011/08/03 22:40:32 Done.
409 render_text_->GetSelectionStart())));
402 } 410 }
403 411
404 void TextfieldViewsModel::GetSelectedRange(ui::Range* range) const { 412 void TextfieldViewsModel::GetSelectedRange(ui::Range* range) const {
405 *range = render_text_->GetSelection(); 413 range->set_start(render_text_->GetSelectionStart());
414 range->set_end(render_text_->GetCursorPosition());
406 } 415 }
407 416
408 void TextfieldViewsModel::SelectRange(const ui::Range& range) { 417 void TextfieldViewsModel::SelectRange(const ui::Range& range) {
409 if (HasCompositionText()) 418 if (HasCompositionText())
410 ConfirmCompositionText(); 419 ConfirmCompositionText();
411 render_text_->SetSelection(range); 420 gfx::SelectionModel selection(range.start(), range.end(),
421 range.end(), gfx::SelectionModel::PREVIOUS_GRAPHEME_TRAILING);
422 render_text_->SetSelectionModel(selection);
msw 2011/08/03 19:46:39 call TextfieldViewsModel::SelectSelectionModel ins
xji 2011/08/03 22:40:32 Done.
423 }
424
425 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) {
426 if (HasCompositionText())
427 ConfirmCompositionText();
428 render_text_->SetSelectionModel(sel);
412 } 429 }
413 430
414 void TextfieldViewsModel::SelectAll() { 431 void TextfieldViewsModel::SelectAll() {
415 if (HasCompositionText()) 432 if (HasCompositionText())
416 ConfirmCompositionText(); 433 ConfirmCompositionText();
417 render_text_->SelectAll(); 434 render_text_->SelectAll();
418 } 435 }
419 436
420 void TextfieldViewsModel::SelectWord() { 437 void TextfieldViewsModel::SelectWord() {
421 if (HasCompositionText()) 438 if (HasCompositionText())
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 502
486 bool TextfieldViewsModel::Cut() { 503 bool TextfieldViewsModel::Cut() {
487 if (!HasCompositionText() && HasSelection()) { 504 if (!HasCompositionText() && HasSelection()) {
488 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate 505 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate
489 ->GetClipboard()).WriteText(GetSelectedText()); 506 ->GetClipboard()).WriteText(GetSelectedText());
490 // A trick to let undo/redo handle cursor correctly. 507 // A trick to let undo/redo handle cursor correctly.
491 // Undoing CUT moves the cursor to the end of the change rather 508 // Undoing CUT moves the cursor to the end of the change rather
492 // than beginning, unlike Delete/Backspace. 509 // than beginning, unlike Delete/Backspace.
493 // TODO(oshima): Change Delete/Backspace to use DeleteSelection, 510 // TODO(oshima): Change Delete/Backspace to use DeleteSelection,
494 // update DeleteEdit and remove this trick. 511 // update DeleteEdit and remove this trick.
495 ui::Range selection = render_text_->GetSelection(); 512 gfx::SelectionModel sel(render_text_->GetCursorPosition(),
496 render_text_->SetSelection(ui::Range(selection.end(), selection.start())); 513 render_text_->GetSelectionStart(),
514 render_text_->GetSelectionStart(),
515 gfx::SelectionModel::LEADING);
516 render_text_->SetSelectionModel(sel);
497 DeleteSelection(); 517 DeleteSelection();
498 return true; 518 return true;
499 } 519 }
500 return false; 520 return false;
501 } 521 }
502 522
503 void TextfieldViewsModel::Copy() { 523 void TextfieldViewsModel::Copy() {
504 if (!HasCompositionText() && HasSelection()) { 524 if (!HasCompositionText() && HasSelection()) {
505 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate 525 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate
506 ->GetClipboard()).WriteText(GetSelectedText()); 526 ->GetClipboard()).WriteText(GetSelectedText());
507 } 527 }
508 } 528 }
509 529
510 bool TextfieldViewsModel::Paste() { 530 bool TextfieldViewsModel::Paste() {
511 string16 result; 531 string16 result;
512 views::ViewsDelegate::views_delegate->GetClipboard() 532 views::ViewsDelegate::views_delegate->GetClipboard()
513 ->ReadText(ui::Clipboard::BUFFER_STANDARD, &result); 533 ->ReadText(ui::Clipboard::BUFFER_STANDARD, &result);
514 if (!result.empty()) { 534 if (!result.empty()) {
515 InsertTextInternal(result, false); 535 InsertTextInternal(result, false);
516 return true; 536 return true;
517 } 537 }
518 return false; 538 return false;
519 } 539 }
520 540
521 bool TextfieldViewsModel::HasSelection() const { 541 bool TextfieldViewsModel::HasSelection() const {
522 return !render_text_->GetSelection().is_empty(); 542 return !render_text_->EmptySelection();
523 } 543 }
524 544
525 void TextfieldViewsModel::DeleteSelection() { 545 void TextfieldViewsModel::DeleteSelection() {
526 DCHECK(!HasCompositionText()); 546 DCHECK(!HasCompositionText());
527 DCHECK(HasSelection()); 547 DCHECK(HasSelection());
528 ui::Range selection = render_text_->GetSelection(); 548 ExecuteAndRecordDelete(render_text_->GetSelectionStart(),
529 ExecuteAndRecordDelete(selection.start(), selection.end(), false); 549 render_text_->GetCursorPosition(), false);
530 } 550 }
531 551
532 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt( 552 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt(
533 const string16& text, size_t position) { 553 const string16& text, size_t position) {
534 if (HasCompositionText()) 554 if (HasCompositionText())
535 CancelCompositionText(); 555 CancelCompositionText();
536 ExecuteAndRecordReplace(DO_NOT_MERGE, 556 ExecuteAndRecordReplace(DO_NOT_MERGE,
537 GetCursorPosition(), 557 GetCursorPosition(),
538 position + text.length(), 558 position + text.length(),
539 text, 559 text,
(...skipping 20 matching lines...) Expand all
560 if (composition.text.empty()) 580 if (composition.text.empty())
561 return; 581 return;
562 582
563 size_t cursor = GetCursorPosition(); 583 size_t cursor = GetCursorPosition();
564 string16 new_text = GetText(); 584 string16 new_text = GetText();
565 render_text_->SetText(new_text.insert(cursor, composition.text)); 585 render_text_->SetText(new_text.insert(cursor, composition.text));
566 ui::Range range(cursor, cursor + composition.text.length()); 586 ui::Range range(cursor, cursor + composition.text.length());
567 render_text_->SetCompositionRange(range); 587 render_text_->SetCompositionRange(range);
568 // TODO(msw): Support multiple composition underline ranges. 588 // TODO(msw): Support multiple composition underline ranges.
569 589
570 if (composition.selection.IsValid()) 590 if (composition.selection.IsValid()) {
571 render_text_->SetSelection(ui::Range( 591 size_t start = std::min(range.start() + composition.selection.start(),
572 std::min(range.start() + composition.selection.start(), range.end()), 592 range.end());
573 std::min(range.start() + composition.selection.end(), range.end()))); 593 size_t end = std::min(range.start() + composition.selection.end(),
574 else 594 range.end());
595 gfx::SelectionModel sel(start, end, end,
596 gfx::SelectionModel::PREVIOUS_GRAPHEME_TRAILING);
597 render_text_->SetSelectionModel(sel);
598 } else {
575 render_text_->SetCursorPosition(range.end()); 599 render_text_->SetCursorPosition(range.end());
600 }
576 } 601 }
577 602
578 void TextfieldViewsModel::ConfirmCompositionText() { 603 void TextfieldViewsModel::ConfirmCompositionText() {
579 DCHECK(HasCompositionText()); 604 DCHECK(HasCompositionText());
580 ui::Range range = render_text_->GetCompositionRange(); 605 ui::Range range = render_text_->GetCompositionRange();
581 string16 text = GetText().substr(range.start(), range.length()); 606 string16 text = GetText().substr(range.start(), range.length());
582 // TODO(oshima): current behavior on ChromeOS is a bit weird and not 607 // TODO(oshima): current behavior on ChromeOS is a bit weird and not
583 // sure exactly how this should work. Find out and fix if necessary. 608 // sure exactly how this should work. Find out and fix if necessary.
584 AddOrMergeEditHistory(new InsertEdit(false, text, range.start())); 609 AddOrMergeEditHistory(new InsertEdit(false, text, range.start()));
585 render_text_->SetCursorPosition(range.end()); 610 render_text_->SetCursorPosition(range.end());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 ExecuteAndRecordInsert(text, mergeable); 658 ExecuteAndRecordInsert(text, mergeable);
634 } 659 }
635 } 660 }
636 661
637 void TextfieldViewsModel::ReplaceTextInternal(const string16& text, 662 void TextfieldViewsModel::ReplaceTextInternal(const string16& text,
638 bool mergeable) { 663 bool mergeable) {
639 if (HasCompositionText()) { 664 if (HasCompositionText()) {
640 CancelCompositionText(); 665 CancelCompositionText();
641 } else if (!HasSelection()) { 666 } else if (!HasSelection()) {
642 size_t cursor = GetCursorPosition(); 667 size_t cursor = GetCursorPosition();
643 render_text_->SetSelection(ui::Range(cursor + text.length(), cursor)); 668 gfx::SelectionModel sel(render_text_->selection_model());
669 sel.set_selection_start(cursor + text.length());
670 render_text_->SetSelectionModel(sel);
644 } 671 }
645 // Edit history is recorded in InsertText. 672 // Edit history is recorded in InsertText.
646 InsertTextInternal(text, mergeable); 673 InsertTextInternal(text, mergeable);
647 } 674 }
648 675
649 void TextfieldViewsModel::ClearEditHistory() { 676 void TextfieldViewsModel::ClearEditHistory() {
650 STLDeleteContainerPointers(edit_history_.begin(), 677 STLDeleteContainerPointers(edit_history_.begin(),
651 edit_history_.end()); 678 edit_history_.end());
652 edit_history_.clear(); 679 edit_history_.clear();
653 current_edit_ = edit_history_.end(); 680 current_edit_ = edit_history_.end();
(...skipping 10 matching lines...) Expand all
664 delete_start++; 691 delete_start++;
665 STLDeleteContainerPointers(delete_start, edit_history_.end()); 692 STLDeleteContainerPointers(delete_start, edit_history_.end());
666 edit_history_.erase(delete_start, edit_history_.end()); 693 edit_history_.erase(delete_start, edit_history_.end());
667 } 694 }
668 695
669 void TextfieldViewsModel::ExecuteAndRecordDelete(size_t from, 696 void TextfieldViewsModel::ExecuteAndRecordDelete(size_t from,
670 size_t to, 697 size_t to,
671 bool mergeable) { 698 bool mergeable) {
672 size_t old_text_start = std::min(from, to); 699 size_t old_text_start = std::min(from, to);
673 const string16 text = GetText().substr(old_text_start, 700 const string16 text = GetText().substr(old_text_start,
674 std::abs(static_cast<long>(from - to))); 701 std::abs(static_cast<long>(from - to)));
675 bool backward = from > to; 702 bool backward = from > to;
676 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward); 703 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward);
677 bool delete_edit = AddOrMergeEditHistory(edit); 704 bool delete_edit = AddOrMergeEditHistory(edit);
678 edit->Redo(this); 705 edit->Redo(this);
679 if (delete_edit) 706 if (delete_edit)
680 delete edit; 707 delete edit;
681 } 708 }
682 709
683 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection( 710 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection(
684 MergeType merge_type, const string16& new_text) { 711 MergeType merge_type, const string16& new_text) {
685 size_t new_text_start = render_text_->GetSelection().GetMin(); 712 size_t new_text_start = render_text_->MinOfSelection();
686 size_t new_cursor_pos = new_text_start + new_text.length(); 713 size_t new_cursor_pos = new_text_start + new_text.length();
687 ExecuteAndRecordReplace(merge_type, 714 ExecuteAndRecordReplace(merge_type,
688 GetCursorPosition(), 715 GetCursorPosition(),
689 new_cursor_pos, 716 new_cursor_pos,
690 new_text, 717 new_text,
691 new_text_start); 718 new_text_start);
692 } 719 }
693 720
694 void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type, 721 void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type,
695 size_t old_cursor_pos, 722 size_t old_cursor_pos,
696 size_t new_cursor_pos, 723 size_t new_cursor_pos,
697 const string16& new_text, 724 const string16& new_text,
698 size_t new_text_start) { 725 size_t new_text_start) {
699 size_t old_text_start = render_text_->GetSelection().GetMin(); 726 size_t old_text_start = render_text_->MinOfSelection();
700 bool backward = render_text_->GetSelection().is_reversed(); 727 bool backward = render_text_->GetSelectionStart() >
728 render_text_->GetCursorPosition();
701 Edit* edit = new ReplaceEdit(merge_type, 729 Edit* edit = new ReplaceEdit(merge_type,
702 GetSelectedText(), 730 GetSelectedText(),
703 old_cursor_pos, 731 old_cursor_pos,
704 old_text_start, 732 old_text_start,
705 backward, 733 backward,
706 new_cursor_pos, 734 new_cursor_pos,
707 new_text, 735 new_text,
708 new_text_start); 736 new_text_start);
709 bool delete_edit = AddOrMergeEditHistory(edit); 737 bool delete_edit = AddOrMergeEditHistory(edit);
710 edit->Redo(this); 738 edit->Redo(this);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 if (delete_from != delete_to) 780 if (delete_from != delete_to)
753 render_text_->SetText(text.erase(delete_from, delete_to - delete_from)); 781 render_text_->SetText(text.erase(delete_from, delete_to - delete_from));
754 if (!new_text.empty()) 782 if (!new_text.empty())
755 render_text_->SetText(text.insert(new_text_insert_at, new_text)); 783 render_text_->SetText(text.insert(new_text_insert_at, new_text));
756 render_text_->SetCursorPosition(new_cursor_pos); 784 render_text_->SetCursorPosition(new_cursor_pos);
757 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't). 785 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't).
758 // This looks fine feature and we may want to do the same. 786 // This looks fine feature and we may want to do the same.
759 } 787 }
760 788
761 } // namespace views 789 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698