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

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: '' 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 (render_text_->MaxOfSelection() - render_text_->MinOfSelection()));
402 } 409 }
403 410
404 void TextfieldViewsModel::GetSelectedRange(ui::Range* range) const { 411 void TextfieldViewsModel::GetSelectedRange(ui::Range* range) const {
405 *range = render_text_->GetSelection(); 412 range->set_start(render_text_->GetSelectionStart());
413 range->set_end(render_text_->GetCursorPosition());
406 } 414 }
407 415
408 void TextfieldViewsModel::SelectRange(const ui::Range& range) { 416 void TextfieldViewsModel::SelectRange(const ui::Range& range) {
417 gfx::SelectionModel selection(range.start(), range.end(),
418 range.end(), gfx::SelectionModel::PREVIOUS_GRAPHEME_TRAILING);
419 SelectSelectionModel(selection);
420 }
421
422 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) {
409 if (HasCompositionText()) 423 if (HasCompositionText())
410 ConfirmCompositionText(); 424 ConfirmCompositionText();
411 render_text_->SetSelection(range); 425 render_text_->SetSelectionModel(sel);
412 } 426 }
413 427
414 void TextfieldViewsModel::SelectAll() { 428 void TextfieldViewsModel::SelectAll() {
415 if (HasCompositionText()) 429 if (HasCompositionText())
416 ConfirmCompositionText(); 430 ConfirmCompositionText();
417 render_text_->SelectAll(); 431 render_text_->SelectAll();
418 } 432 }
419 433
420 void TextfieldViewsModel::SelectWord() { 434 void TextfieldViewsModel::SelectWord() {
421 if (HasCompositionText()) 435 if (HasCompositionText())
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 499
486 bool TextfieldViewsModel::Cut() { 500 bool TextfieldViewsModel::Cut() {
487 if (!HasCompositionText() && HasSelection()) { 501 if (!HasCompositionText() && HasSelection()) {
488 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate 502 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate
489 ->GetClipboard()).WriteText(GetSelectedText()); 503 ->GetClipboard()).WriteText(GetSelectedText());
490 // A trick to let undo/redo handle cursor correctly. 504 // A trick to let undo/redo handle cursor correctly.
491 // Undoing CUT moves the cursor to the end of the change rather 505 // Undoing CUT moves the cursor to the end of the change rather
492 // than beginning, unlike Delete/Backspace. 506 // than beginning, unlike Delete/Backspace.
493 // TODO(oshima): Change Delete/Backspace to use DeleteSelection, 507 // TODO(oshima): Change Delete/Backspace to use DeleteSelection,
494 // update DeleteEdit and remove this trick. 508 // update DeleteEdit and remove this trick.
495 ui::Range selection = render_text_->GetSelection(); 509 gfx::SelectionModel sel(render_text_->GetCursorPosition(),
496 render_text_->SetSelection(ui::Range(selection.end(), selection.start())); 510 render_text_->GetSelectionStart(),
511 render_text_->GetSelectionStart(),
512 gfx::SelectionModel::LEADING);
513 render_text_->SetSelectionModel(sel);
497 DeleteSelection(); 514 DeleteSelection();
498 return true; 515 return true;
499 } 516 }
500 return false; 517 return false;
501 } 518 }
502 519
503 void TextfieldViewsModel::Copy() { 520 void TextfieldViewsModel::Copy() {
504 if (!HasCompositionText() && HasSelection()) { 521 if (!HasCompositionText() && HasSelection()) {
505 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate 522 ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate
506 ->GetClipboard()).WriteText(GetSelectedText()); 523 ->GetClipboard()).WriteText(GetSelectedText());
507 } 524 }
508 } 525 }
509 526
510 bool TextfieldViewsModel::Paste() { 527 bool TextfieldViewsModel::Paste() {
511 string16 result; 528 string16 result;
512 views::ViewsDelegate::views_delegate->GetClipboard() 529 views::ViewsDelegate::views_delegate->GetClipboard()
513 ->ReadText(ui::Clipboard::BUFFER_STANDARD, &result); 530 ->ReadText(ui::Clipboard::BUFFER_STANDARD, &result);
514 if (!result.empty()) { 531 if (!result.empty()) {
515 InsertTextInternal(result, false); 532 InsertTextInternal(result, false);
516 return true; 533 return true;
517 } 534 }
518 return false; 535 return false;
519 } 536 }
520 537
521 bool TextfieldViewsModel::HasSelection() const { 538 bool TextfieldViewsModel::HasSelection() const {
522 return !render_text_->GetSelection().is_empty(); 539 return !render_text_->EmptySelection();
523 } 540 }
524 541
525 void TextfieldViewsModel::DeleteSelection() { 542 void TextfieldViewsModel::DeleteSelection() {
526 DCHECK(!HasCompositionText()); 543 DCHECK(!HasCompositionText());
527 DCHECK(HasSelection()); 544 DCHECK(HasSelection());
528 ui::Range selection = render_text_->GetSelection(); 545 ExecuteAndRecordDelete(render_text_->GetSelectionStart(),
529 ExecuteAndRecordDelete(selection.start(), selection.end(), false); 546 render_text_->GetCursorPosition(), false);
530 } 547 }
531 548
532 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt( 549 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt(
533 const string16& text, size_t position) { 550 const string16& text, size_t position) {
534 if (HasCompositionText()) 551 if (HasCompositionText())
535 CancelCompositionText(); 552 CancelCompositionText();
536 ExecuteAndRecordReplace(DO_NOT_MERGE, 553 ExecuteAndRecordReplace(DO_NOT_MERGE,
537 GetCursorPosition(), 554 GetCursorPosition(),
538 position + text.length(), 555 position + text.length(),
539 text, 556 text,
(...skipping 20 matching lines...) Expand all
560 if (composition.text.empty()) 577 if (composition.text.empty())
561 return; 578 return;
562 579
563 size_t cursor = GetCursorPosition(); 580 size_t cursor = GetCursorPosition();
564 string16 new_text = GetText(); 581 string16 new_text = GetText();
565 render_text_->SetText(new_text.insert(cursor, composition.text)); 582 render_text_->SetText(new_text.insert(cursor, composition.text));
566 ui::Range range(cursor, cursor + composition.text.length()); 583 ui::Range range(cursor, cursor + composition.text.length());
567 render_text_->SetCompositionRange(range); 584 render_text_->SetCompositionRange(range);
568 // TODO(msw): Support multiple composition underline ranges. 585 // TODO(msw): Support multiple composition underline ranges.
569 586
570 if (composition.selection.IsValid()) 587 if (composition.selection.IsValid()) {
571 render_text_->SetSelection(ui::Range( 588 size_t start = std::min(range.start() + composition.selection.start(),
572 std::min(range.start() + composition.selection.start(), range.end()), 589 range.end());
msw 2011/08/03 23:44:38 Move everything after the assignment operator onto
xji 2011/08/04 06:26:50 Done.
573 std::min(range.start() + composition.selection.end(), range.end()))); 590 size_t end = std::min(range.start() + composition.selection.end(),
574 else 591 range.end());
msw 2011/08/03 23:44:38 ditto on the line split here.
xji 2011/08/04 06:26:50 Done.
592 gfx::SelectionModel sel(start, end, end,
593 gfx::SelectionModel::PREVIOUS_GRAPHEME_TRAILING);
594 render_text_->SetSelectionModel(sel);
595 } else {
575 render_text_->SetCursorPosition(range.end()); 596 render_text_->SetCursorPosition(range.end());
597 }
576 } 598 }
577 599
578 void TextfieldViewsModel::ConfirmCompositionText() { 600 void TextfieldViewsModel::ConfirmCompositionText() {
579 DCHECK(HasCompositionText()); 601 DCHECK(HasCompositionText());
580 ui::Range range = render_text_->GetCompositionRange(); 602 ui::Range range = render_text_->GetCompositionRange();
581 string16 text = GetText().substr(range.start(), range.length()); 603 string16 text = GetText().substr(range.start(), range.length());
582 // TODO(oshima): current behavior on ChromeOS is a bit weird and not 604 // 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. 605 // sure exactly how this should work. Find out and fix if necessary.
584 AddOrMergeEditHistory(new InsertEdit(false, text, range.start())); 606 AddOrMergeEditHistory(new InsertEdit(false, text, range.start()));
585 render_text_->SetCursorPosition(range.end()); 607 render_text_->SetCursorPosition(range.end());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 ExecuteAndRecordInsert(text, mergeable); 655 ExecuteAndRecordInsert(text, mergeable);
634 } 656 }
635 } 657 }
636 658
637 void TextfieldViewsModel::ReplaceTextInternal(const string16& text, 659 void TextfieldViewsModel::ReplaceTextInternal(const string16& text,
638 bool mergeable) { 660 bool mergeable) {
639 if (HasCompositionText()) { 661 if (HasCompositionText()) {
640 CancelCompositionText(); 662 CancelCompositionText();
641 } else if (!HasSelection()) { 663 } else if (!HasSelection()) {
642 size_t cursor = GetCursorPosition(); 664 size_t cursor = GetCursorPosition();
643 render_text_->SetSelection(ui::Range(cursor + text.length(), cursor)); 665 gfx::SelectionModel sel(render_text_->selection_model());
666 sel.set_selection_start(cursor + text.length());
667 render_text_->SetSelectionModel(sel);
644 } 668 }
645 // Edit history is recorded in InsertText. 669 // Edit history is recorded in InsertText.
646 InsertTextInternal(text, mergeable); 670 InsertTextInternal(text, mergeable);
647 } 671 }
648 672
649 void TextfieldViewsModel::ClearEditHistory() { 673 void TextfieldViewsModel::ClearEditHistory() {
650 STLDeleteContainerPointers(edit_history_.begin(), 674 STLDeleteContainerPointers(edit_history_.begin(),
651 edit_history_.end()); 675 edit_history_.end());
652 edit_history_.clear(); 676 edit_history_.clear();
653 current_edit_ = edit_history_.end(); 677 current_edit_ = edit_history_.end();
(...skipping 10 matching lines...) Expand all
664 delete_start++; 688 delete_start++;
665 STLDeleteContainerPointers(delete_start, edit_history_.end()); 689 STLDeleteContainerPointers(delete_start, edit_history_.end());
666 edit_history_.erase(delete_start, edit_history_.end()); 690 edit_history_.erase(delete_start, edit_history_.end());
667 } 691 }
668 692
669 void TextfieldViewsModel::ExecuteAndRecordDelete(size_t from, 693 void TextfieldViewsModel::ExecuteAndRecordDelete(size_t from,
670 size_t to, 694 size_t to,
671 bool mergeable) { 695 bool mergeable) {
672 size_t old_text_start = std::min(from, to); 696 size_t old_text_start = std::min(from, to);
673 const string16 text = GetText().substr(old_text_start, 697 const string16 text = GetText().substr(old_text_start,
674 std::abs(static_cast<long>(from - to))); 698 std::abs(static_cast<long>(from - to)));
675 bool backward = from > to; 699 bool backward = from > to;
676 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward); 700 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward);
677 bool delete_edit = AddOrMergeEditHistory(edit); 701 bool delete_edit = AddOrMergeEditHistory(edit);
678 edit->Redo(this); 702 edit->Redo(this);
679 if (delete_edit) 703 if (delete_edit)
680 delete edit; 704 delete edit;
681 } 705 }
682 706
683 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection( 707 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection(
684 MergeType merge_type, const string16& new_text) { 708 MergeType merge_type, const string16& new_text) {
685 size_t new_text_start = render_text_->GetSelection().GetMin(); 709 size_t new_text_start = render_text_->MinOfSelection();
686 size_t new_cursor_pos = new_text_start + new_text.length(); 710 size_t new_cursor_pos = new_text_start + new_text.length();
687 ExecuteAndRecordReplace(merge_type, 711 ExecuteAndRecordReplace(merge_type,
688 GetCursorPosition(), 712 GetCursorPosition(),
689 new_cursor_pos, 713 new_cursor_pos,
690 new_text, 714 new_text,
691 new_text_start); 715 new_text_start);
692 } 716 }
693 717
694 void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type, 718 void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type,
695 size_t old_cursor_pos, 719 size_t old_cursor_pos,
696 size_t new_cursor_pos, 720 size_t new_cursor_pos,
697 const string16& new_text, 721 const string16& new_text,
698 size_t new_text_start) { 722 size_t new_text_start) {
699 size_t old_text_start = render_text_->GetSelection().GetMin(); 723 size_t old_text_start = render_text_->MinOfSelection();
700 bool backward = render_text_->GetSelection().is_reversed(); 724 bool backward = render_text_->GetSelectionStart() >
725 render_text_->GetCursorPosition();
msw 2011/08/03 23:44:38 ditto (put the whole comparison on the next line)
xji 2011/08/04 06:26:50 Done.
701 Edit* edit = new ReplaceEdit(merge_type, 726 Edit* edit = new ReplaceEdit(merge_type,
702 GetSelectedText(), 727 GetSelectedText(),
703 old_cursor_pos, 728 old_cursor_pos,
704 old_text_start, 729 old_text_start,
705 backward, 730 backward,
706 new_cursor_pos, 731 new_cursor_pos,
707 new_text, 732 new_text,
708 new_text_start); 733 new_text_start);
709 bool delete_edit = AddOrMergeEditHistory(edit); 734 bool delete_edit = AddOrMergeEditHistory(edit);
710 edit->Redo(this); 735 edit->Redo(this);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 if (delete_from != delete_to) 777 if (delete_from != delete_to)
753 render_text_->SetText(text.erase(delete_from, delete_to - delete_from)); 778 render_text_->SetText(text.erase(delete_from, delete_to - delete_from));
754 if (!new_text.empty()) 779 if (!new_text.empty())
755 render_text_->SetText(text.insert(new_text_insert_at, new_text)); 780 render_text_->SetText(text.insert(new_text_insert_at, new_text));
756 render_text_->SetCursorPosition(new_cursor_pos); 781 render_text_->SetCursorPosition(new_cursor_pos);
757 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't). 782 // 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. 783 // This looks fine feature and we may want to do the same.
759 } 784 }
760 785
761 } // namespace views 786 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698