|  | // 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_ |