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

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

Issue 24012002: Move Range code to gfx. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: d Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_views_model.h" 5 #include "ui/views/controls/textfield/textfield_views_model.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/i18n/break_iterator.h" 9 #include "base/i18n/break_iterator.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "ui/base/clipboard/clipboard.h" 13 #include "ui/base/clipboard/clipboard.h"
14 #include "ui/base/clipboard/scoped_clipboard_writer.h" 14 #include "ui/base/clipboard/scoped_clipboard_writer.h"
15 #include "ui/base/range/range.h"
16 #include "ui/base/text/utf16_indexing.h" 15 #include "ui/base/text/utf16_indexing.h"
17 #include "ui/gfx/canvas.h" 16 #include "ui/gfx/canvas.h"
18 #include "ui/gfx/font.h" 17 #include "ui/gfx/font.h"
18 #include "ui/gfx/range/range.h"
19 #include "ui/gfx/render_text.h" 19 #include "ui/gfx/render_text.h"
20 #include "ui/gfx/text_constants.h" 20 #include "ui/gfx/text_constants.h"
21 #include "ui/views/controls/textfield/textfield.h" 21 #include "ui/views/controls/textfield/textfield.h"
22 22
23 namespace views { 23 namespace views {
24 24
25 namespace internal { 25 namespace internal {
26 26
27 // An edit object holds enough information/state to undo/redo the 27 // An edit object holds enough information/state to undo/redo the
28 // change. Two edits are merged when possible, for example, when 28 // change. Two edits are merged when possible, for example, when
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 } 262 }
263 }; 263 };
264 264
265 } // namespace internal 265 } // namespace internal
266 266
267 namespace { 267 namespace {
268 268
269 // Returns the first segment that is visually emphasized. Usually it's used for 269 // Returns the first segment that is visually emphasized. Usually it's used for
270 // representing the target clause (on Windows). Returns an invalid range if 270 // representing the target clause (on Windows). Returns an invalid range if
271 // there is no such a range. 271 // there is no such a range.
272 ui::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) { 272 gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) {
273 for (size_t i = 0; i < composition.underlines.size(); ++i) { 273 for (size_t i = 0; i < composition.underlines.size(); ++i) {
274 const ui::CompositionUnderline& underline = composition.underlines[i]; 274 const ui::CompositionUnderline& underline = composition.underlines[i];
275 if (underline.thick) 275 if (underline.thick)
276 return ui::Range(underline.start_offset, underline.end_offset); 276 return gfx::Range(underline.start_offset, underline.end_offset);
277 } 277 }
278 return ui::Range::InvalidRange(); 278 return gfx::Range::InvalidRange();
279 } 279 }
280 280
281 } // namespace 281 } // namespace
282 282
283 using internal::Edit; 283 using internal::Edit;
284 using internal::DeleteEdit; 284 using internal::DeleteEdit;
285 using internal::InsertEdit; 285 using internal::InsertEdit;
286 using internal::ReplaceEdit; 286 using internal::ReplaceEdit;
287 using internal::MergeType; 287 using internal::MergeType;
288 using internal::DO_NOT_MERGE; 288 using internal::DO_NOT_MERGE;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 return true; 356 return true;
357 } 357 }
358 if (HasSelection()) { 358 if (HasSelection()) {
359 DeleteSelection(); 359 DeleteSelection();
360 return true; 360 return true;
361 } 361 }
362 if (GetText().length() > GetCursorPosition()) { 362 if (GetText().length() > GetCursorPosition()) {
363 size_t cursor_position = GetCursorPosition(); 363 size_t cursor_position = GetCursorPosition();
364 size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme( 364 size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme(
365 cursor_position, gfx::CURSOR_FORWARD); 365 cursor_position, gfx::CURSOR_FORWARD);
366 ExecuteAndRecordDelete(ui::Range(cursor_position, next_grapheme_index), 366 ExecuteAndRecordDelete(gfx::Range(cursor_position, next_grapheme_index),
367 true); 367 true);
368 return true; 368 return true;
369 } 369 }
370 return false; 370 return false;
371 } 371 }
372 372
373 bool TextfieldViewsModel::Backspace() { 373 bool TextfieldViewsModel::Backspace() {
374 if (HasCompositionText()) { 374 if (HasCompositionText()) {
375 // No undo/redo for composition text. 375 // No undo/redo for composition text.
376 CancelCompositionText(); 376 CancelCompositionText();
377 return true; 377 return true;
378 } 378 }
379 if (HasSelection()) { 379 if (HasSelection()) {
380 DeleteSelection(); 380 DeleteSelection();
381 return true; 381 return true;
382 } 382 }
383 size_t cursor_position = GetCursorPosition(); 383 size_t cursor_position = GetCursorPosition();
384 if (cursor_position > 0) { 384 if (cursor_position > 0) {
385 // Delete one code point, which may be two UTF-16 words. 385 // Delete one code point, which may be two UTF-16 words.
386 size_t previous_char = 386 size_t previous_char =
387 ui::UTF16OffsetToIndex(GetText(), cursor_position, -1); 387 ui::UTF16OffsetToIndex(GetText(), cursor_position, -1);
388 ExecuteAndRecordDelete(ui::Range(cursor_position, previous_char), true); 388 ExecuteAndRecordDelete(gfx::Range(cursor_position, previous_char), true);
389 return true; 389 return true;
390 } 390 }
391 return false; 391 return false;
392 } 392 }
393 393
394 size_t TextfieldViewsModel::GetCursorPosition() const { 394 size_t TextfieldViewsModel::GetCursorPosition() const {
395 return render_text_->cursor_position(); 395 return render_text_->cursor_position();
396 } 396 }
397 397
398 void TextfieldViewsModel::MoveCursor(gfx::BreakType break_type, 398 void TextfieldViewsModel::MoveCursor(gfx::BreakType break_type,
399 gfx::VisualCursorDirection direction, 399 gfx::VisualCursorDirection direction,
400 bool select) { 400 bool select) {
401 if (HasCompositionText()) 401 if (HasCompositionText())
402 ConfirmCompositionText(); 402 ConfirmCompositionText();
403 render_text_->MoveCursor(break_type, direction, select); 403 render_text_->MoveCursor(break_type, direction, select);
404 } 404 }
405 405
406 bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& model) { 406 bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& model) {
407 if (HasCompositionText()) { 407 if (HasCompositionText()) {
408 ConfirmCompositionText(); 408 ConfirmCompositionText();
409 // ConfirmCompositionText() updates cursor position. Need to reflect it in 409 // ConfirmCompositionText() updates cursor position. Need to reflect it in
410 // the SelectionModel parameter of MoveCursorTo(). 410 // the SelectionModel parameter of MoveCursorTo().
411 ui::Range range(render_text_->selection().start(), model.caret_pos()); 411 gfx::Range range(render_text_->selection().start(), model.caret_pos());
412 if (!range.is_empty()) 412 if (!range.is_empty())
413 return render_text_->SelectRange(range); 413 return render_text_->SelectRange(range);
414 return render_text_->MoveCursorTo( 414 return render_text_->MoveCursorTo(
415 gfx::SelectionModel(model.caret_pos(), model.caret_affinity())); 415 gfx::SelectionModel(model.caret_pos(), model.caret_affinity()));
416 } 416 }
417 return render_text_->MoveCursorTo(model); 417 return render_text_->MoveCursorTo(model);
418 } 418 }
419 419
420 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) { 420 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) {
421 if (HasCompositionText()) 421 if (HasCompositionText())
422 ConfirmCompositionText(); 422 ConfirmCompositionText();
423 return render_text_->MoveCursorTo(point, select); 423 return render_text_->MoveCursorTo(point, select);
424 } 424 }
425 425
426 string16 TextfieldViewsModel::GetSelectedText() const { 426 string16 TextfieldViewsModel::GetSelectedText() const {
427 return GetText().substr(render_text_->selection().GetMin(), 427 return GetText().substr(render_text_->selection().GetMin(),
428 render_text_->selection().length()); 428 render_text_->selection().length());
429 } 429 }
430 430
431 void TextfieldViewsModel::SelectRange(const ui::Range& range) { 431 void TextfieldViewsModel::SelectRange(const gfx::Range& range) {
432 if (HasCompositionText()) 432 if (HasCompositionText())
433 ConfirmCompositionText(); 433 ConfirmCompositionText();
434 render_text_->SelectRange(range); 434 render_text_->SelectRange(range);
435 } 435 }
436 436
437 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) { 437 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) {
438 if (HasCompositionText()) 438 if (HasCompositionText())
439 ConfirmCompositionText(); 439 ConfirmCompositionText();
440 render_text_->MoveCursorTo(sel); 440 render_text_->MoveCursorTo(sel);
441 } 441 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 bool TextfieldViewsModel::Cut() { 511 bool TextfieldViewsModel::Cut() {
512 if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) { 512 if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) {
513 ui::ScopedClipboardWriter( 513 ui::ScopedClipboardWriter(
514 ui::Clipboard::GetForCurrentThread(), 514 ui::Clipboard::GetForCurrentThread(),
515 ui::Clipboard::BUFFER_STANDARD).WriteText(GetSelectedText()); 515 ui::Clipboard::BUFFER_STANDARD).WriteText(GetSelectedText());
516 // A trick to let undo/redo handle cursor correctly. 516 // A trick to let undo/redo handle cursor correctly.
517 // Undoing CUT moves the cursor to the end of the change rather 517 // Undoing CUT moves the cursor to the end of the change rather
518 // than beginning, unlike Delete/Backspace. 518 // than beginning, unlike Delete/Backspace.
519 // TODO(oshima): Change Delete/Backspace to use DeleteSelection, 519 // TODO(oshima): Change Delete/Backspace to use DeleteSelection,
520 // update DeleteEdit and remove this trick. 520 // update DeleteEdit and remove this trick.
521 const ui::Range& selection = render_text_->selection(); 521 const gfx::Range& selection = render_text_->selection();
522 render_text_->SelectRange(ui::Range(selection.end(), selection.start())); 522 render_text_->SelectRange(gfx::Range(selection.end(), selection.start()));
523 DeleteSelection(); 523 DeleteSelection();
524 return true; 524 return true;
525 } 525 }
526 return false; 526 return false;
527 } 527 }
528 528
529 bool TextfieldViewsModel::Copy() { 529 bool TextfieldViewsModel::Copy() {
530 if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) { 530 if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) {
531 ui::ScopedClipboardWriter( 531 ui::ScopedClipboardWriter(
532 ui::Clipboard::GetForCurrentThread(), 532 ui::Clipboard::GetForCurrentThread(),
(...skipping 28 matching lines...) Expand all
561 const string16& text, size_t position) { 561 const string16& text, size_t position) {
562 if (HasCompositionText()) 562 if (HasCompositionText())
563 CancelCompositionText(); 563 CancelCompositionText();
564 ExecuteAndRecordReplace(DO_NOT_MERGE, 564 ExecuteAndRecordReplace(DO_NOT_MERGE,
565 GetCursorPosition(), 565 GetCursorPosition(),
566 position + text.length(), 566 position + text.length(),
567 text, 567 text,
568 position); 568 position);
569 } 569 }
570 570
571 string16 TextfieldViewsModel::GetTextFromRange(const ui::Range& range) const { 571 string16 TextfieldViewsModel::GetTextFromRange(const gfx::Range& range) const {
572 if (range.IsValid() && range.GetMin() < GetText().length()) 572 if (range.IsValid() && range.GetMin() < GetText().length())
573 return GetText().substr(range.GetMin(), range.length()); 573 return GetText().substr(range.GetMin(), range.length());
574 return string16(); 574 return string16();
575 } 575 }
576 576
577 void TextfieldViewsModel::GetTextRange(ui::Range* range) const { 577 void TextfieldViewsModel::GetTextRange(gfx::Range* range) const {
578 *range = ui::Range(0, GetText().length()); 578 *range = gfx::Range(0, GetText().length());
579 } 579 }
580 580
581 void TextfieldViewsModel::SetCompositionText( 581 void TextfieldViewsModel::SetCompositionText(
582 const ui::CompositionText& composition) { 582 const ui::CompositionText& composition) {
583 if (HasCompositionText()) 583 if (HasCompositionText())
584 CancelCompositionText(); 584 CancelCompositionText();
585 else if (HasSelection()) 585 else if (HasSelection())
586 DeleteSelection(); 586 DeleteSelection();
587 587
588 if (composition.text.empty()) 588 if (composition.text.empty())
589 return; 589 return;
590 590
591 size_t cursor = GetCursorPosition(); 591 size_t cursor = GetCursorPosition();
592 string16 new_text = GetText(); 592 string16 new_text = GetText();
593 render_text_->SetText(new_text.insert(cursor, composition.text)); 593 render_text_->SetText(new_text.insert(cursor, composition.text));
594 ui::Range range(cursor, cursor + composition.text.length()); 594 gfx::Range range(cursor, cursor + composition.text.length());
595 render_text_->SetCompositionRange(range); 595 render_text_->SetCompositionRange(range);
596 ui::Range emphasized_range = GetFirstEmphasizedRange(composition); 596 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition);
597 if (emphasized_range.IsValid()) { 597 if (emphasized_range.IsValid()) {
598 // This is a workaround due to the lack of support in RenderText to draw 598 // This is a workaround due to the lack of support in RenderText to draw
599 // a thick underline. In a composition returned from an IME, the segment 599 // a thick underline. In a composition returned from an IME, the segment
600 // emphasized by a thick underline usually represents the target clause. 600 // emphasized by a thick underline usually represents the target clause.
601 // Because the target clause is more important than the actual selection 601 // Because the target clause is more important than the actual selection
602 // range (or caret position) in the composition here we use a selection-like 602 // range (or caret position) in the composition here we use a selection-like
603 // marker instead to show this range. 603 // marker instead to show this range.
604 // TODO(yukawa, msw): Support thick underline in RenderText and remove 604 // TODO(yukawa, msw): Support thick underline in RenderText and remove
605 // this workaround. 605 // this workaround.
606 render_text_->SelectRange(ui::Range( 606 render_text_->SelectRange(gfx::Range(
607 cursor + emphasized_range.GetMin(), 607 cursor + emphasized_range.GetMin(),
608 cursor + emphasized_range.GetMax())); 608 cursor + emphasized_range.GetMax()));
609 } else if (!composition.selection.is_empty()) { 609 } else if (!composition.selection.is_empty()) {
610 render_text_->SelectRange(ui::Range( 610 render_text_->SelectRange(gfx::Range(
611 cursor + composition.selection.GetMin(), 611 cursor + composition.selection.GetMin(),
612 cursor + composition.selection.GetMax())); 612 cursor + composition.selection.GetMax()));
613 } else { 613 } else {
614 render_text_->SetCursorPosition(cursor + composition.selection.end()); 614 render_text_->SetCursorPosition(cursor + composition.selection.end());
615 } 615 }
616 } 616 }
617 617
618 void TextfieldViewsModel::ConfirmCompositionText() { 618 void TextfieldViewsModel::ConfirmCompositionText() {
619 DCHECK(HasCompositionText()); 619 DCHECK(HasCompositionText());
620 ui::Range range = render_text_->GetCompositionRange(); 620 gfx::Range range = render_text_->GetCompositionRange();
621 string16 text = GetText().substr(range.start(), range.length()); 621 string16 text = GetText().substr(range.start(), range.length());
622 // TODO(oshima): current behavior on ChromeOS is a bit weird and not 622 // TODO(oshima): current behavior on ChromeOS is a bit weird and not
623 // sure exactly how this should work. Find out and fix if necessary. 623 // sure exactly how this should work. Find out and fix if necessary.
624 AddOrMergeEditHistory(new InsertEdit(false, text, range.start())); 624 AddOrMergeEditHistory(new InsertEdit(false, text, range.start()));
625 render_text_->SetCursorPosition(range.end()); 625 render_text_->SetCursorPosition(range.end());
626 ClearComposition(); 626 ClearComposition();
627 if (delegate_) 627 if (delegate_)
628 delegate_->OnCompositionTextConfirmedOrCleared(); 628 delegate_->OnCompositionTextConfirmedOrCleared();
629 } 629 }
630 630
631 void TextfieldViewsModel::CancelCompositionText() { 631 void TextfieldViewsModel::CancelCompositionText() {
632 DCHECK(HasCompositionText()); 632 DCHECK(HasCompositionText());
633 ui::Range range = render_text_->GetCompositionRange(); 633 gfx::Range range = render_text_->GetCompositionRange();
634 ClearComposition(); 634 ClearComposition();
635 string16 new_text = GetText(); 635 string16 new_text = GetText();
636 render_text_->SetText(new_text.erase(range.start(), range.length())); 636 render_text_->SetText(new_text.erase(range.start(), range.length()));
637 render_text_->SetCursorPosition(range.start()); 637 render_text_->SetCursorPosition(range.start());
638 if (delegate_) 638 if (delegate_)
639 delegate_->OnCompositionTextConfirmedOrCleared(); 639 delegate_->OnCompositionTextConfirmedOrCleared();
640 } 640 }
641 641
642 void TextfieldViewsModel::ClearComposition() { 642 void TextfieldViewsModel::ClearComposition() {
643 render_text_->SetCompositionRange(ui::Range::InvalidRange()); 643 render_text_->SetCompositionRange(gfx::Range::InvalidRange());
644 } 644 }
645 645
646 void TextfieldViewsModel::GetCompositionTextRange(ui::Range* range) const { 646 void TextfieldViewsModel::GetCompositionTextRange(gfx::Range* range) const {
647 *range = ui::Range(render_text_->GetCompositionRange()); 647 *range = gfx::Range(render_text_->GetCompositionRange());
648 } 648 }
649 649
650 bool TextfieldViewsModel::HasCompositionText() const { 650 bool TextfieldViewsModel::HasCompositionText() const {
651 return !render_text_->GetCompositionRange().is_empty(); 651 return !render_text_->GetCompositionRange().is_empty();
652 } 652 }
653 653
654 ///////////////////////////////////////////////////////////////// 654 /////////////////////////////////////////////////////////////////
655 // TextfieldViewsModel: private 655 // TextfieldViewsModel: private
656 656
657 void TextfieldViewsModel::InsertTextInternal(const string16& text, 657 void TextfieldViewsModel::InsertTextInternal(const string16& text,
(...skipping 16 matching lines...) Expand all
674 } else if (!HasSelection()) { 674 } else if (!HasSelection()) {
675 size_t cursor = GetCursorPosition(); 675 size_t cursor = GetCursorPosition();
676 const gfx::SelectionModel& model = render_text_->selection_model(); 676 const gfx::SelectionModel& model = render_text_->selection_model();
677 // When there is no selection, the default is to replace the next grapheme 677 // When there is no selection, the default is to replace the next grapheme
678 // with |text|. So, need to find the index of next grapheme first. 678 // with |text|. So, need to find the index of next grapheme first.
679 size_t next = 679 size_t next =
680 render_text_->IndexOfAdjacentGrapheme(cursor, gfx::CURSOR_FORWARD); 680 render_text_->IndexOfAdjacentGrapheme(cursor, gfx::CURSOR_FORWARD);
681 if (next == model.caret_pos()) 681 if (next == model.caret_pos())
682 render_text_->MoveCursorTo(model); 682 render_text_->MoveCursorTo(model);
683 else 683 else
684 render_text_->SelectRange(ui::Range(next, model.caret_pos())); 684 render_text_->SelectRange(gfx::Range(next, model.caret_pos()));
685 } 685 }
686 // Edit history is recorded in InsertText. 686 // Edit history is recorded in InsertText.
687 InsertTextInternal(text, mergeable); 687 InsertTextInternal(text, mergeable);
688 } 688 }
689 689
690 void TextfieldViewsModel::ClearEditHistory() { 690 void TextfieldViewsModel::ClearEditHistory() {
691 STLDeleteElements(&edit_history_); 691 STLDeleteElements(&edit_history_);
692 current_edit_ = edit_history_.end(); 692 current_edit_ = edit_history_.end();
693 } 693 }
694 694
695 void TextfieldViewsModel::ClearRedoHistory() { 695 void TextfieldViewsModel::ClearRedoHistory() {
696 if (edit_history_.begin() == edit_history_.end()) 696 if (edit_history_.begin() == edit_history_.end())
697 return; 697 return;
698 if (current_edit_ == edit_history_.end()) { 698 if (current_edit_ == edit_history_.end()) {
699 ClearEditHistory(); 699 ClearEditHistory();
700 return; 700 return;
701 } 701 }
702 EditHistory::iterator delete_start = current_edit_; 702 EditHistory::iterator delete_start = current_edit_;
703 delete_start++; 703 delete_start++;
704 STLDeleteContainerPointers(delete_start, edit_history_.end()); 704 STLDeleteContainerPointers(delete_start, edit_history_.end());
705 edit_history_.erase(delete_start, edit_history_.end()); 705 edit_history_.erase(delete_start, edit_history_.end());
706 } 706 }
707 707
708 void TextfieldViewsModel::ExecuteAndRecordDelete(ui::Range range, 708 void TextfieldViewsModel::ExecuteAndRecordDelete(gfx::Range range,
709 bool mergeable) { 709 bool mergeable) {
710 size_t old_text_start = range.GetMin(); 710 size_t old_text_start = range.GetMin();
711 const string16 text = GetText().substr(old_text_start, range.length()); 711 const string16 text = GetText().substr(old_text_start, range.length());
712 bool backward = range.is_reversed(); 712 bool backward = range.is_reversed();
713 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward); 713 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward);
714 bool delete_edit = AddOrMergeEditHistory(edit); 714 bool delete_edit = AddOrMergeEditHistory(edit);
715 edit->Redo(this); 715 edit->Redo(this);
716 if (delete_edit) 716 if (delete_edit)
717 delete edit; 717 delete edit;
718 } 718 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 if (delete_from != delete_to) 790 if (delete_from != delete_to)
791 render_text_->SetText(text.erase(delete_from, delete_to - delete_from)); 791 render_text_->SetText(text.erase(delete_from, delete_to - delete_from));
792 if (!new_text.empty()) 792 if (!new_text.empty())
793 render_text_->SetText(text.insert(new_text_insert_at, new_text)); 793 render_text_->SetText(text.insert(new_text_insert_at, new_text));
794 render_text_->SetCursorPosition(new_cursor_pos); 794 render_text_->SetCursorPosition(new_cursor_pos);
795 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't). 795 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't).
796 // This looks fine feature and we may want to do the same. 796 // This looks fine feature and we may want to do the same.
797 } 797 }
798 798
799 } // namespace views 799 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield_views_model.h ('k') | ui/views/controls/textfield/textfield_views_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698