Chromium Code Reviews| Index: chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc |
| diff --git a/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc b/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc |
| index 4d155a6316751c33aa8231b8d03b95732bcb3cd3..f7e54dcf8844ca19d86b847273d3abbefa9f314e 100644 |
| --- a/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc |
| +++ b/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc |
| @@ -10,6 +10,7 @@ |
| #include "ui/aura/window.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/gfx/animation/linear_animation.h" |
| +#include "ui/gfx/animation/throb_animation.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/strings/grit/ui_strings.h" |
| #include "ui/views/controls/label.h" |
| @@ -29,6 +30,16 @@ const SkColor kExitLabelShadowColor = SkColorSetARGBInline(255, 11, 11, 11); |
| constexpr int kExitLabelWidth = 300; |
| constexpr int kExitLabelHeight = 20; |
| +const SkColor kHintLabelTextColor = SK_ColorBLACK; |
| +const SkColor kHintSublabelTextColor = SkColorSetARGBInline(255, 161, 161, 161); |
| + |
| +const SkColor kInnerCircleColor = SK_ColorWHITE; |
| +const SkColor kOuterCircleColor = SkColorSetA(kInnerCircleColor, 128); |
| + |
| +constexpr int kCircleAnimationDurationMs = 900; |
| + |
| +constexpr int kHintRectBorderRadius = 10; |
| + |
| constexpr float kBackgroundFinalOpacity = 0.75f; |
| // Returns the initialization params for the widget that contains the touch |
| @@ -47,13 +58,217 @@ views::Widget::InitParams GetWidgetParams(aura::Window* root_window) { |
| return params; |
| } |
| +// Returns a font size that would fit the text exactly in the given bounds. |
| +int GetFontSizeForRect(gfx::Rect bounds, base::string16 text) { |
|
oshima
2017/01/05 23:29:04
a few questions.
1) Why do we want to use fixed si
malaykeshav
2017/01/09 18:59:41
Font size is now fixed along with the bounds which
oshima
2017/01/10 17:11:18
I thought we're going to adjust the bounds using G
malaykeshav
2017/01/10 23:07:48
Done
|
| + int font_size = 0; |
| + gfx::FontList font_list; |
| + int height, width; |
| + do { |
| + font_size++; |
| + font_list = ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( |
| + font_size, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL); |
| + gfx::Canvas::SizeStringInt(text, font_list, &width, &height, 0, 0); |
| + } while (width <= bounds.width() && height <= bounds.height()); |
|
stevenjb
2016/12/28 01:04:50
Is this guaranteed to exit? It seems like if font_
malaykeshav
2017/01/09 18:59:40
Removed. No longer required.
|
| + return font_size - 1; |
| +} |
| + |
| } // namespace |
| +// Creates a throbbing animated view with two concentric circles. The radius of |
| +// the inner circle is fixed while that of the outer circle oscillates between a |
| +// min and max radius. The animation takes |animation_duration| milliseconds |
| +// to complete. The center of these circles are at the center of the view |
| +// element. |
| +class CircularThrobberView : public views::View, public gfx::AnimationDelegate { |
| + public: |
| + CircularThrobberView(int width, |
| + const SkColor& inner_circle_color, |
| + const SkColor& outer_circle_color, |
| + int animation_duration); |
| + ~CircularThrobberView() override; |
| + |
| + // views::View overrides: |
| + void OnPaint(gfx::Canvas* canvas) override; |
| + |
| + // gfx::AnimationDelegate overrides: |
| + void AnimationProgressed(const gfx::Animation* animation) override; |
| + |
| + private: |
| + // Radius of the inner circle. |
| + const int inner_radius_; |
| + |
| + // Current radius of the outer circle. |
| + int outer_radius_; |
| + |
| + // Minimum radius for outer animated circle. |
| + const int min_outer_radius_; |
| + |
| + // Maximum radius for outer animated circle. |
| + const int max_outer_radius_; |
|
oshima
2017/01/05 23:29:04
It's probably better to say "smallest/largest size
malaykeshav
2017/01/09 18:59:41
Done
|
| + |
| + SkPaint inner_circle_paint_; |
| + SkPaint outer_circle_paint_; |
| + |
| + std::unique_ptr<gfx::ThrobAnimation> animation_; |
| + |
| + // Center of the concentric circles. |
| + const gfx::Point center_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CircularThrobberView); |
| +}; |
| + |
| +CircularThrobberView::CircularThrobberView(int width, |
| + const SkColor& inner_circle_color, |
| + const SkColor& outer_circle_color, |
| + int animation_duration) |
| + : inner_radius_(width / 4), |
| + outer_radius_(inner_radius_), |
| + min_outer_radius_(3.f * width / 8.f), |
|
oshima
2017/01/05 23:29:04
can you define a constant for this factor against
malaykeshav
2017/01/09 18:59:40
Done
|
| + max_outer_radius_(width / 2), |
| + center_(gfx::Point(width / 2, width / 2)) { |
| + SetSize(gfx::Size(width, width)); |
| + |
| + inner_circle_paint_.setColor(inner_circle_color); |
| + inner_circle_paint_.setStyle(SkPaint::kFill_Style); |
| + inner_circle_paint_.setFlags(SkPaint::kAntiAlias_Flag); |
| + |
| + outer_circle_paint_.setColor(outer_circle_color); |
| + outer_circle_paint_.setStyle(SkPaint::kFill_Style); |
| + outer_circle_paint_.setFlags(SkPaint::kAntiAlias_Flag); |
| + |
| + animation_.reset(new gfx::ThrobAnimation(this)); |
| + animation_->SetThrobDuration(animation_duration); |
| + animation_->StartThrobbing(-1); |
| + |
| + SchedulePaint(); |
| +} |
| + |
| +CircularThrobberView::~CircularThrobberView() {} |
| + |
| +void CircularThrobberView::OnPaint(gfx::Canvas* canvas) { |
| + canvas->DrawCircle(center_, outer_radius_, outer_circle_paint_); |
| + canvas->DrawCircle(center_, inner_radius_, inner_circle_paint_); |
| +} |
| + |
| +void CircularThrobberView::AnimationProgressed( |
| + const gfx::Animation* animation) { |
| + if (animation != animation_.get()) |
| + return; |
| + outer_radius_ = |
| + animation->CurrentValueBetween(min_outer_radius_, max_outer_radius_); |
| + SchedulePaint(); |
| +} |
| + |
| +// Circular _________________________________ |
| +// Throbber | | |
| +// View | | |
| +// ___________ | | |
| +// | | | | |
| +// | | | | |
| +// | . | | Hint Box | |
| +// | | | | |
| +// |___________| | | |
| +// | | |
| +// | | |
| +// |_________________________________| |
| +// |
| +// This view is set next to the throbber circle view such that their centers |
| +// align. The hint box has a label text and a sublabel text to assist the |
| +// user by informing them about the next step in the calibration process. |
| +class HintBox : public views::View { |
| + public: |
| + explicit HintBox(const gfx::Rect& bounds, int border_radius); |
|
oshima
2017/01/05 23:29:04
no explicit
malaykeshav
2017/01/09 18:59:40
Done
|
| + ~HintBox() override; |
| + |
| + // views::View overrides: |
| + void OnPaint(gfx::Canvas* canvas) override; |
| + |
| + void SetLabel(const base::string16& text, const SkColor& color); |
| + void SetSubLabel(const base::string16& text, const SkColor& color); |
| + |
| + private: |
| + base::string16 label_text_; |
| + base::string16 sublabel_text_; |
| + |
| + SkColor label_color_; |
| + SkColor sublabel_color_; |
| + |
| + const int border_radius_; |
| + |
| + gfx::FontList label_font_list_; |
| + gfx::FontList sublabel_font_list_; |
| + |
| + gfx::Rect label_text_bounds_; |
| + gfx::Rect sublabel_text_bounds_; |
| + |
| + SkPaint paint_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(HintBox); |
| +}; |
| + |
| +HintBox::HintBox(const gfx::Rect& bounds, int border_radius) |
| + : border_radius_(border_radius) { |
| + SetBoundsRect(bounds); |
| + |
| + paint_.setColor(SK_ColorWHITE); |
| + paint_.setStyle(SkPaint::kFill_Style); |
| + paint_.setFlags(SkPaint::kAntiAlias_Flag); |
| + |
| + int left_offset = width() * 0.08f; |
|
stevenjb
2016/12/28 01:04:50
Does this work as expected with RTL?
malaykeshav
2017/01/09 18:59:40
The updated code works with RTL.
https://screensho
|
| + int top_offset = left_offset; |
| + int line_gap = height() * 0.015f; |
| + |
| + label_text_bounds_.SetRect(left_offset, top_offset, width() - 4 * left_offset, |
| + height() * 0.11f); |
|
oshima
2017/01/05 23:29:04
Can you use Inset()?
malaykeshav
2017/01/09 18:59:40
Done.
oshima
2017/01/09 19:44:16
My apologies, I misread the code. SetRect looks ok
malaykeshav
2017/01/09 22:29:57
Done.
|
| + |
| + top_offset += label_text_bounds_.height() + line_gap; |
| + |
| + sublabel_text_bounds_.SetRect(left_offset, top_offset, |
| + width() - 2 * left_offset, height() * 0.12f); |
| +} |
| + |
| +HintBox::~HintBox() {} |
| + |
| +void HintBox::SetLabel(const base::string16& text, const SkColor& color) { |
| + label_text_ = text; |
| + label_color_ = color; |
| + |
| + int font_size = GetFontSizeForRect(label_text_bounds_, label_text_); |
| + |
| + label_font_list_ = |
| + ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( |
| + font_size, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL); |
| +} |
| + |
| +void HintBox::SetSubLabel(const base::string16& text, const SkColor& color) { |
| + sublabel_text_ = text; |
| + sublabel_color_ = color; |
| + |
| + int font_size = GetFontSizeForRect(sublabel_text_bounds_, sublabel_text_); |
| + |
| + sublabel_font_list_ = |
| + ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( |
| + font_size, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL); |
| +} |
| + |
| +void HintBox::OnPaint(gfx::Canvas* canvas) { |
| + canvas->DrawRoundRect(GetLocalBounds(), border_radius_, paint_); |
| + canvas->DrawStringRectWithFlags(label_text_, label_font_list_, label_color_, |
| + label_text_bounds_, gfx::Canvas::NO_ELLIPSIS); |
| + canvas->DrawStringRectWithFlags(sublabel_text_, sublabel_font_list_, |
| + sublabel_color_, sublabel_text_bounds_, |
| + gfx::Canvas::NO_ELLIPSIS); |
| +} |
| + |
| TouchCalibratorView::TouchCalibratorView(const display::Display& target_display, |
| bool is_primary_view) |
| : display_(target_display), |
| + touch_point_offset_(display_.bounds().width() / 12), |
| is_primary_view_(is_primary_view), |
| - exit_label_(nullptr) { |
| + exit_label_(nullptr), |
| + throbber_circle_(nullptr), |
| + hint_box_view_(nullptr), |
| + touch_point_view_(nullptr) { |
| aura::Window* root = ash::Shell::GetInstance() |
| ->window_tree_host_manager() |
| ->GetRootWindowForDisplayId(display_.id()); |
| @@ -100,6 +315,54 @@ void TouchCalibratorView::InitViewContents() { |
| exit_label_->SetVisible(false); |
| AddChildView(exit_label_); |
| + |
| + // If this is not the screen that is being calibrated, then this is all we |
| + // need to display. |
| + if (!is_primary_view_) |
| + return; |
| + |
| + // Initialize the touch point view that contains the animated circle that the |
| + // user needs to tap. |
| + const float kThrobberCircleViewWidth = display_.bounds().width() / 10.f; |
| + const int touch_point_offset_ = display_.bounds().width() / 12; |
| + const float kTapLabelHeight = kThrobberCircleViewWidth * 3.f / 8.f; |
| + const int kTouchPointViewHeight = kThrobberCircleViewWidth + kTapLabelHeight; |
| + |
| + throbber_circle_ = |
| + new CircularThrobberView(kThrobberCircleViewWidth, kInnerCircleColor, |
| + kOuterCircleColor, kCircleAnimationDurationMs); |
| + throbber_circle_->SetPosition(gfx::Point(0, 0)); |
| + |
| + touch_point_view_ = new views::View; |
| + touch_point_view_->SetBounds(touch_point_offset_, touch_point_offset_, |
| + kThrobberCircleViewWidth, kTouchPointViewHeight); |
| + touch_point_view_->SetVisible(false); |
| + |
| + touch_point_view_->AddChildView(throbber_circle_); |
| + |
| + AddChildView(touch_point_view_); |
| + |
| + // Initialize the Hint Box view. |
| + base::string16 hint_label_text = |
| + rb.GetLocalizedString(IDS_DISPLAY_TOUCH_CALIBRATION_HINT_LABEL_TEXT); |
| + base::string16 hint_sublabel_text = |
| + rb.GetLocalizedString(IDS_DISPLAY_TOUCH_CALIBRATION_HINT_SUBLABEL_TEXT); |
| + |
| + int tpv_width = touch_point_view_->width(); |
| + |
| + gfx::Size size(tpv_width * 2.95f, tpv_width * 1.75f); |
| + |
| + gfx::Point position( |
| + touch_point_view_->x() + tpv_width * 1.2f, |
| + touch_point_view_->y() + (tpv_width / 2.f) - (size.height() / 2.f)); |
| + |
| + hint_box_view_ = |
| + new HintBox(gfx::Rect(position, size), kHintRectBorderRadius); |
| + hint_box_view_->SetVisible(false); |
| + hint_box_view_->SetLabel(hint_label_text, kHintLabelTextColor); |
| + hint_box_view_->SetSubLabel(hint_sublabel_text, kHintSublabelTextColor); |
| + |
| + AddChildView(hint_box_view_); |
| } |
| void TouchCalibratorView::OnPaint(gfx::Canvas* canvas) { |
| @@ -137,6 +400,10 @@ void TouchCalibratorView::AnimationEnded(const gfx::Animation* animation) { |
| case BACKGROUND_FADING_IN: |
| exit_label_->SetVisible(true); |
| state_ = is_primary_view_ ? DISPLAY_POINT_1 : CALIBRATION_COMPLETE; |
| + if (is_primary_view_) { |
| + touch_point_view_->SetVisible(true); |
| + hint_box_view_->SetVisible(true); |
| + } |
| break; |
| default: |
| break; |