Chromium Code Reviews| Index: ui/views/controls/textfield/textfield_model.cc |
| diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc |
| index 7c6d5917f209fdcfbc0b5bb6c1c71ad1622e0044..45ab2aae843a85969761497602c6596e4e4ea5dc 100644 |
| --- a/ui/views/controls/textfield/textfield_model.cc |
| +++ b/ui/views/controls/textfield/textfield_model.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/logging.h" |
| #include "base/macros.h" |
| +#include "base/message_loop/message_loop.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| @@ -263,6 +264,24 @@ gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) { |
| return gfx::Range::InvalidRange(); |
| } |
| +// Returns a reference to the kill buffer which holds the text to be inserted on |
| +// executing yank command. Singleton since it needs to be persisted across |
| +// multiple textfields. |
| +// On Mac, the size of the kill ring (no. of buffers) is controlled by |
| +// NSTextKillRingSize, a text system default. However to keep things simple, |
| +// the default kill ring size of 1 (i.e. a single buffer) is assumed. |
| +base::string16& GetKillBuffer() { |
|
sky
2016/07/22 15:22:49
return a pointer (references are generally restric
karandeepb
2016/07/25 06:38:11
Done.
|
| + CR_DEFINE_STATIC_LOCAL(base::string16, kill_buffer, ()); |
| + DCHECK(base::MessageLoopForUI::IsCurrent()); |
| + return kill_buffer; |
| +} |
| + |
| +// Helper method to set the kill buffer. |
| +void SetKillBuffer(const base::string16& buffer) { |
| + base::string16& kill_buffer = GetKillBuffer(); |
| + kill_buffer = buffer; |
| +} |
| + |
| } // namespace |
| using internal::Edit; |
| @@ -325,13 +344,15 @@ void TextfieldModel::Append(const base::string16& new_text) { |
| ClearSelection(); |
| } |
| -bool TextfieldModel::Delete() { |
| +bool TextfieldModel::Delete(bool add_to_kill_buffer) { |
| if (HasCompositionText()) { |
| // No undo/redo for composition text. |
| CancelCompositionText(); |
| return true; |
| } |
| if (HasSelection()) { |
| + if (add_to_kill_buffer) |
| + SetKillBuffer(GetSelectedText()); |
| DeleteSelection(); |
| return true; |
| } |
| @@ -339,20 +360,24 @@ bool TextfieldModel::Delete() { |
| size_t cursor_position = GetCursorPosition(); |
| size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme( |
| cursor_position, gfx::CURSOR_FORWARD); |
| - ExecuteAndRecordDelete(gfx::Range(cursor_position, next_grapheme_index), |
| - true); |
| + gfx::Range range_to_delete(cursor_position, next_grapheme_index); |
| + if (add_to_kill_buffer) |
| + SetKillBuffer(GetTextFromRange(range_to_delete)); |
| + ExecuteAndRecordDelete(range_to_delete, true); |
| return true; |
| } |
| return false; |
| } |
| -bool TextfieldModel::Backspace() { |
| +bool TextfieldModel::Backspace(bool add_to_kill_buffer) { |
| if (HasCompositionText()) { |
| // No undo/redo for composition text. |
| CancelCompositionText(); |
| return true; |
| } |
| if (HasSelection()) { |
| + if (add_to_kill_buffer) |
| + SetKillBuffer(GetSelectedText()); |
| DeleteSelection(); |
| return true; |
| } |
| @@ -360,7 +385,10 @@ bool TextfieldModel::Backspace() { |
| if (cursor_position > 0) { |
| // Delete one code point, which may be two UTF-16 words. |
| size_t previous_char = gfx::UTF16OffsetToIndex(text(), cursor_position, -1); |
|
msw
2016/07/22 17:44:03
optional nit: |previous_grapheme_index| for consis
karandeepb
2016/07/25 06:38:11
Done.
|
| - ExecuteAndRecordDelete(gfx::Range(cursor_position, previous_char), true); |
| + gfx::Range range_to_delete(cursor_position, previous_char); |
| + if (add_to_kill_buffer) |
| + SetKillBuffer(GetTextFromRange(range_to_delete)); |
| + ExecuteAndRecordDelete(range_to_delete, true); |
| return true; |
| } |
| return false; |
| @@ -557,6 +585,15 @@ bool TextfieldModel::Transpose() { |
| return true; |
| } |
| +bool TextfieldModel::Yank() { |
| + const base::string16& kill_buffer = GetKillBuffer(); |
| + if (!kill_buffer.empty() || HasSelection()) { |
|
msw
2016/07/22 17:44:03
Why would this try to insert an empty string if th
karandeepb
2016/07/25 06:38:11
That's how Yank works on Mac/Cocoa. Open a new Chr
msw
2016/07/25 18:35:49
Ah, so it's just doing a delete in that case? Okay
karandeepb
2016/07/26 03:45:41
Yeah!
|
| + InsertTextInternal(kill_buffer, false); |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| bool TextfieldModel::HasSelection() const { |
| return !render_text_->selection().is_empty(); |
| } |
| @@ -672,6 +709,11 @@ void TextfieldModel::ClearEditHistory() { |
| current_edit_ = edit_history_.end(); |
| } |
| +// static |
| +void TextfieldModel::ClearKillBufferForTesting() { |
| + SetKillBuffer(base::string16()); |
| +} |
| + |
| ///////////////////////////////////////////////////////////////// |
| // TextfieldModel: private |