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

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

Powered by Google App Engine
This is Rietveld 408576698