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/chromeos/display/touch_calibrator/touch_calibrator_view .h" | 5 #include "chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view .h" |
6 | 6 |
7 #include "ash/display/window_tree_host_manager.h" | 7 #include "ash/display/window_tree_host_manager.h" |
8 #include "ash/public/cpp/shell_window_ids.h" | 8 #include "ash/public/cpp/shell_window_ids.h" |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
11 #include "ui/base/resource/resource_bundle.h" | 11 #include "ui/base/resource/resource_bundle.h" |
12 #include "ui/gfx/animation/linear_animation.h" | 12 #include "ui/gfx/animation/linear_animation.h" |
13 #include "ui/gfx/animation/throb_animation.h" | |
13 #include "ui/gfx/canvas.h" | 14 #include "ui/gfx/canvas.h" |
14 #include "ui/strings/grit/ui_strings.h" | 15 #include "ui/strings/grit/ui_strings.h" |
15 #include "ui/views/controls/label.h" | 16 #include "ui/views/controls/label.h" |
16 #include "ui/views/widget/widget.h" | 17 #include "ui/views/widget/widget.h" |
17 | 18 |
18 namespace chromeos { | 19 namespace chromeos { |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 constexpr char kWidgetName[] = "TouchCalibratorOverlay"; | 23 constexpr char kWidgetName[] = "TouchCalibratorOverlay"; |
23 | 24 |
24 constexpr int kAnimationFrameRate = 100; | 25 constexpr int kAnimationFrameRate = 100; |
25 constexpr int kFadeDurationInMs = 150; | 26 constexpr int kFadeDurationInMs = 150; |
26 | 27 |
27 const SkColor kExitLabelColor = SkColorSetARGBInline(255, 96, 96, 96); | 28 const SkColor kExitLabelColor = SkColorSetARGBInline(255, 96, 96, 96); |
28 const SkColor kExitLabelShadowColor = SkColorSetARGBInline(255, 11, 11, 11); | 29 const SkColor kExitLabelShadowColor = SkColorSetARGBInline(255, 11, 11, 11); |
29 constexpr int kExitLabelWidth = 300; | 30 constexpr int kExitLabelWidth = 300; |
30 constexpr int kExitLabelHeight = 20; | 31 constexpr int kExitLabelHeight = 20; |
31 | 32 |
33 constexpr int kHintBoxWidth = 298; | |
34 constexpr int kHintBoxHeight = 180; | |
35 constexpr int kHintBoxLabelTextSize = 5; | |
36 constexpr int kHintBoxSublabelTextSize = 3; | |
37 | |
38 constexpr int kThrobberCircleViewWidth = 128; | |
39 constexpr float kThrobberCircleRadiusFactor = 3.f / 8.f; | |
40 | |
41 constexpr int kTouchPointViewOffset = 100; | |
42 | |
43 constexpr int kTapLabelHeight = 48; | |
44 | |
45 const SkColor kHintLabelTextColor = SK_ColorBLACK; | |
46 const SkColor kHintSublabelTextColor = SkColorSetARGBInline(255, 161, 161, 161); | |
47 | |
48 const SkColor kInnerCircleColor = SK_ColorWHITE; | |
49 const SkColor kOuterCircleColor = SkColorSetA(kInnerCircleColor, 128); | |
50 | |
51 constexpr int kCircleAnimationDurationMs = 900; | |
52 | |
53 constexpr int kHintRectBorderRadius = 10; | |
54 | |
32 constexpr float kBackgroundFinalOpacity = 0.75f; | 55 constexpr float kBackgroundFinalOpacity = 0.75f; |
33 | 56 |
34 // Returns the initialization params for the widget that contains the touch | 57 // Returns the initialization params for the widget that contains the touch |
35 // calibrator view. | 58 // calibrator view. |
36 views::Widget::InitParams GetWidgetParams(aura::Window* root_window) { | 59 views::Widget::InitParams GetWidgetParams(aura::Window* root_window) { |
37 views::Widget::InitParams params; | 60 views::Widget::InitParams params; |
38 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; | 61 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; |
39 params.name = kWidgetName; | 62 params.name = kWidgetName; |
40 params.keep_on_top = true; | 63 params.keep_on_top = true; |
41 params.accept_events = true; | 64 params.accept_events = true; |
42 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; | 65 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; |
43 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 66 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
44 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | 67 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
45 params.parent = ash::Shell::GetContainer( | 68 params.parent = ash::Shell::GetContainer( |
46 root_window, ash::kShellWindowId_OverlayContainer); | 69 root_window, ash::kShellWindowId_OverlayContainer); |
47 return params; | 70 return params; |
48 } | 71 } |
49 | 72 |
73 // Returns the size of bounding box required for |text| of given |font_list|. | |
74 const gfx::Size GetSizeForString(base::string16 text, gfx::FontList font_list) { | |
oshima
2017/01/11 18:17:14
const for return value doesn't make much sense.
P
malaykeshav
2017/01/11 18:45:43
Done.
| |
75 int height, width; | |
76 gfx::Canvas::SizeStringInt(text, font_list, &width, &height, 0, 0); | |
77 return gfx::Size(width, height); | |
78 } | |
79 | |
50 } // namespace | 80 } // namespace |
51 | 81 |
82 // Creates a throbbing animated view with two concentric circles. The radius of | |
83 // the inner circle is fixed while that of the outer circle oscillates between a | |
84 // min and max radius. The animation takes |animation_duration| milliseconds | |
85 // to complete. The center of these circles are at the center of the view | |
86 // element. | |
87 class CircularThrobberView : public views::View, public gfx::AnimationDelegate { | |
88 public: | |
89 CircularThrobberView(int width, | |
90 const SkColor& inner_circle_color, | |
91 const SkColor& outer_circle_color, | |
92 int animation_duration); | |
93 ~CircularThrobberView() override; | |
94 | |
95 // views::View overrides: | |
96 void OnPaint(gfx::Canvas* canvas) override; | |
97 | |
98 // gfx::AnimationDelegate overrides: | |
99 void AnimationProgressed(const gfx::Animation* animation) override; | |
100 | |
101 private: | |
102 // Radius of the inner circle. | |
103 const int inner_radius_; | |
104 | |
105 // Current radius of the outer circle. | |
106 int outer_radius_; | |
107 | |
108 // Minimum radius for outer animated circle. | |
109 const int smallest_radius_animated_circle_; | |
110 | |
111 // Maximum radius for outer animated circle. | |
112 const int largest_radius_animated_circle_; | |
113 | |
114 SkPaint inner_circle_paint_; | |
115 SkPaint outer_circle_paint_; | |
116 | |
117 std::unique_ptr<gfx::ThrobAnimation> animation_; | |
118 | |
119 // Center of the concentric circles. | |
120 const gfx::Point center_; | |
121 | |
122 DISALLOW_COPY_AND_ASSIGN(CircularThrobberView); | |
123 }; | |
124 | |
125 CircularThrobberView::CircularThrobberView(int width, | |
126 const SkColor& inner_circle_color, | |
127 const SkColor& outer_circle_color, | |
128 int animation_duration) | |
129 : inner_radius_(width / 4), | |
130 outer_radius_(inner_radius_), | |
131 smallest_radius_animated_circle_(width * kThrobberCircleRadiusFactor), | |
132 largest_radius_animated_circle_(width / 2), | |
133 center_(gfx::Point(width / 2, width / 2)) { | |
134 SetSize(gfx::Size(width, width)); | |
135 | |
136 inner_circle_paint_.setColor(inner_circle_color); | |
137 inner_circle_paint_.setStyle(SkPaint::kFill_Style); | |
138 inner_circle_paint_.setFlags(SkPaint::kAntiAlias_Flag); | |
139 | |
140 outer_circle_paint_.setColor(outer_circle_color); | |
141 outer_circle_paint_.setStyle(SkPaint::kFill_Style); | |
142 outer_circle_paint_.setFlags(SkPaint::kAntiAlias_Flag); | |
143 | |
144 animation_.reset(new gfx::ThrobAnimation(this)); | |
145 animation_->SetThrobDuration(animation_duration); | |
146 animation_->StartThrobbing(-1); | |
147 | |
148 SchedulePaint(); | |
149 } | |
150 | |
151 CircularThrobberView::~CircularThrobberView() {} | |
152 | |
153 void CircularThrobberView::OnPaint(gfx::Canvas* canvas) { | |
154 canvas->DrawCircle(center_, outer_radius_, outer_circle_paint_); | |
155 canvas->DrawCircle(center_, inner_radius_, inner_circle_paint_); | |
156 } | |
157 | |
158 void CircularThrobberView::AnimationProgressed( | |
159 const gfx::Animation* animation) { | |
160 if (animation != animation_.get()) | |
161 return; | |
162 outer_radius_ = animation->CurrentValueBetween( | |
163 smallest_radius_animated_circle_, largest_radius_animated_circle_); | |
164 SchedulePaint(); | |
165 } | |
166 | |
167 // Circular _________________________________ | |
168 // Throbber | | | |
169 // View | | | |
170 // ___________ | | | |
171 // | | | | | |
172 // | | | | | |
173 // | . | | Hint Box | | |
174 // | | | | | |
175 // |___________| | | | |
176 // | | | |
177 // | | | |
178 // |_________________________________| | |
179 // | |
180 // This view is set next to the throbber circle view such that their centers | |
181 // align. The hint box has a label text and a sublabel text to assist the | |
182 // user by informing them about the next step in the calibration process. | |
183 class HintBox : public views::View { | |
184 public: | |
185 HintBox(const gfx::Rect& bounds, int border_radius); | |
186 ~HintBox() override; | |
187 | |
188 // views::View overrides: | |
189 void OnPaint(gfx::Canvas* canvas) override; | |
190 | |
191 void SetLabel(const base::string16& text, const SkColor& color); | |
192 void SetSubLabel(const base::string16& text, const SkColor& color); | |
193 | |
194 private: | |
195 base::string16 label_text_; | |
196 base::string16 sublabel_text_; | |
197 | |
198 SkColor label_color_; | |
199 SkColor sublabel_color_; | |
200 | |
201 const int border_radius_; | |
202 | |
203 int horizontal_offset_; | |
204 | |
205 gfx::FontList label_font_list_; | |
206 gfx::FontList sublabel_font_list_; | |
207 | |
208 gfx::Rect label_text_bounds_; | |
209 gfx::Rect sublabel_text_bounds_; | |
210 | |
211 SkPaint paint_; | |
212 | |
213 DISALLOW_COPY_AND_ASSIGN(HintBox); | |
214 }; | |
215 | |
216 HintBox::HintBox(const gfx::Rect& bounds, int border_radius) | |
217 : border_radius_(border_radius) { | |
218 SetBoundsRect(bounds); | |
219 | |
220 paint_.setColor(SK_ColorWHITE); | |
221 paint_.setStyle(SkPaint::kFill_Style); | |
222 paint_.setFlags(SkPaint::kAntiAlias_Flag); | |
223 | |
224 horizontal_offset_ = width() * 0.08f; | |
225 int top_offset = horizontal_offset_; | |
226 int line_gap = height() * 0.018f; | |
227 int label_height = height() * 0.11f; | |
228 | |
229 label_text_bounds_.SetRect(horizontal_offset_, top_offset, 0, label_height); | |
230 | |
231 top_offset += label_text_bounds_.height() + line_gap; | |
232 | |
233 sublabel_text_bounds_.SetRect(horizontal_offset_, top_offset, 0, | |
234 label_height); | |
235 } | |
236 | |
237 HintBox::~HintBox() {} | |
238 | |
239 void HintBox::SetLabel(const base::string16& text, const SkColor& color) { | |
240 label_text_ = text; | |
241 label_color_ = color; | |
242 | |
243 label_font_list_ = | |
244 ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( | |
245 kHintBoxLabelTextSize, gfx::Font::FontStyle::NORMAL, | |
246 gfx::Font::Weight::NORMAL); | |
247 | |
248 // Adjust size of label bounds based on text and font. | |
249 gfx::Size size = GetSizeForString(label_text_, label_font_list_); | |
250 label_text_bounds_.set_size( | |
251 gfx::Size(size.width(), label_text_bounds_.height())); | |
252 | |
253 // Check if the width of hint box needs to be updated. | |
254 int minimum_expected_width = size.width() + 2 * horizontal_offset_; | |
255 if (minimum_expected_width > width()) | |
256 SetSize(gfx::Size(minimum_expected_width, height())); | |
257 } | |
258 | |
259 void HintBox::SetSubLabel(const base::string16& text, const SkColor& color) { | |
260 sublabel_text_ = text; | |
261 sublabel_color_ = color; | |
262 | |
263 sublabel_font_list_ = | |
264 ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( | |
265 kHintBoxSublabelTextSize, gfx::Font::FontStyle::NORMAL, | |
266 gfx::Font::Weight::NORMAL); | |
267 | |
268 // Adjust size of sublabel label bounds based on text and font. | |
269 gfx::Size size = GetSizeForString(sublabel_text_, sublabel_font_list_); | |
270 sublabel_text_bounds_.set_size( | |
271 gfx::Size(size.width(), sublabel_text_bounds_.height())); | |
272 | |
273 // Check if the width of hint box needs to be updated. | |
274 int minimum_expected_width = size.width() + 2 * horizontal_offset_; | |
275 if (minimum_expected_width > width()) | |
276 SetSize(gfx::Size(minimum_expected_width, height())); | |
277 } | |
278 | |
279 void HintBox::OnPaint(gfx::Canvas* canvas) { | |
280 canvas->DrawRoundRect(GetLocalBounds(), border_radius_, paint_); | |
281 canvas->DrawStringRectWithFlags(label_text_, label_font_list_, label_color_, | |
282 label_text_bounds_, gfx::Canvas::NO_ELLIPSIS); | |
283 canvas->DrawStringRectWithFlags(sublabel_text_, sublabel_font_list_, | |
284 sublabel_color_, sublabel_text_bounds_, | |
285 gfx::Canvas::NO_ELLIPSIS); | |
286 } | |
287 | |
52 TouchCalibratorView::TouchCalibratorView(const display::Display& target_display, | 288 TouchCalibratorView::TouchCalibratorView(const display::Display& target_display, |
53 bool is_primary_view) | 289 bool is_primary_view) |
54 : display_(target_display), | 290 : display_(target_display), |
55 is_primary_view_(is_primary_view), | 291 is_primary_view_(is_primary_view), |
56 exit_label_(nullptr) { | 292 exit_label_(nullptr), |
293 throbber_circle_(nullptr), | |
294 hint_box_view_(nullptr), | |
295 touch_point_view_(nullptr) { | |
57 aura::Window* root = ash::Shell::GetInstance() | 296 aura::Window* root = ash::Shell::GetInstance() |
58 ->window_tree_host_manager() | 297 ->window_tree_host_manager() |
59 ->GetRootWindowForDisplayId(display_.id()); | 298 ->GetRootWindowForDisplayId(display_.id()); |
60 widget_.reset(new views::Widget); | 299 widget_.reset(new views::Widget); |
61 widget_->Init(GetWidgetParams(root)); | 300 widget_->Init(GetWidgetParams(root)); |
62 widget_->SetContentsView(this); | 301 widget_->SetContentsView(this); |
63 widget_->SetBounds(display_.bounds()); | 302 widget_->SetBounds(display_.bounds()); |
64 widget_->Show(); | 303 widget_->Show(); |
65 set_owned_by_client(); | 304 set_owned_by_client(); |
66 | 305 |
(...skipping 26 matching lines...) Expand all Loading... | |
93 display_.bounds().height() * 3.f / 4, kExitLabelWidth, | 332 display_.bounds().height() * 3.f / 4, kExitLabelWidth, |
94 kExitLabelHeight); | 333 kExitLabelHeight); |
95 exit_label_->SetEnabledColor(kExitLabelColor); | 334 exit_label_->SetEnabledColor(kExitLabelColor); |
96 exit_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); | 335 exit_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); |
97 exit_label_->SetShadows(gfx::ShadowValues( | 336 exit_label_->SetShadows(gfx::ShadowValues( |
98 1, gfx::ShadowValue(gfx::Vector2d(1, 1), 1, kExitLabelShadowColor))); | 337 1, gfx::ShadowValue(gfx::Vector2d(1, 1), 1, kExitLabelShadowColor))); |
99 exit_label_->SetSubpixelRenderingEnabled(false); | 338 exit_label_->SetSubpixelRenderingEnabled(false); |
100 exit_label_->SetVisible(false); | 339 exit_label_->SetVisible(false); |
101 | 340 |
102 AddChildView(exit_label_); | 341 AddChildView(exit_label_); |
342 | |
343 // If this is not the screen that is being calibrated, then this is all we | |
344 // need to display. | |
345 if (!is_primary_view_) | |
346 return; | |
347 | |
348 // Initialize the touch point view that contains the animated circle that the | |
349 // user needs to tap. | |
350 const int kTouchPointViewHeight = kThrobberCircleViewWidth + kTapLabelHeight; | |
351 | |
352 throbber_circle_ = | |
353 new CircularThrobberView(kThrobberCircleViewWidth, kInnerCircleColor, | |
354 kOuterCircleColor, kCircleAnimationDurationMs); | |
355 throbber_circle_->SetPosition(gfx::Point(0, 0)); | |
356 | |
357 touch_point_view_ = new views::View; | |
358 touch_point_view_->SetBounds(kTouchPointViewOffset, kTouchPointViewOffset, | |
359 kThrobberCircleViewWidth, kTouchPointViewHeight); | |
360 touch_point_view_->SetVisible(false); | |
361 | |
362 touch_point_view_->AddChildView(throbber_circle_); | |
363 | |
364 AddChildView(touch_point_view_); | |
365 | |
366 // Initialize the Hint Box view. | |
367 base::string16 hint_label_text = | |
368 rb.GetLocalizedString(IDS_DISPLAY_TOUCH_CALIBRATION_HINT_LABEL_TEXT); | |
369 base::string16 hint_sublabel_text = | |
370 rb.GetLocalizedString(IDS_DISPLAY_TOUCH_CALIBRATION_HINT_SUBLABEL_TEXT); | |
371 | |
372 int tpv_width = touch_point_view_->width(); | |
373 | |
374 gfx::Size size(kHintBoxWidth, kHintBoxHeight); | |
375 | |
376 gfx::Point position( | |
377 touch_point_view_->x() + tpv_width * 1.2f, | |
378 touch_point_view_->y() + (tpv_width / 2.f) - (size.height() / 2.f)); | |
379 | |
380 HintBox* hint_box = | |
381 new HintBox(gfx::Rect(position, size), kHintRectBorderRadius); | |
382 hint_box->SetVisible(false); | |
383 hint_box->SetLabel(hint_label_text, kHintLabelTextColor); | |
384 hint_box->SetSubLabel(hint_sublabel_text, kHintSublabelTextColor); | |
385 hint_box_view_ = hint_box; | |
386 | |
387 AddChildView(hint_box_view_); | |
103 } | 388 } |
104 | 389 |
105 void TouchCalibratorView::OnPaint(gfx::Canvas* canvas) { | 390 void TouchCalibratorView::OnPaint(gfx::Canvas* canvas) { |
106 OnPaintBackground(canvas); | 391 OnPaintBackground(canvas); |
107 } | 392 } |
108 | 393 |
109 void TouchCalibratorView::OnPaintBackground(gfx::Canvas* canvas) { | 394 void TouchCalibratorView::OnPaintBackground(gfx::Canvas* canvas) { |
110 float opacity; | 395 float opacity; |
111 | 396 |
112 // If current state is a fade in or fade out state then update opacity | 397 // If current state is a fade in or fade out state then update opacity |
(...skipping 17 matching lines...) Expand all Loading... | |
130 | 415 |
131 void TouchCalibratorView::AnimationCanceled(const gfx::Animation* animation) { | 416 void TouchCalibratorView::AnimationCanceled(const gfx::Animation* animation) { |
132 AnimationEnded(animation); | 417 AnimationEnded(animation); |
133 } | 418 } |
134 | 419 |
135 void TouchCalibratorView::AnimationEnded(const gfx::Animation* animation) { | 420 void TouchCalibratorView::AnimationEnded(const gfx::Animation* animation) { |
136 switch (state_) { | 421 switch (state_) { |
137 case BACKGROUND_FADING_IN: | 422 case BACKGROUND_FADING_IN: |
138 exit_label_->SetVisible(true); | 423 exit_label_->SetVisible(true); |
139 state_ = is_primary_view_ ? DISPLAY_POINT_1 : CALIBRATION_COMPLETE; | 424 state_ = is_primary_view_ ? DISPLAY_POINT_1 : CALIBRATION_COMPLETE; |
425 if (is_primary_view_) { | |
426 touch_point_view_->SetVisible(true); | |
427 hint_box_view_->SetVisible(true); | |
428 } | |
140 break; | 429 break; |
141 default: | 430 default: |
142 break; | 431 break; |
143 } | 432 } |
144 } | 433 } |
145 | 434 |
146 void TouchCalibratorView::AdvanceToNextState() { | 435 void TouchCalibratorView::AdvanceToNextState() { |
147 // Stop any previous animations and skip them to the end. | 436 // Stop any previous animations and skip them to the end. |
148 animator_->End(); | 437 animator_->End(); |
149 | 438 |
(...skipping 21 matching lines...) Expand all Loading... | |
171 } | 460 } |
172 | 461 |
173 void TouchCalibratorView::SkipToFinalState() {} | 462 void TouchCalibratorView::SkipToFinalState() {} |
174 | 463 |
175 void TouchCalibratorView::SkipCurrentAnimationForTest() { | 464 void TouchCalibratorView::SkipCurrentAnimationForTest() { |
176 if (animator_->is_animating()) | 465 if (animator_->is_animating()) |
177 animator_->End(); | 466 animator_->End(); |
178 } | 467 } |
179 | 468 |
180 } // namespace chromeos | 469 } // namespace chromeos |
OLD | NEW |