// Copyright 2013 The Flutter 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 FLUTTER_SHELL_PLATFORM_COMMON_TEXT_INPUT_MODEL_H_ #define FLUTTER_SHELL_PLATFORM_COMMON_TEXT_INPUT_MODEL_H_ #include #include #include "flutter/shell/platform/common/text_range.h" namespace flutter { // Handles underlying text input state, using a simple ASCII model. // // Ignores special states like "insert mode" for now. class TextInputModel { public: TextInputModel(); virtual ~TextInputModel(); // Sets the text, as well as the selection and the composing region. // // This method is typically used to update the TextInputModel's editing state // when the Flutter framework sends its latest text editing state. bool SetText(const std::string& text, const TextRange& selection = TextRange(0), const TextRange& composing_range = TextRange(0)); // Attempts to set the text selection. // // Returns false if the selection is not within the bounds of the text. // While in composing mode, the selection is restricted to the composing // range; otherwise, it is restricted to the length of the text. // // To update both the text and the selection/composing range within the text // (for instance, when the framework sends its latest text editing state), // call |SetText| instead. bool SetSelection(const TextRange& range); // Attempts to set the composing range. // // Returns false if the range or offset are out of range for the text, or if // the offset is outside the composing range. // // To update both the text and the selection/composing range within the text // (for instance, when the framework sends its latest text editing state), // call |SetText| instead. bool SetComposingRange(const TextRange& range, size_t cursor_offset); // Begins IME composing mode. // // Resets the composing base and extent to the selection start. The existing // selection is preserved in case composing is aborted with no changes. Until // |EndComposing| is called, any further changes to selection base and extent // are restricted to the composing range. void BeginComposing(); // Replaces the composing range with new UTF-16 text. // // If a selection of non-zero length exists, it is deleted if the composing // text is non-empty. The composing range is adjusted to the length of // |text| and the selection base and offset are set to the end of the // composing range. void UpdateComposingText(const std::u16string& text); // Replaces the composing range with new UTF-8 text. // // If a selection of non-zero length exists, it is deleted if the composing // text is non-empty. The composing range is adjusted to the length of // |text| and the selection base and offset are set to the end of the // composing range. void UpdateComposingText(const std::string& text); // Commits composing range to the string. // // Causes the composing base and extent to be collapsed to the end of the // range. void CommitComposing(); // Ends IME composing mode. // // Collapses the composing base and offset to 0. void EndComposing(); // Adds a Unicode code point. // // Either appends after the cursor (when selection base and extent are the // same), or deletes the selected text, replacing it with the given // code point. void AddCodePoint(char32_t c); // Adds UTF-16 text. // // Either appends after the cursor (when selection base and extent are the // same), or deletes the selected text, replacing it with the given text. void AddText(const std::u16string& text); // Adds UTF-8 text. // // Either appends after the cursor (when selection base and extent are the // same), or deletes the selected text, replacing it with the given text. void AddText(const std::string& text); // Deletes either the selection, or one character ahead of the cursor. // // Deleting one character ahead of the cursor occurs when the selection base // and extent are the same. When composing is active, deletions are // restricted to text between the composing base and extent. // // Returns true if any deletion actually occurred. bool Delete(); // Deletes text near the cursor. // // A section is made starting at |offset_from_cursor| code points past the // cursor (negative values go before the cursor). |count| code points are // removed. The selection may go outside the bounds of the available text and // will result in only the part selection that covers the available text // being deleted. The existing selection is ignored and removed after this // operation. When composing is active, deletions are restricted to the // composing range. // // Returns true if any deletion actually occurred. bool DeleteSurrounding(int offset_from_cursor, int count); // Deletes either the selection, or one character behind the cursor. // // Deleting one character behind the cursor occurs when the selection base // and extent are the same. When composing is active, deletions are // restricted to the text between the composing base and extent. // // Returns true if any deletion actually occurred. bool Backspace(); // Attempts to move the cursor backward. // // Returns true if the cursor could be moved. If a selection is active, moves // to the start of the selection. If composing is active, motion is // restricted to the composing range. bool MoveCursorBack(); // Attempts to move the cursor forward. // // Returns true if the cursor could be moved. If a selection is active, moves // to the end of the selection. If composing is active, motion is restricted // to the composing range. bool MoveCursorForward(); // Attempts to move the cursor to the beginning. // // If composing is active, the cursor is moved to the beginning of the // composing range; otherwise, it is moved to the beginning of the text. If // composing is active, motion is restricted to the composing range. // // Returns true if the cursor could be moved. bool MoveCursorToBeginning(); // Attempts to move the cursor to the end. // // If composing is active, the cursor is moved to the end of the composing // range; otherwise, it is moved to the end of the text. If composing is // active, motion is restricted to the composing range. // // Returns true if the cursor could be moved. bool MoveCursorToEnd(); // Attempts to select text from the cursor position to the beginning. // // If composing is active, the selection is applied to the beginning of the // composing range; otherwise, it is applied to the beginning of the text. // // Returns true if the selection could be applied. bool SelectToBeginning(); // Attempts to select text from the cursor position to the end. // // If composing is active, the selection is applied to the end of the // composing range; otherwise, it is moved to the end of the text. // // Returns true if the selection could be applied. bool SelectToEnd(); // Gets the current text as UTF-8. std::string GetText() const; // Gets the cursor position as a byte offset in UTF-8 string returned from // GetText(). int GetCursorOffset() const; // Returns a range covering the entire text. TextRange text_range() const { return TextRange(0, text_.length()); } // The current selection. TextRange selection() const { return selection_; } // The composing range. // // If not in composing mode, returns a collapsed range at position 0. TextRange composing_range() const { return composing_range_; } // Whether multi-step input composing mode is active. bool composing() const { return composing_; } private: // Deletes the current selection, if any. // // Returns true if any text is deleted. The selection base and extent are // reset to the start of the selected range. bool DeleteSelected(); // Returns the currently editable text range. // // In composing mode, returns the composing range; otherwise, returns a range // covering the entire text. TextRange editable_range() const { return composing_ ? composing_range_ : text_range(); } std::u16string text_; TextRange selection_ = TextRange(0); TextRange composing_range_ = TextRange(0); bool composing_ = false; }; } // namespace flutter #endif // FLUTTER_SHELL_PLATFORM_COMMON_TEXT_INPUT_MODEL_H_