Commit ec7f48d5 authored by msw@chromium.org's avatar msw@chromium.org

Rename GetLeft/RightCursorPosition to GetLeft/RightSelectionModel.

Discard selection from the the GetLeft/RightSelectionModel return value.
Update the cursor properly on edits.

BUG=90426
TEST=--use-pure-views cursor movement, position after editing.

Review URL: http://codereview.chromium.org/7598014

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95945 0039d316-1c4b-4281-b951-d872f2087c98
parent 62f6b6dd
......@@ -182,64 +182,52 @@ void RenderText::SetCursorPosition(const size_t position) {
SelectionModel sel(selection_model());
sel.set_selection_start(position);
sel.set_selection_end(position);
sel.set_caret_pos(GetIndexOfPreviousGrapheme(position));
sel.set_caret_placement(SelectionModel::TRAILING);
SetSelectionModel(sel);
}
void RenderText::MoveCursorLeft(BreakType break_type, bool select) {
if (break_type == LINE_BREAK) {
SelectionModel selection(GetSelectionStart(), 0,
0, SelectionModel::LEADING);
if (!select)
selection.set_selection_start(selection.selection_end());
MoveCursorTo(selection);
return;
}
SelectionModel position = selection_model_;
SelectionModel position(selection_model());
position.set_selection_start(GetCursorPosition());
// Cancelling a selection moves to the edge of the selection.
if (!EmptySelection() && !select) {
if (break_type != LINE_BREAK && !EmptySelection() && !select) {
// Use the selection start if it is left of the selection end.
SelectionModel selection_start(GetSelectionStart(), GetSelectionStart(),
GetSelectionStart(), SelectionModel::LEADING);
SelectionModel::LEADING);
if (GetCursorBounds(selection_start, false).x() <
GetCursorBounds(position, false).x())
position = selection_start;
// If |move_by_word|, use the nearest word boundary left of the selection.
// For word breaks, use the nearest word boundary left of the selection.
if (break_type == WORD_BREAK)
position = GetLeftCursorPosition(position, true);
position = GetLeftSelectionModel(position, break_type);
} else {
position = GetLeftCursorPosition(position, break_type == WORD_BREAK);
position = GetLeftSelectionModel(position, break_type);
}
if (!select)
position.set_selection_start(position.selection_end());
if (select)
position.set_selection_start(GetSelectionStart());
MoveCursorTo(position);
}
void RenderText::MoveCursorRight(BreakType break_type, bool select) {
if (break_type == LINE_BREAK) {
SelectionModel selection(GetSelectionStart(), text().length(),
text().length(), SelectionModel::PREVIOUS_GRAPHEME_TRAILING);
if (!select)
selection.set_selection_start(selection.selection_end());
MoveCursorTo(selection);
return;
}
SelectionModel position = selection_model_;
SelectionModel position(selection_model());
position.set_selection_start(GetCursorPosition());
// Cancelling a selection moves to the edge of the selection.
if (!EmptySelection() && !select) {
if (break_type != LINE_BREAK && !EmptySelection() && !select) {
// Use the selection start if it is right of the selection end.
SelectionModel selection_start(GetSelectionStart(), GetSelectionStart(),
GetSelectionStart(), SelectionModel::LEADING);
SelectionModel::LEADING);
if (GetCursorBounds(selection_start, false).x() >
GetCursorBounds(position, false).x())
position = selection_start;
// If |move_by_word|, use the nearest word boundary right of the selection.
// For word breaks, use the nearest word boundary right of the selection.
if (break_type == WORD_BREAK)
position = GetRightCursorPosition(position, true);
position = GetRightSelectionModel(position, break_type);
} else {
position = GetRightCursorPosition(position, break_type == WORD_BREAK);
position = GetRightSelectionModel(position, break_type);
}
if (!select)
position.set_selection_start(position.selection_end());
if (select)
position.set_selection_start(GetSelectionStart());
MoveCursorTo(position);
}
......@@ -253,8 +241,6 @@ bool RenderText::MoveCursorTo(const Point& point, bool select) {
SelectionModel selection = FindCursorPosition(point);
if (select)
selection.set_selection_start(GetSelectionStart());
else
selection.set_selection_start(selection.selection_end());
return MoveCursorTo(selection);
}
......@@ -267,7 +253,9 @@ bool RenderText::IsPointInSelection(const Point& point) {
}
void RenderText::ClearSelection() {
SetCursorPosition(GetCursorPosition());
SelectionModel sel(selection_model());
sel.set_selection_start(GetCursorPosition());
SetSelectionModel(sel);
}
void RenderText::SelectAll() {
......@@ -503,15 +491,15 @@ RenderText::RenderText()
display_offset_() {
}
SelectionModel RenderText::GetLeftCursorPosition(const SelectionModel& current,
bool move_by_word) {
size_t position = current.selection_end();
SelectionModel left = current;
if (!move_by_word) {
left.set_selection_end(std::max(static_cast<long>(position - 1),
static_cast<long>(0)));
return left;
}
SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current,
BreakType break_type) {
if (break_type == LINE_BREAK)
return SelectionModel(0, 0, SelectionModel::LEADING);
size_t pos = std::max(static_cast<long>(current.selection_end() - 1),
static_cast<long>(0));
if (break_type == CHARACTER_BREAK)
return SelectionModel(pos, pos, SelectionModel::LEADING);
// Notes: We always iterate words from the begining.
// This is probably fast enough for our usage, but we may
// want to modify WordIterator so that it can start from the
......@@ -519,59 +507,54 @@ SelectionModel RenderText::GetLeftCursorPosition(const SelectionModel& current,
base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
bool success = iter.Init();
DCHECK(success);
if (!success) {
left.set_selection_end(position);
return left;
}
int last = 0;
if (!success)
return current;
while (iter.Advance()) {
if (iter.IsWord()) {
size_t begin = iter.pos() - iter.GetString().length();
if (begin == position) {
if (begin == current.selection_end()) {
// The cursor is at the beginning of a word.
// Move to previous word.
break;
} else if (iter.pos() >= position) {
} else if (iter.pos() >= current.selection_end()) {
// The cursor is in the middle or at the end of a word.
// Move to the top of current word.
last = begin;
pos = begin;
break;
} else {
last = iter.pos() - iter.GetString().length();
pos = iter.pos() - iter.GetString().length();
}
}
}
left.set_selection_end(last);
return left;
return SelectionModel(pos, pos, SelectionModel::LEADING);
}
SelectionModel RenderText::GetRightCursorPosition(const SelectionModel& current,
bool move_by_word) {
size_t position = current.selection_end();
SelectionModel right = current;
if (!move_by_word) {
right.set_selection_end(std::min(position + 1, text().length()));
return right;
}
SelectionModel RenderText::GetRightSelectionModel(const SelectionModel& current,
BreakType break_type) {
if (break_type == LINE_BREAK)
return SelectionModel(text().length(),
GetIndexOfPreviousGrapheme(text().length()), SelectionModel::TRAILING);
size_t pos = std::min(current.selection_end() + 1, text().length());
if (break_type == CHARACTER_BREAK)
return SelectionModel(pos, pos, SelectionModel::LEADING);
base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
bool success = iter.Init();
DCHECK(success);
if (!success) {
right.set_selection_end(position);
return right;
}
size_t pos = 0;
if (!success)
return current;
while (iter.Advance()) {
pos = iter.pos();
if (iter.IsWord() && pos > position) {
if (iter.IsWord() && pos > current.selection_end())
break;
}
}
right.set_selection_end(pos);
return right;
return SelectionModel(pos, pos, SelectionModel::LEADING);
}
size_t RenderText::GetIndexOfPreviousGrapheme(size_t position) const {
// TODO(msw): Handle complex script.
return std::max(static_cast<int>(position - 1), static_cast<int>(0));
}
void RenderText::ApplyCompositionAndSelectionStyles(
......
......@@ -49,7 +49,10 @@ struct UI_EXPORT StyleRange {
typedef std::vector<StyleRange> StyleRanges;
// TODO(msw): Distinguish between logical character and glyph?
// TODO(msw): Distinguish between logical character stops and glyph stops?
// CHARACTER_BREAK cursor movements should stop at neighboring characters.
// WORD_BREAK cursor movements should stop at the nearest word boundaries.
// LINE_BREAK cursor movements should stop at the text ends as shown on screen.
enum BreakType {
CHARACTER_BREAK,
WORD_BREAK,
......@@ -186,9 +189,6 @@ class UI_EXPORT RenderText {
// Moves the cursor left or right. Cursor movement is visual, meaning that
// left and right are relative to screen, not the directionality of the text.
// If |select| is false, the selection range is emptied at the new position.
// If |break_type| is CHARACTER_BREAK, move to the neighboring character.
// If |break_type| is WORD_BREAK, move to the nearest word boundary.
// If |break_type| is LINE_BREAK, move to text edge as shown on screen.
void MoveCursorLeft(BreakType break_type, bool select);
void MoveCursorRight(BreakType break_type, bool select);
......@@ -263,12 +263,15 @@ class UI_EXPORT RenderText {
const StyleRanges& style_ranges() const { return style_ranges_; }
// Get the cursor position that visually neighbors |position|.
// If |move_by_word| is true, return the neighboring word delimiter position.
virtual SelectionModel GetLeftCursorPosition(const SelectionModel& current,
bool move_by_word);
virtual SelectionModel GetRightCursorPosition(const SelectionModel& current,
bool move_by_word);
// Get the selection model that visually neighbors |position| by |break_type|.
// The returned value represents a cursor/caret position without a selection.
virtual SelectionModel GetLeftSelectionModel(const SelectionModel& current,
BreakType break_type);
virtual SelectionModel GetRightSelectionModel(const SelectionModel& current,
BreakType break_type);
// Get the logical index of the grapheme preceeding the argument |position|.
virtual size_t GetIndexOfPreviousGrapheme(size_t position) const;
// Apply composition style (underline) to composition range and selection
// style (foreground) to selection range.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment