OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h" | 5 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h" |
6 | 6 |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "chrome/browser/ui/layout_constants.h" | 8 #include "chrome/browser/ui/layout_constants.h" |
9 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 9 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
11 #include "ui/events/base_event_utils.h" | |
12 #include "ui/events/gesture_detection/gesture_configuration.h" | |
13 #include "ui/events/test/event_generator.h" | |
14 #include "ui/views/animation/test/ink_drop_host_view_test_api.h" | |
15 #include "ui/views/animation/test/test_ink_drop.h" | |
11 #include "ui/views/controls/image_view.h" | 16 #include "ui/views/controls/image_view.h" |
12 #include "ui/views/test/views_test_base.h" | 17 #include "ui/views/test/views_test_base.h" |
13 | 18 |
14 #if defined(USE_ASH) | 19 #if defined(USE_ASH) |
15 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
16 #endif | 21 #endif |
17 | 22 |
23 using views::test::InkDropHostViewTestApi; | |
24 using views::test::TestInkDrop; | |
25 | |
18 namespace { | 26 namespace { |
19 | 27 |
20 const int kStayOpenTimeMS = 100; | 28 const int kStayOpenTimeMS = 100; |
21 const int kOpenTimeMS = 100; | 29 const int kOpenTimeMS = 100; |
22 const int kAnimationDurationMS = (kOpenTimeMS * 2) + kStayOpenTimeMS; | 30 const int kAnimationDurationMS = (kOpenTimeMS * 2) + kStayOpenTimeMS; |
23 const int kImageSize = 15; | 31 const int kImageSize = 15; |
24 const SkColor kTestColor = SkColorSetRGB(64, 64, 64); | 32 const SkColor kTestColor = SkColorSetRGB(64, 64, 64); |
25 const int kNumberOfSteps = 300; | 33 const int kNumberOfSteps = 300; |
26 | 34 |
27 class TestIconLabelBubbleView : public IconLabelBubbleView { | 35 class TestIconLabelBubbleView : public IconLabelBubbleView { |
28 public: | 36 public: |
29 enum State { | 37 enum State { |
30 GROWING, | 38 GROWING, |
31 STEADY, | 39 STEADY, |
32 SHRINKING, | 40 SHRINKING, |
33 }; | 41 }; |
34 | 42 |
35 explicit TestIconLabelBubbleView(const gfx::FontList& font_list) | 43 explicit TestIconLabelBubbleView(const gfx::FontList& font_list) |
36 : IconLabelBubbleView(font_list, false), value_(0) { | 44 : IconLabelBubbleView(font_list, false), |
45 value_(0), | |
46 is_bubble_shown_(false) { | |
37 GetImageView()->SetImageSize(gfx::Size(kImageSize, kImageSize)); | 47 GetImageView()->SetImageSize(gfx::Size(kImageSize, kImageSize)); |
38 SetLabel(base::ASCIIToUTF16("Label")); | 48 SetLabel(base::ASCIIToUTF16("Label")); |
39 } | 49 } |
40 | 50 |
41 void SetCurrentAnimationValue(int value) { | 51 void SetCurrentAnimationValue(int value) { |
42 value_ = value; | 52 value_ = value; |
43 SizeToPreferredSize(); | 53 SizeToPreferredSize(); |
44 } | 54 } |
45 | 55 |
46 int width() const { return bounds().width(); } | 56 int width() const { return bounds().width(); } |
47 bool IsLabelVisible() const { return label()->visible(); } | 57 bool IsLabelVisible() const { return label()->visible(); } |
48 void SetLabelVisible(bool visible) { label()->SetVisible(visible); } | 58 void SetLabelVisible(bool visible) { label()->SetVisible(visible); } |
49 const gfx::Rect& GetLabelBounds() const { return label()->bounds(); } | 59 const gfx::Rect& GetLabelBounds() const { return label()->bounds(); } |
50 | 60 |
51 State state() const { | 61 State state() const { |
52 const double kOpenFraction = | 62 const double kOpenFraction = |
53 static_cast<double>(kOpenTimeMS) / kAnimationDurationMS; | 63 static_cast<double>(kOpenTimeMS) / kAnimationDurationMS; |
54 double state = value_ / (double)kNumberOfSteps; | 64 double state = value_ / (double)kNumberOfSteps; |
55 if (state < kOpenFraction) | 65 if (state < kOpenFraction) |
56 return GROWING; | 66 return GROWING; |
57 if (state > (1.0 - kOpenFraction)) | 67 if (state > (1.0 - kOpenFraction)) |
58 return SHRINKING; | 68 return SHRINKING; |
59 return STEADY; | 69 return STEADY; |
60 } | 70 } |
61 | 71 |
72 void HideBubble() { OnWidgetVisibilityChanged(nullptr, false); } | |
73 | |
74 void set_is_bubble_shown(bool is_bubble_shown) { | |
75 is_bubble_shown_ = is_bubble_shown; | |
76 } | |
77 | |
62 protected: | 78 protected: |
63 // IconLabelBubbleView: | 79 // IconLabelBubbleView: |
64 SkColor GetTextColor() const override { return kTestColor; } | 80 SkColor GetTextColor() const override { return kTestColor; } |
65 | 81 |
66 bool ShouldShowLabel() const override { | 82 bool ShouldShowLabel() const override { |
67 return !IsShrinking() || | 83 return !IsShrinking() || |
68 (width() > (image()->GetPreferredSize().width() + | 84 (width() > (image()->GetPreferredSize().width() + |
69 2 * LocationBarView::kIconInteriorPadding + | 85 2 * LocationBarView::kIconInteriorPadding + |
70 2 * GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING))); | 86 2 * GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING))); |
71 } | 87 } |
72 | 88 |
73 double WidthMultiplier() const override { | 89 double WidthMultiplier() const override { |
74 const double kOpenFraction = | 90 const double kOpenFraction = |
75 static_cast<double>(kOpenTimeMS) / kAnimationDurationMS; | 91 static_cast<double>(kOpenTimeMS) / kAnimationDurationMS; |
76 double fraction = value_ / (double)kNumberOfSteps; | 92 double fraction = value_ / (double)kNumberOfSteps; |
77 switch (state()) { | 93 switch (state()) { |
78 case GROWING: | 94 case GROWING: |
79 return fraction / kOpenFraction; | 95 return fraction / kOpenFraction; |
80 case STEADY: | 96 case STEADY: |
81 return 1.0; | 97 return 1.0; |
82 case SHRINKING: | 98 case SHRINKING: |
83 return (1.0 - fraction) / kOpenFraction; | 99 return (1.0 - fraction) / kOpenFraction; |
84 } | 100 } |
85 NOTREACHED(); | 101 NOTREACHED(); |
86 return 1.0; | 102 return 1.0; |
87 } | 103 } |
88 | 104 |
89 bool IsShrinking() const override { return state() == SHRINKING; } | 105 bool IsShrinking() const override { return state() == SHRINKING; } |
90 | 106 |
107 bool IsBubbleShown() const override { return is_bubble_shown_; } | |
108 | |
109 bool ShowBubble(const ui::Event& event) override { | |
110 return !is_bubble_shown_; | |
111 }; | |
sky
2017/05/12 13:11:48
no ;
spqchan
2017/05/18 01:13:05
Done.
| |
112 | |
91 private: | 113 private: |
92 int value_; | 114 int value_; |
115 bool is_bubble_shown_; | |
93 DISALLOW_COPY_AND_ASSIGN(TestIconLabelBubbleView); | 116 DISALLOW_COPY_AND_ASSIGN(TestIconLabelBubbleView); |
94 }; | 117 }; |
95 | 118 |
96 } // namespace | 119 } // namespace |
97 | 120 |
98 class IconLabelBubbleViewTest : public views::ViewsTestBase { | 121 class IconLabelBubbleViewTest : public views::ViewsTestBase { |
99 public: | 122 public: |
100 IconLabelBubbleViewTest() | 123 IconLabelBubbleViewTest() |
101 : views::ViewsTestBase(), | 124 : views::ViewsTestBase(), |
125 widget_(nullptr), | |
126 view_(nullptr), | |
127 ink_drop_(nullptr), | |
102 steady_reached_(false), | 128 steady_reached_(false), |
103 shrinking_reached_(false), | 129 shrinking_reached_(false), |
104 minimum_size_reached_(false), | 130 minimum_size_reached_(false), |
105 previous_width_(0), | 131 previous_width_(0), |
106 initial_image_x_(0) {} | 132 initial_image_x_(0) {} |
107 ~IconLabelBubbleViewTest() override {} | 133 ~IconLabelBubbleViewTest() override {} |
108 | 134 |
109 protected: | 135 protected: |
110 // views::ViewsTestBase: | 136 // views::ViewsTestBase: |
111 void SetUp() override { | 137 void SetUp() override { |
112 views::ViewsTestBase::SetUp(); | 138 views::ViewsTestBase::SetUp(); |
113 gfx::FontList font_list; | 139 gfx::FontList font_list; |
114 view_.reset(new TestIconLabelBubbleView(font_list)); | 140 |
141 CreateWidget(); | |
142 generator_.reset(new ui::test::EventGenerator(widget_->GetNativeWindow())); | |
143 view_ = new TestIconLabelBubbleView(font_list); | |
144 view_->SetBoundsRect(gfx::Rect(0, 0, 24, 24)); | |
145 widget_->SetContentsView(view_); | |
146 | |
147 widget_->Show(); | |
148 } | |
149 | |
150 void TearDown() override { | |
151 generator_.reset(); | |
152 if (widget_ && !widget_->IsClosed()) | |
153 widget_->Close(); | |
154 | |
155 ViewsTestBase::TearDown(); | |
115 } | 156 } |
116 | 157 |
117 void VerifyWithAnimationStep(int step) { | 158 void VerifyWithAnimationStep(int step) { |
118 Reset(); | 159 Reset(); |
119 for (int value = 0; value < kNumberOfSteps; value += step) { | 160 for (int value = 0; value < kNumberOfSteps; value += step) { |
120 SetValue(value); | 161 SetValue(value); |
121 VerifyAnimationStep(); | 162 VerifyAnimationStep(); |
122 } | 163 } |
123 view_->SetLabelVisible(false); | 164 view_->SetLabelVisible(false); |
124 } | 165 } |
125 | 166 |
167 TestInkDrop* ink_drop() { return ink_drop_; } | |
168 | |
169 TestIconLabelBubbleView* view() { return view_; } | |
170 | |
171 ui::test::EventGenerator* generator() { return generator_.get(); } | |
172 | |
173 void AttachInkDrop() { | |
174 ink_drop_ = new TestInkDrop(); | |
175 InkDropHostViewTestApi(view_).SetInkDrop(base::WrapUnique(ink_drop_)); | |
176 } | |
177 | |
126 private: | 178 private: |
179 void CreateWidget() { | |
180 DCHECK(!widget_); | |
181 | |
182 widget_ = new views::Widget; | |
183 views::Widget::InitParams params = | |
184 CreateParams(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); | |
185 params.bounds = gfx::Rect(0, 0, 200, 200); | |
186 widget_->Init(params); | |
187 } | |
188 | |
127 void Reset() { | 189 void Reset() { |
128 view_->SetLabelVisible(true); | 190 view_->SetLabelVisible(true); |
129 SetValue(0); | 191 SetValue(0); |
130 steady_reached_ = false; | 192 steady_reached_ = false; |
131 shrinking_reached_ = false; | 193 shrinking_reached_ = false; |
132 minimum_size_reached_ = false; | 194 minimum_size_reached_ = false; |
133 previous_width_ = 0; | 195 previous_width_ = 0; |
134 initial_image_x_ = GetImageBounds().x(); | 196 initial_image_x_ = GetImageBounds().x(); |
135 EXPECT_EQ(0, initial_image_x_); | 197 EXPECT_EQ(0, initial_image_x_); |
136 } | 198 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 int width() { return view_->width(); } | 257 int width() { return view_->width(); } |
196 | 258 |
197 bool IsLabelVisible() { return view_->IsLabelVisible(); } | 259 bool IsLabelVisible() { return view_->IsLabelVisible(); } |
198 | 260 |
199 const gfx::Rect& GetLabelBounds() const { return view_->GetLabelBounds(); } | 261 const gfx::Rect& GetLabelBounds() const { return view_->GetLabelBounds(); } |
200 | 262 |
201 const gfx::Rect& GetImageBounds() const { | 263 const gfx::Rect& GetImageBounds() const { |
202 return view_->GetImageView()->bounds(); | 264 return view_->GetImageView()->bounds(); |
203 } | 265 } |
204 | 266 |
205 std::unique_ptr<TestIconLabelBubbleView> view_; | 267 views::Widget* widget_; |
268 TestIconLabelBubbleView* view_; | |
269 TestInkDrop* ink_drop_; | |
270 std::unique_ptr<ui::test::EventGenerator> generator_; | |
206 | 271 |
207 bool steady_reached_; | 272 bool steady_reached_; |
208 bool shrinking_reached_; | 273 bool shrinking_reached_; |
209 bool minimum_size_reached_; | 274 bool minimum_size_reached_; |
210 int previous_width_; | 275 int previous_width_; |
211 int initial_image_x_; | 276 int initial_image_x_; |
212 }; | 277 }; |
213 | 278 |
214 // Tests layout rules for IconLabelBubbleView while simulating animation. | 279 // Tests layout rules for IconLabelBubbleView while simulating animation. |
215 // The animation is first growing the bubble from zero, then keeping its size | 280 // The animation is first growing the bubble from zero, then keeping its size |
216 // constant and finally shrinking it down to its minimum size which is the image | 281 // constant and finally shrinking it down to its minimum size which is the image |
217 // size. | 282 // size. |
218 // Various step sizes during animation simulate different possible timing. | 283 // Various step sizes during animation simulate different possible timing. |
219 TEST_F(IconLabelBubbleViewTest, AnimateLayout) { | 284 TEST_F(IconLabelBubbleViewTest, AnimateLayout) { |
220 VerifyWithAnimationStep(1); | 285 VerifyWithAnimationStep(1); |
221 VerifyWithAnimationStep(5); | 286 VerifyWithAnimationStep(5); |
222 VerifyWithAnimationStep(10); | 287 VerifyWithAnimationStep(10); |
223 VerifyWithAnimationStep(25); | 288 VerifyWithAnimationStep(25); |
224 } | 289 } |
225 | 290 |
291 TEST_F(IconLabelBubbleViewTest, MouseInkDropState) { | |
292 AttachInkDrop(); | |
293 generator()->PressLeftButton(); | |
294 EXPECT_EQ(views::InkDropState::ACTION_PENDING, | |
295 ink_drop()->GetTargetInkDropState()); | |
296 generator()->ReleaseLeftButton(); | |
297 EXPECT_EQ(views::InkDropState::ACTIVATED, | |
298 ink_drop()->GetTargetInkDropState()); | |
299 view()->HideBubble(); | |
300 EXPECT_EQ(views::InkDropState::HIDDEN, ink_drop()->GetTargetInkDropState()); | |
301 | |
302 // If the bubble is shown, the InkDropState should not change to | |
303 // ACTION_PENDING. | |
304 generator()->PressLeftButton(); | |
305 EXPECT_EQ(views::InkDropState::ACTION_PENDING, | |
306 ink_drop()->GetTargetInkDropState()); | |
307 generator()->ReleaseLeftButton(); | |
308 EXPECT_EQ(views::InkDropState::ACTIVATED, | |
309 ink_drop()->GetTargetInkDropState()); | |
310 view()->set_is_bubble_shown(true); | |
311 generator()->PressLeftButton(); | |
312 EXPECT_NE(views::InkDropState::ACTION_PENDING, | |
313 ink_drop()->GetTargetInkDropState()); | |
314 } | |
315 | |
316 #if !defined(OS_MACOSX) | |
317 TEST_F(IconLabelBubbleViewTest, GestureInkDropState) { | |
318 AttachInkDrop(); | |
319 view()->set_is_bubble_shown(false); | |
320 generator()->GestureTapAt(gfx::Point()); | |
321 EXPECT_EQ(views::InkDropState::ACTIVATED, | |
322 ink_drop()->GetTargetInkDropState()); | |
323 view()->HideBubble(); | |
324 EXPECT_EQ(views::InkDropState::HIDDEN, ink_drop()->GetTargetInkDropState()); | |
325 | |
326 // If the bubble is shown, the InkDropState should not change to | |
327 // ACTIVATED. | |
328 generator()->GestureTapAt(gfx::Point()); | |
329 EXPECT_EQ(views::InkDropState::ACTIVATED, | |
330 ink_drop()->GetTargetInkDropState()); | |
331 view()->set_is_bubble_shown(true); | |
332 generator()->GestureTapAt(gfx::Point()); | |
333 EXPECT_EQ(views::InkDropState::HIDDEN, ink_drop()->GetTargetInkDropState()); | |
334 } | |
335 #endif | |
336 | |
226 #if defined(USE_ASH) | 337 #if defined(USE_ASH) |
227 // Verifies IconLabelBubbleView::GetPreferredSize() doesn't crash when there is | 338 // Verifies IconLabelBubbleView::GetPreferredSize() doesn't crash when there is |
228 // a widget but no compositor. | 339 // a widget but no compositor. |
229 using IconLabelBubbleViewCrashTest = views::ViewsTestBase; | 340 using IconLabelBubbleViewCrashTest = views::ViewsTestBase; |
230 | 341 |
231 TEST_F(IconLabelBubbleViewCrashTest, | 342 TEST_F(IconLabelBubbleViewCrashTest, |
232 GetPreferredSizeDoesntCrashWhenNoCompositor) { | 343 GetPreferredSizeDoesntCrashWhenNoCompositor) { |
233 gfx::FontList font_list; | 344 gfx::FontList font_list; |
234 views::Widget::InitParams params = | 345 views::Widget::InitParams params = |
235 CreateParams(views::Widget::InitParams::TYPE_WINDOW); | 346 CreateParams(views::Widget::InitParams::TYPE_WINDOW); |
236 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 347 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
237 views::Widget widget; | 348 views::Widget widget; |
238 widget.Init(params); | 349 widget.Init(params); |
239 IconLabelBubbleView* icon_label_bubble_view = | 350 IconLabelBubbleView* icon_label_bubble_view = |
240 new TestIconLabelBubbleView(font_list); | 351 new TestIconLabelBubbleView(font_list); |
241 icon_label_bubble_view->SetLabel(base::ASCIIToUTF16("x")); | 352 icon_label_bubble_view->SetLabel(base::ASCIIToUTF16("x")); |
242 widget.GetContentsView()->AddChildView(icon_label_bubble_view); | 353 widget.GetContentsView()->AddChildView(icon_label_bubble_view); |
243 aura::Window* widget_native_view = widget.GetNativeView(); | 354 aura::Window* widget_native_view = widget.GetNativeView(); |
244 // Remove the window from its parent. This means GetWidget() in | 355 // Remove the window from its parent. This means GetWidget() in |
245 // IconLabelBubbleView will return non-null, but GetWidget()->GetCompositor() | 356 // IconLabelBubbleView will return non-null, but GetWidget()->GetCompositor() |
246 // will return null. | 357 // will return null. |
247 ASSERT_TRUE(widget_native_view->parent()); | 358 ASSERT_TRUE(widget_native_view->parent()); |
248 widget_native_view->parent()->RemoveChild(widget_native_view); | 359 widget_native_view->parent()->RemoveChild(widget_native_view); |
249 static_cast<views::View*>(icon_label_bubble_view)->GetPreferredSize(); | 360 static_cast<views::View*>(icon_label_bubble_view)->GetPreferredSize(); |
250 } | 361 } |
251 #endif | 362 #endif |
OLD | NEW |