15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef UI_GFX_SELECTION_MODEL_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UI_GFX_SELECTION_MODEL_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/gfx_export.h"
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/range/range.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VisualCursorDirection and LogicalCursorDirection represent directions of
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// motion of the cursor in BiDi text. The combinations that make sense are:
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  base::i18n::TextDirection  VisualCursorDirection  LogicalCursorDirection
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       LEFT_TO_RIGHT             CURSOR_LEFT           CURSOR_BACKWARD
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       LEFT_TO_RIGHT             CURSOR_RIGHT          CURSOR_FORWARD
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       RIGHT_TO_LEFT             CURSOR_RIGHT          CURSOR_BACKWARD
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       RIGHT_TO_LEFT             CURSOR_LEFT           CURSOR_FORWARD
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum VisualCursorDirection {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CURSOR_LEFT,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CURSOR_RIGHT
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum LogicalCursorDirection {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CURSOR_BACKWARD,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CURSOR_FORWARD
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xji): publish bidi-editing guide line and replace the place holder.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SelectionModel is used to represent the logical selection and visual
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// position of cursor.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For bi-directional text, the mapping between visual position and logical
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// position is not one-to-one. For example, logical text "abcDEF" where capital
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// letters stand for Hebrew, the visual display is "abcFED". According to the
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bidi editing guide (http://bidi-editing-guideline):
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. If pointing to the right half of the cell of a LTR character, the current
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// position must be set after this character and the caret must be displayed
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after this character.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. If pointing to the right half of the cell of a RTL character, the current
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// position must be set before this character and the caret must be displayed
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before this character.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pointing to the right half of 'c' and pointing to the right half of 'D' both
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// set the logical cursor position to 3. But the cursor displayed visually at
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different places:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pointing to the right half of 'c' displays the cursor right of 'c' as
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "abc|FED".
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pointing to the right half of 'D' displays the cursor right of 'D' as
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "abcFED|".
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So, besides the logical selection start point and end point, we need extra
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// information to specify to which character the visual cursor is bound. This
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is given by a "caret affinity" which is either CURSOR_BACKWARD (indicating
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the trailing half of the 'c' in this case) or CURSOR_FORWARD (indicating
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the leading half of the 'D').
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class GFX_EXPORT SelectionModel {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a default SelectionModel to be overwritten later.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a SelectionModel representing a caret |position| without a
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // selection. The |affinity| is meaningful only when the caret is positioned
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // between bidi runs that are not visually contiguous: in that case, it
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // indicates the run to which the caret is attached for display purposes.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel(size_t position, LogicalCursorDirection affinity);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a SelectionModel representing a selection (which may be empty).
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The caret position is the end of the range.
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SelectionModel(const Range& selection, LogicalCursorDirection affinity);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const Range& selection() const { return selection_; }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t caret_pos() const { return selection_.end(); }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogicalCursorDirection caret_affinity() const { return caret_affinity_; }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // WARNING: Generally the selection start should not be changed without
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // considering the effect on the caret affinity.
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void set_selection_start(size_t pos) { selection_.set_start(pos); }
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator==(const SelectionModel& sel) const;
8158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  bool operator!=(const SelectionModel& sel) const { return !(*this == sel); }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string ToString() const;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Logical selection. The logical caret position is the end of the selection.
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Range selection_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The logical direction from the caret position (selection_.end()) to the
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // character it is attached to for display purposes. This matters only when
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the surrounding characters are not visually contiguous, which happens only
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in bidi text (and only at bidi run boundaries). The text is treated as
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // though it was surrounded on both sides by runs in the dominant text
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // direction. For example, supposing the dominant direction is LTR and the
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // logical text is "abcDEF", where DEF is right-to-left text, the visual
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cursor will display as follows:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    caret position    CURSOR_BACKWARD affinity    CURSOR_FORWARD affinity
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          0                  |abcFED                     |abcFED
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          1                  a|bcFED                     a|bcFED
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          2                  ab|cFED                     ab|cFED
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          3                  abc|FED                     abcFED|
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          4                  abcFE|D                     abcFE|D
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          5                  abcF|ED                     abcF|ED
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          6                  abc|FED                     abcFED|
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogicalCursorDirection caret_affinity_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // UI_GFX_SELECTION_MODEL_H_
111