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

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

Issue 117983002: Prefix string16 with base:: in ui/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 7 years 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 void Commit() { merge_type_ = DO_NOT_MERGE; } 74 void Commit() { merge_type_ = DO_NOT_MERGE; }
75 75
76 private: 76 private:
77 friend class InsertEdit; 77 friend class InsertEdit;
78 friend class ReplaceEdit; 78 friend class ReplaceEdit;
79 friend class DeleteEdit; 79 friend class DeleteEdit;
80 80
81 Edit(Type type, 81 Edit(Type type,
82 MergeType merge_type, 82 MergeType merge_type,
83 size_t old_cursor_pos, 83 size_t old_cursor_pos,
84 const string16& old_text, 84 const base::string16& old_text,
85 size_t old_text_start, 85 size_t old_text_start,
86 bool delete_backward, 86 bool delete_backward,
87 size_t new_cursor_pos, 87 size_t new_cursor_pos,
88 const string16& new_text, 88 const base::string16& new_text,
89 size_t new_text_start) 89 size_t new_text_start)
90 : type_(type), 90 : type_(type),
91 merge_type_(merge_type), 91 merge_type_(merge_type),
92 old_cursor_pos_(old_cursor_pos), 92 old_cursor_pos_(old_cursor_pos),
93 old_text_(old_text), 93 old_text_(old_text),
94 old_text_start_(old_text_start), 94 old_text_start_(old_text_start),
95 delete_backward_(delete_backward), 95 delete_backward_(delete_backward),
96 new_cursor_pos_(new_cursor_pos), 96 new_cursor_pos_(new_cursor_pos),
97 new_text_(new_text), 97 new_text_(new_text),
98 new_text_start_(new_text_start) { 98 new_text_start_(new_text_start) {
(...skipping 19 matching lines...) Expand all
118 // Returns the end index of the |new_text_|. 118 // Returns the end index of the |new_text_|.
119 size_t new_text_end() const { return new_text_start_ + new_text_.length(); } 119 size_t new_text_end() const { return new_text_start_ + new_text_.length(); }
120 120
121 // Merge the replace edit into the current edit. This is a special case to 121 // Merge the replace edit into the current edit. This is a special case to
122 // handle an omnibox setting autocomplete string after new character is 122 // handle an omnibox setting autocomplete string after new character is
123 // typed in. 123 // typed in.
124 void MergeReplace(const Edit* edit) { 124 void MergeReplace(const Edit* edit) {
125 CHECK_EQ(REPLACE_EDIT, edit->type_); 125 CHECK_EQ(REPLACE_EDIT, edit->type_);
126 CHECK_EQ(0U, edit->old_text_start_); 126 CHECK_EQ(0U, edit->old_text_start_);
127 CHECK_EQ(0U, edit->new_text_start_); 127 CHECK_EQ(0U, edit->new_text_start_);
128 string16 old_text = edit->old_text_; 128 base::string16 old_text = edit->old_text_;
129 old_text.erase(new_text_start_, new_text_.length()); 129 old_text.erase(new_text_start_, new_text_.length());
130 old_text.insert(old_text_start_, old_text_); 130 old_text.insert(old_text_start_, old_text_);
131 // SetText() replaces entire text. Set |old_text_| to the entire 131 // SetText() replaces entire text. Set |old_text_| to the entire
132 // replaced text with |this| edit undone. 132 // replaced text with |this| edit undone.
133 old_text_ = old_text; 133 old_text_ = old_text;
134 old_text_start_ = edit->old_text_start_; 134 old_text_start_ = edit->old_text_start_;
135 delete_backward_ = false; 135 delete_backward_ = false;
136 136
137 new_text_ = edit->new_text_; 137 new_text_ = edit->new_text_;
138 new_text_start_ = edit->new_text_start_; 138 new_text_start_ = edit->new_text_start_;
139 merge_type_ = DO_NOT_MERGE; 139 merge_type_ = DO_NOT_MERGE;
140 } 140 }
141 141
142 Type type_; 142 Type type_;
143 143
144 // True if the edit can be marged. 144 // True if the edit can be marged.
145 MergeType merge_type_; 145 MergeType merge_type_;
146 // Old cursor position. 146 // Old cursor position.
147 size_t old_cursor_pos_; 147 size_t old_cursor_pos_;
148 // Deleted text by this edit. 148 // Deleted text by this edit.
149 string16 old_text_; 149 base::string16 old_text_;
150 // The index of |old_text_|. 150 // The index of |old_text_|.
151 size_t old_text_start_; 151 size_t old_text_start_;
152 // True if the deletion is made backward. 152 // True if the deletion is made backward.
153 bool delete_backward_; 153 bool delete_backward_;
154 // New cursor position. 154 // New cursor position.
155 size_t new_cursor_pos_; 155 size_t new_cursor_pos_;
156 // Added text. 156 // Added text.
157 string16 new_text_; 157 base::string16 new_text_;
158 // The index of |new_text_| 158 // The index of |new_text_|
159 size_t new_text_start_; 159 size_t new_text_start_;
160 160
161 DISALLOW_COPY_AND_ASSIGN(Edit); 161 DISALLOW_COPY_AND_ASSIGN(Edit);
162 }; 162 };
163 163
164 class InsertEdit : public Edit { 164 class InsertEdit : public Edit {
165 public: 165 public:
166 InsertEdit(bool mergeable, const string16& new_text, size_t at) 166 InsertEdit(bool mergeable, const base::string16& new_text, size_t at)
167 : Edit(INSERT_EDIT, 167 : Edit(INSERT_EDIT,
168 mergeable ? MERGEABLE : DO_NOT_MERGE, 168 mergeable ? MERGEABLE : DO_NOT_MERGE,
169 at /* old cursor */, 169 at /* old cursor */,
170 string16(), 170 base::string16(),
171 at, 171 at,
172 false /* N/A */, 172 false /* N/A */,
173 at + new_text.length() /* new cursor */, 173 at + new_text.length() /* new cursor */,
174 new_text, 174 new_text,
175 at) { 175 at) {
176 } 176 }
177 177
178 // Edit implementation. 178 // Edit implementation.
179 virtual bool DoMerge(const Edit* edit) OVERRIDE { 179 virtual bool DoMerge(const Edit* edit) OVERRIDE {
180 if (edit->type() != INSERT_EDIT || new_text_end() != edit->new_text_start_) 180 if (edit->type() != INSERT_EDIT || new_text_end() != edit->new_text_start_)
181 return false; 181 return false;
182 // If continuous edit, merge it. 182 // If continuous edit, merge it.
183 // TODO(oshima): gtk splits edits between whitespace. Find out what 183 // TODO(oshima): gtk splits edits between whitespace. Find out what
184 // we want to here and implement if necessary. 184 // we want to here and implement if necessary.
185 new_text_ += edit->new_text_; 185 new_text_ += edit->new_text_;
186 new_cursor_pos_ = edit->new_cursor_pos_; 186 new_cursor_pos_ = edit->new_cursor_pos_;
187 return true; 187 return true;
188 } 188 }
189 }; 189 };
190 190
191 class ReplaceEdit : public Edit { 191 class ReplaceEdit : public Edit {
192 public: 192 public:
193 ReplaceEdit(MergeType merge_type, 193 ReplaceEdit(MergeType merge_type,
194 const string16& old_text, 194 const base::string16& old_text,
195 size_t old_cursor_pos, 195 size_t old_cursor_pos,
196 size_t old_text_start, 196 size_t old_text_start,
197 bool backward, 197 bool backward,
198 size_t new_cursor_pos, 198 size_t new_cursor_pos,
199 const string16& new_text, 199 const base::string16& new_text,
200 size_t new_text_start) 200 size_t new_text_start)
201 : Edit(REPLACE_EDIT, merge_type, 201 : Edit(REPLACE_EDIT, merge_type,
202 old_cursor_pos, 202 old_cursor_pos,
203 old_text, 203 old_text,
204 old_text_start, 204 old_text_start,
205 backward, 205 backward,
206 new_cursor_pos, 206 new_cursor_pos,
207 new_text, 207 new_text,
208 new_text_start) { 208 new_text_start) {
209 } 209 }
210 210
211 // Edit implementation. 211 // Edit implementation.
212 virtual bool DoMerge(const Edit* edit) OVERRIDE { 212 virtual bool DoMerge(const Edit* edit) OVERRIDE {
213 if (edit->type() == DELETE_EDIT || 213 if (edit->type() == DELETE_EDIT ||
214 new_text_end() != edit->old_text_start_ || 214 new_text_end() != edit->old_text_start_ ||
215 edit->old_text_start_ != edit->new_text_start_) 215 edit->old_text_start_ != edit->new_text_start_)
216 return false; 216 return false;
217 old_text_ += edit->old_text_; 217 old_text_ += edit->old_text_;
218 new_text_ += edit->new_text_; 218 new_text_ += edit->new_text_;
219 new_cursor_pos_ = edit->new_cursor_pos_; 219 new_cursor_pos_ = edit->new_cursor_pos_;
220 return true; 220 return true;
221 } 221 }
222 }; 222 };
223 223
224 class DeleteEdit : public Edit { 224 class DeleteEdit : public Edit {
225 public: 225 public:
226 DeleteEdit(bool mergeable, 226 DeleteEdit(bool mergeable,
227 const string16& text, 227 const base::string16& text,
228 size_t text_start, 228 size_t text_start,
229 bool backward) 229 bool backward)
230 : Edit(DELETE_EDIT, 230 : Edit(DELETE_EDIT,
231 mergeable ? MERGEABLE : DO_NOT_MERGE, 231 mergeable ? MERGEABLE : DO_NOT_MERGE,
232 (backward ? text_start + text.length() : text_start), 232 (backward ? text_start + text.length() : text_start),
233 text, 233 text,
234 text_start, 234 text_start,
235 backward, 235 backward,
236 text_start, 236 text_start,
237 string16(), 237 base::string16(),
238 text_start) { 238 text_start) {
239 } 239 }
240 240
241 // Edit implementation. 241 // Edit implementation.
242 virtual bool DoMerge(const Edit* edit) OVERRIDE { 242 virtual bool DoMerge(const Edit* edit) OVERRIDE {
243 if (edit->type() != DELETE_EDIT) 243 if (edit->type() != DELETE_EDIT)
244 return false; 244 return false;
245 245
246 if (delete_backward_) { 246 if (delete_backward_) {
247 // backspace can be merged only with backspace at the 247 // backspace can be merged only with backspace at the
(...skipping 51 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 const string16& TextfieldViewsModel::GetText() const { 309 const base::string16& TextfieldViewsModel::GetText() const {
310 return render_text_->text(); 310 return render_text_->text();
311 } 311 }
312 312
313 bool TextfieldViewsModel::SetText(const string16& text) { 313 bool TextfieldViewsModel::SetText(const base::string16& text) {
314 bool changed = false; 314 bool changed = false;
315 if (HasCompositionText()) { 315 if (HasCompositionText()) {
316 ConfirmCompositionText(); 316 ConfirmCompositionText();
317 changed = true; 317 changed = true;
318 } 318 }
319 if (GetText() != text) { 319 if (GetText() != text) {
320 if (changed) // No need to remember composition. 320 if (changed) // No need to remember composition.
321 Undo(); 321 Undo();
322 size_t old_cursor = GetCursorPosition(); 322 size_t old_cursor = GetCursorPosition();
323 // SetText moves the cursor to the end. 323 // SetText moves the cursor to the end.
324 size_t new_cursor = text.length(); 324 size_t new_cursor = text.length();
325 SelectAll(false); 325 SelectAll(false);
326 // 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.
327 // Otherwise, force merge the edits. 327 // Otherwise, force merge the edits.
328 ExecuteAndRecordReplace( 328 ExecuteAndRecordReplace(
329 changed ? DO_NOT_MERGE : MERGE_WITH_PREVIOUS, 329 changed ? DO_NOT_MERGE : MERGE_WITH_PREVIOUS,
330 old_cursor, 330 old_cursor,
331 new_cursor, 331 new_cursor,
332 text, 332 text,
333 0U); 333 0U);
334 render_text_->SetCursorPosition(new_cursor); 334 render_text_->SetCursorPosition(new_cursor);
335 } 335 }
336 ClearSelection(); 336 ClearSelection();
337 return changed; 337 return changed;
338 } 338 }
339 339
340 void TextfieldViewsModel::Append(const string16& text) { 340 void TextfieldViewsModel::Append(const base::string16& text) {
341 if (HasCompositionText()) 341 if (HasCompositionText())
342 ConfirmCompositionText(); 342 ConfirmCompositionText();
343 size_t save = GetCursorPosition(); 343 size_t save = GetCursorPosition();
344 MoveCursor(gfx::LINE_BREAK, 344 MoveCursor(gfx::LINE_BREAK,
345 render_text_->GetVisualDirectionOfLogicalEnd(), 345 render_text_->GetVisualDirectionOfLogicalEnd(),
346 false); 346 false);
347 InsertText(text); 347 InsertText(text);
348 render_text_->SetCursorPosition(save); 348 render_text_->SetCursorPosition(save);
349 ClearSelection(); 349 ClearSelection();
350 } 350 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 base::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 gfx::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
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 ++iter != edit_history_.end(); 472 ++iter != edit_history_.end();
473 } 473 }
474 474
475 bool TextfieldViewsModel::Undo() { 475 bool TextfieldViewsModel::Undo() {
476 if (!CanUndo()) 476 if (!CanUndo())
477 return false; 477 return false;
478 DCHECK(!HasCompositionText()); 478 DCHECK(!HasCompositionText());
479 if (HasCompositionText()) // safe guard for release build. 479 if (HasCompositionText()) // safe guard for release build.
480 CancelCompositionText(); 480 CancelCompositionText();
481 481
482 string16 old = GetText(); 482 base::string16 old = GetText();
483 size_t old_cursor = GetCursorPosition(); 483 size_t old_cursor = GetCursorPosition();
484 (*current_edit_)->Commit(); 484 (*current_edit_)->Commit();
485 (*current_edit_)->Undo(this); 485 (*current_edit_)->Undo(this);
486 486
487 if (current_edit_ == edit_history_.begin()) 487 if (current_edit_ == edit_history_.begin())
488 current_edit_ = edit_history_.end(); 488 current_edit_ = edit_history_.end();
489 else 489 else
490 current_edit_--; 490 current_edit_--;
491 return old != GetText() || old_cursor != GetCursorPosition(); 491 return old != GetText() || old_cursor != GetCursorPosition();
492 } 492 }
493 493
494 bool TextfieldViewsModel::Redo() { 494 bool TextfieldViewsModel::Redo() {
495 if (!CanRedo()) 495 if (!CanRedo())
496 return false; 496 return false;
497 DCHECK(!HasCompositionText()); 497 DCHECK(!HasCompositionText());
498 if (HasCompositionText()) // safe guard for release build. 498 if (HasCompositionText()) // safe guard for release build.
499 CancelCompositionText(); 499 CancelCompositionText();
500 500
501 if (current_edit_ == edit_history_.end()) 501 if (current_edit_ == edit_history_.end())
502 current_edit_ = edit_history_.begin(); 502 current_edit_ = edit_history_.begin();
503 else 503 else
504 current_edit_ ++; 504 current_edit_ ++;
505 string16 old = GetText(); 505 base::string16 old = GetText();
506 size_t old_cursor = GetCursorPosition(); 506 size_t old_cursor = GetCursorPosition();
507 (*current_edit_)->Redo(this); 507 (*current_edit_)->Redo(this);
508 return old != GetText() || old_cursor != GetCursorPosition(); 508 return old != GetText() || old_cursor != GetCursorPosition();
509 } 509 }
510 510
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_TYPE_COPY_PASTE).WriteText(GetSelectedText()); 515 ui::CLIPBOARD_TYPE_COPY_PASTE).WriteText(GetSelectedText());
(...skipping 14 matching lines...) Expand all
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(),
533 ui::CLIPBOARD_TYPE_COPY_PASTE).WriteText(GetSelectedText()); 533 ui::CLIPBOARD_TYPE_COPY_PASTE).WriteText(GetSelectedText());
534 return true; 534 return true;
535 } 535 }
536 return false; 536 return false;
537 } 537 }
538 538
539 bool TextfieldViewsModel::Paste() { 539 bool TextfieldViewsModel::Paste() {
540 string16 result; 540 base::string16 result;
541 ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, 541 ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE,
542 &result); 542 &result);
543 if (!result.empty()) { 543 if (!result.empty()) {
544 InsertTextInternal(result, false); 544 InsertTextInternal(result, false);
545 return true; 545 return true;
546 } 546 }
547 return false; 547 return false;
548 } 548 }
549 549
550 bool TextfieldViewsModel::HasSelection() const { 550 bool TextfieldViewsModel::HasSelection() const {
551 return !render_text_->selection().is_empty(); 551 return !render_text_->selection().is_empty();
552 } 552 }
553 553
554 void TextfieldViewsModel::DeleteSelection() { 554 void TextfieldViewsModel::DeleteSelection() {
555 DCHECK(!HasCompositionText()); 555 DCHECK(!HasCompositionText());
556 DCHECK(HasSelection()); 556 DCHECK(HasSelection());
557 ExecuteAndRecordDelete(render_text_->selection(), false); 557 ExecuteAndRecordDelete(render_text_->selection(), false);
558 } 558 }
559 559
560 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt( 560 void TextfieldViewsModel::DeleteSelectionAndInsertTextAt(
561 const string16& text, size_t position) { 561 const base::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 gfx::Range& range) const { 571 base::string16 TextfieldViewsModel::GetTextFromRange(
572 const gfx::Range& range) const {
572 if (range.IsValid() && range.GetMin() < GetText().length()) 573 if (range.IsValid() && range.GetMin() < GetText().length())
573 return GetText().substr(range.GetMin(), range.length()); 574 return GetText().substr(range.GetMin(), range.length());
574 return string16(); 575 return base::string16();
575 } 576 }
576 577
577 void TextfieldViewsModel::GetTextRange(gfx::Range* range) const { 578 void TextfieldViewsModel::GetTextRange(gfx::Range* range) const {
578 *range = gfx::Range(0, GetText().length()); 579 *range = gfx::Range(0, GetText().length());
579 } 580 }
580 581
581 void TextfieldViewsModel::SetCompositionText( 582 void TextfieldViewsModel::SetCompositionText(
582 const ui::CompositionText& composition) { 583 const ui::CompositionText& composition) {
583 if (HasCompositionText()) 584 if (HasCompositionText())
584 CancelCompositionText(); 585 CancelCompositionText();
585 else if (HasSelection()) 586 else if (HasSelection())
586 DeleteSelection(); 587 DeleteSelection();
587 588
588 if (composition.text.empty()) 589 if (composition.text.empty())
589 return; 590 return;
590 591
591 size_t cursor = GetCursorPosition(); 592 size_t cursor = GetCursorPosition();
592 string16 new_text = GetText(); 593 base::string16 new_text = GetText();
593 render_text_->SetText(new_text.insert(cursor, composition.text)); 594 render_text_->SetText(new_text.insert(cursor, composition.text));
594 gfx::Range range(cursor, cursor + composition.text.length()); 595 gfx::Range range(cursor, cursor + composition.text.length());
595 render_text_->SetCompositionRange(range); 596 render_text_->SetCompositionRange(range);
596 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition); 597 gfx::Range emphasized_range = GetFirstEmphasizedRange(composition);
597 if (emphasized_range.IsValid()) { 598 if (emphasized_range.IsValid()) {
598 // 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
599 // 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
600 // emphasized by a thick underline usually represents the target clause. 601 // emphasized by a thick underline usually represents the target clause.
601 // Because the target clause is more important than the actual selection 602 // 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 603 // range (or caret position) in the composition here we use a selection-like
603 // marker instead to show this range. 604 // marker instead to show this range.
604 // TODO(yukawa, msw): Support thick underline in RenderText and remove 605 // TODO(yukawa, msw): Support thick underline in RenderText and remove
605 // this workaround. 606 // this workaround.
606 render_text_->SelectRange(gfx::Range( 607 render_text_->SelectRange(gfx::Range(
607 cursor + emphasized_range.GetMin(), 608 cursor + emphasized_range.GetMin(),
608 cursor + emphasized_range.GetMax())); 609 cursor + emphasized_range.GetMax()));
609 } else if (!composition.selection.is_empty()) { 610 } else if (!composition.selection.is_empty()) {
610 render_text_->SelectRange(gfx::Range( 611 render_text_->SelectRange(gfx::Range(
611 cursor + composition.selection.GetMin(), 612 cursor + composition.selection.GetMin(),
612 cursor + composition.selection.GetMax())); 613 cursor + composition.selection.GetMax()));
613 } else { 614 } else {
614 render_text_->SetCursorPosition(cursor + composition.selection.end()); 615 render_text_->SetCursorPosition(cursor + composition.selection.end());
615 } 616 }
616 } 617 }
617 618
618 void TextfieldViewsModel::ConfirmCompositionText() { 619 void TextfieldViewsModel::ConfirmCompositionText() {
619 DCHECK(HasCompositionText()); 620 DCHECK(HasCompositionText());
620 gfx::Range range = render_text_->GetCompositionRange(); 621 gfx::Range range = render_text_->GetCompositionRange();
621 string16 text = GetText().substr(range.start(), range.length()); 622 base::string16 text = GetText().substr(range.start(), range.length());
622 // 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
623 // 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.
624 AddOrMergeEditHistory(new InsertEdit(false, text, range.start())); 625 AddOrMergeEditHistory(new InsertEdit(false, text, range.start()));
625 render_text_->SetCursorPosition(range.end()); 626 render_text_->SetCursorPosition(range.end());
626 ClearComposition(); 627 ClearComposition();
627 if (delegate_) 628 if (delegate_)
628 delegate_->OnCompositionTextConfirmedOrCleared(); 629 delegate_->OnCompositionTextConfirmedOrCleared();
629 } 630 }
630 631
631 void TextfieldViewsModel::CancelCompositionText() { 632 void TextfieldViewsModel::CancelCompositionText() {
632 DCHECK(HasCompositionText()); 633 DCHECK(HasCompositionText());
633 gfx::Range range = render_text_->GetCompositionRange(); 634 gfx::Range range = render_text_->GetCompositionRange();
634 ClearComposition(); 635 ClearComposition();
635 string16 new_text = GetText(); 636 base::string16 new_text = GetText();
636 render_text_->SetText(new_text.erase(range.start(), range.length())); 637 render_text_->SetText(new_text.erase(range.start(), range.length()));
637 render_text_->SetCursorPosition(range.start()); 638 render_text_->SetCursorPosition(range.start());
638 if (delegate_) 639 if (delegate_)
639 delegate_->OnCompositionTextConfirmedOrCleared(); 640 delegate_->OnCompositionTextConfirmedOrCleared();
640 } 641 }
641 642
642 void TextfieldViewsModel::ClearComposition() { 643 void TextfieldViewsModel::ClearComposition() {
643 render_text_->SetCompositionRange(gfx::Range::InvalidRange()); 644 render_text_->SetCompositionRange(gfx::Range::InvalidRange());
644 } 645 }
645 646
646 void TextfieldViewsModel::GetCompositionTextRange(gfx::Range* range) const { 647 void TextfieldViewsModel::GetCompositionTextRange(gfx::Range* range) const {
647 *range = gfx::Range(render_text_->GetCompositionRange()); 648 *range = gfx::Range(render_text_->GetCompositionRange());
648 } 649 }
649 650
650 bool TextfieldViewsModel::HasCompositionText() const { 651 bool TextfieldViewsModel::HasCompositionText() const {
651 return !render_text_->GetCompositionRange().is_empty(); 652 return !render_text_->GetCompositionRange().is_empty();
652 } 653 }
653 654
654 ///////////////////////////////////////////////////////////////// 655 /////////////////////////////////////////////////////////////////
655 // TextfieldViewsModel: private 656 // TextfieldViewsModel: private
656 657
657 void TextfieldViewsModel::InsertTextInternal(const string16& text, 658 void TextfieldViewsModel::InsertTextInternal(const base::string16& text,
658 bool mergeable) { 659 bool mergeable) {
659 if (HasCompositionText()) { 660 if (HasCompositionText()) {
660 CancelCompositionText(); 661 CancelCompositionText();
661 ExecuteAndRecordInsert(text, mergeable); 662 ExecuteAndRecordInsert(text, mergeable);
662 } else if (HasSelection()) { 663 } else if (HasSelection()) {
663 ExecuteAndRecordReplaceSelection(mergeable ? MERGEABLE : DO_NOT_MERGE, 664 ExecuteAndRecordReplaceSelection(mergeable ? MERGEABLE : DO_NOT_MERGE,
664 text); 665 text);
665 } else { 666 } else {
666 ExecuteAndRecordInsert(text, mergeable); 667 ExecuteAndRecordInsert(text, mergeable);
667 } 668 }
668 } 669 }
669 670
670 void TextfieldViewsModel::ReplaceTextInternal(const string16& text, 671 void TextfieldViewsModel::ReplaceTextInternal(const base::string16& text,
671 bool mergeable) { 672 bool mergeable) {
672 if (HasCompositionText()) { 673 if (HasCompositionText()) {
673 CancelCompositionText(); 674 CancelCompositionText();
674 } else if (!HasSelection()) { 675 } else if (!HasSelection()) {
675 size_t cursor = GetCursorPosition(); 676 size_t cursor = GetCursorPosition();
676 const gfx::SelectionModel& model = render_text_->selection_model(); 677 const gfx::SelectionModel& model = render_text_->selection_model();
677 // 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
678 // with |text|. So, need to find the index of next grapheme first. 679 // with |text|. So, need to find the index of next grapheme first.
679 size_t next = 680 size_t next =
680 render_text_->IndexOfAdjacentGrapheme(cursor, gfx::CURSOR_FORWARD); 681 render_text_->IndexOfAdjacentGrapheme(cursor, gfx::CURSOR_FORWARD);
(...skipping 20 matching lines...) Expand all
701 } 702 }
702 EditHistory::iterator delete_start = current_edit_; 703 EditHistory::iterator delete_start = current_edit_;
703 delete_start++; 704 delete_start++;
704 STLDeleteContainerPointers(delete_start, edit_history_.end()); 705 STLDeleteContainerPointers(delete_start, edit_history_.end());
705 edit_history_.erase(delete_start, edit_history_.end()); 706 edit_history_.erase(delete_start, edit_history_.end());
706 } 707 }
707 708
708 void TextfieldViewsModel::ExecuteAndRecordDelete(gfx::Range range, 709 void TextfieldViewsModel::ExecuteAndRecordDelete(gfx::Range range,
709 bool mergeable) { 710 bool mergeable) {
710 size_t old_text_start = range.GetMin(); 711 size_t old_text_start = range.GetMin();
711 const string16 text = GetText().substr(old_text_start, range.length()); 712 const base::string16 text = GetText().substr(old_text_start, range.length());
712 bool backward = range.is_reversed(); 713 bool backward = range.is_reversed();
713 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward); 714 Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward);
714 bool delete_edit = AddOrMergeEditHistory(edit); 715 bool delete_edit = AddOrMergeEditHistory(edit);
715 edit->Redo(this); 716 edit->Redo(this);
716 if (delete_edit) 717 if (delete_edit)
717 delete edit; 718 delete edit;
718 } 719 }
719 720
720 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection( 721 void TextfieldViewsModel::ExecuteAndRecordReplaceSelection(
721 MergeType merge_type, const string16& new_text) { 722 MergeType merge_type, const base::string16& new_text) {
722 size_t new_text_start = render_text_->selection().GetMin(); 723 size_t new_text_start = render_text_->selection().GetMin();
723 size_t new_cursor_pos = new_text_start + new_text.length(); 724 size_t new_cursor_pos = new_text_start + new_text.length();
724 ExecuteAndRecordReplace(merge_type, 725 ExecuteAndRecordReplace(merge_type,
725 GetCursorPosition(), 726 GetCursorPosition(),
726 new_cursor_pos, 727 new_cursor_pos,
727 new_text, 728 new_text,
728 new_text_start); 729 new_text_start);
729 } 730 }
730 731
731 void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type, 732 void TextfieldViewsModel::ExecuteAndRecordReplace(
732 size_t old_cursor_pos, 733 MergeType merge_type,
733 size_t new_cursor_pos, 734 size_t old_cursor_pos,
734 const string16& new_text, 735 size_t new_cursor_pos,
735 size_t new_text_start) { 736 const base::string16& new_text,
737 size_t new_text_start) {
736 size_t old_text_start = render_text_->selection().GetMin(); 738 size_t old_text_start = render_text_->selection().GetMin();
737 bool backward = render_text_->selection().is_reversed(); 739 bool backward = render_text_->selection().is_reversed();
738 Edit* edit = new ReplaceEdit(merge_type, 740 Edit* edit = new ReplaceEdit(merge_type,
739 GetSelectedText(), 741 GetSelectedText(),
740 old_cursor_pos, 742 old_cursor_pos,
741 old_text_start, 743 old_text_start,
742 backward, 744 backward,
743 new_cursor_pos, 745 new_cursor_pos,
744 new_text, 746 new_text,
745 new_text_start); 747 new_text_start);
746 bool delete_edit = AddOrMergeEditHistory(edit); 748 bool delete_edit = AddOrMergeEditHistory(edit);
747 edit->Redo(this); 749 edit->Redo(this);
748 if (delete_edit) 750 if (delete_edit)
749 delete edit; 751 delete edit;
750 } 752 }
751 753
752 void TextfieldViewsModel::ExecuteAndRecordInsert(const string16& text, 754 void TextfieldViewsModel::ExecuteAndRecordInsert(const base::string16& text,
753 bool mergeable) { 755 bool mergeable) {
754 Edit* edit = new InsertEdit(mergeable, text, GetCursorPosition()); 756 Edit* edit = new InsertEdit(mergeable, text, GetCursorPosition());
755 bool delete_edit = AddOrMergeEditHistory(edit); 757 bool delete_edit = AddOrMergeEditHistory(edit);
756 edit->Redo(this); 758 edit->Redo(this);
757 if (delete_edit) 759 if (delete_edit)
758 delete edit; 760 delete edit;
759 } 761 }
760 762
761 bool TextfieldViewsModel::AddOrMergeEditHistory(Edit* edit) { 763 bool TextfieldViewsModel::AddOrMergeEditHistory(Edit* edit) {
762 ClearRedoHistory(); 764 ClearRedoHistory();
(...skipping 11 matching lines...) Expand all
774 DCHECK_EQ(1u, edit_history_.size()); 776 DCHECK_EQ(1u, edit_history_.size());
775 current_edit_ = edit_history_.begin(); 777 current_edit_ = edit_history_.begin();
776 } else { 778 } else {
777 current_edit_++; 779 current_edit_++;
778 } 780 }
779 return false; 781 return false;
780 } 782 }
781 783
782 void TextfieldViewsModel::ModifyText(size_t delete_from, 784 void TextfieldViewsModel::ModifyText(size_t delete_from,
783 size_t delete_to, 785 size_t delete_to,
784 const string16& new_text, 786 const base::string16& new_text,
785 size_t new_text_insert_at, 787 size_t new_text_insert_at,
786 size_t new_cursor_pos) { 788 size_t new_cursor_pos) {
787 DCHECK_LE(delete_from, delete_to); 789 DCHECK_LE(delete_from, delete_to);
788 string16 text = GetText(); 790 base::string16 text = GetText();
789 ClearComposition(); 791 ClearComposition();
790 if (delete_from != delete_to) 792 if (delete_from != delete_to)
791 render_text_->SetText(text.erase(delete_from, delete_to - delete_from)); 793 render_text_->SetText(text.erase(delete_from, delete_to - delete_from));
792 if (!new_text.empty()) 794 if (!new_text.empty())
793 render_text_->SetText(text.insert(new_text_insert_at, new_text)); 795 render_text_->SetText(text.insert(new_text_insert_at, new_text));
794 render_text_->SetCursorPosition(new_cursor_pos); 796 render_text_->SetCursorPosition(new_cursor_pos);
795 // 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).
796 // 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.
797 } 799 }
798 800
799 } // 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