diff options
author | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-13 04:44:55 +0000 |
---|---|---|
committer | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-13 04:44:55 +0000 |
commit | f5f0c2acc32a94ba0035bb316aa6b66d212bf3cf (patch) | |
tree | 5c6e7928ca754c123cfa82d21778427536f4326c /ui/views/controls | |
parent | 24cddd42154b07c6559846b2159a88a3feabb5d5 (diff) | |
download | chromium_src-f5f0c2acc32a94ba0035bb316aa6b66d212bf3cf.zip chromium_src-f5f0c2acc32a94ba0035bb316aa6b66d212bf3cf.tar.gz chromium_src-f5f0c2acc32a94ba0035bb316aa6b66d212bf3cf.tar.bz2 |
Add and specify Views::Textfield::SelectAll |reversed| flag, etc.
SelectAll should be consistent and explicit with range reversal.
This dictates if leading or trailing text is shown when textfields overflow.
Currently, NativeTextfield[Win|Views]::SelectAll behavior is implicit and differs.
(Windows native reverses the selection, while ChromeOS/Views doesn't)
Revise SelectAll in RenderText, NativeTextfieldWin, and OmniboxViewViews.
Add the |reversed| parameter and plumbing to related interfaces/functions.
Add/update RenderTextTest.SelectAll and TextfieldViewsModelTest.Selection.
Specify explicit reversal behavior in all the following cases:
1) Use reversed selection (changes ChromeOS/Views behavior) in:
a) BookmarkBubbleView::ShowBubble (focus on bookmark title when shown).
b) BookmarkEditorView::Accept (focus on invalid bookmark URL on "Save").
c) BookmarkEditorView::Show (focus on bookmark title when shown).
d) FindBarView::UpdateForResult (find bar matches are found/iterated).
e) FindBarView::SetFocusAndSelection (find bar shown, etc.).
f) FindBarView::SearchTextfieldView::RequestFocus (click find bar parts, etc.).
g) EditSearchEngineDialog::Show (focus on search engine title when shown).
h) LoginView::OnAutofillDataAvailable (HTTP/FTP auth window shown).
i) MessageBoxView::ViewHierarchyChanged (JS dialog with text input shown).
2) Use forward selection (changes Windows native behavior) in:
a) NativeTextfieldWin::ExecuteCommand (textfield context menu "Select All").
(note: the Omnibox context menu "Select All" already uses forward selection)
b) Textfield::AboutToRequestFocusFromTabTraversal (focus via tab-traversal).
(note1: THIS IS CONTENTIOUS! Though OmniBoxViewWin is unaffected)
(note2: OmniboxViewViews should be fixed later as per crbug.com/134701#c9)
c) TreeView::StartEditing (editing tree view nodes ex/ collected cookies).
d) NativeTextfieldViewsTest.* and ViewTest.* (changes inconsequential to tests)
3) Formally specify existing implicit behavior (no behavioral change):
a) NativeTextfieldWin::OnAfterPossibleChange (temporary selection is reversed).
b) NativeTextfieldViews::OnGestureEvent (double tap is forwards).
c) NativeTextfieldViews::ExecuteCommand (context menu "Select All" is forwards).
d) NativeTextfieldViews::HandleKeyEvent (CTRL-A is forwards).
e) NativeTextfieldViews::HandleMousePressEvent (triple-click is forwards).
f) TextfieldViewsModel::SetText (temporary selection is forwards).
g) TextfieldViewsModelTest.* is mostly forwards, |Selection| tests reversed.
TBR=ben@chromium.org
BUG=134762
TEST=New RenderTextTest.SelectAll, updated TextfieldViewsModelTest.Selection, other unit tests, manual.
Review URL: https://chromiumcodereview.appspot.com/10693160
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146520 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views/controls')
13 files changed, 64 insertions, 51 deletions
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc index 23151f1..960b316 100644 --- a/ui/views/controls/message_box_view.cc +++ b/ui/views/controls/message_box_view.cc @@ -125,7 +125,7 @@ void MessageBoxView::ViewHierarchyChanged(bool is_add, View* child) { if (child == this && is_add) { if (prompt_field_) - prompt_field_->SelectAll(); + prompt_field_->SelectAll(true); GetWidget()->NotifyAccessibilityEvent( this, ui::AccessibilityTypes::EVENT_ALERT, true); diff --git a/ui/views/controls/textfield/native_textfield_views.cc b/ui/views/controls/textfield/native_textfield_views.cc index 80e785a..beb1437 100644 --- a/ui/views/controls/textfield/native_textfield_views.cc +++ b/ui/views/controls/textfield/native_textfield_views.cc @@ -159,7 +159,7 @@ ui::GestureStatus NativeTextfieldViews::OnGestureEvent( OnAfterUserAction(); return ui::GESTURE_STATUS_CONSUMED; case ui::ET_GESTURE_DOUBLE_TAP: - SelectAll(); + SelectAll(false); return ui::GESTURE_STATUS_CONSUMED; case ui::ET_GESTURE_SCROLL_UPDATE: OnBeforeUserAction(); @@ -370,9 +370,9 @@ string16 NativeTextfieldViews::GetSelectedText() const { return model_->GetSelectedText(); } -void NativeTextfieldViews::SelectAll() { +void NativeTextfieldViews::SelectAll(bool reversed) { OnBeforeUserAction(); - model_->SelectAll(); + model_->SelectAll(reversed); OnCaretBoundsChanged(); SchedulePaint(); OnAfterUserAction(); @@ -618,7 +618,7 @@ void NativeTextfieldViews::ExecuteCommand(int command_id) { text_changed = model_->Delete(); break; case IDS_APP_SELECT_ALL: - SelectAll(); + SelectAll(false); break; default: textfield_->GetController()->ExecuteCommand(command_id); @@ -927,7 +927,7 @@ bool NativeTextfieldViews::HandleKeyEvent(const KeyEvent& key_event) { break; case ui::VKEY_A: if (control) { - model_->SelectAll(); + model_->SelectAll(false); cursor_changed = true; } break; @@ -1177,7 +1177,7 @@ void NativeTextfieldViews::HandleMousePressEvent(const MouseEvent& event) { OnCaretBoundsChanged(); break; case 2: - model_->SelectAll(); + model_->SelectAll(false); OnCaretBoundsChanged(); break; default: diff --git a/ui/views/controls/textfield/native_textfield_views.h b/ui/views/controls/textfield/native_textfield_views.h index f5ea868..9142c5a 100644 --- a/ui/views/controls/textfield/native_textfield_views.h +++ b/ui/views/controls/textfield/native_textfield_views.h @@ -94,7 +94,7 @@ class VIEWS_EXPORT NativeTextfieldViews : public TouchSelectionClientView, virtual void UpdateText() OVERRIDE; virtual void AppendText(const string16& text) OVERRIDE; virtual string16 GetSelectedText() const OVERRIDE; - virtual void SelectAll() OVERRIDE; + virtual void SelectAll(bool reversed) OVERRIDE; virtual void ClearSelection() OVERRIDE; virtual void UpdateBorder() OVERRIDE; virtual void UpdateTextColor() OVERRIDE; diff --git a/ui/views/controls/textfield/native_textfield_views_unittest.cc b/ui/views/controls/textfield/native_textfield_views_unittest.cc index b299e37..de5bc3a 100644 --- a/ui/views/controls/textfield/native_textfield_views_unittest.cc +++ b/ui/views/controls/textfield/native_textfield_views_unittest.cc @@ -352,7 +352,7 @@ TEST_F(NativeTextfieldViewsTest, ModelChangesTest) { EXPECT_TRUE(last_contents_.empty()); EXPECT_EQ(string16(), textfield_->GetSelectedText()); - textfield_->SelectAll(); + textfield_->SelectAll(false); EXPECT_STR_EQ("this is a test", textfield_->GetSelectedText()); EXPECT_TRUE(last_contents_.empty()); } @@ -523,7 +523,7 @@ TEST_F(NativeTextfieldViewsTest, InsertionDeletionTest) { EXPECT_STR_EQ("this is ", textfield_->text()); // Select all and replace with "k". - textfield_->SelectAll(); + textfield_->SelectAll(false); SendKeyEvent(ui::VKEY_K); EXPECT_STR_EQ("k", textfield_->text()); @@ -573,7 +573,7 @@ TEST_F(NativeTextfieldViewsTest, PasswordTest) { EXPECT_TRUE(last_contents_.empty()); // Cut and copy should be disabled in the context menu. - model_->SelectAll(); + model_->SelectAll(false); EXPECT_FALSE(IsCommandIdEnabled(IDS_APP_CUT)); EXPECT_FALSE(IsCommandIdEnabled(IDS_APP_COPY)); @@ -756,7 +756,7 @@ TEST_F(NativeTextfieldViewsTest, ContextMenuDisplayTest) { EXPECT_TRUE(GetContextMenuModel()); VerifyTextfieldContextMenuContents(false, GetContextMenuModel()); - textfield_->SelectAll(); + textfield_->SelectAll(false); VerifyTextfieldContextMenuContents(true, GetContextMenuModel()); } @@ -1075,7 +1075,7 @@ TEST_F(NativeTextfieldViewsTest, ReadOnlyTest) { EXPECT_EQ(5U, textfield_->GetCursorPosition()); EXPECT_STR_EQ("two ", textfield_->GetSelectedText()); - textfield_->SelectAll(); + textfield_->SelectAll(false); EXPECT_STR_EQ(" one two three ", textfield_->GetSelectedText()); // CUT&PASTE does not work, but COPY works @@ -1099,7 +1099,7 @@ TEST_F(NativeTextfieldViewsTest, ReadOnlyTest) { EXPECT_STR_EQ(" four five six ", textfield_->text()); EXPECT_TRUE(textfield_->GetSelectedText().empty()); - textfield_->SelectAll(); + textfield_->SelectAll(false); EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); // Text field is unmodifiable and selection shouldn't change. diff --git a/ui/views/controls/textfield/native_textfield_win.cc b/ui/views/controls/textfield/native_textfield_win.cc index ec98132..5372cbc 100644 --- a/ui/views/controls/textfield/native_textfield_win.cc +++ b/ui/views/controls/textfield/native_textfield_win.cc @@ -219,10 +219,11 @@ string16 NativeTextfieldWin::GetSelectedText() const { return str; } -void NativeTextfieldWin::SelectAll() { - // Select from the end to the front so that the first part of the text is - // always visible. - SetSel(GetTextLength(), 0); +void NativeTextfieldWin::SelectAll(bool reversed) { + if (reversed) + SetSel(GetTextLength(), 0); + else + SetSel(0, GetTextLength()); } void NativeTextfieldWin::ClearSelection() { @@ -449,12 +450,12 @@ void NativeTextfieldWin::ExecuteCommand(int command_id) { ScopedFreeze freeze(this, GetTextObjectModel()); OnBeforePossibleChange(); switch (command_id) { - case IDS_APP_UNDO: Undo(); break; - case IDS_APP_CUT: Cut(); break; - case IDS_APP_COPY: Copy(); break; - case IDS_APP_PASTE: Paste(); break; - case IDS_APP_SELECT_ALL: SelectAll(); break; - default: NOTREACHED(); break; + case IDS_APP_UNDO: Undo(); break; + case IDS_APP_CUT: Cut(); break; + case IDS_APP_COPY: Copy(); break; + case IDS_APP_PASTE: Paste(); break; + case IDS_APP_SELECT_ALL: SelectAll(false); break; + default: NOTREACHED(); break; } OnAfterPossibleChange(true); } @@ -1095,7 +1096,7 @@ void NativeTextfieldWin::OnAfterPossibleChange(bool should_redraw_text) { string16 text(GetText()); ScopedSuspendUndo suspend_undo(GetTextObjectModel()); - SelectAll(); + SelectAll(true); ReplaceSel(reinterpret_cast<LPCTSTR>(text.c_str()), true); SetSel(original_sel); } diff --git a/ui/views/controls/textfield/native_textfield_win.h b/ui/views/controls/textfield/native_textfield_win.h index dfebcdb..b7591bd 100644 --- a/ui/views/controls/textfield/native_textfield_win.h +++ b/ui/views/controls/textfield/native_textfield_win.h @@ -69,7 +69,7 @@ class NativeTextfieldWin virtual void UpdateText() OVERRIDE; virtual void AppendText(const string16& text) OVERRIDE; virtual string16 GetSelectedText() const OVERRIDE; - virtual void SelectAll() OVERRIDE; + virtual void SelectAll(bool reversed) OVERRIDE; virtual void ClearSelection() OVERRIDE; virtual void UpdateBorder() OVERRIDE; virtual void UpdateTextColor() OVERRIDE; diff --git a/ui/views/controls/textfield/native_textfield_wrapper.h b/ui/views/controls/textfield/native_textfield_wrapper.h index 43aed03..06d972f3 100644 --- a/ui/views/controls/textfield/native_textfield_wrapper.h +++ b/ui/views/controls/textfield/native_textfield_wrapper.h @@ -47,9 +47,10 @@ class VIEWS_EXPORT NativeTextfieldWrapper { // Gets the text that is selected in the wrapped native text field. virtual string16 GetSelectedText() const = 0; - // Selects all the text in the edit. Use this in place of SetSelAll() to - // avoid selecting the "phantom newline" at the end of the edit. - virtual void SelectAll() = 0; + // Select the entire text range. If |reversed| is true, the range will end at + // the logical beginning of the text; this generally shows the leading portion + // of text that overflows its display area. + virtual void SelectAll(bool reversed) = 0; // Clears the selection within the edit field and sets the caret to the end. virtual void ClearSelection() = 0; diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 8b3a254..a34be2d 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc @@ -159,9 +159,9 @@ void Textfield::AppendText(const string16& text) { native_wrapper_->AppendText(text); } -void Textfield::SelectAll() { +void Textfield::SelectAll(bool reversed) { if (native_wrapper_) - native_wrapper_->SelectAll(); + native_wrapper_->SelectAll(reversed); } string16 Textfield::GetSelectedText() const { @@ -370,7 +370,7 @@ gfx::Size Textfield::GetPreferredSize() { } void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) { - SelectAll(); + SelectAll(false); } bool Textfield::SkipDefaultKeyEventProcessing(const KeyEvent& e) { diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h index 39bc4a0..224169b 100644 --- a/ui/views/controls/textfield/textfield.h +++ b/ui/views/controls/textfield/textfield.h @@ -88,8 +88,10 @@ class VIEWS_EXPORT Textfield : public View { // Returns the text that is currently selected. string16 GetSelectedText() const; - // Causes the edit field to be fully selected. - void SelectAll(); + // Select the entire text range. If |reversed| is true, the range will end at + // the logical beginning of the text; this generally shows the leading portion + // of text that overflows its display area. + void SelectAll(bool reversed); // Clears the selection within the edit field and sets the caret to the end. void ClearSelection() const; diff --git a/ui/views/controls/textfield/textfield_views_model.cc b/ui/views/controls/textfield/textfield_views_model.cc index f052df9..372fcf1 100644 --- a/ui/views/controls/textfield/textfield_views_model.cc +++ b/ui/views/controls/textfield/textfield_views_model.cc @@ -317,7 +317,7 @@ bool TextfieldViewsModel::SetText(const string16& text) { size_t old_cursor = GetCursorPosition(); // SetText moves the cursor to the end. size_t new_cursor = text.length(); - SelectAll(); + SelectAll(false); // If there is a composition text, don't merge with previous edit. // Otherwise, force merge the edits. ExecuteAndRecordReplace( @@ -439,10 +439,10 @@ void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) { render_text_->MoveCursorTo(sel); } -void TextfieldViewsModel::SelectAll() { +void TextfieldViewsModel::SelectAll(bool reversed) { if (HasCompositionText()) ConfirmCompositionText(); - render_text_->SelectAll(); + render_text_->SelectAll(reversed); } void TextfieldViewsModel::SelectWord() { diff --git a/ui/views/controls/textfield/textfield_views_model.h b/ui/views/controls/textfield/textfield_views_model.h index 94bf984..8268595 100644 --- a/ui/views/controls/textfield/textfield_views_model.h +++ b/ui/views/controls/textfield/textfield_views_model.h @@ -151,9 +151,11 @@ class VIEWS_EXPORT TextfieldViewsModel { // render_text_'s selection model is set to |sel|. void SelectSelectionModel(const gfx::SelectionModel& sel); - // Selects all text. + // Select the entire text range. If |reversed| is true, the range will end at + // the logical beginning of the text; this generally shows the leading portion + // of text that overflows its display area. // The current composition text will be confirmed. - void SelectAll(); + void SelectAll(bool reversed); // Selects the word at which the cursor is currently positioned. // The current composition text will be confirmed. diff --git a/ui/views/controls/textfield/textfield_views_model_unittest.cc b/ui/views/controls/textfield/textfield_views_model_unittest.cc index 7140436..376f7d4 100644 --- a/ui/views/controls/textfield/textfield_views_model_unittest.cc +++ b/ui/views/controls/textfield/textfield_views_model_unittest.cc @@ -276,13 +276,20 @@ TEST_F(TextfieldViewsModelTest, Selection) { EXPECT_STR_EQ("ELLO", model.GetSelectedText()); model.ClearSelection(); EXPECT_EQ(string16(), model.GetSelectedText()); - model.SelectAll(); + + // SelectAll(false) selects towards the end. + model.SelectAll(false); EXPECT_STR_EQ("HELLO", model.GetSelectedText()); - // SelectAll should select towards the end. gfx::SelectionModel sel; model.GetSelectionModel(&sel); EXPECT_EQ(ui::Range(0, 5), sel.selection()); + // SelectAll(true) selects towards the beginning. + model.SelectAll(true); + EXPECT_STR_EQ("HELLO", model.GetSelectedText()); + model.GetSelectionModel(&sel); + EXPECT_EQ(ui::Range(5, 0), sel.selection()); + // Select and move cursor model.SelectRange(ui::Range(1U, 3U)); EXPECT_STR_EQ("EL", model.GetSelectedText()); @@ -293,10 +300,10 @@ TEST_F(TextfieldViewsModelTest, Selection) { EXPECT_EQ(3U, model.GetCursorPosition()); // Select all and move cursor - model.SelectAll(); + model.SelectAll(false); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false); EXPECT_EQ(0U, model.GetCursorPosition()); - model.SelectAll(); + model.SelectAll(false); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); EXPECT_EQ(5U, model.GetCursorPosition()); } @@ -337,7 +344,7 @@ TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) { model.ClearSelection(); EXPECT_EQ(string16(), model.GetSelectedText()); - model.SelectAll(); + model.SelectAll(false); EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"def"), model.GetSelectedText()); #endif @@ -380,7 +387,7 @@ TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) { model.ClearSelection(); EXPECT_EQ(string16(), model.GetSelectedText()); - model.SelectAll(); + model.SelectAll(false); EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText()); } @@ -468,7 +475,7 @@ TEST_F(TextfieldViewsModelTest, SetText) { EXPECT_STR_EQ("GOODBYE", model.GetText()); // SetText move the cursor to the end of the new text. EXPECT_EQ(7U, model.GetCursorPosition()); - model.SelectAll(); + model.SelectAll(false); EXPECT_STR_EQ("GOODBYE", model.GetSelectedText()); model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); EXPECT_EQ(7U, model.GetCursorPosition()); @@ -515,7 +522,7 @@ TEST_F(TextfieldViewsModelTest, MAYBE_Clipboard) { // Cut on obscured (password) text should do nothing. model.render_text()->SetObscured(true); - model.SelectAll(); + model.SelectAll(false); EXPECT_FALSE(model.Cut()); clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); EXPECT_EQ(initial_clipboard_text, clipboard_text); @@ -523,7 +530,7 @@ TEST_F(TextfieldViewsModelTest, MAYBE_Clipboard) { EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText()); // Copy on obscured text should do nothing. - model.SelectAll(); + model.SelectAll(false); EXPECT_FALSE(model.Copy()); clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); EXPECT_EQ(initial_clipboard_text, clipboard_text); @@ -542,7 +549,7 @@ TEST_F(TextfieldViewsModelTest, MAYBE_Clipboard) { // Copy with non-empty selection. model.Append(ASCIIToUTF16("HELLO WORLD")); - model.SelectAll(); + model.SelectAll(false); model.Copy(); clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text); @@ -975,7 +982,7 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) { EXPECT_STR_EQ("678", model.GetText()); model.SetCompositionText(composition); - model.SelectAll(); + model.SelectAll(false); EXPECT_TRUE(composition_text_confirmed_or_cleared_); composition_text_confirmed_or_cleared_ = false; EXPECT_STR_EQ("678", model.GetText()); diff --git a/ui/views/controls/tree/tree_view_views.cc b/ui/views/controls/tree/tree_view_views.cc index b13080e..c97bb41 100644 --- a/ui/views/controls/tree/tree_view_views.cc +++ b/ui/views/controls/tree/tree_view_views.cc @@ -143,7 +143,7 @@ void TreeView::StartEditing(TreeModelNode* node) { LayoutEditor(); SchedulePaintForNode(selected_node_); editor_->RequestFocus(); - editor_->SelectAll(); + editor_->SelectAll(false); // Listen for focus changes so that we can cancel editing. focus_manager_ = GetFocusManager(); |