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 UI_GFX_SELECTION_MODEL_H_ | 5 #ifndef UI_GFX_SELECTION_MODEL_H_ |
| 6 #define UI_GFX_SELECTION_MODEL_H_ | 6 #define UI_GFX_SELECTION_MODEL_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <stdlib.h> | 9 #include <iosfwd> |
| 10 | 10 |
| 11 #include "ui/base/range/range.h" | |
| 11 #include "ui/base/ui_export.h" | 12 #include "ui/base/ui_export.h" |
| 12 | 13 |
| 13 namespace gfx { | 14 namespace gfx { |
| 14 | 15 |
| 16 // VisualCursorDirection and LogicalCursorDirection represent directions of | |
| 17 // motion of the cursor in BiDi text. The combinations that make sense are: | |
| 18 // | |
| 19 // base::i18n::TextDirection VisualCursorDirection LogicalCursorDirection | |
| 20 // LEFT_TO_RIGHT CURSOR_LEFT CURSOR_BACKWARD | |
| 21 // LEFT_TO_RIGHT CURSOR_RIGHT CURSOR_FORWARD | |
| 22 // RIGHT_TO_LEFT CURSOR_RIGHT CURSOR_BACKWARD | |
| 23 // RIGHT_TO_LEFT CURSOR_LEFT CURSOR_FORWARD | |
| 24 enum VisualCursorDirection { | |
| 25 CURSOR_LEFT, | |
| 26 CURSOR_RIGHT | |
| 27 }; | |
| 28 enum LogicalCursorDirection { | |
| 29 CURSOR_BACKWARD, | |
| 30 CURSOR_FORWARD | |
| 31 }; | |
| 32 | |
| 15 // TODO(xji): publish bidi-editing guide line and replace the place holder. | 33 // TODO(xji): publish bidi-editing guide line and replace the place holder. |
| 16 // SelectionModel is used to represent the logical selection and visual | 34 // SelectionModel is used to represent the logical selection and visual |
| 17 // position of cursor. | 35 // position of cursor. |
| 18 // | 36 // |
| 19 // For bi-directional text, the mapping between visual position and logical | 37 // For bi-directional text, the mapping between visual position and logical |
| 20 // position is not one-to-one. For example, logical text "abcDEF" where capital | 38 // position is not one-to-one. For example, logical text "abcDEF" where capital |
| 21 // letters stand for Hebrew, the visual display is "abcFED". According to the | 39 // letters stand for Hebrew, the visual display is "abcFED". According to the |
| 22 // bidi editing guide (http://bidi-editing-guideline): | 40 // bidi editing guide (http://bidi-editing-guideline): |
| 23 // 1. If pointing to the right half of the cell of a LTR character, the current | 41 // 1. If pointing to the right half of the cell of a LTR character, the current |
| 24 // position must be set after this character and the caret must be displayed | 42 // position must be set after this character and the caret must be displayed |
| 25 // after this character. | 43 // after this character. |
| 26 // 2. If pointing to the right half of the cell of a RTL character, the current | 44 // 2. If pointing to the right half of the cell of a RTL character, the current |
| 27 // position must be set before this character and the caret must be displayed | 45 // position must be set before this character and the caret must be displayed |
| 28 // before this character. | 46 // before this character. |
| 29 // | 47 // |
| 30 // Pointing to the right half of 'c' and pointing to the right half of 'D' both | 48 // Pointing to the right half of 'c' and pointing to the right half of 'D' both |
| 31 // set the logical cursor position to 3. But the cursor displayed visually at | 49 // set the logical cursor position to 3. But the cursor displayed visually at |
| 32 // different places: | 50 // different places: |
| 33 // Pointing to the right half of 'c' displays the cursor right of 'c' as | 51 // Pointing to the right half of 'c' displays the cursor right of 'c' as |
| 34 // "abc|FED". | 52 // "abc|FED". |
| 35 // Pointing to the right half of 'D' displays the cursor right of 'D' as | 53 // Pointing to the right half of 'D' displays the cursor right of 'D' as |
| 36 // "abcFED|". | 54 // "abcFED|". |
| 37 // So, besides the logical selection start point and end point, we need extra | 55 // So, besides the logical selection start point and end point, we need extra |
| 38 // information to specify to which character and on which edge of the character | 56 // information to specify to which character and on which edge of the character |
| 39 // the visual cursor is bound to. For example, the visual cursor is bound to | 57 // the visual cursor is bound to. For example, the visual cursor is bound to |
| 40 // the trailing side of the 2nd character 'c' when pointing to right half of | 58 // the trailing side of the 2nd character 'c' when pointing to right half of |
| 41 // 'c'. And it is bound to the leading edge of the 3rd character 'D' when | 59 // 'c'. And it is bound to the leading edge of the 3rd character 'D' when |
| 42 // pointing to right of 'D'. | 60 // pointing to right of 'D'. |
|
xji
2012/03/08 20:30:02
This paragraph probably need re-write since you ar
benrg
2012/03/08 21:22:03
Well, the cursor is bound to the trailing side of
| |
| 43 class UI_EXPORT SelectionModel { | 61 class UI_EXPORT SelectionModel { |
| 44 public: | 62 public: |
| 45 enum CaretPlacement { | 63 // Create a default SelectionModel to be overwritten later. |
| 46 LEADING, | 64 SelectionModel(); |
| 47 TRAILING, | 65 // Create a SelectionModel representing a caret |position| without a |
| 48 }; | 66 // selection. The |affinity| is meaningful only when the caret is positioned |
| 67 // between bidi runs that are not visually contiguous: in that case, it | |
| 68 // indicates the run to which the caret is attached for display purposes. | |
| 69 SelectionModel(size_t position, LogicalCursorDirection affinity); | |
| 70 // Create a SelectionModel representing a selection (which may be empty). | |
| 71 // The caret position is the end of the range. | |
| 72 SelectionModel(ui::Range selection, LogicalCursorDirection affinity); | |
| 49 | 73 |
| 50 SelectionModel(); | 74 const ui::Range& selection() const { return selection_; } |
| 51 explicit SelectionModel(size_t pos); | 75 size_t caret_pos() const { return selection_.end(); } |
| 52 SelectionModel(size_t end, size_t pos, CaretPlacement status); | 76 LogicalCursorDirection caret_affinity() const { return caret_affinity_; } |
| 53 SelectionModel(size_t start, size_t end, size_t pos, CaretPlacement status); | |
| 54 | 77 |
| 55 virtual ~SelectionModel(); | 78 bool operator==(const SelectionModel& sel) const; |
| 56 | 79 bool operator!=(const SelectionModel& sel) { return !(*this == sel); } |
| 57 size_t selection_start() const { return selection_start_; } | |
| 58 size_t selection_end() const { return selection_end_; } | |
| 59 size_t caret_pos() const { return caret_pos_; } | |
| 60 CaretPlacement caret_placement() const { return caret_placement_; } | |
| 61 | |
| 62 bool Equals(const SelectionModel& sel) const; | |
| 63 | 80 |
| 64 private: | 81 private: |
| 65 friend class RenderText; | 82 friend class RenderText; |
| 66 | 83 |
| 67 void Init(size_t start, size_t end, size_t pos, CaretPlacement status); | 84 // TODO(benrg): This setter is available only to RenderText and should |
| 85 // perhaps be removed. Code generally should not set the selection start | |
| 86 // without considering the effect on the caret affinity. | |
| 87 void set_selection_start(size_t pos) { selection_.set_start(pos); } | |
| 68 | 88 |
| 69 void set_selection_start(size_t pos) { selection_start_ = pos; } | 89 // Logical selection. The logical caret position is the end of the selection. |
| 70 void set_selection_end(size_t pos) { selection_end_ = pos; } | 90 ui::Range selection_; |
| 71 void set_caret_pos(size_t pos) { caret_pos_ = pos; } | |
| 72 void set_caret_placement(CaretPlacement placement) { | |
| 73 caret_placement_ = placement; | |
| 74 } | |
| 75 | 91 |
| 76 // Logical selection start. If there is non-empty selection, if | 92 // The logical direction from the caret position (selection_.end()) to the |
| 77 // selection_start_ is less than selection_end_, the selection starts visually | 93 // character it is attached to for display purposes. This matters only when |
| 78 // at the leading edge of the selection_start_. If selection_start_ is greater | 94 // the surrounding characters are not visually contiguous, which happens only |
| 79 // than selection_end_, the selection starts visually at the trailing edge of | 95 // in bidi text (and only at bidi run boundaries). The text is treated as |
| 80 // selection_start_'s previous grapheme. So, we do not need extra information | 96 // though it was surrounded on both sides by runs in the dominant text |
| 81 // for visual bounding. | 97 // direction. For example, supposing the dominant direction is LTR and the |
| 82 size_t selection_start_; | 98 // logical text is "abcDEF", where DEF is right-to-left text, the visual |
| 99 // cursor will display as follows: | |
| 100 // caret position CURSOR_BACKWARD affinity CURSOR_FORWARD affinity | |
| 101 // 0 |abcFED |abcFED | |
| 102 // 1 a|bcFED a|bcFED | |
| 103 // 2 ab|cFED ab|cFED | |
| 104 // 3 abc|FED abcFED| | |
| 105 // 4 abcFE|D abcFE|D | |
| 106 // 5 abcF|ED abcF|ED | |
| 107 // 6 abc|FED abcFED| | |
| 108 LogicalCursorDirection caret_affinity_; | |
| 109 }; | |
| 83 | 110 |
| 84 // The logical cursor position that next character will be inserted into. | 111 UI_EXPORT std::ostream& operator<<(std::ostream& out, |
| 85 // It is also the end of the selection. | 112 const SelectionModel& sel); |
| 86 size_t selection_end_; | |
| 87 | |
| 88 // The following two fields are used to guide cursor visual position. | |
| 89 // The index of the character that cursor is visually attached to. | |
| 90 size_t caret_pos_; | |
| 91 // The visual placement of the cursor, relative to its associated character. | |
| 92 CaretPlacement caret_placement_; | |
| 93 }; | |
| 94 | 113 |
| 95 } // namespace gfx | 114 } // namespace gfx |
| 96 | 115 |
| 97 #endif // UI_GFX_SELECTION_MODEL_H_ | 116 #endif // UI_GFX_SELECTION_MODEL_H_ |
| OLD | NEW |