Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #ifndef VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_ | 5 #ifndef VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_ |
| 6 #define VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_ | 6 #define VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <list> | 9 #include <list> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/gtest_prod_util.h" | 12 #include "base/gtest_prod_util.h" |
| 13 #include "base/string16.h" | 13 #include "base/string16.h" |
| 14 #include "third_party/skia/include/core/SkColor.h" | 14 #include "third_party/skia/include/core/SkColor.h" |
| 15 #include "ui/base/ime/composition_text.h" | 15 #include "ui/base/ime/composition_text.h" |
| 16 #include "ui/gfx/rect.h" | 16 #include "ui/gfx/rect.h" |
| 17 #include "ui/gfx/render_text.h" | |
| 17 | 18 |
| 18 namespace gfx { | 19 namespace gfx { |
| 20 class Canvas; | |
| 19 class Font; | 21 class Font; |
| 22 class RenderText; | |
| 23 struct StyleRange; | |
| 20 } // namespace gfx | 24 } // namespace gfx |
| 21 | 25 |
| 22 namespace ui { | 26 namespace ui { |
| 23 class Range; | 27 class Range; |
| 24 } // namespace ui | 28 } // namespace ui |
| 25 | 29 |
| 26 namespace views { | 30 namespace views { |
| 27 | 31 |
| 28 class TextStyle; | |
| 29 typedef std::vector<TextStyle*> TextStyles; | |
| 30 | |
| 31 namespace internal { | 32 namespace internal { |
| 32 // Internal Edit class that keeps track of edits for undo/redo. | 33 // Internal Edit class that keeps track of edits for undo/redo. |
| 33 class Edit; | 34 class Edit; |
| 34 | 35 |
| 35 struct TextStyleRange; | |
| 36 | |
| 37 // C++ doesn't allow forward decl enum, so let's define here. | 36 // C++ doesn't allow forward decl enum, so let's define here. |
| 38 enum MergeType { | 37 enum MergeType { |
| 39 // The edit should not be merged with next edit. It still may | 38 // The edit should not be merged with next edit. It still may |
| 40 // be merged with an edit with MERGE_WITH_PREVIOUS. | 39 // be merged with an edit with MERGE_WITH_PREVIOUS. |
| 41 DO_NOT_MERGE, | 40 DO_NOT_MERGE, |
| 42 // The edit can be merged with next edit when possible. | 41 // The edit can be merged with next edit when possible. |
| 43 MERGEABLE, | 42 MERGEABLE, |
| 44 // Does the edit have to be merged with previous edit? | 43 // Does the edit have to be merged with previous edit? |
| 45 // This forces the merge even if the previous edit is marked | 44 // This forces the merge even if the previous edit is marked |
| 46 // as DO_NOT_MERGE. | 45 // as DO_NOT_MERGE. |
| 47 MERGE_WITH_PREVIOUS, | 46 MERGE_WITH_PREVIOUS, |
| 48 }; | 47 }; |
| 49 | 48 |
| 50 } // namespace internal | 49 } // namespace internal |
| 51 | 50 |
| 52 typedef std::vector<internal::TextStyleRange*> TextStyleRanges; | |
| 53 | |
| 54 // A model that represents a text content for TextfieldViews. | 51 // A model that represents a text content for TextfieldViews. |
| 55 // It supports editing, selection and cursor manipulation. | 52 // It supports editing, selection and cursor manipulation. |
| 56 class TextfieldViewsModel { | 53 class TextfieldViewsModel { |
| 57 public: | 54 public: |
| 58 | 55 |
| 59 // Delegate interface implemented by the textfield view class to provided | 56 // Delegate interface implemented by the textfield view class to provided |
| 60 // additional functionalities required by the model. | 57 // additional functionalities required by the model. |
| 61 class Delegate { | 58 class Delegate { |
| 62 public: | 59 public: |
| 63 // Called when the current composition text is confirmed or cleared. | 60 // Called when the current composition text is confirmed or cleared. |
| 64 virtual void OnCompositionTextConfirmedOrCleared() = 0; | 61 virtual void OnCompositionTextConfirmedOrCleared() = 0; |
| 65 | 62 |
| 66 protected: | 63 protected: |
| 67 virtual ~Delegate(); | 64 virtual ~Delegate(); |
| 68 }; | 65 }; |
| 69 | 66 |
| 70 explicit TextfieldViewsModel(Delegate* delegate); | 67 explicit TextfieldViewsModel(Delegate* delegate); |
| 71 virtual ~TextfieldViewsModel(); | 68 virtual ~TextfieldViewsModel(); |
| 72 | 69 |
| 73 // Text fragment info. Used to draw selected text. | |
| 74 // We may replace this with TextAttribute class | |
| 75 // in the future to support multi-color text | |
| 76 // for omnibox. | |
| 77 struct TextFragment { | |
| 78 TextFragment(size_t start, size_t end, const views::TextStyle* s) | |
| 79 : range(start, end), style(s) { | |
| 80 } | |
| 81 // The start and end position of text fragment. | |
| 82 ui::Range range; | |
| 83 const TextStyle* style; | |
| 84 }; | |
| 85 typedef std::vector<TextFragment> TextFragments; | |
| 86 | |
| 87 // Gets the text element info. | |
| 88 void GetFragments(TextFragments* elements); | |
| 89 | |
| 90 void set_is_password(bool is_password) { | 70 void set_is_password(bool is_password) { |
| 91 is_password_ = is_password; | 71 is_password_ = is_password; |
| 92 } | 72 } |
| 93 const string16& text() const { return text_; } | |
| 94 | 73 |
| 95 // Edit related methods. | 74 // Edit related methods. |
| 96 | 75 |
| 97 // Sest the text. Returns true if the text has been modified. The | 76 const string16& GetText() const; |
| 77 // Sets the text. Returns true if the text has been modified. The | |
| 98 // current composition text will be confirmed first. Setting | 78 // current composition text will be confirmed first. Setting |
| 99 // the same text will not add edit history because it's not user | 79 // the same text will not add edit history because it's not user |
| 100 // visible change nor user-initiated change. This allow a client | 80 // visible change nor user-initiated change. This allow a client |
| 101 // code to set the same text multiple times without worrying about | 81 // code to set the same text multiple times without worrying about |
| 102 // messing edit history. | 82 // messing edit history. |
| 103 bool SetText(const string16& text); | 83 bool SetText(const string16& text); |
| 104 | 84 |
| 85 gfx::RenderText* get_render_text() { return render_text_; } | |
|
oshima
2011/07/23 09:51:12
ditto
msw
2011/07/25 05:09:54
Done.
| |
| 86 | |
| 105 // Inserts given |text| at the current cursor position. | 87 // Inserts given |text| at the current cursor position. |
| 106 // The current composition text will be cleared. | 88 // The current composition text will be cleared. |
| 107 void InsertText(const string16& text) { | 89 void InsertText(const string16& text) { |
| 108 InsertTextInternal(text, false); | 90 InsertTextInternal(text, false); |
| 109 } | 91 } |
| 110 | 92 |
| 111 // Inserts a character at the current cursor position. | 93 // Inserts a character at the current cursor position. |
| 112 void InsertChar(char16 c) { | 94 void InsertChar(char16 c) { |
| 113 InsertTextInternal(string16(&c, 1), true); | 95 InsertTextInternal(string16(&c, 1), true); |
| 114 } | 96 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 136 | 118 |
| 137 // Deletes the first character before the current cursor position (as if, the | 119 // Deletes the first character before the current cursor position (as if, the |
| 138 // the user has pressed backspace key in the textfield). Returns true if | 120 // the user has pressed backspace key in the textfield). Returns true if |
| 139 // the removal is successful. | 121 // the removal is successful. |
| 140 // If there is composition text, it'll be deleted instead. | 122 // If there is composition text, it'll be deleted instead. |
| 141 bool Backspace(); | 123 bool Backspace(); |
| 142 | 124 |
| 143 // Cursor related methods. | 125 // Cursor related methods. |
| 144 | 126 |
| 145 // Returns the current cursor position. | 127 // Returns the current cursor position. |
| 146 size_t cursor_pos() const { return cursor_pos_; } | 128 size_t GetCursorPosition() const; |
| 147 | 129 |
| 148 // Moves the cursor left by one position (as if, the user has pressed the left | 130 // Moves the cursor, see RenderText for additional details. |
| 149 // arrow key). If |select| is true, it updates the selection accordingly. | |
| 150 // The current composition text will be confirmed. | 131 // The current composition text will be confirmed. |
| 151 void MoveCursorLeft(bool select); | 132 void MoveCursorLeft(gfx::BreakType break_type, bool select); |
| 152 | 133 void MoveCursorRight(gfx::BreakType break_type, bool select); |
| 153 // Moves the cursor right by one position (as if, the user has pressed the | |
| 154 // right arrow key). If |select| is true, it updates the selection | |
| 155 // accordingly. | |
| 156 // The current composition text will be confirmed. | |
| 157 void MoveCursorRight(bool select); | |
| 158 | |
| 159 // Moves the cursor left by one word (word boundry is defined by space). | |
| 160 // If |select| is true, it updates the selection accordingly. | |
| 161 // The current composition text will be confirmed. | |
| 162 void MoveCursorToPreviousWord(bool select); | |
| 163 | |
| 164 // Moves the cursor right by one word (word boundry is defined by space). | |
| 165 // If |select| is true, it updates the selection accordingly. | |
| 166 // The current composition text will be confirmed. | |
| 167 void MoveCursorToNextWord(bool select); | |
| 168 | |
| 169 // Moves the cursor to start of the textfield contents. | |
| 170 // If |select| is true, it updates the selection accordingly. | |
| 171 // The current composition text will be confirmed. | |
| 172 void MoveCursorToHome(bool select); | |
| 173 | |
| 174 // Moves the cursor to end of the textfield contents. | |
| 175 // If |select| is true, it updates the selection accordingly. | |
| 176 // The current composition text will be confirmed. | |
| 177 void MoveCursorToEnd(bool select); | |
| 178 | 134 |
| 179 // Moves the cursor to the specified |position|. | 135 // Moves the cursor to the specified |position|. |
| 180 // If |select| is true, it updates the selection accordingly. | 136 // If |select| is true, it updates the selection accordingly. |
| 181 // The current composition text will be confirmed. | 137 // The current composition text will be confirmed. |
| 182 bool MoveCursorTo(size_t position, bool select); | 138 bool MoveCursorTo(size_t position, bool select); |
| 183 | 139 |
| 140 // Helper function to call MoveCursorTo on the TextfieldViewsModel. | |
| 141 bool MoveCursorTo(const gfx::Point& point, bool select); | |
| 142 | |
| 184 // Returns the bounds of selected text. | 143 // Returns the bounds of selected text. |
| 185 gfx::Rect GetSelectionBounds(const gfx::Font& font) const; | 144 std::vector<gfx::Rect> GetSelectionBounds() const; |
| 186 | 145 |
| 187 // Selection related method | 146 // Selection related method |
| 188 | 147 |
| 189 // Returns the selected text. | 148 // Returns the selected text. |
| 190 string16 GetSelectedText() const; | 149 string16 GetSelectedText() const; |
| 191 | 150 |
| 192 void GetSelectedRange(ui::Range* range) const; | 151 void GetSelectedRange(ui::Range* range) const; |
| 193 | 152 |
| 194 // The current composition text will be confirmed. The | 153 // The current composition text will be confirmed. The |
| 195 // selection starts with the range's start position, | 154 // selection starts with the range's start position, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 216 bool CanRedo(); | 175 bool CanRedo(); |
| 217 | 176 |
| 218 // Undo edit. Returns true if undo changed the text. | 177 // Undo edit. Returns true if undo changed the text. |
| 219 bool Undo(); | 178 bool Undo(); |
| 220 | 179 |
| 221 // Redo edit. Returns true if redo changed the text. | 180 // Redo edit. Returns true if redo changed the text. |
| 222 bool Redo(); | 181 bool Redo(); |
| 223 | 182 |
| 224 // Returns visible text. If the field is password, it returns the | 183 // Returns visible text. If the field is password, it returns the |
| 225 // sequence of "*". | 184 // sequence of "*". |
| 226 string16 GetVisibleText() const { | 185 string16 GetVisibleText() const; |
| 227 return GetVisibleText(0U, text_.length()); | |
| 228 } | |
| 229 | 186 |
| 230 // Cuts the currently selected text and puts it to clipboard. Returns true | 187 // Cuts the currently selected text and puts it to clipboard. Returns true |
| 231 // if text has changed after cutting. | 188 // if text has changed after cutting. |
| 232 bool Cut(); | 189 bool Cut(); |
| 233 | 190 |
| 234 // Copies the currently selected text and puts it to clipboard. | 191 // Copies the currently selected text and puts it to clipboard. |
| 235 void Copy(); | 192 void Copy(); |
| 236 | 193 |
| 237 // Pastes text from the clipboard at current cursor position. Returns true | 194 // Pastes text from the clipboard at current cursor position. Returns true |
| 238 // if text has changed after pasting. | 195 // if text has changed after pasting. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 | 227 |
| 271 // Removes current composition text. | 228 // Removes current composition text. |
| 272 void CancelCompositionText(); | 229 void CancelCompositionText(); |
| 273 | 230 |
| 274 // Retrieves the range of current composition text. | 231 // Retrieves the range of current composition text. |
| 275 void GetCompositionTextRange(ui::Range* range) const; | 232 void GetCompositionTextRange(ui::Range* range) const; |
| 276 | 233 |
| 277 // Returns true if there is composition text. | 234 // Returns true if there is composition text. |
| 278 bool HasCompositionText() const; | 235 bool HasCompositionText() const; |
| 279 | 236 |
| 280 TextStyle* CreateTextStyle(); | |
| 281 | |
| 282 void ClearAllTextStyles(); | |
| 283 | |
| 284 private: | 237 private: |
| 285 friend class NativeTextfieldViews; | 238 friend class NativeTextfieldViews; |
| 286 friend class NativeTextfieldViewsTest; | 239 friend class NativeTextfieldViewsTest; |
| 287 friend class TextfieldViewsModelTest; | 240 friend class TextfieldViewsModelTest; |
| 288 friend class TextStyle; | |
| 289 friend class UndoRedo_BasicTest; | 241 friend class UndoRedo_BasicTest; |
| 290 friend class UndoRedo_CutCopyPasteTest; | 242 friend class UndoRedo_CutCopyPasteTest; |
| 291 friend class UndoRedo_ReplaceTest; | 243 friend class UndoRedo_ReplaceTest; |
| 292 friend class internal::Edit; | 244 friend class internal::Edit; |
| 293 | 245 |
| 294 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_BasicTest); | 246 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_BasicTest); |
| 295 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest); | 247 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest); |
| 296 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_ReplaceTest); | 248 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_ReplaceTest); |
| 297 FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, TextStyleTest); | |
| 298 | 249 |
| 299 // Returns the visible text given |start| and |end|. | 250 // Returns the visible text given |start| and |end|. |
| 300 string16 GetVisibleText(size_t start, size_t end) const; | 251 string16 GetVisibleText(size_t start, size_t end) const; |
| 301 | 252 |
| 302 // Utility for SelectWord(). Checks whether position pos is at word boundary. | |
| 303 bool IsPositionAtWordSelectionBoundary(size_t pos); | |
| 304 | |
| 305 // Returns the normalized cursor position that does not exceed the | |
| 306 // text length. | |
| 307 size_t GetSafePosition(size_t position) const; | |
| 308 | |
| 309 // Insert the given |text|. |mergeable| indicates if this insert | 253 // Insert the given |text|. |mergeable| indicates if this insert |
| 310 // operation can be merged to previous edit in the edit history. | 254 // operation can be merged to previous edit in the edit history. |
| 311 void InsertTextInternal(const string16& text, bool mergeable); | 255 void InsertTextInternal(const string16& text, bool mergeable); |
| 312 | 256 |
| 313 // Replace the current text with the given |text|. |mergeable| | 257 // Replace the current text with the given |text|. |mergeable| |
| 314 // indicates if this replace operation can be merged to previous | 258 // indicates if this replace operation can be merged to previous |
| 315 // edit in the edit history. | 259 // edit in the edit history. |
| 316 void ReplaceTextInternal(const string16& text, bool mergeable); | 260 void ReplaceTextInternal(const string16& text, bool mergeable); |
| 317 | 261 |
| 318 // Clears all edit history. | 262 // Clears all edit history. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 342 // Note that the index is after deletion. | 286 // Note that the index is after deletion. |
| 343 // 3) Move the cursor to |new_cursor_pos|. | 287 // 3) Move the cursor to |new_cursor_pos|. |
| 344 void ModifyText(size_t delete_from, | 288 void ModifyText(size_t delete_from, |
| 345 size_t delete_to, | 289 size_t delete_to, |
| 346 const string16& new_text, | 290 const string16& new_text, |
| 347 size_t new_text_insert_at, | 291 size_t new_text_insert_at, |
| 348 size_t new_cursor_pos); | 292 size_t new_cursor_pos); |
| 349 | 293 |
| 350 void ClearComposition(); | 294 void ClearComposition(); |
| 351 | 295 |
| 352 void ApplyTextStyle(const TextStyle* style, const ui::Range& range); | |
| 353 | |
| 354 static TextStyle* CreateUnderlineStyle(); | |
| 355 | |
| 356 // Pointer to a TextfieldViewsModel::Delegate instance, should be provided by | 296 // Pointer to a TextfieldViewsModel::Delegate instance, should be provided by |
| 357 // the View object. | 297 // the View object. |
| 358 Delegate* delegate_; | 298 Delegate* delegate_; |
| 359 | 299 |
| 360 // The text in utf16 format. | 300 // The stylized text, cursor, selection, and the visual layout model. |
| 361 string16 text_; | 301 gfx::RenderText* render_text_; |
| 362 | |
| 363 // Current cursor position. | |
| 364 size_t cursor_pos_; | |
| 365 | |
| 366 // Selection range. | |
| 367 size_t selection_start_; | |
| 368 | |
| 369 // Composition text range. | |
| 370 size_t composition_start_; | |
| 371 size_t composition_end_; | |
| 372 | 302 |
| 373 // True if the text is the password. | 303 // True if the text is the password. |
| 374 bool is_password_; | 304 bool is_password_; |
| 375 | 305 |
| 376 typedef std::list<internal::Edit*> EditHistory; | 306 typedef std::list<internal::Edit*> EditHistory; |
| 377 EditHistory edit_history_; | 307 EditHistory edit_history_; |
| 378 | 308 |
| 379 // An iterator that points to the current edit that can be undone. | 309 // An iterator that points to the current edit that can be undone. |
| 380 // This iterator moves from the |end()|, meaining no edit to undo, | 310 // This iterator moves from the |end()|, meaining no edit to undo, |
| 381 // to the last element (one before |end()|), meaning no edit to redo. | 311 // to the last element (one before |end()|), meaning no edit to redo. |
| 382 // There is no edit to undo (== end()) when: | 312 // There is no edit to undo (== end()) when: |
| 383 // 1) in initial state. (nothing to undo) | 313 // 1) in initial state. (nothing to undo) |
| 384 // 2) very 1st edit is undone. | 314 // 2) very 1st edit is undone. |
| 385 // 3) all edit history is removed. | 315 // 3) all edit history is removed. |
| 386 // There is no edit to redo (== last element or no element) when: | 316 // There is no edit to redo (== last element or no element) when: |
| 387 // 1) in initial state. (nothing to redo) | 317 // 1) in initial state. (nothing to redo) |
| 388 // 2) new edit is added. (redo history is cleared) | 318 // 2) new edit is added. (redo history is cleared) |
| 389 // 3) redone all undone edits. | 319 // 3) redone all undone edits. |
| 390 EditHistory::iterator current_edit_; | 320 EditHistory::iterator current_edit_; |
| 391 | 321 |
| 392 // This manages all styles objects. | |
| 393 TextStyles text_styles_; | |
| 394 | |
| 395 // List of style ranges. Elements in the list never overlap each other. | |
| 396 // Elements are not sorted at the time of insertion, and gets sorted | |
| 397 // when it's painted (if necessary). | |
| 398 TextStyleRanges style_ranges_; | |
| 399 // True if the style_ranges_ needs to be sorted. | |
| 400 bool sort_style_ranges_; | |
| 401 | |
| 402 // List of style ranges for composition text. | |
| 403 TextStyleRanges composition_style_ranges_; | |
| 404 | |
| 405 DISALLOW_COPY_AND_ASSIGN(TextfieldViewsModel); | 322 DISALLOW_COPY_AND_ASSIGN(TextfieldViewsModel); |
| 406 }; | 323 }; |
| 407 | 324 |
| 408 } // namespace views | 325 } // namespace views |
| 409 | 326 |
| 410 #endif // VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_ | 327 #endif // VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_ |
| OLD | NEW |