Roll icu to 241739 and drop a version from icudt*dat
[chromium-blink-merge.git] / ui / views / controls / textfield / textfield_views_model.h
blob4e625c4d2d65b2f823d047f15f0a3c4e2e355584
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
3 // found in the LICENSE file.
5 #ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_
6 #define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_
8 #include <list>
9 #include <vector>
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string16.h"
14 #include "third_party/skia/include/core/SkColor.h"
15 #include "ui/base/ime/composition_text.h"
16 #include "ui/gfx/rect.h"
17 #include "ui/gfx/render_text.h"
18 #include "ui/gfx/text_constants.h"
19 #include "ui/views/views_export.h"
21 namespace gfx {
22 class Range;
23 class RenderText;
24 } // namespace gfx
26 namespace views {
28 namespace internal {
29 // Internal Edit class that keeps track of edits for undo/redo.
30 class Edit;
32 // C++ doesn't allow forward decl enum, so let's define here.
33 enum MergeType {
34 // The edit should not be merged with next edit. It still may
35 // be merged with an edit with MERGE_WITH_PREVIOUS.
36 DO_NOT_MERGE,
37 // The edit can be merged with next edit when possible.
38 MERGEABLE,
39 // Does the edit have to be merged with previous edit?
40 // This forces the merge even if the previous edit is marked
41 // as DO_NOT_MERGE.
42 MERGE_WITH_PREVIOUS,
45 } // namespace internal
47 // A model that represents a text content for TextfieldViews.
48 // It supports editing, selection and cursor manipulation.
49 class VIEWS_EXPORT TextfieldViewsModel {
50 public:
51 // Delegate interface implemented by the textfield view class to provided
52 // additional functionalities required by the model.
53 class VIEWS_EXPORT Delegate {
54 public:
55 // Called when the current composition text is confirmed or cleared.
56 virtual void OnCompositionTextConfirmedOrCleared() = 0;
58 protected:
59 virtual ~Delegate();
62 explicit TextfieldViewsModel(Delegate* delegate);
63 virtual ~TextfieldViewsModel();
65 // Edit related methods.
67 const base::string16& GetText() const;
68 // Sets the text. Returns true if the text has been modified. The
69 // current composition text will be confirmed first. Setting
70 // the same text will not add edit history because it's not user
71 // visible change nor user-initiated change. This allow a client
72 // code to set the same text multiple times without worrying about
73 // messing edit history.
74 bool SetText(const base::string16& text);
76 gfx::RenderText* render_text() { return render_text_.get(); }
78 // Inserts given |text| at the current cursor position.
79 // The current composition text will be cleared.
80 void InsertText(const base::string16& text) {
81 InsertTextInternal(text, false);
84 // Inserts a character at the current cursor position.
85 void InsertChar(char16 c) {
86 InsertTextInternal(base::string16(&c, 1), true);
89 // Replaces characters at the current position with characters in given text.
90 // The current composition text will be cleared.
91 void ReplaceText(const base::string16& text) {
92 ReplaceTextInternal(text, false);
95 // Replaces the char at the current position with given character.
96 void ReplaceChar(char16 c) {
97 ReplaceTextInternal(base::string16(&c, 1), true);
100 // Appends the text.
101 // The current composition text will be confirmed.
102 void Append(const base::string16& text);
104 // Deletes the first character after the current cursor position (as if, the
105 // the user has pressed delete key in the textfield). Returns true if
106 // the deletion is successful.
107 // If there is composition text, it'll be deleted instead.
108 bool Delete();
110 // Deletes the first character before the current cursor position (as if, the
111 // the user has pressed backspace key in the textfield). Returns true if
112 // the removal is successful.
113 // If there is composition text, it'll be deleted instead.
114 bool Backspace();
116 // Cursor related methods.
118 // Returns the current cursor position.
119 size_t GetCursorPosition() const;
121 // Moves the cursor, see RenderText for additional details.
122 // The current composition text will be confirmed.
123 void MoveCursor(gfx::BreakType break_type,
124 gfx::VisualCursorDirection direction,
125 bool select);
127 // Moves the selection to the specified selection in |selection|.
128 // If there is composition text, it will be confirmed, which will update the
129 // selection range, and it overrides the selection_start to which the
130 // selection will move to.
131 bool MoveCursorTo(const gfx::SelectionModel& selection);
133 // Helper function to call MoveCursorTo on the TextfieldViewsModel.
134 bool MoveCursorTo(const gfx::Point& point, bool select);
136 // Selection related method
138 // Returns the selected text.
139 base::string16 GetSelectedText() const;
141 // The current composition text will be confirmed. The selection starts with
142 // the range's start position, and ends with the range's end position,
143 // therefore the cursor position becomes the end position.
144 void SelectRange(const gfx::Range& range);
146 // The current composition text will be confirmed.
147 // render_text_'s selection model is set to |sel|.
148 void SelectSelectionModel(const gfx::SelectionModel& sel);
150 // Select the entire text range. If |reversed| is true, the range will end at
151 // the logical beginning of the text; this generally shows the leading portion
152 // of text that overflows its display area.
153 // The current composition text will be confirmed.
154 void SelectAll(bool reversed);
156 // Selects the word at which the cursor is currently positioned. If there is a
157 // non-empty selection, the selection bounds are extended to their nearest
158 // word boundaries.
159 // The current composition text will be confirmed.
160 void SelectWord();
162 // Clears selection.
163 // The current composition text will be confirmed.
164 void ClearSelection();
166 // Returns true if there is an undoable edit.
167 bool CanUndo();
169 // Returns true if there is an redoable edit.
170 bool CanRedo();
172 // Undo edit. Returns true if undo changed the text.
173 bool Undo();
175 // Redo edit. Returns true if redo changed the text.
176 bool Redo();
178 // Cuts the currently selected text and puts it to clipboard. Returns true
179 // if text has changed after cutting.
180 bool Cut();
182 // Copies the currently selected text and puts it to clipboard. Returns true
183 // if something was copied to the clipboard.
184 bool Copy();
186 // Pastes text from the clipboard at current cursor position. Returns true
187 // if any text is pasted.
188 bool Paste();
190 // Tells if any text is selected, even if the selection is in composition
191 // text.
192 bool HasSelection() const;
194 // Deletes the selected text. This method shouldn't be called with
195 // composition text.
196 void DeleteSelection();
198 // Deletes the selected text (if any) and insert text at given
199 // position.
200 void DeleteSelectionAndInsertTextAt(
201 const base::string16& text, size_t position);
203 // Retrieves the text content in a given range.
204 base::string16 GetTextFromRange(const gfx::Range& range) const;
206 // Retrieves the range containing all text in the model.
207 void GetTextRange(gfx::Range* range) const;
209 // Sets composition text and attributes. If there is composition text already,
210 // it'll be replaced by the new one. Otherwise, current selection will be
211 // replaced. If there is no selection, the composition text will be inserted
212 // at the insertion point.
213 // Any changes to the model except text insertion will confirm the current
214 // composition text.
215 void SetCompositionText(const ui::CompositionText& composition);
217 // Converts current composition text into final content.
218 void ConfirmCompositionText();
220 // Removes current composition text.
221 void CancelCompositionText();
223 // Retrieves the range of current composition text.
224 void GetCompositionTextRange(gfx::Range* range) const;
226 // Returns true if there is composition text.
227 bool HasCompositionText() const;
229 private:
230 friend class NativeTextfieldViews;
231 friend class NativeTextfieldViewsTest;
232 friend class TextfieldViewsModelTest;
233 friend class UndoRedo_BasicTest;
234 friend class UndoRedo_CutCopyPasteTest;
235 friend class UndoRedo_ReplaceTest;
236 friend class internal::Edit;
238 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_BasicTest);
239 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest);
240 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_ReplaceTest);
242 // Insert the given |text|. |mergeable| indicates if this insert
243 // operation can be merged to previous edit in the edit history.
244 void InsertTextInternal(const base::string16& text, bool mergeable);
246 // Replace the current text with the given |text|. |mergeable|
247 // indicates if this replace operation can be merged to previous
248 // edit in the edit history.
249 void ReplaceTextInternal(const base::string16& text, bool mergeable);
251 // Clears all edit history.
252 void ClearEditHistory();
254 // Clears redo history.
255 void ClearRedoHistory();
257 // Executes and records edit operations.
258 void ExecuteAndRecordDelete(gfx::Range range, bool mergeable);
259 void ExecuteAndRecordReplaceSelection(internal::MergeType merge_type,
260 const base::string16& text);
261 void ExecuteAndRecordReplace(internal::MergeType merge_type,
262 size_t old_cursor_pos,
263 size_t new_cursor_pos,
264 const base::string16& text,
265 size_t new_text_start);
266 void ExecuteAndRecordInsert(const base::string16& text, bool mergeable);
268 // Adds or merge |edit| into edit history. Return true if the edit
269 // has been merged and must be deleted after redo.
270 bool AddOrMergeEditHistory(internal::Edit* edit);
272 // Modify the text buffer in following way:
273 // 1) Delete the string from |delete_from| to |delte_to|.
274 // 2) Insert the |new_text| at the index |new_text_insert_at|.
275 // Note that the index is after deletion.
276 // 3) Move the cursor to |new_cursor_pos|.
277 void ModifyText(size_t delete_from,
278 size_t delete_to,
279 const base::string16& new_text,
280 size_t new_text_insert_at,
281 size_t new_cursor_pos);
283 void ClearComposition();
285 // Pointer to a TextfieldViewsModel::Delegate instance, should be provided by
286 // the View object.
287 Delegate* delegate_;
289 // The stylized text, cursor, selection, and the visual layout model.
290 scoped_ptr<gfx::RenderText> render_text_;
292 typedef std::list<internal::Edit*> EditHistory;
293 EditHistory edit_history_;
295 // An iterator that points to the current edit that can be undone.
296 // This iterator moves from the |end()|, meaining no edit to undo,
297 // to the last element (one before |end()|), meaning no edit to redo.
298 // There is no edit to undo (== end()) when:
299 // 1) in initial state. (nothing to undo)
300 // 2) very 1st edit is undone.
301 // 3) all edit history is removed.
302 // There is no edit to redo (== last element or no element) when:
303 // 1) in initial state. (nothing to redo)
304 // 2) new edit is added. (redo history is cleared)
305 // 3) redone all undone edits.
306 EditHistory::iterator current_edit_;
308 DISALLOW_COPY_AND_ASSIGN(TextfieldViewsModel);
311 } // namespace views
313 #endif // UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_