OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/utf_string_conversions.h" |
| 6 #include "ui/gfx/point.h" |
| 7 #include "ui/gfx/rect.h" |
| 8 #include "ui/gfx/render_text.h" |
| 9 #include "views/controls/textfield/native_textfield_views.h" |
| 10 #include "views/controls/textfield/textfield.h" |
| 11 #include "views/test/views_test_base.h" |
| 12 #include "views/touchui/touch_selection_controller.h" |
| 13 #include "views/touchui/touch_selection_controller_impl.h" |
| 14 #include "views/widget/widget.h" |
| 15 |
| 16 namespace views { |
| 17 |
| 18 class TouchSelectionControllerImplTest : public ViewsTestBase { |
| 19 public: |
| 20 TouchSelectionControllerImplTest() |
| 21 : widget_(NULL), |
| 22 textfield_(NULL), |
| 23 textfield_view_(NULL) { |
| 24 } |
| 25 |
| 26 virtual void SetUp() { |
| 27 Widget::SetPureViews(true); |
| 28 } |
| 29 |
| 30 virtual void TearDown() { |
| 31 Widget::SetPureViews(false); |
| 32 if (widget_) |
| 33 widget_->Close(); |
| 34 ViewsTestBase::TearDown(); |
| 35 } |
| 36 |
| 37 void CreateTextfield() { |
| 38 textfield_ = new Textfield(); |
| 39 widget_ = new Widget; |
| 40 Widget::InitParams params(Widget::InitParams::TYPE_POPUP); |
| 41 params.bounds = gfx::Rect(0, 0, 100, 100); |
| 42 widget_->Init(params); |
| 43 View* container = new View(); |
| 44 widget_->SetContentsView(container); |
| 45 container->AddChildView(textfield_); |
| 46 |
| 47 textfield_view_ = static_cast<NativeTextfieldViews*>( |
| 48 textfield_->GetNativeWrapperForTesting()); |
| 49 textfield_view_->SetBoundsRect(params.bounds); |
| 50 textfield_->set_id(1); |
| 51 |
| 52 DCHECK(textfield_view_); |
| 53 textfield_->RequestFocus(); |
| 54 } |
| 55 |
| 56 protected: |
| 57 gfx::Point GetCursorPosition(int cursor_pos) { |
| 58 gfx::RenderText* render_text = textfield_view_->GetRenderText(); |
| 59 gfx::Rect cursor_bounds = render_text->GetCursorBounds( |
| 60 gfx::SelectionModel(cursor_pos), false); |
| 61 gfx::Rect display_rect = render_text->display_rect(); |
| 62 int total_offset_x = display_rect.x() + render_text->display_offset().x(); |
| 63 int total_offset_y = display_rect.y() + render_text->display_offset().y() + |
| 64 (display_rect.height() - cursor_bounds.height()) / 2; |
| 65 return gfx::Point(cursor_bounds.x() + total_offset_x, |
| 66 cursor_bounds.bottom() + total_offset_y); |
| 67 } |
| 68 |
| 69 TouchSelectionControllerImpl* GetSelectionController() { |
| 70 return static_cast<TouchSelectionControllerImpl*>( |
| 71 textfield_view_->touch_selection_controller_.get()); |
| 72 } |
| 73 |
| 74 void SimulateSelectionHandleDrag(gfx::Point p, int selection_handle) { |
| 75 TouchSelectionControllerImpl* controller = GetSelectionController(); |
| 76 // Do the work of OnMousePressed(). |
| 77 if (selection_handle == 1) |
| 78 controller->dragging_handle_ = controller->selection_handle_1_.get(); |
| 79 else |
| 80 controller->dragging_handle_ = controller->selection_handle_2_.get(); |
| 81 |
| 82 controller->SelectionHandleDragged(p); |
| 83 |
| 84 // Do the work of OnMouseReleased(). |
| 85 controller->dragging_handle_ = NULL; |
| 86 } |
| 87 |
| 88 // If textfield has selection, this method verifies that the selection handles |
| 89 // are visible and at the correct positions (at the end points of selection). |
| 90 // |cursor_at_selection_handle_1| is used to decide whether selection |
| 91 // handle 1's position is matched against the start of selection or the end. |
| 92 void VerifySelectionHandlePositions(bool cursor_at_selection_handle_1) { |
| 93 if (textfield_->HasSelection()) { |
| 94 EXPECT_TRUE(GetSelectionController()->IsSelectionHandle1Visible()); |
| 95 EXPECT_TRUE(GetSelectionController()->IsSelectionHandle2Visible()); |
| 96 ui::Range selected_range; |
| 97 textfield_view_->GetSelectedRange(&selected_range); |
| 98 gfx::Point selection_start = GetCursorPosition(selected_range.start()); |
| 99 gfx::Point selection_end = GetCursorPosition(selected_range.end()); |
| 100 gfx::Point sh1 = GetSelectionController()->GetSelectionHandle1Position(); |
| 101 gfx::Point sh2 = GetSelectionController()->GetSelectionHandle2Position(); |
| 102 sh1.Offset(10, 0); // offset by kSelectionHandleRadius. |
| 103 sh2.Offset(10, 0); |
| 104 |
| 105 if (cursor_at_selection_handle_1) { |
| 106 EXPECT_EQ(sh1, selection_end); |
| 107 EXPECT_EQ(sh2, selection_start); |
| 108 } else { |
| 109 EXPECT_EQ(sh1, selection_start); |
| 110 EXPECT_EQ(sh2, selection_end); |
| 111 } |
| 112 } else { |
| 113 EXPECT_FALSE(GetSelectionController()->IsSelectionHandle1Visible()); |
| 114 EXPECT_FALSE(GetSelectionController()->IsSelectionHandle2Visible()); |
| 115 } |
| 116 } |
| 117 |
| 118 Widget* widget_; |
| 119 |
| 120 Textfield* textfield_; |
| 121 NativeTextfieldViews* textfield_view_; |
| 122 |
| 123 private: |
| 124 DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImplTest); |
| 125 }; |
| 126 |
| 127 // Tests that the selection handles are placed appropriately when selection in |
| 128 // a Textfield changes. |
| 129 TEST_F(TouchSelectionControllerImplTest, SelectionInTextfieldTest) { |
| 130 CreateTextfield(); |
| 131 textfield_->SetText(ASCIIToUTF16("some text")); |
| 132 |
| 133 // Test selecting a range. |
| 134 textfield_->SelectRange(ui::Range(3, 7)); |
| 135 VerifySelectionHandlePositions(false); |
| 136 |
| 137 // Test selecting everything. |
| 138 textfield_->SelectAll(); |
| 139 VerifySelectionHandlePositions(false); |
| 140 |
| 141 // Test with no selection. |
| 142 textfield_->ClearSelection(); |
| 143 VerifySelectionHandlePositions(false); |
| 144 |
| 145 // Test with lost focus. |
| 146 widget_->GetFocusManager()->ClearFocus(); |
| 147 VerifySelectionHandlePositions(false); |
| 148 |
| 149 // Test with focus re-gained. |
| 150 widget_->GetFocusManager()->SetFocusedView(textfield_); |
| 151 VerifySelectionHandlePositions(false); |
| 152 } |
| 153 |
| 154 // Tests if the SelectRect callback is called appropriately when selection |
| 155 // handles are moved. |
| 156 TEST_F(TouchSelectionControllerImplTest, SelectRectCallbackTest) { |
| 157 CreateTextfield(); |
| 158 textfield_->SetText(ASCIIToUTF16("textfield with selected text")); |
| 159 textfield_->SelectRange(ui::Range(3, 7)); |
| 160 |
| 161 EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "tfie"); |
| 162 VerifySelectionHandlePositions(false); |
| 163 |
| 164 // Drag selection handle 2 to right by 3 chars. |
| 165 int x = textfield_->font().GetStringWidth(ASCIIToUTF16("ld ")); |
| 166 SimulateSelectionHandleDrag(gfx::Point(x, 0), 2); |
| 167 EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "tfield "); |
| 168 VerifySelectionHandlePositions(false); |
| 169 |
| 170 // Drag selection handle 1 to the left by a large amount (selection should |
| 171 // just stick to the beginning of the textfield). |
| 172 SimulateSelectionHandleDrag(gfx::Point(-50, 0), 1); |
| 173 EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "textfield "); |
| 174 VerifySelectionHandlePositions(true); |
| 175 |
| 176 // Drag selection handle 1 across selection handle 2. |
| 177 x = textfield_->font().GetStringWidth(ASCIIToUTF16("textfield with ")); |
| 178 SimulateSelectionHandleDrag(gfx::Point(x, 0), 1); |
| 179 EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "with "); |
| 180 VerifySelectionHandlePositions(true); |
| 181 |
| 182 // Drag selection handle 2 across selection handle 1. |
| 183 x = textfield_->font().GetStringWidth(ASCIIToUTF16("with selected ")); |
| 184 SimulateSelectionHandleDrag(gfx::Point(x, 0), 2); |
| 185 EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "selected "); |
| 186 VerifySelectionHandlePositions(false); |
| 187 } |
| 188 |
| 189 } // namespace views |
OLD | NEW |