summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxji@google.com <xji@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-12 20:03:45 +0000
committerxji@google.com <xji@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-12 20:03:45 +0000
commit67e85519340234bbf3e3981caa8d68e4663aff07 (patch)
tree7cdffd782898ecc01232ac6f6c9406d9725690cf
parent679a41d1084397c7ca9cdd7956ed2edbf9aa0784 (diff)
downloadchromium_src-67e85519340234bbf3e3981caa8d68e4663aff07.zip
chromium_src-67e85519340234bbf3e3981caa8d68e4663aff07.tar.gz
chromium_src-67e85519340234bbf3e3981caa8d68e4663aff07.tar.bz2
1. change the setters of gfx::SelectionModel to be private. Set one alone might make SelectionModel into un-stable state, which should not be allowed.
2. Removing SelectionModel(size_t, size_t) constructor. Introduce RenderText::SelectRange(const ui::Range&) to handle range. 3. revert removal of SelectRange/GetSelectedRange in r103188. BUG=90426 TEST=view_unittests. Review URL: http://codereview.chromium.org/8044004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105138 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/views/omnibox/omnibox_view_views.cc59
-rw-r--r--ui/gfx/render_text.cc29
-rw-r--r--ui/gfx/render_text.h11
-rw-r--r--ui/gfx/selection_model.cc4
-rw-r--r--ui/gfx/selection_model.h19
-rw-r--r--views/controls/textfield/native_textfield_gtk.cc12
-rw-r--r--views/controls/textfield/native_textfield_gtk.h2
-rw-r--r--views/controls/textfield/native_textfield_views.cc37
-rw-r--r--views/controls/textfield/native_textfield_views.h2
-rw-r--r--views/controls/textfield/native_textfield_views_unittest.cc11
-rw-r--r--views/controls/textfield/native_textfield_win.cc8
-rw-r--r--views/controls/textfield/native_textfield_win.h2
-rw-r--r--views/controls/textfield/native_textfield_wrapper.h6
-rw-r--r--views/controls/textfield/textfield.cc24
-rw-r--r--views/controls/textfield/textfield.h8
-rw-r--r--views/controls/textfield/textfield_views_model.cc40
-rw-r--r--views/controls/textfield/textfield_views_model.h8
-rw-r--r--views/controls/textfield/textfield_views_model_unittest.cc193
-rw-r--r--views/touchui/touch_selection_controller_impl_unittest.cc153
19 files changed, 467 insertions, 161 deletions
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 30b0631..d8988d1 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -241,7 +241,7 @@ bool OmniboxViewViews::HandleAfterKeyEvent(const views::KeyEvent& event,
GetSelectionBounds(&start, &end);
if (start != end || start < length) {
OnBeforePossibleChange();
- textfield_->SelectSelectionModel(gfx::SelectionModel(length, length));
+ textfield_->SelectRange(ui::Range(length, length));
OnAfterPossibleChange();
handled = true;
}
@@ -413,12 +413,10 @@ void OmniboxViewViews::SetWindowTextAndCaretPos(const string16& text,
void OmniboxViewViews::SetForcedQuery() {
const string16 current_text(GetText());
const size_t start = current_text.find_first_not_of(kWhitespaceUTF16);
- if (start == string16::npos || (current_text[start] != '?')) {
+ if (start == string16::npos || (current_text[start] != '?'))
SetUserText(ASCIIToUTF16("?"));
- } else {
- textfield_->SelectSelectionModel(gfx::SelectionModel(current_text.size(),
- start + 1));
- }
+ else
+ textfield_->SelectRange(ui::Range(current_text.size(), start + 1));
}
bool OmniboxViewViews::IsSelectAll() {
@@ -432,17 +430,17 @@ bool OmniboxViewViews::DeleteAtEndPressed() {
void OmniboxViewViews::GetSelectionBounds(string16::size_type* start,
string16::size_type* end) {
- gfx::SelectionModel sel;
- textfield_->GetSelectionModel(&sel);
- *start = static_cast<size_t>(sel.selection_end());
- *end = static_cast<size_t>(sel.selection_start());
+ ui::Range range;
+ textfield_->GetSelectedRange(&range);
+ *start = static_cast<size_t>(range.end());
+ *end = static_cast<size_t>(range.start());
}
void OmniboxViewViews::SelectAll(bool reversed) {
if (reversed)
- textfield_->SelectSelectionModel(gfx::SelectionModel(GetTextLength(), 0));
+ textfield_->SelectRange(ui::Range(GetTextLength(), 0));
else
- textfield_->SelectSelectionModel(gfx::SelectionModel(0, GetTextLength()));
+ textfield_->SelectRange(ui::Range(0, GetTextLength()));
}
void OmniboxViewViews::RevertAll() {
@@ -458,15 +456,12 @@ void OmniboxViewViews::UpdatePopup() {
// Don't inline autocomplete when the caret/selection isn't at the end of
// the text, or in the middle of composition.
- gfx::SelectionModel sel;
- textfield_->GetSelectionModel(&sel);
- size_t max_of_selection = std::max(sel.selection_start(),
- sel.selection_end());
+ ui::Range sel;
+ textfield_->GetSelectedRange(&sel);
bool no_inline_autocomplete =
- max_of_selection < GetTextLength() || textfield_->IsIMEComposing();
+ sel.GetMax() < GetTextLength() || textfield_->IsIMEComposing();
- bool is_sel_empty = (sel.selection_start() == sel.selection_end());
- model_->StartAutocomplete(!is_sel_empty, no_inline_autocomplete);
+ model_->StartAutocomplete(!sel.is_empty(), no_inline_autocomplete);
}
void OmniboxViewViews::ClosePopup() {
@@ -481,12 +476,8 @@ void OmniboxViewViews::SetFocus() {
void OmniboxViewViews::OnTemporaryTextMaybeChanged(
const string16& display_text,
bool save_original_selection) {
- if (save_original_selection) {
- gfx::SelectionModel sel;
- textfield_->GetSelectionModel(&sel);
- saved_temporary_selection_.set_start(sel.selection_start());
- saved_temporary_selection_.set_end(sel.selection_end());
- }
+ if (save_original_selection)
+ textfield_->GetSelectedRange(&saved_temporary_selection_);
SetWindowTextAndCaretPos(display_text, display_text.length());
TextChanged();
@@ -504,28 +495,20 @@ bool OmniboxViewViews::OnInlineAutocompleteTextMaybeChanged(
}
void OmniboxViewViews::OnRevertTemporaryText() {
- gfx::SelectionModel sel(saved_temporary_selection_.start(),
- saved_temporary_selection_.end());
- textfield_->SelectSelectionModel(sel);
+ textfield_->SelectRange(saved_temporary_selection_);
TextChanged();
}
void OmniboxViewViews::OnBeforePossibleChange() {
// Record our state.
text_before_change_ = GetText();
- gfx::SelectionModel sel;
- textfield_->GetSelectionModel(&sel);
- sel_before_change_.set_start(sel.selection_start());
- sel_before_change_.set_end(sel.selection_end());
+ textfield_->GetSelectedRange(&sel_before_change_);
ime_composing_before_change_ = textfield_->IsIMEComposing();
}
bool OmniboxViewViews::OnAfterPossibleChange() {
- gfx::SelectionModel sel;
- textfield_->GetSelectionModel(&sel);
ui::Range new_sel;
- new_sel.set_start(sel.selection_start());
- new_sel.set_end(sel.selection_end());
+ textfield_->GetSelectedRange(&new_sel);
// See if the text or selection have changed since OnBeforePossibleChange().
const string16 new_text = GetText();
@@ -714,8 +697,7 @@ void OmniboxViewViews::SetTextAndSelectedRange(const string16& text,
const ui::Range& range) {
if (text != GetText())
textfield_->SetText(text);
- textfield_->SelectSelectionModel(gfx::SelectionModel(
- range.start(), range.end()));
+ textfield_->SelectRange(range);
}
string16 OmniboxViewViews::GetSelectedText() const {
@@ -723,7 +705,6 @@ string16 OmniboxViewViews::GetSelectedText() const {
return textfield_->GetSelectedText();
}
-
AutocompletePopupView* OmniboxViewViews::CreatePopupView(
View* location_bar) {
#if defined(TOUCH_UI)
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 001b4b2..6d360b7 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -220,6 +220,30 @@ bool RenderText::MoveCursorTo(const Point& point, bool select) {
return MoveCursorTo(selection);
}
+bool RenderText::SelectRange(const ui::Range& range) {
+ size_t text_length = text().length();
+ size_t start = std::min(range.start(), text_length);
+ size_t end = std::min(range.end(), text_length);
+
+ if (!IsCursorablePosition(start) || !IsCursorablePosition(end))
+ return false;
+
+ size_t pos = end;
+ SelectionModel::CaretPlacement placement = SelectionModel::LEADING;
+ if (start < end) {
+ pos = GetIndexOfPreviousGrapheme(end);
+ DCHECK_LT(pos, end);
+ placement = SelectionModel::TRAILING;
+ } else if (end == text_length) {
+ SelectionModel boundary = GetTextDirection() == base::i18n::RIGHT_TO_LEFT ?
+ LeftEndSelectionModel() : RightEndSelectionModel();
+ pos = boundary.caret_pos();
+ placement = boundary.caret_placement();
+ }
+ SetSelectionModel(SelectionModel(start, end, pos, placement));
+ return true;
+}
+
bool RenderText::IsPointInSelection(const Point& point) {
if (EmptySelection())
return false;
@@ -450,7 +474,7 @@ const Point& RenderText::GetUpdatedDisplayOffset() {
SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current,
BreakType break_type) {
if (break_type == LINE_BREAK)
- return SelectionModel(0, 0, SelectionModel::LEADING);
+ return LeftEndSelectionModel();
size_t pos = std::max(static_cast<long>(current.selection_end() - 1),
static_cast<long>(0));
if (break_type == CHARACTER_BREAK)
@@ -491,8 +515,7 @@ SelectionModel RenderText::GetRightSelectionModel(const SelectionModel& current,
if (text_.empty())
return SelectionModel(0, 0, SelectionModel::LEADING);
if (break_type == LINE_BREAK)
- return SelectionModel(text().length(),
- GetIndexOfPreviousGrapheme(text().length()), SelectionModel::TRAILING);
+ return RightEndSelectionModel();
size_t pos = std::min(current.selection_end() + 1, text().length());
if (break_type == CHARACTER_BREAK)
return SelectionModel(pos, pos, SelectionModel::LEADING);
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 7e98b0c..b6c6342 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -100,10 +100,6 @@ class UI_EXPORT RenderText {
size_t GetCursorPosition() const;
void SetCursorPosition(size_t position);
- void SetCaretPlacement(SelectionModel::CaretPlacement placement) {
- selection_model_.set_caret_placement(placement);
- }
-
// 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 start is moved to the same position.
@@ -123,6 +119,13 @@ class UI_EXPORT RenderText {
// Returns true if the cursor position or selection range changed.
bool MoveCursorTo(const Point& point, bool select);
+ // Set the selection_model_ based on |range|.
+ // If the |range| start or end is greater than text length, it is modified
+ // to be the text length.
+ // If the |range| start or end is not a cursorable position (not on grapheme
+ // boundary), it is a NO-OP and returns false. Otherwise, returns true.
+ bool SelectRange(const ui::Range& range);
+
size_t GetSelectionStart() const {
return selection_model_.selection_start();
}
diff --git a/ui/gfx/selection_model.cc b/ui/gfx/selection_model.cc
index 743f35d..3dec8be 100644
--- a/ui/gfx/selection_model.cc
+++ b/ui/gfx/selection_model.cc
@@ -14,10 +14,6 @@ SelectionModel::SelectionModel(size_t pos) {
Init(pos, pos, pos, LEADING);
}
-SelectionModel::SelectionModel(size_t start, size_t end) {
- Init(start, end, end, LEADING);
-}
-
SelectionModel::SelectionModel(size_t end,
size_t pos,
CaretPlacement placement) {
diff --git a/ui/gfx/selection_model.h b/ui/gfx/selection_model.h
index 3e7cf9f..4ef3ca0 100644
--- a/ui/gfx/selection_model.h
+++ b/ui/gfx/selection_model.h
@@ -49,31 +49,30 @@ class UI_EXPORT SelectionModel {
SelectionModel();
explicit SelectionModel(size_t pos);
- SelectionModel(size_t start, size_t end);
SelectionModel(size_t end, size_t pos, CaretPlacement status);
SelectionModel(size_t start, size_t end, size_t pos, CaretPlacement status);
virtual ~SelectionModel();
size_t selection_start() const { return selection_start_; }
- void set_selection_start(size_t pos) { selection_start_ = pos; }
-
size_t selection_end() const { return selection_end_; }
- void set_selection_end(size_t pos) { selection_end_ = pos; }
-
size_t caret_pos() const { return caret_pos_; }
- void set_caret_pos(size_t pos) { caret_pos_ = pos; }
-
CaretPlacement caret_placement() const { return caret_placement_; }
- void set_caret_placement(CaretPlacement placement) {
- caret_placement_ = placement;
- }
bool Equals(const SelectionModel& sel) const;
private:
+ friend class RenderText;
+
void Init(size_t start, size_t end, size_t pos, CaretPlacement status);
+ void set_selection_start(size_t pos) { selection_start_ = pos; }
+ void set_selection_end(size_t pos) { selection_end_ = pos; }
+ void set_caret_pos(size_t pos) { caret_pos_ = pos; }
+ void set_caret_placement(CaretPlacement placement) {
+ caret_placement_ = placement;
+ }
+
// Logical selection start. If there is non-empty selection, if
// selection_start_ is less than selection_end_, the selection starts visually
// at the leading edge of the selection_start_. If selection_start_ is greater
diff --git a/views/controls/textfield/native_textfield_gtk.cc b/views/controls/textfield/native_textfield_gtk.cc
index 9fe5784c..b4a98f8 100644
--- a/views/controls/textfield/native_textfield_gtk.cc
+++ b/views/controls/textfield/native_textfield_gtk.cc
@@ -249,12 +249,20 @@ bool NativeTextfieldGtk::IsIMEComposing() const {
return false;
}
-void NativeTextfieldGtk::GetSelectionModel(gfx::SelectionModel* sel) const {
+void NativeTextfieldGtk::GetSelectedRange(ui::Range* range) const {
gint start_pos;
gint end_pos;
gtk_editable_get_selection_bounds(
GTK_EDITABLE(native_view()), &start_pos, &end_pos);
- *sel = gfx::SelectionModel(start_pos, end_pos);
+ *range = ui::Range(start_pos, end_pos);
+}
+
+void NativeTextfieldGtk::SelectRange(const ui::Range& range) {
+ NOTREACHED();
+}
+
+void NativeTextfieldGtk::GetSelectionModel(gfx::SelectionModel* sel) const {
+ NOTREACHED();
}
void NativeTextfieldGtk::SelectSelectionModel(const gfx::SelectionModel& sel) {
diff --git a/views/controls/textfield/native_textfield_gtk.h b/views/controls/textfield/native_textfield_gtk.h
index 2a6190b..e7be873 100644
--- a/views/controls/textfield/native_textfield_gtk.h
+++ b/views/controls/textfield/native_textfield_gtk.h
@@ -53,6 +53,8 @@ class NativeTextfieldGtk : public NativeControlGtk,
virtual View* GetView() OVERRIDE;
virtual gfx::NativeView GetTestingHandle() const OVERRIDE;
virtual bool IsIMEComposing() const OVERRIDE;
+ virtual void GetSelectedRange(ui::Range* range) const OVERRIDE;
+ virtual void SelectRange(const ui::Range& range) OVERRIDE;
virtual void GetSelectionModel(gfx::SelectionModel* sel) const OVERRIDE;
virtual void SelectSelectionModel(const gfx::SelectionModel& sel) OVERRIDE;
virtual size_t GetCursorPosition() const OVERRIDE;
diff --git a/views/controls/textfield/native_textfield_views.cc b/views/controls/textfield/native_textfield_views.cc
index 8d8f609..20ebbc7 100644
--- a/views/controls/textfield/native_textfield_views.cc
+++ b/views/controls/textfield/native_textfield_views.cc
@@ -226,15 +226,13 @@ int NativeTextfieldViews::OnPerformDrop(const DropTargetEvent& event) {
selected.selection_end());
size_t selected_range_length = max_of_selected_range -
min_of_selected_range;
- if (max_of_selected_range <= drop_destination.selection_end())
- drop_destination.set_selection_end(
- drop_destination.selection_end() - selected_range_length);
- else if (min_of_selected_range <= drop_destination.selection_end())
- drop_destination.set_selection_end(min_of_selected_range);
- model_->DeleteSelectionAndInsertTextAt(text,
- drop_destination.selection_end());
+ size_t drop_destination_end = drop_destination.selection_end();
+ if (max_of_selected_range <= drop_destination_end)
+ drop_destination_end -= selected_range_length;
+ else if (min_of_selected_range <= drop_destination_end)
+ drop_destination_end = min_of_selected_range;
+ model_->DeleteSelectionAndInsertTextAt(text, drop_destination_end);
} else {
- drop_destination.set_selection_start(drop_destination.selection_end());
model_->MoveCursorTo(drop_destination);
// Drop always inserts text even if the textfield is not in insert mode.
model_->InsertText(text);
@@ -278,9 +276,11 @@ void NativeTextfieldViews::SelectRect(const gfx::Point& start,
// Merge selection models of "start_pos" and "end_pos" so that
// selection start is the value from "start_pos", while selection end,
// caret position, and caret placement are values from "end_pos".
- gfx::SelectionModel sel(end_pos);
- sel.set_selection_start(start_pos.selection_start());
- model_->SelectSelectionModel(sel);
+ if (start_pos.selection_start() == end_pos.selection_end())
+ model_->SelectSelectionModel(end_pos);
+ else
+ model_->SelectRange(ui::Range(start_pos.selection_start(),
+ end_pos.selection_end()));
OnCaretBoundsChanged();
SchedulePaint();
@@ -490,6 +490,16 @@ bool NativeTextfieldViews::IsIMEComposing() const {
return model_->HasCompositionText();
}
+void NativeTextfieldViews::GetSelectedRange(ui::Range* range) const {
+ model_->GetSelectedRange(range);
+}
+
+void NativeTextfieldViews::SelectRange(const ui::Range& range) {
+ model_->SelectRange(range);
+ OnCaretBoundsChanged();
+ SchedulePaint();
+}
+
void NativeTextfieldViews::GetSelectionModel(gfx::SelectionModel* sel) const {
model_->GetSelectionModel(sel);
}
@@ -758,7 +768,7 @@ bool NativeTextfieldViews::SetSelectionRange(const ui::Range& range) {
return false;
OnBeforeUserAction();
- SelectSelectionModel(gfx::SelectionModel(range.start(), range.end()));
+ SelectRange(range);
OnAfterUserAction();
return true;
}
@@ -768,8 +778,7 @@ bool NativeTextfieldViews::DeleteRange(const ui::Range& range) {
return false;
OnBeforeUserAction();
- gfx::SelectionModel selection(range.start(), range.end());
- model_->SelectSelectionModel(selection);
+ model_->SelectRange(range);
if (model_->HasSelection()) {
model_->DeleteSelection();
UpdateAfterChange(true, true);
diff --git a/views/controls/textfield/native_textfield_views.h b/views/controls/textfield/native_textfield_views.h
index f646e7f..d6c00a3 100644
--- a/views/controls/textfield/native_textfield_views.h
+++ b/views/controls/textfield/native_textfield_views.h
@@ -110,6 +110,8 @@ class VIEWS_EXPORT NativeTextfieldViews : public TouchSelectionClientView,
virtual View* GetView() OVERRIDE;
virtual gfx::NativeView GetTestingHandle() const OVERRIDE;
virtual bool IsIMEComposing() const OVERRIDE;
+ virtual void GetSelectedRange(ui::Range* range) const OVERRIDE;
+ virtual void SelectRange(const ui::Range& range) OVERRIDE;
virtual void GetSelectionModel(gfx::SelectionModel* sel) const OVERRIDE;
virtual void SelectSelectionModel(const gfx::SelectionModel& sel) OVERRIDE;
virtual size_t GetCursorPosition() const OVERRIDE;
diff --git a/views/controls/textfield/native_textfield_views_unittest.cc b/views/controls/textfield/native_textfield_views_unittest.cc
index 05c3d41..f0c24b7 100644
--- a/views/controls/textfield/native_textfield_views_unittest.cc
+++ b/views/controls/textfield/native_textfield_views_unittest.cc
@@ -794,7 +794,8 @@ TEST_F(NativeTextfieldViewsTest, MAYBE_DragAndDrop_InitiateDrag) {
// Ensure the textfield will provide selected text for drag data.
string16 string;
ui::OSExchangeData data;
- textfield_->SelectSelectionModel(gfx::SelectionModel(6, 12));
+ const ui::Range kStringRange(6, 12);
+ textfield_->SelectRange(kStringRange);
const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
textfield_view_->WriteDragDataForView(NULL, kStringPoint, &data);
EXPECT_TRUE(data.GetString(&string));
@@ -809,7 +810,7 @@ TEST_F(NativeTextfieldViewsTest, MAYBE_DragAndDrop_InitiateDrag) {
textfield_->ClearSelection();
EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
textfield_view_->GetDragOperationsForView(NULL, kStringPoint));
- textfield_->SelectSelectionModel(gfx::SelectionModel(6, 12));
+ textfield_->SelectRange(kStringRange);
// Ensure that textfields only initiate drag operations inside the selection.
EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
textfield_view_->GetDragOperationsForView(NULL, gfx::Point()));
@@ -835,7 +836,7 @@ TEST_F(NativeTextfieldViewsTest, MAYBE_DragAndDrop_ToTheRight) {
std::set<OSExchangeData::CustomFormat> custom_formats;
// Start dragging "ello".
- textfield_->SelectSelectionModel(gfx::SelectionModel(1, 5));
+ textfield_->SelectRange(ui::Range(1, 5));
MouseEvent click_a(ui::ET_MOUSE_PRESSED, GetCursorPositionX(3), 0,
ui::EF_LEFT_BUTTON_DOWN);
textfield_view_->OnMousePressed(click_a);
@@ -889,7 +890,7 @@ TEST_F(NativeTextfieldViewsTest, MAYBE_DragAndDrop_ToTheLeft) {
std::set<OSExchangeData::CustomFormat> custom_formats;
// Start dragging " worl".
- textfield_->SelectSelectionModel(gfx::SelectionModel(5, 10));
+ textfield_->SelectRange(ui::Range(5, 10));
MouseEvent click_a(ui::ET_MOUSE_PRESSED, GetCursorPositionX(7), 0,
ui::EF_LEFT_BUTTON_DOWN);
textfield_view_->OnMousePressed(click_a);
@@ -936,7 +937,7 @@ TEST_F(NativeTextfieldViewsTest, MAYBE_DragAndDrop_Canceled) {
textfield_->SetText(ASCIIToUTF16("hello world"));
// Start dragging "worl".
- textfield_->SelectSelectionModel(gfx::SelectionModel(6, 10));
+ textfield_->SelectRange(ui::Range(6, 10));
MouseEvent click(ui::ET_MOUSE_PRESSED, GetCursorPositionX(8), 0,
ui::EF_LEFT_BUTTON_DOWN);
textfield_view_->OnMousePressed(click);
diff --git a/views/controls/textfield/native_textfield_win.cc b/views/controls/textfield/native_textfield_win.cc
index 95a5ec2..8e29ebc 100644
--- a/views/controls/textfield/native_textfield_win.cc
+++ b/views/controls/textfield/native_textfield_win.cc
@@ -336,6 +336,14 @@ bool NativeTextfieldWin::IsIMEComposing() const {
return composition_size > 0;
}
+void NativeTextfieldWin::GetSelectedRange(ui::Range* range) const {
+ NOTREACHED();
+}
+
+void NativeTextfieldWin::SelectRange(const ui::Range& range) {
+ NOTREACHED();
+}
+
void NativeTextfieldWin::GetSelectionModel(gfx::SelectionModel* sel) const {
NOTREACHED();
}
diff --git a/views/controls/textfield/native_textfield_win.h b/views/controls/textfield/native_textfield_win.h
index 26dc627..7c4880b 100644
--- a/views/controls/textfield/native_textfield_win.h
+++ b/views/controls/textfield/native_textfield_win.h
@@ -82,6 +82,8 @@ class NativeTextfieldWin
virtual View* GetView() OVERRIDE;
virtual gfx::NativeView GetTestingHandle() const OVERRIDE;
virtual bool IsIMEComposing() const OVERRIDE;
+ virtual void GetSelectedRange(ui::Range* range) const OVERRIDE;
+ virtual void SelectRange(const ui::Range& range) OVERRIDE;
virtual void GetSelectionModel(gfx::SelectionModel* sel) const OVERRIDE;
virtual void SelectSelectionModel(const gfx::SelectionModel& sel) OVERRIDE;
virtual size_t GetCursorPosition() const OVERRIDE;
diff --git a/views/controls/textfield/native_textfield_wrapper.h b/views/controls/textfield/native_textfield_wrapper.h
index 4e37d84..f6b0f8a 100644
--- a/views/controls/textfield/native_textfield_wrapper.h
+++ b/views/controls/textfield/native_textfield_wrapper.h
@@ -99,6 +99,12 @@ class VIEWS_EXPORT NativeTextfieldWrapper {
// Returns whether or not an IME is composing text.
virtual bool IsIMEComposing() const = 0;
+ // Gets the selected range.
+ virtual void GetSelectedRange(ui::Range* range) const = 0;
+
+ // Selects the text given by |range|.
+ virtual void SelectRange(const ui::Range& range) = 0;
+
// Gets the selection model.
virtual void GetSelectionModel(gfx::SelectionModel* sel) const = 0;
diff --git a/views/controls/textfield/textfield.cc b/views/controls/textfield/textfield.cc
index 435e637..8eaa0de 100644
--- a/views/controls/textfield/textfield.cc
+++ b/views/controls/textfield/textfield.cc
@@ -158,10 +158,10 @@ void Textfield::ClearSelection() const {
}
bool Textfield::HasSelection() const {
- gfx::SelectionModel sel;
+ ui::Range range;
if (native_wrapper_)
- native_wrapper_->GetSelectionModel(&sel);
- return sel.selection_start() != sel.selection_end();
+ native_wrapper_->GetSelectedRange(&range);
+ return !range.is_empty();
}
void Textfield::SetTextColor(SkColor color) {
@@ -268,6 +268,16 @@ bool Textfield::IsIMEComposing() const {
return native_wrapper_ && native_wrapper_->IsIMEComposing();
}
+void Textfield::GetSelectedRange(ui::Range* range) const {
+ DCHECK(native_wrapper_);
+ native_wrapper_->GetSelectedRange(range);
+}
+
+void Textfield::SelectRange(const ui::Range& range) {
+ DCHECK(native_wrapper_);
+ native_wrapper_->SelectRange(range);
+}
+
void Textfield::GetSelectionModel(gfx::SelectionModel* sel) const {
DCHECK(native_wrapper_);
native_wrapper_->GetSelectionModel(sel);
@@ -394,10 +404,10 @@ void Textfield::GetAccessibleState(ui::AccessibleViewState* state) {
state->value = text_;
DCHECK(native_wrapper_);
- gfx::SelectionModel sel;
- native_wrapper_->GetSelectionModel(&sel);
- state->selection_start = sel.selection_start();
- state->selection_end = sel.selection_end();
+ ui::Range range;
+ native_wrapper_->GetSelectedRange(&range);
+ state->selection_start = range.start();
+ state->selection_end = range.end();
}
TextInputClient* Textfield::GetTextInputClient() {
diff --git a/views/controls/textfield/textfield.h b/views/controls/textfield/textfield.h
index 20d3b43..7e73caf 100644
--- a/views/controls/textfield/textfield.h
+++ b/views/controls/textfield/textfield.h
@@ -178,6 +178,14 @@ class VIEWS_EXPORT Textfield : public View {
// Returns whether or not an IME is composing text.
bool IsIMEComposing() const;
+ // Gets the selected range. This is views-implementation only and
+ // has to be called after the wrapper is created.
+ void GetSelectedRange(ui::Range* range) const;
+
+ // Selects the text given by |range|. This is views-implementation only and
+ // has to be called after the wrapper is created.
+ void SelectRange(const ui::Range& range);
+
// Gets the selection model. This is views-implementation only and
// has to be called after the wrapper is created.
void GetSelectionModel(gfx::SelectionModel* sel) const;
diff --git a/views/controls/textfield/textfield_views_model.cc b/views/controls/textfield/textfield_views_model.cc
index bfe0349..7c5ee0b 100644
--- a/views/controls/textfield/textfield_views_model.cc
+++ b/views/controls/textfield/textfield_views_model.cc
@@ -390,8 +390,12 @@ bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& selection) {
ConfirmCompositionText();
// ConfirmCompositionText() updates cursor position. Need to reflect it in
// the SelectionModel parameter of MoveCursorTo().
- gfx::SelectionModel sel(selection);
- sel.set_selection_start(render_text_->GetSelectionStart());
+ if (render_text_->GetSelectionStart() != selection.selection_end())
+ return render_text_->SelectRange(ui::Range(
+ render_text_->GetSelectionStart(), selection.selection_end()));
+ gfx::SelectionModel sel(selection.selection_end(),
+ selection.caret_pos(),
+ selection.caret_placement());
return render_text_->MoveCursorTo(sel);
}
return render_text_->MoveCursorTo(selection);
@@ -408,6 +412,17 @@ string16 TextfieldViewsModel::GetSelectedText() const {
(render_text_->MaxOfSelection() - render_text_->MinOfSelection()));
}
+void TextfieldViewsModel::GetSelectedRange(ui::Range* range) const {
+ range->set_start(render_text_->GetSelectionStart());
+ range->set_end(render_text_->GetCursorPosition());
+}
+
+void TextfieldViewsModel::SelectRange(const ui::Range& range) {
+ if (HasCompositionText())
+ ConfirmCompositionText();
+ render_text_->SelectRange(range);
+}
+
void TextfieldViewsModel::GetSelectionModel(gfx::SelectionModel* sel) const {
*sel = render_text_->selection_model();
}
@@ -499,11 +514,8 @@ bool TextfieldViewsModel::Cut() {
// than beginning, unlike Delete/Backspace.
// TODO(oshima): Change Delete/Backspace to use DeleteSelection,
// update DeleteEdit and remove this trick.
- gfx::SelectionModel sel(render_text_->GetCursorPosition(),
- render_text_->GetSelectionStart(),
- render_text_->GetSelectionStart(),
- gfx::SelectionModel::LEADING);
- render_text_->MoveCursorTo(sel);
+ render_text_->SelectRange(ui::Range(render_text_->GetCursorPosition(),
+ render_text_->GetSelectionStart()));
DeleteSelection();
return true;
}
@@ -582,8 +594,7 @@ void TextfieldViewsModel::SetCompositionText(
std::min(range.start() + composition.selection.start(), range.end());
size_t end =
std::min(range.start() + composition.selection.end(), range.end());
- gfx::SelectionModel sel(start, end);
- render_text_->MoveCursorTo(sel);
+ render_text_->SelectRange(ui::Range(start, end));
} else {
render_text_->SetCursorPosition(range.end());
}
@@ -654,9 +665,14 @@ void TextfieldViewsModel::ReplaceTextInternal(const string16& text,
CancelCompositionText();
} else if (!HasSelection()) {
size_t cursor = GetCursorPosition();
- gfx::SelectionModel sel(render_text_->selection_model());
- sel.set_selection_start(render_text_->GetIndexOfNextGrapheme(cursor));
- render_text_->MoveCursorTo(sel);
+ const gfx::SelectionModel& model = render_text_->selection_model();
+ // When there is no selection, the default is to replace the next grapheme
+ // with |text|. So, need to find the index of next grapheme first.
+ size_t next = render_text_->GetIndexOfNextGrapheme(cursor);
+ if (next == model.selection_end())
+ render_text_->MoveCursorTo(model);
+ else
+ render_text_->SelectRange(ui::Range(next, model.selection_end()));
}
// Edit history is recorded in InsertText.
InsertTextInternal(text, mergeable);
diff --git a/views/controls/textfield/textfield_views_model.h b/views/controls/textfield/textfield_views_model.h
index e178c23..103673b 100644
--- a/views/controls/textfield/textfield_views_model.h
+++ b/views/controls/textfield/textfield_views_model.h
@@ -148,6 +148,14 @@ class VIEWS_EXPORT TextfieldViewsModel {
// Returns the selected text.
string16 GetSelectedText() const;
+ // Gets the selected range.
+ void GetSelectedRange(ui::Range* range) const;
+
+ // The current composition text will be confirmed. The selection starts with
+ // the range's start position, and ends with the range's end position,
+ // therefore the cursor position becomes the end position.
+ void SelectRange(const ui::Range& range);
+
void GetSelectionModel(gfx::SelectionModel* sel) const;
// The current composition text will be confirmed.
diff --git a/views/controls/textfield/textfield_views_model_unittest.cc b/views/controls/textfield/textfield_views_model_unittest.cc
index 36f8fe6..5e02185 100644
--- a/views/controls/textfield/textfield_views_model_unittest.cc
+++ b/views/controls/textfield/textfield_views_model_unittest.cc
@@ -280,11 +280,11 @@ TEST_F(TextfieldViewsModelTest, Selection) {
EXPECT_EQ(5U, sel.selection_end());
// Select and move cursor
- model.MoveCursorTo(gfx::SelectionModel(1U, 3U));
+ model.SelectRange(ui::Range(1U, 3U));
EXPECT_STR_EQ("EL", model.GetSelectedText());
model.MoveCursorLeft(gfx::CHARACTER_BREAK, false);
EXPECT_EQ(1U, model.GetCursorPosition());
- model.MoveCursorTo(gfx::SelectionModel(1U, 3U));
+ model.SelectRange(ui::Range(1U, 3U));
model.MoveCursorRight(gfx::CHARACTER_BREAK, false);
EXPECT_EQ(3U, model.GetCursorPosition());
@@ -641,6 +641,115 @@ TEST_F(TextfieldViewsModelTest, SelectWordTest_MixScripts) {
}
#endif
+TEST_F(TextfieldViewsModelTest, RangeTest) {
+ TextfieldViewsModel model(NULL);
+ model.Append(ASCIIToUTF16("HELLO WORLD"));
+ model.MoveCursorLeft(gfx::LINE_BREAK, false);
+ ui::Range range;
+ model.GetSelectedRange(&range);
+ EXPECT_TRUE(range.is_empty());
+ EXPECT_EQ(0U, range.start());
+ EXPECT_EQ(0U, range.end());
+
+ model.MoveCursorRight(gfx::WORD_BREAK, true);
+ model.GetSelectedRange(&range);
+ EXPECT_FALSE(range.is_empty());
+ EXPECT_FALSE(range.is_reversed());
+ EXPECT_EQ(0U, range.start());
+ EXPECT_EQ(5U, range.end());
+
+ model.MoveCursorLeft(gfx::CHARACTER_BREAK, true);
+ model.GetSelectedRange(&range);
+ EXPECT_FALSE(range.is_empty());
+ EXPECT_EQ(0U, range.start());
+ EXPECT_EQ(4U, range.end());
+
+ model.MoveCursorLeft(gfx::WORD_BREAK, true);
+ model.GetSelectedRange(&range);
+ EXPECT_TRUE(range.is_empty());
+ EXPECT_EQ(0U, range.start());
+ EXPECT_EQ(0U, range.end());
+
+ // now from the end.
+ model.MoveCursorRight(gfx::LINE_BREAK, false);
+ model.GetSelectedRange(&range);
+ EXPECT_TRUE(range.is_empty());
+ EXPECT_EQ(11U, range.start());
+ EXPECT_EQ(11U, range.end());
+
+ model.MoveCursorLeft(gfx::WORD_BREAK, true);
+ model.GetSelectedRange(&range);
+ EXPECT_FALSE(range.is_empty());
+ EXPECT_TRUE(range.is_reversed());
+ EXPECT_EQ(11U, range.start());
+ EXPECT_EQ(6U, range.end());
+
+ model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
+ model.GetSelectedRange(&range);
+ EXPECT_FALSE(range.is_empty());
+ EXPECT_TRUE(range.is_reversed());
+ EXPECT_EQ(11U, range.start());
+ EXPECT_EQ(7U, range.end());
+
+ model.MoveCursorRight(gfx::WORD_BREAK, true);
+ model.GetSelectedRange(&range);
+ EXPECT_TRUE(range.is_empty());
+ EXPECT_EQ(11U, range.start());
+ EXPECT_EQ(11U, range.end());
+
+ // Select All
+ model.MoveCursorLeft(gfx::LINE_BREAK, true);
+ model.GetSelectedRange(&range);
+ EXPECT_FALSE(range.is_empty());
+ EXPECT_TRUE(range.is_reversed());
+ EXPECT_EQ(11U, range.start());
+ EXPECT_EQ(0U, range.end());
+}
+
+TEST_F(TextfieldViewsModelTest, SelectRangeTest) {
+ TextfieldViewsModel model(NULL);
+ model.Append(ASCIIToUTF16("HELLO WORLD"));
+ ui::Range range(0, 6);
+ EXPECT_FALSE(range.is_reversed());
+ model.SelectRange(range);
+ EXPECT_STR_EQ("HELLO ", model.GetSelectedText());
+
+ range = ui::Range(6, 1);
+ EXPECT_TRUE(range.is_reversed());
+ model.SelectRange(range);
+ EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
+
+ range = ui::Range(2, 1000);
+ EXPECT_FALSE(range.is_reversed());
+ model.SelectRange(range);
+ EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
+
+ range = ui::Range(1000, 3);
+ EXPECT_TRUE(range.is_reversed());
+ model.SelectRange(range);
+ EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
+
+ range = ui::Range(0, 0);
+ EXPECT_TRUE(range.is_empty());
+ model.SelectRange(range);
+ EXPECT_TRUE(model.GetSelectedText().empty());
+
+ range = ui::Range(3, 3);
+ EXPECT_TRUE(range.is_empty());
+ model.SelectRange(range);
+ EXPECT_TRUE(model.GetSelectedText().empty());
+
+ range = ui::Range(1000, 100);
+ EXPECT_FALSE(range.is_empty());
+ model.SelectRange(range);
+ EXPECT_TRUE(model.GetSelectedText().empty());
+
+ range = ui::Range(1000, 1000);
+ EXPECT_TRUE(range.is_empty());
+ model.SelectRange(range);
+ EXPECT_TRUE(model.GetSelectedText().empty());
+}
+
TEST_F(TextfieldViewsModelTest, SelectionModelTest) {
TextfieldViewsModel model(NULL);
model.Append(ASCIIToUTF16("HELLO WORLD"));
@@ -709,35 +818,43 @@ TEST_F(TextfieldViewsModelTest, SelectionModelTest) {
TEST_F(TextfieldViewsModelTest, SelectSelectionModelTest) {
TextfieldViewsModel model(NULL);
model.Append(ASCIIToUTF16("HELLO WORLD"));
- model.SelectSelectionModel(gfx::SelectionModel(0, 6));
+ model.SelectSelectionModel(gfx::SelectionModel(0, 6, 5,
+ gfx::SelectionModel::TRAILING));
EXPECT_STR_EQ("HELLO ", model.GetSelectedText());
- model.SelectSelectionModel(gfx::SelectionModel(6, 1));
+ model.SelectSelectionModel(gfx::SelectionModel(6, 1, 1,
+ gfx::SelectionModel::LEADING));
EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
- model.SelectSelectionModel(gfx::SelectionModel(2, 1000));
+ model.SelectSelectionModel(gfx::SelectionModel(2, 1000, 999,
+ gfx::SelectionModel::TRAILING));
EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
- model.SelectSelectionModel(gfx::SelectionModel(1000, 3));
+ model.SelectSelectionModel(gfx::SelectionModel(1000, 3, 3,
+ gfx::SelectionModel::LEADING));
EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
- model.SelectSelectionModel(gfx::SelectionModel(0, 0));
+ model.SelectSelectionModel(gfx::SelectionModel(0, 0, 0,
+ gfx::SelectionModel::LEADING));
EXPECT_TRUE(model.GetSelectedText().empty());
- model.SelectSelectionModel(gfx::SelectionModel(3, 3));
+ model.SelectSelectionModel(gfx::SelectionModel(3, 3, 3,
+ gfx::SelectionModel::LEADING));
EXPECT_TRUE(model.GetSelectedText().empty());
- model.SelectSelectionModel(gfx::SelectionModel(1000, 100));
+ model.SelectSelectionModel(gfx::SelectionModel(1000, 100, 100,
+ gfx::SelectionModel::LEADING));
EXPECT_TRUE(model.GetSelectedText().empty());
- model.SelectSelectionModel(gfx::SelectionModel(1000, 1000));
+ model.SelectSelectionModel(gfx::SelectionModel(1000, 1000, 1000,
+ gfx::SelectionModel::TRAILING));
EXPECT_TRUE(model.GetSelectedText().empty());
}
TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
TextfieldViewsModel model(this);
model.Append(ASCIIToUTF16("1234590"));
- model.SelectSelectionModel(gfx::SelectionModel(5, 5));
+ model.SelectRange(ui::Range(5, 5));
EXPECT_FALSE(model.HasSelection());
EXPECT_EQ(5U, model.GetCursorPosition());
@@ -865,15 +982,15 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
EXPECT_STR_EQ("678", model.GetText());
model.SetCompositionText(composition);
- gfx::SelectionModel sel(0);
- sel.set_selection_start(model.render_text()->GetSelectionStart());
+ gfx::SelectionModel sel(model.render_text()->GetSelectionStart(),
+ 0, 0, gfx::SelectionModel::LEADING);
model.MoveCursorTo(sel);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
EXPECT_STR_EQ("678678", model.GetText());
model.SetCompositionText(composition);
- model.SelectSelectionModel(gfx::SelectionModel(0, 3));
+ model.SelectRange(ui::Range(0, 3));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
EXPECT_STR_EQ("678", model.GetText());
@@ -1007,19 +1124,19 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_SetText) {
model.SetText(ASCIIToUTF16("www.google.com"));
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_STR_EQ("www.google.com", model.GetText());
- model.SelectSelectionModel(gfx::SelectionModel(14, 1));
+ model.SelectRange(ui::Range(14, 1));
model.InsertChar('w');
EXPECT_STR_EQ("ww", model.GetText());
model.SetText(ASCIIToUTF16("www.google.com"));
- model.SelectSelectionModel(gfx::SelectionModel(14, 2));
+ model.SelectRange(ui::Range(14, 2));
model.InsertChar('w');
EXPECT_STR_EQ("www", model.GetText());
model.SetText(ASCIIToUTF16("www.google.com"));
- model.SelectSelectionModel(gfx::SelectionModel(14, 3));
+ model.SelectRange(ui::Range(14, 3));
model.InsertChar('.');
EXPECT_STR_EQ("www.", model.GetText());
model.SetText(ASCIIToUTF16("www.google.com"));
- model.SelectSelectionModel(gfx::SelectionModel(14, 4));
+ model.SelectRange(ui::Range(14, 4));
model.InsertChar('y');
EXPECT_STR_EQ("www.y", model.GetText());
model.SetText(ASCIIToUTF16("www.youtube.com"));
@@ -1072,7 +1189,7 @@ TEST_F(TextfieldViewsModelTest, MAYBE_UndoRedo_CutCopyPasteTest) {
model.SetText(ASCIIToUTF16("ABCDE"));
EXPECT_FALSE(model.Redo()); // nothing to redo
// Cut
- model.MoveCursorTo(gfx::SelectionModel(1, 3));
+ model.SelectRange(ui::Range(1, 3));
model.Cut();
EXPECT_STR_EQ("ADE", model.GetText());
EXPECT_EQ(1U, model.GetCursorPosition());
@@ -1134,12 +1251,12 @@ TEST_F(TextfieldViewsModelTest, MAYBE_UndoRedo_CutCopyPasteTest) {
EXPECT_EQ(7U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
- // with SelectSelectionModel
- model.SelectSelectionModel(gfx::SelectionModel(1, 3));
+ // with SelectRange
+ model.SelectRange(ui::Range(1, 3));
EXPECT_TRUE(model.Cut());
EXPECT_STR_EQ("ABCBCDE", model.GetText());
EXPECT_EQ(1U, model.GetCursorPosition());
- model.SelectSelectionModel(gfx::SelectionModel(1, 1));
+ model.SelectRange(ui::Range(1, 1));
EXPECT_FALSE(model.Cut());
model.MoveCursorRight(gfx::LINE_BREAK, false);
EXPECT_TRUE(model.Paste());
@@ -1158,7 +1275,7 @@ TEST_F(TextfieldViewsModelTest, MAYBE_UndoRedo_CutCopyPasteTest) {
model.SetText(ASCIIToUTF16("12345"));
EXPECT_STR_EQ("12345", model.GetText());
EXPECT_EQ(0U, model.GetCursorPosition());
- model.MoveCursorTo(gfx::SelectionModel(1, 3));
+ model.SelectRange(ui::Range(1, 3));
model.Copy(); // Copy "23"
EXPECT_STR_EQ("12345", model.GetText());
EXPECT_EQ(3U, model.GetCursorPosition());
@@ -1191,8 +1308,8 @@ TEST_F(TextfieldViewsModelTest, MAYBE_UndoRedo_CutCopyPasteTest) {
EXPECT_FALSE(model.Redo());
EXPECT_STR_EQ("1232345", model.GetText());
- // Test using SelectSelectionModel
- model.SelectSelectionModel(gfx::SelectionModel(1, 3));
+ // Test using SelectRange
+ model.SelectRange(ui::Range(1, 3));
model.Copy();
EXPECT_STR_EQ("1232345", model.GetText());
model.MoveCursorRight(gfx::LINE_BREAK, false);
@@ -1282,57 +1399,57 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_ReplaceTest) {
SCOPED_TRACE("forward & insert by cursor");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.MoveCursorTo(gfx::SelectionModel(1, 3));
+ model.SelectRange(ui::Range(1, 3));
RunInsertReplaceTest(model);
}
{
SCOPED_TRACE("backward & insert by cursor");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.MoveCursorTo(gfx::SelectionModel(3, 1));
+ model.SelectRange(ui::Range(3, 1));
RunInsertReplaceTest(model);
}
{
SCOPED_TRACE("forward & overwrite by cursor");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.MoveCursorTo(gfx::SelectionModel(1, 3));
+ model.SelectRange(ui::Range(1, 3));
RunOverwriteReplaceTest(model);
}
{
SCOPED_TRACE("backward & overwrite by cursor");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.MoveCursorTo(gfx::SelectionModel(3, 1));
+ model.SelectRange(ui::Range(3, 1));
RunOverwriteReplaceTest(model);
}
- // By SelectSelectionModel API
+ // By SelectRange API
{
- SCOPED_TRACE("forward & insert by SelectSelectionModel");
+ SCOPED_TRACE("forward & insert by SelectRange");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.SelectSelectionModel(gfx::SelectionModel(1, 3));
+ model.SelectRange(ui::Range(1, 3));
RunInsertReplaceTest(model);
}
{
- SCOPED_TRACE("backward & insert by SelectSelectionModel");
+ SCOPED_TRACE("backward & insert by SelectRange");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.SelectSelectionModel(gfx::SelectionModel(3, 1));
+ model.SelectRange(ui::Range(3, 1));
RunInsertReplaceTest(model);
}
{
- SCOPED_TRACE("forward & overwrite by SelectSelectionModel");
+ SCOPED_TRACE("forward & overwrite by SelectRange");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.SelectSelectionModel(gfx::SelectionModel(1, 3));
+ model.SelectRange(ui::Range(1, 3));
RunOverwriteReplaceTest(model);
}
{
- SCOPED_TRACE("backward & overwrite by SelectSelectionModel");
+ SCOPED_TRACE("backward & overwrite by SelectRange");
TextfieldViewsModel model(NULL);
model.SetText(ASCIIToUTF16("abcd"));
- model.SelectSelectionModel(gfx::SelectionModel(3, 1));
+ model.SelectRange(ui::Range(3, 1));
RunOverwriteReplaceTest(model);
}
}
diff --git a/views/touchui/touch_selection_controller_impl_unittest.cc b/views/touchui/touch_selection_controller_impl_unittest.cc
index 3780b4a..9741c26 100644
--- a/views/touchui/touch_selection_controller_impl_unittest.cc
+++ b/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -122,7 +122,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInTextfieldTest) {
textfield_->SetText(ASCIIToUTF16("some text"));
// Test selecting a range.
- textfield_->SelectSelectionModel(gfx::SelectionModel(3, 7));
+ textfield_->SelectRange(ui::Range(3, 7));
VerifySelectionHandlePositions(false);
// Test selecting everything.
@@ -153,46 +153,35 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInBidiTextfieldTest) {
VerifySelectionHandlePositions(false);
// Test selection range inside one run and starts or ends at run boundary.
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(2, 3, 2, gfx::SelectionModel::TRAILING));
+ textfield_->SelectRange(ui::Range(2, 3));
VerifySelectionHandlePositions(false);
- // TODO(xji): change to textfield_->SelectRange(3, 2).
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(3, 2, 2, gfx::SelectionModel::LEADING));
+ textfield_->SelectRange(ui::Range(3, 2));
VerifySelectionHandlePositions(false);
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(3, 4, 3, gfx::SelectionModel::TRAILING));
+ textfield_->SelectRange(ui::Range(3, 4));
VerifySelectionHandlePositions(false);
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(4, 3, 3, gfx::SelectionModel::LEADING));
+ textfield_->SelectRange(ui::Range(4, 3));
VerifySelectionHandlePositions(false);
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(3, 6, 5, gfx::SelectionModel::TRAILING));
+ textfield_->SelectRange(ui::Range(3, 6));
VerifySelectionHandlePositions(false);
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(6, 3, 3, gfx::SelectionModel::LEADING));
+ textfield_->SelectRange(ui::Range(6, 3));
VerifySelectionHandlePositions(false);
// Test selection range accross runs.
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(0, 6, 5, gfx::SelectionModel::TRAILING));
+ textfield_->SelectRange(ui::Range(0, 6));
VerifySelectionHandlePositions(false);
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(6, 0, 0, gfx::SelectionModel::LEADING));
+ textfield_->SelectRange(ui::Range(6, 0));
VerifySelectionHandlePositions(false);
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(1, 4, 3, gfx::SelectionModel::TRAILING));
+ textfield_->SelectRange(ui::Range(1, 4));
VerifySelectionHandlePositions(false);
- textfield_->SelectSelectionModel(
- gfx::SelectionModel(4, 1, 1, gfx::SelectionModel::LEADING));
+ textfield_->SelectRange(ui::Range(4, 1));
VerifySelectionHandlePositions(false);
}
@@ -201,7 +190,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInBidiTextfieldTest) {
TEST_F(TouchSelectionControllerImplTest, SelectRectCallbackTest) {
CreateTextfield();
textfield_->SetText(ASCIIToUTF16("textfield with selected text"));
- textfield_->SelectSelectionModel(gfx::SelectionModel(3, 7));
+ textfield_->SelectRange(ui::Range(3, 7));
EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "tfie");
VerifySelectionHandlePositions(false);
@@ -231,4 +220,122 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectCallbackTest) {
VerifySelectionHandlePositions(false);
}
+TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
+ CreateTextfield();
+ textfield_->SetText(WideToUTF16(L"abc\x05e1\x05e2\x05e3"L"def"));
+
+ // Select [c] from left to right.
+ textfield_->SelectRange(ui::Range(2, 3));
+ EXPECT_EQ(WideToUTF16(L"c"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Drag selection handle 2 to right by 1 char.
+ int x = textfield_->font().GetStringWidth(WideToUTF16(L"\x05e3"));
+ SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
+ EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Drag selection handle 1 to left by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"b"));
+ SimulateSelectionHandleDrag(gfx::Point(-x, 0), 1);
+ EXPECT_EQ(WideToUTF16(L"bc\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(true);
+
+ // Select [c] from right to left.
+ textfield_->SelectRange(ui::Range(3, 2));
+ EXPECT_EQ(WideToUTF16(L"c"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Drag selection handle 1 to right by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"\x05e3"));
+ SimulateSelectionHandleDrag(gfx::Point(x, 0), 1);
+ EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(true);
+
+ // Drag selection handle 2 to left by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"b"));
+ SimulateSelectionHandleDrag(gfx::Point(-x, 0), 2);
+ EXPECT_EQ(WideToUTF16(L"bc\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Select [\x5e1] from right to left.
+ textfield_->SelectRange(ui::Range(3, 4));
+ EXPECT_EQ(WideToUTF16(L"\x05e1"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ /* TODO(xji): for bidi text "abcDEF" whose display is "abcFEDhij", when click
+ right of 'D' and select [D] then move the left selection handle to left
+ by one character, it should select [ED], instead it selects [F].
+ Reason: click right of 'D' and left of 'h' return the same x-axis position,
+ pass this position to FindCursorPosition() returns index of 'h'. which
+ means the selection start changed from 3 to 6.
+ Need further investigation on whether this is a bug in Pango and how to
+ work around it.
+ // Drag selection handle 2 to left by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"\x05e2"));
+ SimulateSelectionHandleDrag(gfx::Point(-x, 0), 2);
+ EXPECT_EQ(WideToUTF16(L"\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+ */
+
+ // Drag selection handle 1 to right by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"d"));
+ SimulateSelectionHandleDrag(gfx::Point(x, 0), 1);
+ EXPECT_EQ(WideToUTF16(L"\x05e2\x05e3"L"d"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(true);
+
+ // Select [\x5e1] from left to right.
+ textfield_->SelectRange(ui::Range(4, 3));
+ EXPECT_EQ(WideToUTF16(L"\x05e1"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ /* TODO(xji): see detail of above commented out test case.
+ // Drag selection handle 1 to left by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"\x05e2"));
+ SimulateSelectionHandleDrag(gfx::Point(-x, 0), 1);
+ EXPECT_EQ(WideToUTF16(L"\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(true);
+ */
+
+ // Drag selection handle 2 to right by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"d"));
+ SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
+ EXPECT_EQ(WideToUTF16(L"\x05e2\x05e3"L"d"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Select [\x05r3] from right to left.
+ textfield_->SelectRange(ui::Range(5, 6));
+ EXPECT_EQ(WideToUTF16(L"\x05e3"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Drag selection handle 2 to left by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"c"));
+ SimulateSelectionHandleDrag(gfx::Point(-x, 0), 2);
+ EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Drag selection handle 1 to right by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"\x05e2"));
+ SimulateSelectionHandleDrag(gfx::Point(x, 0), 1);
+ EXPECT_EQ(WideToUTF16(L"c\x05e1"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(true);
+
+ // Select [\x05r3] from left to right.
+ textfield_->SelectRange(ui::Range(6, 5));
+ EXPECT_EQ(WideToUTF16(L"\x05e3"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+
+ // Drag selection handle 1 to left by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"c"));
+ SimulateSelectionHandleDrag(gfx::Point(-x, 0), 1);
+ EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(true);
+
+ // Drag selection handle 2 to right by 1 char.
+ x = textfield_->font().GetStringWidth(WideToUTF16(L"\x05e2"));
+ SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
+ EXPECT_EQ(WideToUTF16(L"c\x05e1"), textfield_->GetSelectedText());
+ VerifySelectionHandlePositions(false);
+}
+
} // namespace views