selection_model.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
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) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/range/range.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_export.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'). 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UI_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. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectionModel(ui::Range selection, LogicalCursorDirection affinity); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::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) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator==(const SelectionModel& sel) const; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator!=(const SelectionModel& sel) { return !(*this == sel); } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string ToString() const; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class RenderText; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(benrg): Generally the selection start should not be changed without 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // considering the effect on the caret affinity. This setter is exposed only 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to RenderText to discourage misuse, and should probably be removed. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_selection_start(size_t pos) { selection_.set_start(pos); } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Logical selection. The logical caret position is the end of the selection. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::Range selection_; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The logical direction from the caret position (selection_.end()) to the 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // character it is attached to for display purposes. This matters only when 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the surrounding characters are not visually contiguous, which happens only 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in bidi text (and only at bidi run boundaries). The text is treated as 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // though it was surrounded on both sides by runs in the dominant text 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // direction. For example, supposing the dominant direction is LTR and the 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // logical text is "abcDEF", where DEF is right-to-left text, the visual 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cursor will display as follows: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caret position CURSOR_BACKWARD affinity CURSOR_FORWARD affinity 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 |abcFED |abcFED 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1 a|bcFED a|bcFED 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 ab|cFED ab|cFED 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3 abc|FED abcFED| 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4 abcFE|D abcFE|D 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5 abcF|ED abcF|ED 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6 abc|FED abcFED| 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogicalCursorDirection caret_affinity_; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // UI_GFX_SELECTION_MODEL_H_ 114