// Copyright (c) 2012 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_GFX_SELECTION_MODEL_H_ #define UI_GFX_SELECTION_MODEL_H_ #include <string> #include "ui/gfx/gfx_export.h" #include "ui/gfx/range/range.h" namespace gfx { // VisualCursorDirection and LogicalCursorDirection represent directions of // motion of the cursor in BiDi text. The combinations that make sense are: // // base::i18n::TextDirection VisualCursorDirection LogicalCursorDirection // LEFT_TO_RIGHT CURSOR_LEFT CURSOR_BACKWARD // LEFT_TO_RIGHT CURSOR_RIGHT CURSOR_FORWARD // RIGHT_TO_LEFT CURSOR_RIGHT CURSOR_BACKWARD // RIGHT_TO_LEFT CURSOR_LEFT CURSOR_FORWARD enum VisualCursorDirection { CURSOR_LEFT, CURSOR_RIGHT }; enum LogicalCursorDirection { CURSOR_BACKWARD, CURSOR_FORWARD }; // TODO(xji): publish bidi-editing guide line and replace the place holder. // SelectionModel is used to represent the logical selection and visual // position of cursor. // // For bi-directional text, the mapping between visual position and logical // position is not one-to-one. For example, logical text "abcDEF" where capital // letters stand for Hebrew, the visual display is "abcFED". According to the // bidi editing guide (http://bidi-editing-guideline): // 1. If pointing to the right half of the cell of a LTR character, the current // position must be set after this character and the caret must be displayed // after this character. // 2. If pointing to the right half of the cell of a RTL character, the current // position must be set before this character and the caret must be displayed // before this character. // // Pointing to the right half of 'c' and pointing to the right half of 'D' both // set the logical cursor position to 3. But the cursor displayed visually at // different places: // Pointing to the right half of 'c' displays the cursor right of 'c' as // "abc|FED". // Pointing to the right half of 'D' displays the cursor right of 'D' as // "abcFED|". // So, besides the logical selection start point and end point, we need extra // information to specify to which character the visual cursor is bound. This // is given by a "caret affinity" which is either CURSOR_BACKWARD (indicating // the trailing half of the 'c' in this case) or CURSOR_FORWARD (indicating // the leading half of the 'D'). class GFX_EXPORT SelectionModel { public: // Create a default SelectionModel to be overwritten later. SelectionModel(); // Create a SelectionModel representing a caret |position| without a // selection. The |affinity| is meaningful only when the caret is positioned // between bidi runs that are not visually contiguous: in that case, it // indicates the run to which the caret is attached for display purposes. SelectionModel(size_t position, LogicalCursorDirection affinity); // Create a SelectionModel representing a selection (which may be empty). // The caret position is the end of the range. SelectionModel(const Range& selection, LogicalCursorDirection affinity); const Range& selection() const { return selection_; } size_t caret_pos() const { return selection_.end(); } LogicalCursorDirection caret_affinity() const { return caret_affinity_; } // WARNING: Generally the selection start should not be changed without // considering the effect on the caret affinity. void set_selection_start(size_t pos) { selection_.set_start(pos); } bool operator==(const SelectionModel& sel) const; bool operator!=(const SelectionModel& sel) const { return !(*this == sel); } std::string ToString() const; private: // Logical selection. The logical caret position is the end of the selection. Range selection_; // The logical direction from the caret position (selection_.end()) to the // character it is attached to for display purposes. This matters only when // the surrounding characters are not visually contiguous, which happens only // in bidi text (and only at bidi run boundaries). The text is treated as // though it was surrounded on both sides by runs in the dominant text // direction. For example, supposing the dominant direction is LTR and the // logical text is "abcDEF", where DEF is right-to-left text, the visual // cursor will display as follows: // caret position CURSOR_BACKWARD affinity CURSOR_FORWARD affinity // 0 |abcFED |abcFED // 1 a|bcFED a|bcFED // 2 ab|cFED ab|cFED // 3 abc|FED abcFED| // 4 abcFE|D abcFE|D // 5 abcF|ED abcF|ED // 6 abc|FED abcFED| LogicalCursorDirection caret_affinity_; }; } // namespace gfx #endif // UI_GFX_SELECTION_MODEL_H_