OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/views/controls/textfield/textfield_model.h" | 5 #include "ui/views/controls/textfield/textfield_model.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 CancelCompositionText(); | 557 CancelCompositionText(); |
558 else if (HasSelection()) | 558 else if (HasSelection()) |
559 DeleteSelection(); | 559 DeleteSelection(); |
560 | 560 |
561 if (composition.text.empty()) | 561 if (composition.text.empty()) |
562 return; | 562 return; |
563 | 563 |
564 size_t cursor = GetCursorPosition(); | 564 size_t cursor = GetCursorPosition(); |
565 base::string16 new_text = text(); | 565 base::string16 new_text = text(); |
566 render_text_->SetText(new_text.insert(cursor, composition.text)); | 566 render_text_->SetText(new_text.insert(cursor, composition.text)); |
567 gfx::Range range(cursor, cursor + composition.text.length()); | 567 composition_range_ = gfx::Range(cursor, cursor + composition.text.length()); |
568 render_text_->SetCompositionRange(range); | 568 // Don't render transparent composition underlines. |
| 569 if (composition.underlines.size() > 0 && composition.underlines[0].color != 0) |
| 570 render_text_->SetCompositionRange(composition_range_); |
| 571 else |
| 572 render_text_->SetCompositionRange(gfx::Range::InvalidRange()); |
569 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition); | 573 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition); |
570 if (emphasized_range.IsValid()) { | 574 if (emphasized_range.IsValid()) { |
571 // This is a workaround due to the lack of support in RenderText to draw | 575 // This is a workaround due to the lack of support in RenderText to draw |
572 // a thick underline. In a composition returned from an IME, the segment | 576 // a thick underline. In a composition returned from an IME, the segment |
573 // emphasized by a thick underline usually represents the target clause. | 577 // emphasized by a thick underline usually represents the target clause. |
574 // Because the target clause is more important than the actual selection | 578 // Because the target clause is more important than the actual selection |
575 // range (or caret position) in the composition here we use a selection-like | 579 // range (or caret position) in the composition here we use a selection-like |
576 // marker instead to show this range. | 580 // marker instead to show this range. |
577 // TODO(yukawa, msw): Support thick underlines and remove this workaround. | 581 // TODO(yukawa, msw): Support thick underlines and remove this workaround. |
578 render_text_->SelectRange(gfx::Range( | 582 render_text_->SelectRange(gfx::Range( |
579 cursor + emphasized_range.GetMin(), | 583 cursor + emphasized_range.GetMin(), |
580 cursor + emphasized_range.GetMax())); | 584 cursor + emphasized_range.GetMax())); |
581 } else if (!composition.selection.is_empty()) { | 585 } else if (!composition.selection.is_empty()) { |
582 render_text_->SelectRange(gfx::Range( | 586 render_text_->SelectRange(gfx::Range( |
583 cursor + composition.selection.GetMin(), | 587 cursor + composition.selection.GetMin(), |
584 cursor + composition.selection.GetMax())); | 588 cursor + composition.selection.GetMax())); |
585 } else { | 589 } else { |
586 render_text_->SetCursorPosition(cursor + composition.selection.end()); | 590 render_text_->SetCursorPosition(cursor + composition.selection.end()); |
587 } | 591 } |
588 } | 592 } |
589 | 593 |
590 void TextfieldModel::ConfirmCompositionText() { | 594 void TextfieldModel::ConfirmCompositionText() { |
591 DCHECK(HasCompositionText()); | 595 DCHECK(HasCompositionText()); |
592 gfx::Range range = render_text_->GetCompositionRange(); | 596 base::string16 composition = text().substr( |
593 base::string16 composition = text().substr(range.start(), range.length()); | 597 composition_range_.start(), composition_range_.length()); |
594 // TODO(oshima): current behavior on ChromeOS is a bit weird and not | 598 // TODO(oshima): current behavior on ChromeOS is a bit weird and not |
595 // sure exactly how this should work. Find out and fix if necessary. | 599 // sure exactly how this should work. Find out and fix if necessary. |
596 AddOrMergeEditHistory(new InsertEdit(false, composition, range.start())); | 600 AddOrMergeEditHistory( |
597 render_text_->SetCursorPosition(range.end()); | 601 new InsertEdit(false, composition, composition_range_.start())); |
| 602 render_text_->SetCursorPosition(composition_range_.end()); |
598 ClearComposition(); | 603 ClearComposition(); |
599 if (delegate_) | 604 if (delegate_) |
600 delegate_->OnCompositionTextConfirmedOrCleared(); | 605 delegate_->OnCompositionTextConfirmedOrCleared(); |
601 } | 606 } |
602 | 607 |
603 void TextfieldModel::CancelCompositionText() { | 608 void TextfieldModel::CancelCompositionText() { |
604 DCHECK(HasCompositionText()); | 609 DCHECK(HasCompositionText()); |
605 gfx::Range range = render_text_->GetCompositionRange(); | 610 gfx::Range range = composition_range_; |
606 ClearComposition(); | 611 ClearComposition(); |
607 base::string16 new_text = text(); | 612 base::string16 new_text = text(); |
608 render_text_->SetText(new_text.erase(range.start(), range.length())); | 613 render_text_->SetText(new_text.erase(range.start(), range.length())); |
609 render_text_->SetCursorPosition(range.start()); | 614 render_text_->SetCursorPosition(range.start()); |
610 if (delegate_) | 615 if (delegate_) |
611 delegate_->OnCompositionTextConfirmedOrCleared(); | 616 delegate_->OnCompositionTextConfirmedOrCleared(); |
612 } | 617 } |
613 | 618 |
614 void TextfieldModel::ClearComposition() { | 619 void TextfieldModel::ClearComposition() { |
615 render_text_->SetCompositionRange(gfx::Range::InvalidRange()); | 620 composition_range_ = gfx::Range::InvalidRange(); |
| 621 render_text_->SetCompositionRange(composition_range_); |
616 } | 622 } |
617 | 623 |
618 void TextfieldModel::GetCompositionTextRange(gfx::Range* range) const { | 624 void TextfieldModel::GetCompositionTextRange(gfx::Range* range) const { |
619 *range = gfx::Range(render_text_->GetCompositionRange()); | 625 *range = composition_range_; |
620 } | 626 } |
621 | 627 |
622 bool TextfieldModel::HasCompositionText() const { | 628 bool TextfieldModel::HasCompositionText() const { |
623 return !render_text_->GetCompositionRange().is_empty(); | 629 return !composition_range_.is_empty(); |
624 } | 630 } |
625 | 631 |
626 void TextfieldModel::ClearEditHistory() { | 632 void TextfieldModel::ClearEditHistory() { |
627 STLDeleteElements(&edit_history_); | 633 STLDeleteElements(&edit_history_); |
628 current_edit_ = edit_history_.end(); | 634 current_edit_ = edit_history_.end(); |
629 } | 635 } |
630 | 636 |
631 ///////////////////////////////////////////////////////////////// | 637 ///////////////////////////////////////////////////////////////// |
632 // TextfieldModel: private | 638 // TextfieldModel: private |
633 | 639 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 ClearComposition(); | 766 ClearComposition(); |
761 if (delete_from != delete_to) | 767 if (delete_from != delete_to) |
762 render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from)); | 768 render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from)); |
763 if (!new_text.empty()) | 769 if (!new_text.empty()) |
764 render_text_->SetText(old_text.insert(new_text_insert_at, new_text)); | 770 render_text_->SetText(old_text.insert(new_text_insert_at, new_text)); |
765 render_text_->SetCursorPosition(new_cursor_pos); | 771 render_text_->SetCursorPosition(new_cursor_pos); |
766 // TODO(oshima): Select text that was just undone, like Mac (but not GTK). | 772 // TODO(oshima): Select text that was just undone, like Mac (but not GTK). |
767 } | 773 } |
768 | 774 |
769 } // namespace views | 775 } // namespace views |
OLD | NEW |