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

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: revised per comments. Created 5 years, 8 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 // 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
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
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