Chromium Code Reviews| 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 if (composition.underlines.size() > 0 && composition.underlines[0].color != 0) |
|
msw
2015/03/24 20:19:01
nit: add a comment here to explain this behavior;
Shu Chen
2015/03/26 04:22:13
Done.
| |
| 569 render_text_->SetCompositionRange(composition_range_); | |
| 570 else | |
| 571 render_text_->SetCompositionRange(gfx::Range()); | |
| 569 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition); | 572 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition); |
| 570 if (emphasized_range.IsValid()) { | 573 if (emphasized_range.IsValid()) { |
| 571 // This is a workaround due to the lack of support in RenderText to draw | 574 // 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 | 575 // a thick underline. In a composition returned from an IME, the segment |
| 573 // emphasized by a thick underline usually represents the target clause. | 576 // emphasized by a thick underline usually represents the target clause. |
| 574 // Because the target clause is more important than the actual selection | 577 // 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 | 578 // range (or caret position) in the composition here we use a selection-like |
| 576 // marker instead to show this range. | 579 // marker instead to show this range. |
| 577 // TODO(yukawa, msw): Support thick underlines and remove this workaround. | 580 // TODO(yukawa, msw): Support thick underlines and remove this workaround. |
| 578 render_text_->SelectRange(gfx::Range( | 581 render_text_->SelectRange(gfx::Range( |
| 579 cursor + emphasized_range.GetMin(), | 582 cursor + emphasized_range.GetMin(), |
| 580 cursor + emphasized_range.GetMax())); | 583 cursor + emphasized_range.GetMax())); |
| 581 } else if (!composition.selection.is_empty()) { | 584 } else if (!composition.selection.is_empty()) { |
| 582 render_text_->SelectRange(gfx::Range( | 585 render_text_->SelectRange(gfx::Range( |
| 583 cursor + composition.selection.GetMin(), | 586 cursor + composition.selection.GetMin(), |
| 584 cursor + composition.selection.GetMax())); | 587 cursor + composition.selection.GetMax())); |
| 585 } else { | 588 } else { |
| 586 render_text_->SetCursorPosition(cursor + composition.selection.end()); | 589 render_text_->SetCursorPosition(cursor + composition.selection.end()); |
| 587 } | 590 } |
| 588 } | 591 } |
| 589 | 592 |
| 590 void TextfieldModel::ConfirmCompositionText() { | 593 void TextfieldModel::ConfirmCompositionText() { |
| 591 DCHECK(HasCompositionText()); | 594 DCHECK(HasCompositionText()); |
| 592 gfx::Range range = render_text_->GetCompositionRange(); | 595 base::string16 composition = text().substr( |
| 593 base::string16 composition = text().substr(range.start(), range.length()); | 596 composition_range_.start(), composition_range_.length()); |
| 594 // TODO(oshima): current behavior on ChromeOS is a bit weird and not | 597 // 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. | 598 // sure exactly how this should work. Find out and fix if necessary. |
| 596 AddOrMergeEditHistory(new InsertEdit(false, composition, range.start())); | 599 AddOrMergeEditHistory( |
| 597 render_text_->SetCursorPosition(range.end()); | 600 new InsertEdit(false, composition, composition_range_.start())); |
| 601 render_text_->SetCursorPosition(composition_range_.end()); | |
| 598 ClearComposition(); | 602 ClearComposition(); |
| 599 if (delegate_) | 603 if (delegate_) |
| 600 delegate_->OnCompositionTextConfirmedOrCleared(); | 604 delegate_->OnCompositionTextConfirmedOrCleared(); |
| 601 } | 605 } |
| 602 | 606 |
| 603 void TextfieldModel::CancelCompositionText() { | 607 void TextfieldModel::CancelCompositionText() { |
| 604 DCHECK(HasCompositionText()); | 608 DCHECK(HasCompositionText()); |
| 605 gfx::Range range = render_text_->GetCompositionRange(); | |
| 606 ClearComposition(); | 609 ClearComposition(); |
| 607 base::string16 new_text = text(); | 610 base::string16 new_text = text(); |
| 608 render_text_->SetText(new_text.erase(range.start(), range.length())); | 611 render_text_->SetText(new_text.erase( |
| 609 render_text_->SetCursorPosition(range.start()); | 612 composition_range_.start(), composition_range_.length())); |
| 613 render_text_->SetCursorPosition(composition_range_.start()); | |
| 610 if (delegate_) | 614 if (delegate_) |
| 611 delegate_->OnCompositionTextConfirmedOrCleared(); | 615 delegate_->OnCompositionTextConfirmedOrCleared(); |
| 612 } | 616 } |
| 613 | 617 |
| 614 void TextfieldModel::ClearComposition() { | 618 void TextfieldModel::ClearComposition() { |
|
msw
2015/03/24 20:19:01
Shouldn't this also clear |composition_range_|?
Shu Chen
2015/03/26 04:22:13
Done.
| |
| 615 render_text_->SetCompositionRange(gfx::Range::InvalidRange()); | 619 render_text_->SetCompositionRange(gfx::Range::InvalidRange()); |
| 616 } | 620 } |
| 617 | 621 |
| 618 void TextfieldModel::GetCompositionTextRange(gfx::Range* range) const { | 622 void TextfieldModel::GetCompositionTextRange(gfx::Range* range) const { |
| 619 *range = gfx::Range(render_text_->GetCompositionRange()); | 623 *range = composition_range_; |
| 620 } | 624 } |
| 621 | 625 |
| 622 bool TextfieldModel::HasCompositionText() const { | 626 bool TextfieldModel::HasCompositionText() const { |
| 623 return !render_text_->GetCompositionRange().is_empty(); | 627 return !composition_range_.is_empty(); |
| 624 } | 628 } |
| 625 | 629 |
| 626 void TextfieldModel::ClearEditHistory() { | 630 void TextfieldModel::ClearEditHistory() { |
| 627 STLDeleteElements(&edit_history_); | 631 STLDeleteElements(&edit_history_); |
| 628 current_edit_ = edit_history_.end(); | 632 current_edit_ = edit_history_.end(); |
| 629 } | 633 } |
| 630 | 634 |
| 631 ///////////////////////////////////////////////////////////////// | 635 ///////////////////////////////////////////////////////////////// |
| 632 // TextfieldModel: private | 636 // TextfieldModel: private |
| 633 | 637 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 760 ClearComposition(); | 764 ClearComposition(); |
| 761 if (delete_from != delete_to) | 765 if (delete_from != delete_to) |
| 762 render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from)); | 766 render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from)); |
| 763 if (!new_text.empty()) | 767 if (!new_text.empty()) |
| 764 render_text_->SetText(old_text.insert(new_text_insert_at, new_text)); | 768 render_text_->SetText(old_text.insert(new_text_insert_at, new_text)); |
| 765 render_text_->SetCursorPosition(new_cursor_pos); | 769 render_text_->SetCursorPosition(new_cursor_pos); |
| 766 // TODO(oshima): Select text that was just undone, like Mac (but not GTK). | 770 // TODO(oshima): Select text that was just undone, like Mac (but not GTK). |
| 767 } | 771 } |
| 768 | 772 |
| 769 } // namespace views | 773 } // namespace views |
| OLD | NEW |