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