diff options
author | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-14 15:09:04 +0000 |
---|---|---|
committer | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-14 15:09:04 +0000 |
commit | f445b01ec00fc0ac29282f8a959ee271a9a00362 (patch) | |
tree | 32b73df8237c2645a94db0344e2e85afb2f0a396 /ui/views/controls/textfield/textfield_model.h | |
parent | aaaaf2fd6e3a56f2551e725ebbb02b6eaef1b5c9 (diff) | |
download | chromium_src-f445b01ec00fc0ac29282f8a959ee271a9a00362.zip chromium_src-f445b01ec00fc0ac29282f8a959ee271a9a00362.tar.gz chromium_src-f445b01ec00fc0ac29282f8a959ee271a9a00362.tar.bz2 |
Rename TextfieldViewsModel to TextfieldModel.
Simple rename, no behavior changes.
BUG=131660
TEST=No compile failures, no changes, no regressions.
R=oshima@chromium.org
TBR=sky@chromium.org
Review URL: https://codereview.chromium.org/129833005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244714 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views/controls/textfield/textfield_model.h')
-rw-r--r-- | ui/views/controls/textfield/textfield_model.h | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/ui/views/controls/textfield/textfield_model.h b/ui/views/controls/textfield/textfield_model.h new file mode 100644 index 0000000..c420648 --- /dev/null +++ b/ui/views/controls/textfield/textfield_model.h @@ -0,0 +1,309 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_ +#define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_ + +#include <list> +#include <vector> + +#include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string16.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/base/ime/composition_text.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/render_text.h" +#include "ui/gfx/text_constants.h" +#include "ui/views/views_export.h" + +namespace gfx { +class Range; +class RenderText; +} // namespace gfx + +namespace views { + +namespace internal { +// Internal Edit class that keeps track of edits for undo/redo. +class Edit; + +// C++ doesn't allow forward decl enum, so let's define here. +enum MergeType { + // The edit should not be merged with next edit. It still may + // be merged with an edit with MERGE_WITH_PREVIOUS. + DO_NOT_MERGE, + // The edit can be merged with next edit when possible. + MERGEABLE, + // Does the edit have to be merged with previous edit? + // This forces the merge even if the previous edit is marked + // as DO_NOT_MERGE. + MERGE_WITH_PREVIOUS, +}; + +} // namespace internal + +// A model that represents text content for a views::Textfield. +// It supports editing, selection and cursor manipulation. +class VIEWS_EXPORT TextfieldModel { + public: + // Delegate interface implemented by the textfield view class to provided + // additional functionalities required by the model. + class VIEWS_EXPORT Delegate { + public: + // Called when the current composition text is confirmed or cleared. + virtual void OnCompositionTextConfirmedOrCleared() = 0; + + protected: + virtual ~Delegate(); + }; + + explicit TextfieldModel(Delegate* delegate); + virtual ~TextfieldModel(); + + // Edit related methods. + + const base::string16& text() const { return render_text_->text(); } + // Sets the text. Returns true if the text has been modified. The current + // composition text will be confirmed first. Setting the same text will not + // add edit history because it's not user visible change nor user-initiated + // change. This allow a client code to set the same text multiple times + // without worrying about messing edit history. + bool SetText(const base::string16& new_text); + + gfx::RenderText* render_text() { return render_text_.get(); } + + // Inserts given |new_text| at the current cursor position. + // The current composition text will be cleared. + void InsertText(const base::string16& new_text) { + InsertTextInternal(new_text, false); + } + + // Inserts a character at the current cursor position. + void InsertChar(base::char16 c) { + InsertTextInternal(base::string16(&c, 1), true); + } + + // Replaces characters at the current position with characters in given text. + // The current composition text will be cleared. + void ReplaceText(const base::string16& new_text) { + ReplaceTextInternal(new_text, false); + } + + // Replaces the char at the current position with given character. + void ReplaceChar(base::char16 c) { + ReplaceTextInternal(base::string16(&c, 1), true); + } + + // Appends the text. + // The current composition text will be confirmed. + void Append(const base::string16& new_text); + + // Deletes the first character after the current cursor position (as if, the + // the user has pressed delete key in the textfield). Returns true if + // the deletion is successful. + // If there is composition text, it'll be deleted instead. + bool Delete(); + + // Deletes the first character before the current cursor position (as if, the + // the user has pressed backspace key in the textfield). Returns true if + // the removal is successful. + // If there is composition text, it'll be deleted instead. + bool Backspace(); + + // Cursor related methods. + + // Returns the current cursor position. + size_t GetCursorPosition() const; + + // Moves the cursor, see RenderText for additional details. + // The current composition text will be confirmed. + void MoveCursor(gfx::BreakType break_type, + gfx::VisualCursorDirection direction, + bool select); + + // Moves the selection to the specified selection in |selection|. + // If there is composition text, it will be confirmed, which will update the + // selection range, and it overrides the selection_start to which the + // selection will move to. + bool MoveCursorTo(const gfx::SelectionModel& selection); + + // Helper function to call MoveCursorTo on the TextfieldModel. + bool MoveCursorTo(const gfx::Point& point, bool select); + + // Selection related method + + // Returns the selected text. + base::string16 GetSelectedText() const; + + // The current composition text will be confirmed. The selection starts with + // the range's start position, and ends with the range's end position, + // therefore the cursor position becomes the end position. + void SelectRange(const gfx::Range& range); + + // The current composition text will be confirmed. + // render_text_'s selection model is set to |sel|. + void SelectSelectionModel(const gfx::SelectionModel& sel); + + // Select the entire text range. If |reversed| is true, the range will end at + // the logical beginning of the text; this generally shows the leading portion + // of text that overflows its display area. + // The current composition text will be confirmed. + void SelectAll(bool reversed); + + // Selects the word at which the cursor is currently positioned. If there is a + // non-empty selection, the selection bounds are extended to their nearest + // word boundaries. + // The current composition text will be confirmed. + void SelectWord(); + + // Clears selection. + // The current composition text will be confirmed. + void ClearSelection(); + + // Returns true if there is an undoable edit. + bool CanUndo(); + + // Returns true if there is an redoable edit. + bool CanRedo(); + + // Undo edit. Returns true if undo changed the text. + bool Undo(); + + // Redo edit. Returns true if redo changed the text. + bool Redo(); + + // Cuts the currently selected text and puts it to clipboard. Returns true + // if text has changed after cutting. + bool Cut(); + + // Copies the currently selected text and puts it to clipboard. Returns true + // if something was copied to the clipboard. + bool Copy(); + + // Pastes text from the clipboard at current cursor position. Returns true + // if any text is pasted. + bool Paste(); + + // Tells if any text is selected, even if the selection is in composition + // text. + bool HasSelection() const; + + // Deletes the selected text. This method shouldn't be called with + // composition text. + void DeleteSelection(); + + // Deletes the selected text (if any) and insert text at given position. + void DeleteSelectionAndInsertTextAt(const base::string16& new_text, + size_t position); + + // Retrieves the text content in a given range. + base::string16 GetTextFromRange(const gfx::Range& range) const; + + // Retrieves the range containing all text in the model. + void GetTextRange(gfx::Range* range) const; + + // Sets composition text and attributes. If there is composition text already, + // it'll be replaced by the new one. Otherwise, current selection will be + // replaced. If there is no selection, the composition text will be inserted + // at the insertion point. + // Any changes to the model except text insertion will confirm the current + // composition text. + void SetCompositionText(const ui::CompositionText& composition); + + // Converts current composition text into final content. + void ConfirmCompositionText(); + + // Removes current composition text. + void CancelCompositionText(); + + // Retrieves the range of current composition text. + void GetCompositionTextRange(gfx::Range* range) const; + + // Returns true if there is composition text. + bool HasCompositionText() const; + + // Clears all edit history. + void ClearEditHistory(); + + private: + friend class TextfieldModelTest; + friend class UndoRedo_BasicTest; + friend class UndoRedo_CutCopyPasteTest; + friend class UndoRedo_ReplaceTest; + friend class internal::Edit; + + FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_BasicTest); + FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_CutCopyPasteTest); + FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_ReplaceTest); + + // Insert the given |new_text|. |mergeable| indicates if this insert + // operation can be merged to previous edit in the edit history. + void InsertTextInternal(const base::string16& new_text, bool mergeable); + + // Replace the current text with the given |new_text|. |mergeable| + // indicates if this replace operation can be merged to previous + // edit in the edit history. + void ReplaceTextInternal(const base::string16& new_text, bool mergeable); + + // Clears redo history. + void ClearRedoHistory(); + + // Executes and records edit operations. + void ExecuteAndRecordDelete(gfx::Range range, bool mergeable); + void ExecuteAndRecordReplaceSelection(internal::MergeType merge_type, + const base::string16& new_text); + void ExecuteAndRecordReplace(internal::MergeType merge_type, + size_t old_cursor_pos, + size_t new_cursor_pos, + const base::string16& new_text, + size_t new_text_start); + void ExecuteAndRecordInsert(const base::string16& new_text, bool mergeable); + + // Adds or merge |edit| into edit history. Return true if the edit + // has been merged and must be deleted after redo. + bool AddOrMergeEditHistory(internal::Edit* edit); + + // Modify the text buffer in following way: + // 1) Delete the string from |delete_from| to |delte_to|. + // 2) Insert the |new_text| at the index |new_text_insert_at|. + // Note that the index is after deletion. + // 3) Move the cursor to |new_cursor_pos|. + void ModifyText(size_t delete_from, + size_t delete_to, + const base::string16& new_text, + size_t new_text_insert_at, + size_t new_cursor_pos); + + void ClearComposition(); + + // Pointer to a TextfieldModel::Delegate instance, should be provided by + // the View object. + Delegate* delegate_; + + // The stylized text, cursor, selection, and the visual layout model. + scoped_ptr<gfx::RenderText> render_text_; + + typedef std::list<internal::Edit*> EditHistory; + EditHistory edit_history_; + + // An iterator that points to the current edit that can be undone. + // This iterator moves from the |end()|, meaining no edit to undo, + // to the last element (one before |end()|), meaning no edit to redo. + // There is no edit to undo (== end()) when: + // 1) in initial state. (nothing to undo) + // 2) very 1st edit is undone. + // 3) all edit history is removed. + // There is no edit to redo (== last element or no element) when: + // 1) in initial state. (nothing to redo) + // 2) new edit is added. (redo history is cleared) + // 3) redone all undone edits. + EditHistory::iterator current_edit_; + + DISALLOW_COPY_AND_ASSIGN(TextfieldModel); +}; + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_ |