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

Side by Side Diff: ui/views/controls/textfield/textfield_model.cc

Issue 1031533002: Supports the invisible underline for native input fields. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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
« no previous file with comments | « ui/views/controls/textfield/textfield_model.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield_model.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698