diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-20 21:21:14 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-20 21:21:14 +0000 |
commit | aa351ca8d4ec607d94b1559bb78b46d8301daf1b (patch) | |
tree | fad1e2da20e07f483ff3a45ddc4c79a9fc8cccdb /ui/gfx/render_text.cc | |
parent | 9edeb71c75df9eed63d4e27e90c2ddfc287049b8 (diff) | |
download | chromium_src-aa351ca8d4ec607d94b1559bb78b46d8301daf1b.zip chromium_src-aa351ca8d4ec607d94b1559bb78b46d8301daf1b.tar.gz chromium_src-aa351ca8d4ec607d94b1559bb78b46d8301daf1b.tar.bz2 |
Revert 102006 - fix know issues in RenderText
1. add tests.
2. change SelectWord() to use BreakIterator, so it works for Chinese and Complex script.
3. DELETE/ReplaceChar delete/replace a whole grapheme. ReplaceTextInternal should only replace one grapheme when there is no selection.
4. pointing to position outside of text returns HOME/END position.
5. based on Chrome Linux omnibox and gedit, given
"abc| def", double click should select " " instead of "abc". Change test expectation.
BUG=90426
TEST=compile with touchui=1 test omnibox. run views_unittests.NativeTextfieldViewsTest/TextfieldViewsModelTest
Review URL: http://codereview.chromium.org/7841056
TBR=xji@google.com
Review URL: http://codereview.chromium.org/7982013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102020 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx/render_text.cc')
-rw-r--r-- | ui/gfx/render_text.cc | 69 |
1 files changed, 38 insertions, 31 deletions
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index 6d15e5c..1111842 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc @@ -247,12 +247,6 @@ bool RenderText::MoveCursorTo(const SelectionModel& selection_model) { sel.set_caret_pos(end.caret_pos()); sel.set_caret_placement(end.caret_placement()); } - - if (!IsCursorablePosition(sel.selection_start()) || - !IsCursorablePosition(sel.selection_end()) || - !IsCursorablePosition(sel.caret_pos())) - return false; - bool changed = !sel.Equals(selection_model_); SetSelectionModel(sel); return changed; @@ -287,28 +281,41 @@ void RenderText::SelectAll() { SetSelectionModel(sel); } +// TODO(xji): it does not work for languages do not use space as word breaker, +// such as Chinese. Should use BreakIterator. void RenderText::SelectWord() { + size_t selection_start = GetSelectionStart(); size_t cursor_position = GetCursorPosition(); + // First we setup selection_start_ and selection_end_. There are so many cases + // because we try to emulate what select-word looks like in a gtk textfield. + // See associated testcase for different cases. + if (cursor_position > 0 && cursor_position < text().length()) { + if (u_isalnum(text()[cursor_position])) { + selection_start = cursor_position; + cursor_position++; + } else + selection_start = cursor_position - 1; + } else if (cursor_position == 0) { + selection_start = cursor_position; + if (text().length() > 0) + cursor_position++; + } else { + selection_start = cursor_position - 1; + } - base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); - bool success = iter.Init(); - DCHECK(success); - if (!success) - return; - - size_t selection_start = cursor_position; - for (; selection_start != 0; --selection_start) { - if (iter.IsStartOfWord(selection_start) || - iter.IsEndOfWord(selection_start)) + // Now we move selection_start_ to beginning of selection. Selection boundary + // is defined as the position where we have alpha-num character on one side + // and non-alpha-num char on the other side. + for (; selection_start > 0; selection_start--) { + if (IsPositionAtWordSelectionBoundary(selection_start)) break; } - if (selection_start == cursor_position) - ++cursor_position; - - for (; cursor_position < text().length(); ++cursor_position) { - if (iter.IsEndOfWord(cursor_position) || - iter.IsStartOfWord(cursor_position)) + // Now we move selection_end_ to end of selection. Selection boundary + // is defined as the position where we have alpha-num character on one side + // and non-alpha-num char on the other side. + for (; cursor_position < text().length(); cursor_position++) { + if (IsPositionAtWordSelectionBoundary(cursor_position)) break; } @@ -455,10 +462,6 @@ const Rect& RenderText::GetUpdatedCursorBounds() { return cursor_bounds_; } -size_t RenderText::GetIndexOfNextGrapheme(size_t position) { - return IndexOfAdjacentGrapheme(position, true); -} - RenderText::RenderText() : text_(), selection_model_(), @@ -554,7 +557,8 @@ SelectionModel RenderText::RightEndSelectionModel() { } size_t RenderText::GetIndexOfPreviousGrapheme(size_t position) { - return IndexOfAdjacentGrapheme(position, false); + // TODO(msw): Handle complex script. + return std::max(static_cast<long>(position - 1), static_cast<long>(0)); } std::vector<Rect> RenderText::GetSubstringBounds(size_t from, size_t to) { @@ -628,10 +632,13 @@ void RenderText::MoveCursorTo(size_t position, bool select) { SelectionModel::CaretPlacement placement = (caret_pos == cursor) ? SelectionModel::LEADING : SelectionModel::TRAILING; size_t selection_start = select ? GetSelectionStart() : cursor; - if (IsCursorablePosition(cursor)) { - SelectionModel sel(selection_start, cursor, caret_pos, placement); - SetSelectionModel(sel); - } + SelectionModel sel(selection_start, cursor, caret_pos, placement); + SetSelectionModel(sel); +} + +bool RenderText::IsPositionAtWordSelectionBoundary(size_t pos) { + return pos == 0 || (u_isalnum(text()[pos - 1]) && !u_isalnum(text()[pos])) || + (!u_isalnum(text()[pos - 1]) && u_isalnum(text()[pos])); } void RenderText::UpdateCachedBoundsAndOffset() { |