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

Side by Side Diff: ui/views/controls/textfield/textfield_model.h

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_
6 #define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_
7
8 #include <list>
9 #include <vector>
10
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string16.h"
14 #include "ui/base/ime/composition_text.h"
15 #include "ui/gfx/render_text.h"
16 #include "ui/gfx/text_constants.h"
17 #include "ui/views/views_export.h"
18
19 namespace views {
20
21 namespace internal {
22 // Internal Edit class that keeps track of edits for undo/redo.
23 class Edit;
24
25 // The types of merge behavior implemented by Edit operations.
26 enum MergeType {
27 // The edit should not usually be merged with next edit.
28 DO_NOT_MERGE,
29 // The edit should be merged with next edit when possible.
30 MERGEABLE,
31 // The edit should be merged with the prior edit, even if marked DO_NOT_MERGE.
32 FORCE_MERGE,
33 };
34
35 } // namespace internal
36
37 // A model that represents text content for a views::Textfield.
38 // It supports editing, selection and cursor manipulation.
39 class VIEWS_EXPORT TextfieldModel {
40 public:
41 // Delegate interface implemented by the textfield view class to provide
42 // additional functionalities required by the model.
43 class VIEWS_EXPORT Delegate {
44 public:
45 // Called when the current composition text is confirmed or cleared.
46 virtual void OnCompositionTextConfirmedOrCleared() = 0;
47
48 protected:
49 virtual ~Delegate();
50 };
51
52 explicit TextfieldModel(Delegate* delegate);
53 virtual ~TextfieldModel();
54
55 // Edit related methods.
56
57 const base::string16& text() const { return render_text_->text(); }
58 // Sets the text. Returns true if the text has been modified. The current
59 // composition text will be confirmed first. Setting the same text will not
60 // add edit history because it's not user visible change nor user-initiated
61 // change. This allow a client code to set the same text multiple times
62 // without worrying about messing edit history.
63 bool SetText(const base::string16& new_text);
64
65 gfx::RenderText* render_text() { return render_text_.get(); }
66
67 // Inserts given |new_text| at the current cursor position.
68 // The current composition text will be cleared.
69 void InsertText(const base::string16& new_text) {
70 InsertTextInternal(new_text, false);
71 }
72
73 // Inserts a character at the current cursor position.
74 void InsertChar(base::char16 c) {
75 InsertTextInternal(base::string16(&c, 1), true);
76 }
77
78 // Replaces characters at the current position with characters in given text.
79 // The current composition text will be cleared.
80 void ReplaceText(const base::string16& new_text) {
81 ReplaceTextInternal(new_text, false);
82 }
83
84 // Replaces the char at the current position with given character.
85 void ReplaceChar(base::char16 c) {
86 ReplaceTextInternal(base::string16(&c, 1), true);
87 }
88
89 // Appends the text.
90 // The current composition text will be confirmed.
91 void Append(const base::string16& new_text);
92
93 // Deletes the first character after the current cursor position (as if, the
94 // the user has pressed delete key in the textfield). Returns true if
95 // the deletion is successful.
96 // If there is composition text, it'll be deleted instead.
97 bool Delete();
98
99 // Deletes the first character before the current cursor position (as if, the
100 // the user has pressed backspace key in the textfield). Returns true if
101 // the removal is successful.
102 // If there is composition text, it'll be deleted instead.
103 bool Backspace();
104
105 // Cursor related methods.
106
107 // Returns the current cursor position.
108 size_t GetCursorPosition() const;
109
110 // Moves the cursor, see RenderText for additional details.
111 // The current composition text will be confirmed.
112 void MoveCursor(gfx::BreakType break_type,
113 gfx::VisualCursorDirection direction,
114 bool select);
115
116 // Updates the cursor to the specified selection model. Any composition text
117 // will be confirmed, which may alter the specified selection range start.
118 bool MoveCursorTo(const gfx::SelectionModel& cursor);
119
120 // Helper function to call MoveCursorTo on the TextfieldModel.
121 bool MoveCursorTo(const gfx::Point& point, bool select);
122
123 // Selection related methods.
124
125 // Returns the selected text.
126 base::string16 GetSelectedText() const;
127
128 // The current composition text will be confirmed. The selection starts with
129 // the range's start position, and ends with the range's end position,
130 // therefore the cursor position becomes the end position.
131 void SelectRange(const gfx::Range& range);
132
133 // The current composition text will be confirmed.
134 // render_text_'s selection model is set to |sel|.
135 void SelectSelectionModel(const gfx::SelectionModel& sel);
136
137 // Select the entire text range. If |reversed| is true, the range will end at
138 // the logical beginning of the text; this generally shows the leading portion
139 // of text that overflows its display area.
140 // The current composition text will be confirmed.
141 void SelectAll(bool reversed);
142
143 // Selects the word at which the cursor is currently positioned. If there is a
144 // non-empty selection, the selection bounds are extended to their nearest
145 // word boundaries.
146 // The current composition text will be confirmed.
147 void SelectWord();
148
149 // Clears selection.
150 // The current composition text will be confirmed.
151 void ClearSelection();
152
153 // Returns true if there is an undoable edit.
154 bool CanUndo();
155
156 // Returns true if there is an redoable edit.
157 bool CanRedo();
158
159 // Undo edit. Returns true if undo changed the text.
160 bool Undo();
161
162 // Redo edit. Returns true if redo changed the text.
163 bool Redo();
164
165 // Cuts the currently selected text and puts it to clipboard. Returns true
166 // if text has changed after cutting.
167 bool Cut();
168
169 // Copies the currently selected text and puts it to clipboard. Returns true
170 // if something was copied to the clipboard.
171 bool Copy();
172
173 // Pastes text from the clipboard at current cursor position. Returns true
174 // if any text is pasted.
175 bool Paste();
176
177 // Tells if any text is selected, even if the selection is in composition
178 // text.
179 bool HasSelection() const;
180
181 // Deletes the selected text. This method shouldn't be called with
182 // composition text.
183 void DeleteSelection();
184
185 // Deletes the selected text (if any) and insert text at given position.
186 void DeleteSelectionAndInsertTextAt(const base::string16& new_text,
187 size_t position);
188
189 // Retrieves the text content in a given range.
190 base::string16 GetTextFromRange(const gfx::Range& range) const;
191
192 // Retrieves the range containing all text in the model.
193 void GetTextRange(gfx::Range* range) const;
194
195 // Sets composition text and attributes. If there is composition text already,
196 // it'll be replaced by the new one. Otherwise, current selection will be
197 // replaced. If there is no selection, the composition text will be inserted
198 // at the insertion point.
199 // Any changes to the model except text insertion will confirm the current
200 // composition text.
201 void SetCompositionText(const ui::CompositionText& composition);
202
203 // Converts current composition text into final content.
204 void ConfirmCompositionText();
205
206 // Removes current composition text.
207 void CancelCompositionText();
208
209 // Retrieves the range of current composition text.
210 void GetCompositionTextRange(gfx::Range* range) const;
211
212 // Returns true if there is composition text.
213 bool HasCompositionText() const;
214
215 // Clears all edit history.
216 void ClearEditHistory();
217
218 private:
219 friend class internal::Edit;
220
221 FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_BasicTest);
222 FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_CutCopyPasteTest);
223 FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_ReplaceTest);
224
225 // Insert the given |new_text|. |mergeable| indicates if this insert operation
226 // can be merged with previous edits in the history.
227 void InsertTextInternal(const base::string16& new_text, bool mergeable);
228
229 // Replace the current text with the given |new_text|. |mergeable| indicates
230 // if this replace operation can be merged with previous edits in the history.
231 void ReplaceTextInternal(const base::string16& new_text, bool mergeable);
232
233 // Clears redo history.
234 void ClearRedoHistory();
235
236 // Executes and records edit operations.
237 void ExecuteAndRecordDelete(gfx::Range range, bool mergeable);
238 void ExecuteAndRecordReplaceSelection(internal::MergeType merge_type,
239 const base::string16& new_text);
240 void ExecuteAndRecordReplace(internal::MergeType merge_type,
241 size_t old_cursor_pos,
242 size_t new_cursor_pos,
243 const base::string16& new_text,
244 size_t new_text_start);
245 void ExecuteAndRecordInsert(const base::string16& new_text, bool mergeable);
246
247 // Adds or merge |edit| into edit history. Return true if the edit
248 // has been merged and must be deleted after redo.
249 bool AddOrMergeEditHistory(internal::Edit* edit);
250
251 // Modify the text buffer in following way:
252 // 1) Delete the string from |delete_from| to |delte_to|.
253 // 2) Insert the |new_text| at the index |new_text_insert_at|.
254 // Note that the index is after deletion.
255 // 3) Move the cursor to |new_cursor_pos|.
256 void ModifyText(size_t delete_from,
257 size_t delete_to,
258 const base::string16& new_text,
259 size_t new_text_insert_at,
260 size_t new_cursor_pos);
261
262 void ClearComposition();
263
264 // The TextfieldModel::Delegate instance should be provided by the owner.
265 Delegate* delegate_;
266
267 // The stylized text, cursor, selection, and the visual layout model.
268 scoped_ptr<gfx::RenderText> render_text_;
269
270 typedef std::list<internal::Edit*> EditHistory;
271 EditHistory edit_history_;
272
273 // An iterator that points to the current edit that can be undone.
274 // This iterator moves from the |end()|, meaining no edit to undo,
275 // to the last element (one before |end()|), meaning no edit to redo.
276 //
277 // There is no edit to undo (== end()) when:
278 // 1) in initial state. (nothing to undo)
279 // 2) very 1st edit is undone.
280 // 3) all edit history is removed.
281 // There is no edit to redo (== last element or no element) when:
282 // 1) in initial state. (nothing to redo)
283 // 2) new edit is added. (redo history is cleared)
284 // 3) redone all undone edits.
285 EditHistory::iterator current_edit_;
286
287 DISALLOW_COPY_AND_ASSIGN(TextfieldModel);
288 };
289
290 } // namespace views
291
292 #endif // UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield_controller.cc ('k') | ui/views/controls/textfield/textfield_model.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698