Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "ui/base/clipboard/clipboard.h" | 14 #include "ui/base/clipboard/clipboard.h" |
| 15 #include "ui/base/clipboard/scoped_clipboard_writer.h" | 15 #include "ui/base/clipboard/scoped_clipboard_writer.h" |
| 16 #include "ui/gfx/range/range.h" | 16 #include "ui/gfx/range/range.h" |
| 17 #include "ui/gfx/utf16_indexing.h" | 17 #include "ui/gfx/utf16_indexing.h" |
| 18 #include "ui/views/views_delegate.h" | |
| 18 | 19 |
| 19 namespace views { | 20 namespace views { |
| 20 | 21 |
| 21 namespace internal { | 22 namespace internal { |
| 22 | 23 |
| 23 // Edit holds state information to undo/redo editing changes. Editing operations | 24 // Edit holds state information to undo/redo editing changes. Editing operations |
| 24 // are merged when possible, like when characters are typed in sequence. Calling | 25 // are merged when possible, like when characters are typed in sequence. Calling |
| 25 // Commit() marks an edit as an independent operation that shouldn't be merged. | 26 // Commit() marks an edit as an independent operation that shouldn't be merged. |
| 26 class Edit { | 27 class Edit { |
| 27 public: | 28 public: |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 // there is no such a range. | 257 // there is no such a range. |
| 257 gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) { | 258 gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) { |
| 258 for (size_t i = 0; i < composition.underlines.size(); ++i) { | 259 for (size_t i = 0; i < composition.underlines.size(); ++i) { |
| 259 const ui::CompositionUnderline& underline = composition.underlines[i]; | 260 const ui::CompositionUnderline& underline = composition.underlines[i]; |
| 260 if (underline.thick) | 261 if (underline.thick) |
| 261 return gfx::Range(underline.start_offset, underline.end_offset); | 262 return gfx::Range(underline.start_offset, underline.end_offset); |
| 262 } | 263 } |
| 263 return gfx::Range::InvalidRange(); | 264 return gfx::Range::InvalidRange(); |
| 264 } | 265 } |
| 265 | 266 |
| 267 // Helper functions to get/set the kill buffer. | |
| 268 const base::string16& GetKillBuffer() { | |
| 269 DCHECK(ViewsDelegate::GetInstance()); | |
| 270 return ViewsDelegate::GetInstance()->kill_buffer(); | |
| 271 } | |
| 272 | |
| 273 void SetKillBuffer(const base::string16& kill_buffer) { | |
| 274 if(ViewsDelegate::GetInstance()) | |
|
tapted
2016/07/20 06:32:21
nit: space after `if`
karandeepb
2016/07/20 07:51:30
Done. Forgot to run git cl format!
| |
| 275 ViewsDelegate::GetInstance()->set_kill_buffer(kill_buffer); | |
| 276 } | |
| 277 | |
| 266 } // namespace | 278 } // namespace |
| 267 | 279 |
| 268 using internal::Edit; | 280 using internal::Edit; |
| 269 using internal::DeleteEdit; | 281 using internal::DeleteEdit; |
| 270 using internal::InsertEdit; | 282 using internal::InsertEdit; |
| 271 using internal::ReplaceEdit; | 283 using internal::ReplaceEdit; |
| 272 using internal::MergeType; | 284 using internal::MergeType; |
| 273 using internal::DO_NOT_MERGE; | 285 using internal::DO_NOT_MERGE; |
| 274 using internal::FORCE_MERGE; | 286 using internal::FORCE_MERGE; |
| 275 using internal::MERGEABLE; | 287 using internal::MERGEABLE; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 ConfirmCompositionText(); | 330 ConfirmCompositionText(); |
| 319 size_t save = GetCursorPosition(); | 331 size_t save = GetCursorPosition(); |
| 320 MoveCursor(gfx::LINE_BREAK, | 332 MoveCursor(gfx::LINE_BREAK, |
| 321 render_text_->GetVisualDirectionOfLogicalEnd(), | 333 render_text_->GetVisualDirectionOfLogicalEnd(), |
| 322 false); | 334 false); |
| 323 InsertText(new_text); | 335 InsertText(new_text); |
| 324 render_text_->SetCursorPosition(save); | 336 render_text_->SetCursorPosition(save); |
| 325 ClearSelection(); | 337 ClearSelection(); |
| 326 } | 338 } |
| 327 | 339 |
| 328 bool TextfieldModel::Delete() { | 340 bool TextfieldModel::Delete(bool add_to_kill_buffer) { |
| 329 if (HasCompositionText()) { | 341 if (HasCompositionText()) { |
| 330 // No undo/redo for composition text. | 342 // No undo/redo for composition text. |
| 331 CancelCompositionText(); | 343 CancelCompositionText(); |
| 332 return true; | 344 return true; |
| 333 } | 345 } |
| 334 if (HasSelection()) { | 346 if (HasSelection()) { |
| 347 if (add_to_kill_buffer) | |
| 348 SetKillBuffer(GetSelectedText()); | |
| 335 DeleteSelection(); | 349 DeleteSelection(); |
| 336 return true; | 350 return true; |
| 337 } | 351 } |
| 338 if (text().length() > GetCursorPosition()) { | 352 if (text().length() > GetCursorPosition()) { |
| 339 size_t cursor_position = GetCursorPosition(); | 353 size_t cursor_position = GetCursorPosition(); |
| 340 size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme( | 354 size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme( |
| 341 cursor_position, gfx::CURSOR_FORWARD); | 355 cursor_position, gfx::CURSOR_FORWARD); |
| 342 ExecuteAndRecordDelete(gfx::Range(cursor_position, next_grapheme_index), | 356 gfx::Range range_to_delete(cursor_position, next_grapheme_index); |
| 343 true); | 357 if (add_to_kill_buffer) |
| 358 SetKillBuffer(GetTextFromRange(range_to_delete)); | |
| 359 ExecuteAndRecordDelete(range_to_delete, true); | |
| 344 return true; | 360 return true; |
| 345 } | 361 } |
| 346 return false; | 362 return false; |
| 347 } | 363 } |
| 348 | 364 |
| 349 bool TextfieldModel::Backspace() { | 365 bool TextfieldModel::Backspace(bool add_to_kill_buffer) { |
| 350 if (HasCompositionText()) { | 366 if (HasCompositionText()) { |
| 351 // No undo/redo for composition text. | 367 // No undo/redo for composition text. |
| 352 CancelCompositionText(); | 368 CancelCompositionText(); |
| 353 return true; | 369 return true; |
| 354 } | 370 } |
| 355 if (HasSelection()) { | 371 if (HasSelection()) { |
| 372 if (add_to_kill_buffer) | |
| 373 SetKillBuffer(GetSelectedText()); | |
| 356 DeleteSelection(); | 374 DeleteSelection(); |
| 357 return true; | 375 return true; |
| 358 } | 376 } |
| 359 size_t cursor_position = GetCursorPosition(); | 377 size_t cursor_position = GetCursorPosition(); |
| 360 if (cursor_position > 0) { | 378 if (cursor_position > 0) { |
| 361 // Delete one code point, which may be two UTF-16 words. | 379 // Delete one code point, which may be two UTF-16 words. |
| 362 size_t previous_char = gfx::UTF16OffsetToIndex(text(), cursor_position, -1); | 380 size_t previous_char = gfx::UTF16OffsetToIndex(text(), cursor_position, -1); |
| 363 ExecuteAndRecordDelete(gfx::Range(cursor_position, previous_char), true); | 381 gfx::Range range_to_delete(cursor_position, previous_char); |
| 382 if (add_to_kill_buffer) | |
| 383 SetKillBuffer(GetTextFromRange(range_to_delete)); | |
| 384 ExecuteAndRecordDelete(range_to_delete, true); | |
| 364 return true; | 385 return true; |
| 365 } | 386 } |
| 366 return false; | 387 return false; |
| 367 } | 388 } |
| 368 | 389 |
| 369 size_t TextfieldModel::GetCursorPosition() const { | 390 size_t TextfieldModel::GetCursorPosition() const { |
| 370 return render_text_->cursor_position(); | 391 return render_text_->cursor_position(); |
| 371 } | 392 } |
| 372 | 393 |
| 373 void TextfieldModel::MoveCursor(gfx::BreakType break_type, | 394 void TextfieldModel::MoveCursor(gfx::BreakType break_type, |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 550 | 571 |
| 551 SelectRange(gfx::Range(prev, next)); | 572 SelectRange(gfx::Range(prev, next)); |
| 552 base::string16 text = GetSelectedText(); | 573 base::string16 text = GetSelectedText(); |
| 553 base::string16 transposed_text = | 574 base::string16 transposed_text = |
| 554 text.substr(cur - prev) + text.substr(0, cur - prev); | 575 text.substr(cur - prev) + text.substr(0, cur - prev); |
| 555 | 576 |
| 556 InsertTextInternal(transposed_text, false); | 577 InsertTextInternal(transposed_text, false); |
| 557 return true; | 578 return true; |
| 558 } | 579 } |
| 559 | 580 |
| 581 bool TextfieldModel::Yank() { | |
| 582 if(!ViewsDelegate::GetInstance()) | |
|
tapted
2016/07/20 06:32:21
nit: space after `if` (but also can this be reache
karandeepb
2016/07/20 07:51:30
The ViewsDelegate is initialized in ChromeBrowserM
| |
| 583 return false; | |
| 584 | |
| 585 const base::string16& kill_buffer = GetKillBuffer(); | |
| 586 if (!kill_buffer.empty() || HasSelection()) { | |
| 587 InsertTextInternal(kill_buffer, false); | |
| 588 return true; | |
| 589 } | |
| 590 return false; | |
| 591 } | |
| 592 | |
| 560 bool TextfieldModel::HasSelection() const { | 593 bool TextfieldModel::HasSelection() const { |
| 561 return !render_text_->selection().is_empty(); | 594 return !render_text_->selection().is_empty(); |
| 562 } | 595 } |
| 563 | 596 |
| 564 void TextfieldModel::DeleteSelection() { | 597 void TextfieldModel::DeleteSelection() { |
| 565 DCHECK(!HasCompositionText()); | 598 DCHECK(!HasCompositionText()); |
| 566 DCHECK(HasSelection()); | 599 DCHECK(HasSelection()); |
| 567 ExecuteAndRecordDelete(render_text_->selection(), false); | 600 ExecuteAndRecordDelete(render_text_->selection(), false); |
| 568 } | 601 } |
| 569 | 602 |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 804 ClearComposition(); | 837 ClearComposition(); |
| 805 if (delete_from != delete_to) | 838 if (delete_from != delete_to) |
| 806 render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from)); | 839 render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from)); |
| 807 if (!new_text.empty()) | 840 if (!new_text.empty()) |
| 808 render_text_->SetText(old_text.insert(new_text_insert_at, new_text)); | 841 render_text_->SetText(old_text.insert(new_text_insert_at, new_text)); |
| 809 render_text_->SetCursorPosition(new_cursor_pos); | 842 render_text_->SetCursorPosition(new_cursor_pos); |
| 810 // TODO(oshima): Select text that was just undone, like Mac (but not GTK). | 843 // TODO(oshima): Select text that was just undone, like Mac (but not GTK). |
| 811 } | 844 } |
| 812 | 845 |
| 813 } // namespace views | 846 } // namespace views |
| OLD | NEW |