| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/controls/scroll_view.h" | 5 #include "ui/views/controls/scroll_view.h" |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 #include "ui/views/border.h" | 9 #include "ui/views/border.h" |
| 10 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h" |
| 11 #include "ui/views/controls/scrollbar/native_scroll_bar.h" |
| 12 #include "ui/views/controls/scrollbar/native_scroll_bar_views.h" |
| 10 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" | 13 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" |
| 11 #include "ui/views/test/test_views.h" | 14 #include "ui/views/test/test_views.h" |
| 15 #include "ui/views/test/widget_test.h" |
| 12 | 16 |
| 13 #if defined(OS_MACOSX) | 17 #if defined(OS_MACOSX) |
| 14 #include "ui/base/test/scoped_preferred_scroller_style_mac.h" | 18 #include "ui/base/test/scoped_preferred_scroller_style_mac.h" |
| 15 #endif | 19 #endif |
| 16 | 20 |
| 21 enum ScrollBarOrientation { HORIZONTAL, VERTICAL }; |
| 22 |
| 17 namespace views { | 23 namespace views { |
| 24 namespace test { |
| 25 |
| 26 class ScrollViewTestApi { |
| 27 public: |
| 28 explicit ScrollViewTestApi(ScrollView* scroll_view) |
| 29 : scroll_view_(scroll_view) {} |
| 30 |
| 31 BaseScrollBar* GetBaseScrollBar(ScrollBarOrientation orientation) { |
| 32 ScrollBar* scroll_bar = orientation == VERTICAL ? scroll_view_->vert_sb_ |
| 33 : scroll_view_->horiz_sb_; |
| 34 if (scroll_bar->GetClassName() == NativeScrollBar::kViewClassName) { |
| 35 return static_cast<NativeScrollBarViews*>( |
| 36 static_cast<NativeScrollBar*>(scroll_bar)->native_wrapper_); |
| 37 } |
| 38 return static_cast<BaseScrollBar*>(scroll_bar); |
| 39 } |
| 40 |
| 41 const base::Timer& GetScrollBarTimer(ScrollBarOrientation orientation) { |
| 42 return GetBaseScrollBar(orientation)->repeater_.timer_for_testing(); |
| 43 } |
| 44 |
| 45 BaseScrollBarThumb* GetScrollBarThumb(ScrollBarOrientation orientation) { |
| 46 return GetBaseScrollBar(orientation)->thumb_; |
| 47 } |
| 48 |
| 49 View* corner_view() { return scroll_view_->corner_view_; } |
| 50 |
| 51 private: |
| 52 ScrollView* scroll_view_; |
| 53 |
| 54 DISALLOW_COPY_AND_ASSIGN(ScrollViewTestApi); |
| 55 }; |
| 56 |
| 57 } // namespace test |
| 18 | 58 |
| 19 namespace { | 59 namespace { |
| 20 | 60 |
| 21 const int kWidth = 100; | 61 const int kWidth = 100; |
| 22 const int kMinHeight = 50; | 62 const int kMinHeight = 50; |
| 23 const int kMaxHeight = 100; | 63 const int kMaxHeight = 100; |
| 24 | 64 |
| 25 enum ScrollBarOrientation { HORIZONTAL, VERTICAL }; | |
| 26 | |
| 27 // View implementation that allows setting the preferred size. | 65 // View implementation that allows setting the preferred size. |
| 28 class CustomView : public View { | 66 class CustomView : public View { |
| 29 public: | 67 public: |
| 30 CustomView() {} | 68 CustomView() {} |
| 31 | 69 |
| 32 void SetPreferredSize(const gfx::Size& size) { | 70 void SetPreferredSize(const gfx::Size& size) { |
| 33 preferred_size_ = size; | 71 preferred_size_ = size; |
| 34 PreferredSizeChanged(); | 72 PreferredSizeChanged(); |
| 35 } | 73 } |
| 36 | 74 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 60 ? scroll_view.horizontal_scroll_bar() | 98 ? scroll_view.horizontal_scroll_bar() |
| 61 : scroll_view.vertical_scroll_bar(); | 99 : scroll_view.vertical_scroll_bar(); |
| 62 if (should_be_visible) { | 100 if (should_be_visible) { |
| 63 ASSERT_TRUE(scrollbar); | 101 ASSERT_TRUE(scrollbar); |
| 64 EXPECT_TRUE(scrollbar->visible()); | 102 EXPECT_TRUE(scrollbar->visible()); |
| 65 } else { | 103 } else { |
| 66 EXPECT_TRUE(!scrollbar || !scrollbar->visible()); | 104 EXPECT_TRUE(!scrollbar || !scrollbar->visible()); |
| 67 } | 105 } |
| 68 } | 106 } |
| 69 | 107 |
| 108 ui::MouseEvent TestLeftMouseAt(const gfx::Point& location, ui::EventType type) { |
| 109 return ui::MouseEvent(type, location, location, base::TimeTicks(), |
| 110 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
| 111 } |
| 112 |
| 70 } // namespace | 113 } // namespace |
| 71 | 114 |
| 115 using test::ScrollViewTestApi; |
| 116 |
| 117 // Test harness that includes a Widget to help test ui::Event handling. |
| 118 class WidgetScrollViewTest : public test::WidgetTest { |
| 119 public: |
| 120 static const int kDefaultHeight = 100; |
| 121 static const int kDefaultWidth = 100; |
| 122 |
| 123 WidgetScrollViewTest() { |
| 124 #if defined(OS_MACOSX) |
| 125 // Disable scrollbar hiding (i.e. disable overlay scrollbars) by default. |
| 126 scroller_style_.reset(new ui::test::ScopedPreferredScrollerStyle(false)); |
| 127 #endif |
| 128 } |
| 129 |
| 130 // Adds a ScrollView with a contents view of the given |size| and does layout. |
| 131 ScrollView* AddScrollViewWithContentSize(const gfx::Size& contents_size) { |
| 132 const gfx::Rect default_bounds(50, 50, kDefaultWidth, kDefaultHeight); |
| 133 widget_ = CreateTopLevelFramelessPlatformWidget(); |
| 134 |
| 135 ScrollView* scroll_view = new ScrollView(); |
| 136 View* contents = new View; |
| 137 scroll_view->SetContents(contents); |
| 138 contents->SetSize(contents_size); |
| 139 |
| 140 widget_->SetBounds(default_bounds); |
| 141 widget_->Show(); |
| 142 |
| 143 widget_->SetContentsView(scroll_view); |
| 144 scroll_view->Layout(); |
| 145 return scroll_view; |
| 146 } |
| 147 |
| 148 // testing::Test: |
| 149 void TearDown() override { |
| 150 if (widget_) |
| 151 widget_->CloseNow(); |
| 152 WidgetTest::TearDown(); |
| 153 } |
| 154 |
| 155 private: |
| 156 Widget* widget_ = nullptr; |
| 157 |
| 158 #if defined(OS_MACOSX) |
| 159 std::unique_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_; |
| 160 #endif |
| 161 |
| 162 DISALLOW_COPY_AND_ASSIGN(WidgetScrollViewTest); |
| 163 }; |
| 164 |
| 165 const int WidgetScrollViewTest::kDefaultHeight; |
| 166 const int WidgetScrollViewTest::kDefaultWidth; |
| 167 |
| 72 // Verifies the viewport is sized to fit the available space. | 168 // Verifies the viewport is sized to fit the available space. |
| 73 TEST(ScrollViewTest, ViewportSizedToFit) { | 169 TEST(ScrollViewTest, ViewportSizedToFit) { |
| 74 ScrollView scroll_view; | 170 ScrollView scroll_view; |
| 75 View* contents = new View; | 171 View* contents = new View; |
| 76 scroll_view.SetContents(contents); | 172 scroll_view.SetContents(contents); |
| 77 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); | 173 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); |
| 78 scroll_view.Layout(); | 174 scroll_view.Layout(); |
| 79 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString()); | 175 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString()); |
| 80 } | 176 } |
| 81 | 177 |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 EXPECT_EQ(scroll_view.contents()->size().width(), expected_width); | 525 EXPECT_EQ(scroll_view.contents()->size().width(), expected_width); |
| 430 EXPECT_EQ(scroll_view.contents()->size().height(), 1000 * expected_width); | 526 EXPECT_EQ(scroll_view.contents()->size().height(), 1000 * expected_width); |
| 431 EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size()); | 527 EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size()); |
| 432 } | 528 } |
| 433 | 529 |
| 434 TEST(ScrollViewTest, CornerViewVisibility) { | 530 TEST(ScrollViewTest, CornerViewVisibility) { |
| 435 ScrollView scroll_view; | 531 ScrollView scroll_view; |
| 436 View* contents = new View; | 532 View* contents = new View; |
| 437 scroll_view.SetContents(contents); | 533 scroll_view.SetContents(contents); |
| 438 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); | 534 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); |
| 439 View* corner_view = scroll_view.corner_view_; | 535 View* corner_view = ScrollViewTestApi(&scroll_view).corner_view(); |
| 440 | 536 |
| 441 // Corner view should be visible when both scrollbars are visible. | 537 // Corner view should be visible when both scrollbars are visible. |
| 442 contents->SetBounds(0, 0, 200, 200); | 538 contents->SetBounds(0, 0, 200, 200); |
| 443 scroll_view.Layout(); | 539 scroll_view.Layout(); |
| 444 EXPECT_EQ(&scroll_view, corner_view->parent()); | 540 EXPECT_EQ(&scroll_view, corner_view->parent()); |
| 445 EXPECT_TRUE(corner_view->visible()); | 541 EXPECT_TRUE(corner_view->visible()); |
| 446 | 542 |
| 447 // Corner view should be aligned to the scrollbars. | 543 // Corner view should be aligned to the scrollbars. |
| 448 EXPECT_EQ(scroll_view.vertical_scroll_bar()->x(), corner_view->x()); | 544 EXPECT_EQ(scroll_view.vertical_scroll_bar()->x(), corner_view->x()); |
| 449 EXPECT_EQ(scroll_view.horizontal_scroll_bar()->y(), corner_view->y()); | 545 EXPECT_EQ(scroll_view.horizontal_scroll_bar()->y(), corner_view->y()); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 scroller_style_override.reset( | 621 scroller_style_override.reset( |
| 526 new ui::test::ScopedPreferredScrollerStyle(false)); | 622 new ui::test::ScopedPreferredScrollerStyle(false)); |
| 527 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width()); | 623 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width()); |
| 528 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(), | 624 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(), |
| 529 contents->parent()->height()); | 625 contents->parent()->height()); |
| 530 EXPECT_NE(0, scroll_view.GetScrollBarWidth()); | 626 EXPECT_NE(0, scroll_view.GetScrollBarWidth()); |
| 531 EXPECT_NE(0, scroll_view.GetScrollBarHeight()); | 627 EXPECT_NE(0, scroll_view.GetScrollBarHeight()); |
| 532 } | 628 } |
| 533 #endif | 629 #endif |
| 534 | 630 |
| 631 // Test scrolling behavior when clicking on the scroll track. |
| 632 TEST_F(WidgetScrollViewTest, ScrollTrackScrolling) { |
| 633 // Set up with a vertical scroller. |
| 634 ScrollView* scroll_view = |
| 635 AddScrollViewWithContentSize(gfx::Size(10, kDefaultHeight * 5)); |
| 636 ScrollViewTestApi test_api(scroll_view); |
| 637 BaseScrollBar* scroll_bar = test_api.GetBaseScrollBar(VERTICAL); |
| 638 View* thumb = test_api.GetScrollBarThumb(VERTICAL); |
| 639 |
| 640 // Click in the middle of the track, ensuring it's below the thumb. |
| 641 const gfx::Point location = scroll_bar->bounds().CenterPoint(); |
| 642 EXPECT_GT(location.y(), thumb->bounds().bottom()); |
| 643 ui::MouseEvent press(TestLeftMouseAt(location, ui::ET_MOUSE_PRESSED)); |
| 644 ui::MouseEvent release(TestLeftMouseAt(location, ui::ET_MOUSE_RELEASED)); |
| 645 |
| 646 const base::Timer& timer = test_api.GetScrollBarTimer(VERTICAL); |
| 647 EXPECT_FALSE(timer.IsRunning()); |
| 648 |
| 649 EXPECT_EQ(0, scroll_view->GetVisibleRect().y()); |
| 650 scroll_bar->OnMouseEvent(&press); |
| 651 |
| 652 // Clicking the scroll track should scroll one "page". |
| 653 EXPECT_EQ(kDefaultHeight, scroll_view->GetVisibleRect().y()); |
| 654 |
| 655 // While the mouse is pressed, timer should trigger more scroll events. |
| 656 EXPECT_TRUE(timer.IsRunning()); |
| 657 |
| 658 // Upon release timer should stop (and scroll position should remain). |
| 659 scroll_bar->OnMouseEvent(&release); |
| 660 EXPECT_FALSE(timer.IsRunning()); |
| 661 EXPECT_EQ(kDefaultHeight, scroll_view->GetVisibleRect().y()); |
| 662 } |
| 663 |
| 535 } // namespace views | 664 } // namespace views |
| OLD | NEW |