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

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

Issue 135813002: Revert of Merge NativeTextfieldViews into views::Textfield. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 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"
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 : delegate_(delegate), 299 : delegate_(delegate),
300 render_text_(gfx::RenderText::CreateInstance()), 300 render_text_(gfx::RenderText::CreateInstance()),
301 current_edit_(edit_history_.end()) { 301 current_edit_(edit_history_.end()) {
302 } 302 }
303 303
304 TextfieldViewsModel::~TextfieldViewsModel() { 304 TextfieldViewsModel::~TextfieldViewsModel() {
305 ClearEditHistory(); 305 ClearEditHistory();
306 ClearComposition(); 306 ClearComposition();
307 } 307 }
308 308
309 bool TextfieldViewsModel::SetText(const base::string16& new_text) { 309 const base::string16& TextfieldViewsModel::GetText() const {
310 return render_text_->text();
311 }
312
313 bool TextfieldViewsModel::SetText(const base::string16& text) {
310 bool changed = false; 314 bool changed = false;
311 if (HasCompositionText()) { 315 if (HasCompositionText()) {
312 ConfirmCompositionText(); 316 ConfirmCompositionText();
313 changed = true; 317 changed = true;
314 } 318 }
315 if (text() != new_text) { 319 if (GetText() != text) {
316 if (changed) // No need to remember composition. 320 if (changed) // No need to remember composition.
317 Undo(); 321 Undo();
318 size_t old_cursor = GetCursorPosition(); 322 size_t old_cursor = GetCursorPosition();
319 // SetText moves the cursor to the end. 323 // SetText moves the cursor to the end.
320 size_t new_cursor = new_text.length(); 324 size_t new_cursor = text.length();
321 SelectAll(false); 325 SelectAll(false);
322 // If there is a composition text, don't merge with previous edit. 326 // If there is a composition text, don't merge with previous edit.
323 // Otherwise, force merge the edits. 327 // Otherwise, force merge the edits.
324 ExecuteAndRecordReplace( 328 ExecuteAndRecordReplace(
325 changed ? DO_NOT_MERGE : MERGE_WITH_PREVIOUS, 329 changed ? DO_NOT_MERGE : MERGE_WITH_PREVIOUS,
326 old_cursor, 330 old_cursor,
327 new_cursor, 331 new_cursor,
328 new_text, 332 text,
329 0U); 333 0U);
330 render_text_->SetCursorPosition(new_cursor); 334 render_text_->SetCursorPosition(new_cursor);
331 } 335 }
332 ClearSelection(); 336 ClearSelection();
333 return changed; 337 return changed;
334 } 338 }
335 339
336 void TextfieldViewsModel::Append(const base::string16& new_text) { 340 void TextfieldViewsModel::Append(const base::string16& text) {
337 if (HasCompositionText()) 341 if (HasCompositionText())
338 ConfirmCompositionText(); 342 ConfirmCompositionText();
339 size_t save = GetCursorPosition(); 343 size_t save = GetCursorPosition();
340 MoveCursor(gfx::LINE_BREAK, 344 MoveCursor(gfx::LINE_BREAK,
341 render_text_->GetVisualDirectionOfLogicalEnd(), 345 render_text_->GetVisualDirectionOfLogicalEnd(),
342 false); 346 false);
343 InsertText(new_text); 347 InsertText(text);
344 render_text_->SetCursorPosition(save); 348 render_text_->SetCursorPosition(save);
345 ClearSelection(); 349 ClearSelection();
346 } 350 }
347 351
348 bool TextfieldViewsModel::Delete() { 352 bool TextfieldViewsModel::Delete() {
349 if (HasCompositionText()) { 353 if (HasCompositionText()) {
350 // No undo/redo for composition text. 354 // No undo/redo for composition text.
351 CancelCompositionText(); 355 CancelCompositionText();
352 return true; 356 return true;
353 } 357 }
354 if (HasSelection()) { 358 if (HasSelection()) {
355 DeleteSelection(); 359 DeleteSelection();
356 return true; 360 return true;
357 } 361 }
358 if (text().length() > GetCursorPosition()) { 362 if (GetText().length() > GetCursorPosition()) {
359 size_t cursor_position = GetCursorPosition(); 363 size_t cursor_position = GetCursorPosition();
360 size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme( 364 size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme(
361 cursor_position, gfx::CURSOR_FORWARD); 365 cursor_position, gfx::CURSOR_FORWARD);
362 ExecuteAndRecordDelete(gfx::Range(cursor_position, next_grapheme_index), 366 ExecuteAndRecordDelete(gfx::Range(cursor_position, next_grapheme_index),
363 true); 367 true);
364 return true; 368 return true;
365 } 369 }
366 return false; 370 return false;
367 } 371 }
368 372
369 bool TextfieldViewsModel::Backspace() { 373 bool TextfieldViewsModel::Backspace() {
370 if (HasCompositionText()) { 374 if (HasCompositionText()) {
371 // No undo/redo for composition text. 375 // No undo/redo for composition text.
372 CancelCompositionText(); 376 CancelCompositionText();
373 return true; 377 return true;
374 } 378 }
375 if (HasSelection()) { 379 if (HasSelection()) {
376 DeleteSelection(); 380 DeleteSelection();
377 return true; 381 return true;
378 } 382 }
379 size_t cursor_position = GetCursorPosition(); 383 size_t cursor_position = GetCursorPosition();
380 if (cursor_position > 0) { 384 if (cursor_position > 0) {
381 // Delete one code point, which may be two UTF-16 words. 385 // Delete one code point, which may be two UTF-16 words.
382 size_t previous_char = gfx::UTF16OffsetToIndex(text(), cursor_position, -1); 386 size_t previous_char =
387 gfx::UTF16OffsetToIndex(GetText(), cursor_position, -1);
383 ExecuteAndRecordDelete(gfx::Range(cursor_position, previous_char), true); 388 ExecuteAndRecordDelete(gfx::Range(cursor_position, previous_char), true);
384 return true; 389 return true;
385 } 390 }
386 return false; 391 return false;
387 } 392 }
388 393
389 size_t TextfieldViewsModel::GetCursorPosition() const { 394 size_t TextfieldViewsModel::GetCursorPosition() const {
390 return render_text_->cursor_position(); 395 return render_text_->cursor_position();
391 } 396 }
392 397
(...skipping 19 matching lines...) Expand all
412 return render_text_->MoveCursorTo(model); 417 return render_text_->MoveCursorTo(model);
413 } 418 }
414 419
415 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) { 420 bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) {
416 if (HasCompositionText()) 421 if (HasCompositionText())
417 ConfirmCompositionText(); 422 ConfirmCompositionText();
418 return render_text_->MoveCursorTo(point, select); 423 return render_text_->MoveCursorTo(point, select);
419 } 424 }
420 425
421 base::string16 TextfieldViewsModel::GetSelectedText() const { 426 base::string16 TextfieldViewsModel::GetSelectedText() const {
422 return text().substr(render_text_->selection().GetMin(), 427 return GetText().substr(render_text_->selection().GetMin(),
423 render_text_->selection().length()); 428 render_text_->selection().length());
424 } 429 }
425 430
426 void TextfieldViewsModel::SelectRange(const gfx::Range& range) { 431 void TextfieldViewsModel::SelectRange(const gfx::Range& range) {
427 if (HasCompositionText()) 432 if (HasCompositionText())
428 ConfirmCompositionText(); 433 ConfirmCompositionText();
429 render_text_->SelectRange(range); 434 render_text_->SelectRange(range);
430 } 435 }
431 436
432 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) { 437 void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) {
433 if (HasCompositionText()) 438 if (HasCompositionText())
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 ++iter != edit_history_.end(); 472 ++iter != edit_history_.end();
468 } 473 }
469 474
470 bool TextfieldViewsModel::Undo() { 475 bool TextfieldViewsModel::Undo() {
471 if (!CanUndo()) 476 if (!CanUndo())
472 return false; 477 return false;
473 DCHECK(!HasCompositionText()); 478 DCHECK(!HasCompositionText());
474 if (HasCompositionText()) // safe guard for release build. 479 if (HasCompositionText()) // safe guard for release build.
475 CancelCompositionText(); 480 CancelCompositionText();
476 481
477 base::string16 old = text(); 482 base::string16 old = GetText();
478 size_t old_cursor = GetCursorPosition(); 483 size_t old_cursor = GetCursorPosition();
479 (*current_edit_)->Commit(); 484 (*current_edit_)->Commit();
480 (*current_edit_)->Undo(this); 485 (*current_edit_)->Undo(this);
481 486
482 if (current_edit_ == edit_history_.begin()) 487 if (current_edit_ == edit_history_.begin())
483 current_edit_ = edit_history_.end(); 488 current_edit_ = edit_history_.end();
484 else 489 else
485 current_edit_--; 490 current_edit_--;
486 return old != text() || old_cursor != GetCursorPosition(); 491 return old != GetText() || old_cursor != GetCursorPosition();
487 } 492 }
488 493
489 bool TextfieldViewsModel::Redo() { 494 bool TextfieldViewsModel::Redo() {
490 if (!CanRedo()) 495 if (!CanRedo())
491 return false; 496 return false;
492 DCHECK(!HasCompositionText()); 497 DCHECK(!HasCompositionText());
493 if (HasCompositionText()) // safe guard for release build. 498 if (HasCompositionText()) // safe guard for release build.
494 CancelCompositionText(); 499 CancelCompositionText();
495 500
496 if (current_edit_ == edit_history_.end()) 501 if (current_edit_ == edit_history_.end())
497 current_edit_ = edit_history_.begin(); 502 current_edit_ = edit_history_.begin();
498 else 503 else
499 current_edit_ ++; 504 current_edit_ ++;
500 base::string16 old = text(); 505 base::string16 old = GetText();
501 size_t old_cursor = GetCursorPosition(); 506 size_t old_cursor = GetCursorPosition();
502 (*current_edit_)->Redo(this); 507 (*current_edit_)->Redo(this);
503 return old != text() || old_cursor != GetCursorPosition(); 508 return old != GetText() || old_cursor != GetCursorPosition();
504 } 509 }
505 510
506 bool TextfieldViewsModel::Cut() { 511 bool TextfieldViewsModel::Cut() {
507 if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) { 512 if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) {
508 ui::ScopedClipboardWriter( 513 ui::ScopedClipboardWriter(
509 ui::Clipboard::GetForCurrentThread(), 514 ui::Clipboard::GetForCurrentThread(),
510 ui::CLIPBOARD_TYPE_COPY_PASTE).WriteText(GetSelectedText()); 515 ui::CLIPBOARD_TYPE_COPY_PASTE).WriteText(GetSelectedText());
511 // A trick to let undo/redo handle cursor correctly. 516 // A trick to let undo/redo handle cursor correctly.
512 // 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
513 // than beginning, unlike Delete/Backspace. 518 // than beginning, unlike Delete/Backspace.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 return !render_text_->selection().is_empty(); 551 return !render_text_->selection().is_empty();
547 } 552 }
548 553
549 void TextfieldViewsModel::DeleteSelection() { 554 void TextfieldViewsModel::DeleteSelection() {
550 DCHECK(!HasCompositionText()); 555 DCHECK(!HasCompositionText());
551 DCHECK(HasSelection()); 556 DCHECK(HasSelection());
552 ExecuteAndRecordDelete(render_text_->selection(), false); 557 ExecuteAndRecordDelete(render_text_->selection(), false);
553 } 558 }
554 559
555 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt( 560 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt(
556 const base::string16& new_text, 561 const base::string16& text, size_t position) {
557 size_t position) {
558 if (HasCompositionText()) 562 if (HasCompositionText())
559 CancelCompositionText(); 563 CancelCompositionText();
560 ExecuteAndRecordReplace(DO_NOT_MERGE, 564 ExecuteAndRecordReplace(DO_NOT_MERGE,
561 GetCursorPosition(), 565 GetCursorPosition(),
562 position + new_text.length(), 566 position + text.length(),
563 new_text, 567 text,
564 position); 568 position);
565 } 569 }
566 570
567 base::string16 TextfieldViewsModel::GetTextFromRange( 571 base::string16 TextfieldViewsModel::GetTextFromRange(
568 const gfx::Range& range) const { 572 const gfx::Range& range) const {
569 if (range.IsValid() && range.GetMin() < text().length()) 573 if (range.IsValid() && range.GetMin() < GetText().length())
570 return text().substr(range.GetMin(), range.length()); 574 return GetText().substr(range.GetMin(), range.length());
571 return base::string16(); 575 return base::string16();
572 } 576 }
573 577
574 void TextfieldViewsModel::GetTextRange(gfx::Range* range) const { 578 void TextfieldViewsModel::GetTextRange(gfx::Range* range) const {
575 *range = gfx::Range(0, text().length()); 579 *range = gfx::Range(0, GetText().length());
576 } 580 }
577 581
578 void TextfieldViewsModel::SetCompositionText( 582 void TextfieldViewsModel::SetCompositionText(
579 const ui::CompositionText& composition) { 583 const ui::CompositionText& composition) {
580 if (HasCompositionText()) 584 if (HasCompositionText())
581 CancelCompositionText(); 585 CancelCompositionText();
582 else if (HasSelection()) 586 else if (HasSelection())
583 DeleteSelection(); 587 DeleteSelection();
584 588
585 if (composition.text.empty()) 589 if (composition.text.empty())
586 return; 590 return;
587 591
588 size_t cursor = GetCursorPosition(); 592 size_t cursor = GetCursorPosition();
589 base::string16 new_text = text(); 593 base::string16 new_text = GetText();
590 render_text_->SetText(new_text.insert(cursor, composition.text)); 594 render_text_->SetText(new_text.insert(cursor, composition.text));
591 gfx::Range range(cursor, cursor + composition.text.length()); 595 gfx::Range range(cursor, cursor + composition.text.length());
592 render_text_->SetCompositionRange(range); 596 render_text_->SetCompositionRange(range);
593 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition); 597 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition);
594 if (emphasized_range.IsValid()) { 598 if (emphasized_range.IsValid()) {
595 // This is a workaround due to the lack of support in RenderText to draw 599 // This is a workaround due to the lack of support in RenderText to draw
596 // a thick underline. In a composition returned from an IME, the segment 600 // a thick underline. In a composition returned from an IME, the segment
597 // emphasized by a thick underline usually represents the target clause. 601 // emphasized by a thick underline usually represents the target clause.
598 // Because the target clause is more important than the actual selection 602 // Because the target clause is more important than the actual selection
599 // range (or caret position) in the composition here we use a selection-like 603 // range (or caret position) in the composition here we use a selection-like
600 // marker instead to show this range. 604 // marker instead to show this range.
601 // TODO(yukawa, msw): Support thick underline in RenderText and remove 605 // TODO(yukawa, msw): Support thick underline in RenderText and remove
602 // this workaround. 606 // this workaround.
603 render_text_->SelectRange(gfx::Range( 607 render_text_->SelectRange(gfx::Range(
604 cursor + emphasized_range.GetMin(), 608 cursor + emphasized_range.GetMin(),
605 cursor + emphasized_range.GetMax())); 609 cursor + emphasized_range.GetMax()));
606 } else if (!composition.selection.is_empty()) { 610 } else if (!composition.selection.is_empty()) {
607 render_text_->SelectRange(gfx::Range( 611 render_text_->SelectRange(gfx::Range(
608 cursor + composition.selection.GetMin(), 612 cursor + composition.selection.GetMin(),
609 cursor + composition.selection.GetMax())); 613 cursor + composition.selection.GetMax()));
610 } else { 614 } else {
611 render_text_->SetCursorPosition(cursor + composition.selection.end()); 615 render_text_->SetCursorPosition(cursor + composition.selection.end());
612 } 616 }
613 } 617 }
614 618
615 void TextfieldViewsModel::ConfirmCompositionText() { 619 void TextfieldViewsModel::ConfirmCompositionText() {
616 DCHECK(HasCompositionText()); 620 DCHECK(HasCompositionText());
617 gfx::Range range = render_text_->GetCompositionRange(); 621 gfx::Range range = render_text_->GetCompositionRange();
618 base::string16 composition = text().substr(range.start(), range.length()); 622 base::string16 text = GetText().substr(range.start(), range.length());
619 // TODO(oshima): current behavior on ChromeOS is a bit weird and not 623 // TODO(oshima): current behavior on ChromeOS is a bit weird and not
620 // sure exactly how this should work. Find out and fix if necessary. 624 // sure exactly how this should work. Find out and fix if necessary.
621 AddOrMergeEditHistory(new InsertEdit(false, composition, range.start())); 625 AddOrMergeEditHistory(new InsertEdit(false, text, range.start()));
622 render_text_->SetCursorPosition(range.end()); 626 render_text_->SetCursorPosition(range.end());
623 ClearComposition(); 627 ClearComposition();
624 if (delegate_) 628 if (delegate_)
625 delegate_->OnCompositionTextConfirmedOrCleared(); 629 delegate_->OnCompositionTextConfirmedOrCleared();
626 } 630 }
627 631
628 void TextfieldViewsModel::CancelCompositionText() { 632 void TextfieldViewsModel::CancelCompositionText() {
629 DCHECK(HasCompositionText()); 633 DCHECK(HasCompositionText());
630 gfx::Range range = render_text_->GetCompositionRange(); 634 gfx::Range range = render_text_->GetCompositionRange();
631 ClearComposition(); 635 ClearComposition();
632 base::string16 new_text = text(); 636 base::string16 new_text = GetText();
633 render_text_->SetText(new_text.erase(range.start(), range.length())); 637 render_text_->SetText(new_text.erase(range.start(), range.length()));
634 render_text_->SetCursorPosition(range.start()); 638 render_text_->SetCursorPosition(range.start());
635 if (delegate_) 639 if (delegate_)
636 delegate_->OnCompositionTextConfirmedOrCleared(); 640 delegate_->OnCompositionTextConfirmedOrCleared();
637 } 641 }
638 642
639 void TextfieldViewsModel::ClearComposition() { 643 void TextfieldViewsModel::ClearComposition() {
640 render_text_->SetCompositionRange(gfx::Range::InvalidRange()); 644 render_text_->SetCompositionRange(gfx::Range::InvalidRange());
641 } 645 }
642 646
643 void TextfieldViewsModel::GetCompositionTextRange(gfx::Range* range) const { 647 void TextfieldViewsModel::GetCompositionTextRange(gfx::Range* range) const {
644 *range = gfx::Range(render_text_->GetCompositionRange()); 648 *range = gfx::Range(render_text_->GetCompositionRange());
645 } 649 }
646 650
647 bool TextfieldViewsModel::HasCompositionText() const { 651 bool TextfieldViewsModel::HasCompositionText() const {
648 return !render_text_->GetCompositionRange().is_empty(); 652 return !render_text_->GetCompositionRange().is_empty();
649 } 653 }
650 654
651 void TextfieldViewsModel::ClearEditHistory() {
652 STLDeleteElements(&edit_history_);
653 current_edit_ = edit_history_.end();
654 }
655
656 ///////////////////////////////////////////////////////////////// 655 /////////////////////////////////////////////////////////////////
657 // TextfieldViewsModel: private 656 // TextfieldViewsModel: private
658 657
659 void TextfieldViewsModel::InsertTextInternal(const base::string16& new_text, 658 void TextfieldViewsModel::InsertTextInternal(const base::string16& text,
660 bool mergeable) { 659 bool mergeable) {
661 if (HasCompositionText()) { 660 if (HasCompositionText()) {
662 CancelCompositionText(); 661 CancelCompositionText();
663 ExecuteAndRecordInsert(new_text, mergeable); 662 ExecuteAndRecordInsert(text, mergeable);
664 } else if (HasSelection()) { 663 } else if (HasSelection()) {
665 ExecuteAndRecordReplaceSelection(mergeable ? MERGEABLE : DO_NOT_MERGE, 664 ExecuteAndRecordReplaceSelection(mergeable ? MERGEABLE : DO_NOT_MERGE,
666 new_text); 665 text);
667 } else { 666 } else {
668 ExecuteAndRecordInsert(new_text, mergeable); 667 ExecuteAndRecordInsert(text, mergeable);
669 } 668 }
670 } 669 }
671 670
672 void TextfieldViewsModel::ReplaceTextInternal(const base::string16& new_text, 671 void TextfieldViewsModel::ReplaceTextInternal(const base::string16& text,
673 bool mergeable) { 672 bool mergeable) {
674 if (HasCompositionText()) { 673 if (HasCompositionText()) {
675 CancelCompositionText(); 674 CancelCompositionText();
676 } else if (!HasSelection()) { 675 } else if (!HasSelection()) {
677 size_t cursor = GetCursorPosition(); 676 size_t cursor = GetCursorPosition();
678 const gfx::SelectionModel& model = render_text_->selection_model(); 677 const gfx::SelectionModel& model = render_text_->selection_model();
679 // When there is no selection, the default is to replace the next grapheme 678 // When there is no selection, the default is to replace the next grapheme
680 // with |new_text|. So, need to find the index of next grapheme first. 679 // with |text|. So, need to find the index of next grapheme first.
681 size_t next = 680 size_t next =
682 render_text_->IndexOfAdjacentGrapheme(cursor, gfx::CURSOR_FORWARD); 681 render_text_->IndexOfAdjacentGrapheme(cursor, gfx::CURSOR_FORWARD);
683 if (next == model.caret_pos()) 682 if (next == model.caret_pos())
684 render_text_->MoveCursorTo(model); 683 render_text_->MoveCursorTo(model);
685 else 684 else
686 render_text_->SelectRange(gfx::Range(next, model.caret_pos())); 685 render_text_->SelectRange(gfx::Range(next, model.caret_pos()));
687 } 686 }
688 // Edit history is recorded in InsertText. 687 // Edit history is recorded in InsertText.
689 InsertTextInternal(new_text, mergeable); 688 InsertTextInternal(text, mergeable);
689 }
690
691 void TextfieldViewsModel::ClearEditHistory() {
692 STLDeleteElements(&edit_history_);
693 current_edit_ = edit_history_.end();
690 } 694 }
691 695
692 void TextfieldViewsModel::ClearRedoHistory() { 696 void TextfieldViewsModel::ClearRedoHistory() {
693 if (edit_history_.begin() == edit_history_.end()) 697 if (edit_history_.begin() == edit_history_.end())
694 return; 698 return;
695 if (current_edit_ == edit_history_.end()) { 699 if (current_edit_ == edit_history_.end()) {
696 ClearEditHistory(); 700 ClearEditHistory();
697 return; 701 return;
698 } 702 }
699 EditHistory::iterator delete_start = current_edit_; 703 EditHistory::iterator delete_start = current_edit_;
700 delete_start++; 704 delete_start++;
701 STLDeleteContainerPointers(delete_start, edit_history_.end()); 705 STLDeleteContainerPointers(delete_start, edit_history_.end());
702 edit_history_.erase(delete_start, edit_history_.end()); 706 edit_history_.erase(delete_start, edit_history_.end());
703 } 707 }
704 708
705 void TextfieldViewsModel::ExecuteAndRecordDelete(gfx::Range range, 709 void TextfieldViewsModel::ExecuteAndRecordDelete(gfx::Range range,
706 bool mergeable) { 710 bool mergeable) {
707 size_t old_text_start = range.GetMin(); 711 size_t old_text_start = range.GetMin();
708 const base::string16 old_text = text().substr(old_text_start, range.length()); 712 const base::string16 text = GetText().substr(old_text_start, range.length());
709 bool backward = range.is_reversed(); 713 bool backward = range.is_reversed();
710 Edit* edit = new DeleteEdit(mergeable, old_text, old_text_start, backward); 714 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward);
711 bool delete_edit = AddOrMergeEditHistory(edit); 715 bool delete_edit = AddOrMergeEditHistory(edit);
712 edit->Redo(this); 716 edit->Redo(this);
713 if (delete_edit) 717 if (delete_edit)
714 delete edit; 718 delete edit;
715 } 719 }
716 720
717 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection( 721 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection(
718 MergeType merge_type, 722 MergeType merge_type, const base::string16& new_text) {
719 const base::string16& new_text) {
720 size_t new_text_start = render_text_->selection().GetMin(); 723 size_t new_text_start = render_text_->selection().GetMin();
721 size_t new_cursor_pos = new_text_start + new_text.length(); 724 size_t new_cursor_pos = new_text_start + new_text.length();
722 ExecuteAndRecordReplace(merge_type, 725 ExecuteAndRecordReplace(merge_type,
723 GetCursorPosition(), 726 GetCursorPosition(),
724 new_cursor_pos, 727 new_cursor_pos,
725 new_text, 728 new_text,
726 new_text_start); 729 new_text_start);
727 } 730 }
728 731
729 void TextfieldViewsModel::ExecuteAndRecordReplace( 732 void TextfieldViewsModel::ExecuteAndRecordReplace(
(...skipping 11 matching lines...) Expand all
741 backward, 744 backward,
742 new_cursor_pos, 745 new_cursor_pos,
743 new_text, 746 new_text,
744 new_text_start); 747 new_text_start);
745 bool delete_edit = AddOrMergeEditHistory(edit); 748 bool delete_edit = AddOrMergeEditHistory(edit);
746 edit->Redo(this); 749 edit->Redo(this);
747 if (delete_edit) 750 if (delete_edit)
748 delete edit; 751 delete edit;
749 } 752 }
750 753
751 void TextfieldViewsModel::ExecuteAndRecordInsert(const base::string16& new_text, 754 void TextfieldViewsModel::ExecuteAndRecordInsert(const base::string16& text,
752 bool mergeable) { 755 bool mergeable) {
753 Edit* edit = new InsertEdit(mergeable, new_text, GetCursorPosition()); 756 Edit* edit = new InsertEdit(mergeable, text, GetCursorPosition());
754 bool delete_edit = AddOrMergeEditHistory(edit); 757 bool delete_edit = AddOrMergeEditHistory(edit);
755 edit->Redo(this); 758 edit->Redo(this);
756 if (delete_edit) 759 if (delete_edit)
757 delete edit; 760 delete edit;
758 } 761 }
759 762
760 bool TextfieldViewsModel::AddOrMergeEditHistory(Edit* edit) { 763 bool TextfieldViewsModel::AddOrMergeEditHistory(Edit* edit) {
761 ClearRedoHistory(); 764 ClearRedoHistory();
762 765
763 if (current_edit_ != edit_history_.end() && (*current_edit_)->Merge(edit)) { 766 if (current_edit_ != edit_history_.end() && (*current_edit_)->Merge(edit)) {
(...skipping 13 matching lines...) Expand all
777 } 780 }
778 return false; 781 return false;
779 } 782 }
780 783
781 void TextfieldViewsModel::ModifyText(size_t delete_from, 784 void TextfieldViewsModel::ModifyText(size_t delete_from,
782 size_t delete_to, 785 size_t delete_to,
783 const base::string16& new_text, 786 const base::string16& new_text,
784 size_t new_text_insert_at, 787 size_t new_text_insert_at,
785 size_t new_cursor_pos) { 788 size_t new_cursor_pos) {
786 DCHECK_LE(delete_from, delete_to); 789 DCHECK_LE(delete_from, delete_to);
787 base::string16 old_text = text(); 790 base::string16 text = GetText();
788 ClearComposition(); 791 ClearComposition();
789 if (delete_from != delete_to) 792 if (delete_from != delete_to)
790 render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from)); 793 render_text_->SetText(text.erase(delete_from, delete_to - delete_from));
791 if (!new_text.empty()) 794 if (!new_text.empty())
792 render_text_->SetText(old_text.insert(new_text_insert_at, new_text)); 795 render_text_->SetText(text.insert(new_text_insert_at, new_text));
793 render_text_->SetCursorPosition(new_cursor_pos); 796 render_text_->SetCursorPosition(new_cursor_pos);
794 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't). 797 // TODO(oshima): mac selects the text that is just undone (but gtk doesn't).
795 // This looks fine feature and we may want to do the same. 798 // This looks fine feature and we may want to do the same.
796 } 799 }
797 800
798 } // namespace views 801 } // 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