Chromium Code Reviews| 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/bubble/bubble_frame_view.h" | 5 #include "ui/views/bubble/bubble_frame_view.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| 11 #include "ui/base/test/material_design_controller_test_api.h" | |
| 11 #include "ui/gfx/geometry/insets.h" | 12 #include "ui/gfx/geometry/insets.h" |
| 12 #include "ui/gfx/geometry/rect.h" | 13 #include "ui/gfx/geometry/rect.h" |
| 13 #include "ui/gfx/geometry/size.h" | 14 #include "ui/gfx/geometry/size.h" |
| 14 #include "ui/views/bubble/bubble_border.h" | 15 #include "ui/views/bubble/bubble_border.h" |
| 16 #include "ui/views/bubble/bubble_dialog_delegate.h" | |
| 15 #include "ui/views/controls/button/label_button.h" | 17 #include "ui/views/controls/button/label_button.h" |
| 16 #include "ui/views/test/test_views.h" | 18 #include "ui/views/test/test_views.h" |
| 19 #include "ui/views/test/test_views_delegate.h" | |
| 17 #include "ui/views/test/views_test_base.h" | 20 #include "ui/views/test/views_test_base.h" |
| 18 #include "ui/views/widget/widget.h" | 21 #include "ui/views/widget/widget.h" |
| 19 #include "ui/views/widget/widget_delegate.h" | 22 #include "ui/views/widget/widget_delegate.h" |
| 23 #include "ui/views/window/dialog_delegate.h" | |
| 20 | 24 |
| 21 namespace views { | 25 namespace views { |
| 22 | 26 |
| 23 typedef ViewsTestBase BubbleFrameViewTest; | 27 class BubbleFrameViewTestViewsDelegate : public TestViewsDelegate { |
| 28 public: | |
| 29 BubbleFrameViewTestViewsDelegate() {} | |
| 30 ~BubbleFrameViewTestViewsDelegate() override {} | |
| 31 | |
| 32 // TestViewsDelegate: | |
| 33 int GetSnappedDialogWidth(int min_width) const override { | |
| 34 return snapped_width_ ? snapped_width_ : min_width; | |
| 35 } | |
| 36 | |
| 37 void set_snapped_width(int width) { snapped_width_ = width; } | |
| 38 | |
| 39 private: | |
| 40 int snapped_width_ = 0; | |
| 41 | |
| 42 DISALLOW_COPY_AND_ASSIGN(BubbleFrameViewTestViewsDelegate); | |
| 43 }; | |
| 44 | |
| 45 class BubbleFrameViewTest : public ViewsTestBase { | |
| 46 public: | |
| 47 BubbleFrameViewTest() { | |
| 48 views_delegate_ = new BubbleFrameViewTestViewsDelegate; | |
| 49 set_views_delegate(base::WrapUnique(views_delegate_)); | |
| 50 } | |
| 51 ~BubbleFrameViewTest() override {} | |
| 52 | |
| 53 BubbleFrameViewTestViewsDelegate* views_delegate() { return views_delegate_; } | |
| 54 | |
| 55 private: | |
| 56 BubbleFrameViewTestViewsDelegate* views_delegate_; | |
| 57 | |
| 58 DISALLOW_COPY_AND_ASSIGN(BubbleFrameViewTest); | |
| 59 }; | |
| 24 | 60 |
| 25 namespace { | 61 namespace { |
| 26 | 62 |
| 27 const BubbleBorder::Arrow kArrow = BubbleBorder::TOP_LEFT; | 63 const BubbleBorder::Arrow kArrow = BubbleBorder::TOP_LEFT; |
| 28 const SkColor kColor = SK_ColorRED; | 64 const SkColor kColor = SK_ColorRED; |
| 29 const int kMargin = 6; | 65 const int kMargin = 6; |
| 30 const int kMinimumClientWidth = 100; | 66 const int kMinimumClientWidth = 100; |
| 31 const int kMinimumClientHeight = 200; | 67 const int kMinimumClientHeight = 200; |
| 32 const int kMaximumClientWidth = 300; | 68 const int kMaximumClientWidth = 300; |
| 33 const int kMaximumClientHeight = 300; | 69 const int kMaximumClientHeight = 300; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 void SetShouldShowCloseButton(bool should_show_close) { | 102 void SetShouldShowCloseButton(bool should_show_close) { |
| 67 should_show_close_ = should_show_close; | 103 should_show_close_ = should_show_close; |
| 68 } | 104 } |
| 69 | 105 |
| 70 private: | 106 private: |
| 71 Widget* widget_; | 107 Widget* widget_; |
| 72 View* contents_view_ = nullptr; // Owned by |widget_|. | 108 View* contents_view_ = nullptr; // Owned by |widget_|. |
| 73 bool should_show_close_ = false; | 109 bool should_show_close_ = false; |
| 74 }; | 110 }; |
| 75 | 111 |
| 112 // A subclass of TestBubbleFrameViewWidgetDelegate that is also a | |
| 113 // DialogDelegate, used to test creation of Bubbles end-to-end, since the width | |
| 114 // snapping logic for bubbles only applies to bubbles whose widget delegate is a | |
| 115 // DialogDelegate. | |
| 116 // | |
| 117 // Having a multiple-implementation inherited class is perilous, but there does | |
| 118 // not seem to be an easy way to avoid it. | |
| 119 class TestBubbleFrameViewDialogDelegate | |
| 120 : public DialogDelegate, | |
| 121 public TestBubbleFrameViewWidgetDelegate { | |
|
tapted
2017/04/06 00:24:44
I don't think we need this - we're not really inte
Peter Kasting
2017/04/06 06:32:16
+1
| |
| 122 public: | |
| 123 TestBubbleFrameViewDialogDelegate(Widget* widget) | |
| 124 : TestBubbleFrameViewWidgetDelegate(widget) {} | |
| 125 ~TestBubbleFrameViewDialogDelegate() override {} | |
| 126 | |
| 127 // These are defined on both parent classes, so they need to be disambiguated | |
| 128 // thus: | |
| 129 Widget* GetWidget() override { | |
| 130 return TestBubbleFrameViewWidgetDelegate::GetWidget(); | |
| 131 } | |
| 132 const Widget* GetWidget() const override { | |
| 133 return TestBubbleFrameViewWidgetDelegate::GetWidget(); | |
| 134 } | |
| 135 DialogDelegate* AsDialogDelegate() override { return this; } | |
| 136 | |
| 137 private: | |
| 138 DISALLOW_COPY_AND_ASSIGN(TestBubbleFrameViewDialogDelegate); | |
| 139 }; | |
| 140 | |
| 76 class TestBubbleFrameView : public BubbleFrameView { | 141 class TestBubbleFrameView : public BubbleFrameView { |
| 77 public: | 142 public: |
| 78 TestBubbleFrameView(ViewsTestBase* test_base) | 143 TestBubbleFrameView(ViewsTestBase* test_base) |
| 79 : BubbleFrameView(gfx::Insets(), gfx::Insets(kMargin)), | 144 : BubbleFrameView(gfx::Insets(), gfx::Insets(kMargin)), |
| 80 test_base_(test_base), | 145 test_base_(test_base), |
| 81 available_bounds_(gfx::Rect(0, 0, 1000, 1000)) { | 146 available_bounds_(gfx::Rect(0, 0, 1000, 1000)) { |
| 82 SetBubbleBorder(std::unique_ptr<BubbleBorder>( | 147 SetBubbleBorder(std::unique_ptr<BubbleBorder>( |
| 83 new BubbleBorder(kArrow, BubbleBorder::NO_SHADOW, kColor))); | 148 new BubbleBorder(kArrow, BubbleBorder::NO_SHADOW, kColor))); |
| 84 } | 149 } |
| 85 ~TestBubbleFrameView() override {} | 150 ~TestBubbleFrameView() override {} |
| 86 | 151 |
| 87 // View overrides: | 152 // View overrides: |
| 88 const Widget* GetWidget() const override { | 153 const Widget* GetWidget() const override { |
| 89 if (!widget_) { | 154 if (!widget_) { |
| 90 widget_.reset(new Widget); | 155 widget_.reset(new Widget); |
| 91 widget_delegate_.reset( | 156 widget_delegate_ = MakeWidgetDelegate(widget_.get()); |
| 92 new TestBubbleFrameViewWidgetDelegate(widget_.get())); | |
| 93 Widget::InitParams params = | 157 Widget::InitParams params = |
| 94 test_base_->CreateParams(Widget::InitParams::TYPE_BUBBLE); | 158 test_base_->CreateParams(Widget::InitParams::TYPE_BUBBLE); |
| 95 params.delegate = widget_delegate_.get(); | 159 params.delegate = widget_delegate_.get(); |
| 96 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 160 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 97 widget_->Init(params); | 161 widget_->Init(params); |
| 98 } | 162 } |
| 99 | 163 |
| 100 return widget_.get(); | 164 return widget_.get(); |
| 101 } | 165 } |
| 102 | 166 |
| 103 // BubbleFrameView overrides: | 167 // BubbleFrameView overrides: |
| 104 gfx::Rect GetAvailableScreenBounds(const gfx::Rect& rect) const override { | 168 gfx::Rect GetAvailableScreenBounds(const gfx::Rect& rect) const override { |
| 105 return available_bounds_; | 169 return available_bounds_; |
| 106 } | 170 } |
| 107 | 171 |
| 108 TestBubbleFrameViewWidgetDelegate* widget_delegate() { | 172 TestBubbleFrameViewWidgetDelegate* widget_delegate() { |
| 109 return widget_delegate_.get(); | 173 return widget_delegate_.get(); |
| 110 } | 174 } |
| 111 | 175 |
| 176 protected: | |
| 177 virtual std::unique_ptr<TestBubbleFrameViewWidgetDelegate> MakeWidgetDelegate( | |
| 178 Widget* widget) const { | |
| 179 return base::WrapUnique(new TestBubbleFrameViewWidgetDelegate(widget)); | |
|
Peter Kasting
2017/04/06 06:32:16
Nit: WrapUnique(new -> MakeUnique (2 places)
| |
| 180 } | |
| 181 | |
| 112 private: | 182 private: |
| 113 ViewsTestBase* test_base_; | 183 ViewsTestBase* test_base_; |
| 114 | 184 |
| 115 gfx::Rect available_bounds_; | 185 gfx::Rect available_bounds_; |
| 116 | 186 |
| 117 // Widget returned by GetWidget(). Only created if GetWidget() is called. | 187 // Widget returned by GetWidget(). Only created if GetWidget() is called. |
| 118 mutable std::unique_ptr<TestBubbleFrameViewWidgetDelegate> widget_delegate_; | 188 mutable std::unique_ptr<TestBubbleFrameViewWidgetDelegate> widget_delegate_; |
| 119 mutable std::unique_ptr<Widget> widget_; | 189 mutable std::unique_ptr<Widget> widget_; |
| 120 | 190 |
| 121 DISALLOW_COPY_AND_ASSIGN(TestBubbleFrameView); | 191 DISALLOW_COPY_AND_ASSIGN(TestBubbleFrameView); |
| 122 }; | 192 }; |
| 123 | 193 |
| 194 class TestBubbleFrameDialogView : public TestBubbleFrameView { | |
| 195 public: | |
| 196 TestBubbleFrameDialogView(ViewsTestBase* test_base) | |
| 197 : TestBubbleFrameView(test_base) {} | |
| 198 | |
| 199 protected: | |
| 200 std::unique_ptr<TestBubbleFrameViewWidgetDelegate> MakeWidgetDelegate( | |
| 201 Widget* widget) const override { | |
| 202 return base::WrapUnique(new TestBubbleFrameViewDialogDelegate(widget)); | |
| 203 } | |
| 204 }; | |
| 205 | |
| 124 } // namespace | 206 } // namespace |
| 125 | 207 |
| 126 TEST_F(BubbleFrameViewTest, GetBoundsForClientView) { | 208 TEST_F(BubbleFrameViewTest, GetBoundsForClientView) { |
| 127 TestBubbleFrameView frame(this); | 209 TestBubbleFrameView frame(this); |
| 128 EXPECT_EQ(kArrow, frame.bubble_border()->arrow()); | 210 EXPECT_EQ(kArrow, frame.bubble_border()->arrow()); |
| 129 EXPECT_EQ(kColor, frame.bubble_border()->background_color()); | 211 EXPECT_EQ(kColor, frame.bubble_border()->background_color()); |
| 130 | 212 |
| 131 int margin_x = frame.content_margins().left(); | 213 int margin_x = frame.content_margins().left(); |
| 132 int margin_y = frame.content_margins().top(); | 214 int margin_y = frame.content_margins().top(); |
| 133 gfx::Insets insets = frame.bubble_border()->GetInsets(); | 215 gfx::Insets insets = frame.bubble_border()->GetInsets(); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 481 #else | 563 #else |
| 482 maximum_rect.Inset(frame.bubble_border()->GetInsets()); | 564 maximum_rect.Inset(frame.bubble_border()->GetInsets()); |
| 483 | 565 |
| 484 // Should ignore the contents view's maximum size and use the preferred size. | 566 // Should ignore the contents view's maximum size and use the preferred size. |
| 485 gfx::Size expected_size(kPreferredClientWidth + kExpectedAdditionalWidth, | 567 gfx::Size expected_size(kPreferredClientWidth + kExpectedAdditionalWidth, |
| 486 kPreferredClientHeight + kExpectedAdditionalHeight); | 568 kPreferredClientHeight + kExpectedAdditionalHeight); |
| 487 EXPECT_EQ(expected_size, maximum_rect.size()); | 569 EXPECT_EQ(expected_size, maximum_rect.size()); |
| 488 #endif | 570 #endif |
| 489 } | 571 } |
| 490 | 572 |
| 573 // This test ensures that BubbleFrameViews are snapped to the width specified by | |
| 574 // ViewsDelegate::GetSnappedDialogWidth(). | |
| 575 TEST_F(BubbleFrameViewTest, WidthSnapsToUnit) { | |
| 576 TestBubbleFrameDialogView frame(this); | |
| 577 | |
| 578 // The "border width" here is primarily for the bubble shadow, but also for | |
| 579 // the edge stroke of the bubble. This width is *not* included in the width | |
| 580 // snapping, so it needs to be subtracted out. | |
| 581 int border_width = 10; | |
|
Peter Kasting
2017/04/06 06:32:16
Nit: This looks like you're matching a shadow/stro
| |
| 582 | |
| 583 // Check that changing the snapping unit changes the computed width to be a | |
| 584 // multiple of the snapping unit. | |
|
Peter Kasting
2017/04/06 06:32:16
Nit: Technically, the code below tests only that y
| |
| 585 const int kTestWidth = 500; | |
| 586 EXPECT_NE(kTestWidth, frame.GetPreferredSize().width() - border_width); | |
|
Peter Kasting
2017/04/06 06:32:16
Nit: EXPECT_LT?
| |
| 587 views_delegate()->set_snapped_width(kTestWidth); | |
| 588 EXPECT_EQ(kTestWidth, frame.GetPreferredSize().width() - border_width); | |
| 589 } | |
| 590 | |
| 491 } // namespace views | 591 } // namespace views |
| OLD | NEW |