123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/hud_display/reference_lines.h"
- #include "ash/hud_display/hud_constants.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "cc/paint/paint_flags.h"
- #include "third_party/skia/include/core/SkBlendMode.h"
- #include "third_party/skia/include/core/SkPaint.h"
- #include "third_party/skia/include/core/SkPath.h"
- #include "third_party/skia/include/effects/SkDashPathEffect.h"
- #include "ui/base/metadata/metadata_impl_macros.h"
- #include "ui/gfx/canvas.h"
- #include "ui/gfx/text_constants.h"
- namespace ash {
- namespace hud_display {
- namespace {
- constexpr SkColor kHUDGraphReferenceLineColor = SkColorSetRGB(162, 162, 220);
- std::u16string GenerateLabelText(float value, const std::u16string& dimention) {
- if (value == (int)value) {
- return base::ASCIIToUTF16(base::StringPrintf("%d ", (int)value).c_str()) +
- dimention;
- } else {
- return base::ASCIIToUTF16(base::StringPrintf("%.2f ", value).c_str()) +
- dimention;
- }
- }
- } // anonymous namespace
- BEGIN_METADATA(ReferenceLines, views::View)
- END_METADATA
- ReferenceLines::ReferenceLines(float left,
- float top,
- float right,
- float bottom,
- const std::u16string& x_unit,
- const std::u16string& y_unit,
- int horizontal_points_number,
- int horizontal_ticks_interval,
- float vertical_ticks_interval)
- : color_(kHUDGraphReferenceLineColor),
- left_(left),
- top_(top),
- right_(right),
- bottom_(bottom),
- x_unit_(x_unit),
- y_unit_(y_unit),
- horizontal_points_number_(horizontal_points_number),
- horizontal_ticks_interval_(horizontal_ticks_interval),
- vertical_ticks_interval_(vertical_ticks_interval) {
- // Text is set later.
- right_top_label_ = AddChildView(std::make_unique<views::Label>(
- std::u16string(), views::style::CONTEXT_LABEL));
- right_middle_label_ = AddChildView(std::make_unique<views::Label>(
- std::u16string(), views::style::CONTEXT_LABEL));
- right_bottom_label_ = AddChildView(std::make_unique<views::Label>(
- std::u16string(), views::style::CONTEXT_LABEL));
- left_bottom_label_ = AddChildView(std::make_unique<views::Label>(
- std::u16string(), views::style::CONTEXT_LABEL));
- // Set label text.
- SetTopLabel(top_);
- SetBottomLabel(bottom_);
- SetLeftLabel(left_);
- right_top_label_->SetEnabledColor(color_);
- right_top_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- right_middle_label_->SetEnabledColor(color_);
- right_middle_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- right_bottom_label_->SetEnabledColor(color_);
- right_bottom_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- left_bottom_label_->SetEnabledColor(color_);
- left_bottom_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- }
- ReferenceLines::~ReferenceLines() = default;
- void ReferenceLines::Layout() {
- // Align all the right labels on their left edge.
- gfx::Size right_top_label_size = right_top_label_->GetPreferredSize();
- gfx::Size right_middle_label_size = right_middle_label_->GetPreferredSize();
- gfx::Size right_bottom_label_size = right_bottom_label_->GetPreferredSize();
- const int right_labels_width = std::max(
- right_top_label_size.width(), std::max(right_middle_label_size.width(),
- right_bottom_label_size.width()));
- right_top_label_size.set_width(right_labels_width);
- right_middle_label_size.set_width(right_labels_width);
- right_bottom_label_size.set_width(right_labels_width);
- right_top_label_->SetSize(right_top_label_size);
- right_middle_label_->SetSize(right_middle_label_size);
- right_bottom_label_->SetSize(right_bottom_label_size);
- left_bottom_label_->SetSize(left_bottom_label_->GetPreferredSize());
- constexpr int label_border = 3; // Offset to labels from the reference lines.
- const gfx::Point right_top_label_position(
- bounds().width() - right_top_label_size.width() - label_border,
- label_border);
- const gfx::Point right_middle_label_position(
- bounds().width() - right_middle_label_size.width() - label_border,
- bounds().height() / 2 - right_middle_label_size.height() - label_border);
- const gfx::Point right_bottom_label_position(
- bounds().width() - right_bottom_label_size.width() - label_border,
- bounds().height() - right_bottom_label_size.height() - label_border);
- right_top_label_->SetPosition(right_top_label_position);
- right_middle_label_->SetPosition(right_middle_label_position);
- right_bottom_label_->SetPosition(right_bottom_label_position);
- left_bottom_label_->SetPosition(
- {label_border, bounds().height() -
- left_bottom_label_->GetPreferredSize().height() -
- label_border});
- views::View::Layout();
- }
- void ReferenceLines::OnPaint(gfx::Canvas* canvas) {
- SkPath dotted_path;
- SkPath solid_path;
- // Draw dashed line at 50%.
- dotted_path.moveTo({0, bounds().height() / 2.0f});
- dotted_path.lineTo(
- {static_cast<SkScalar>(bounds().width()), bounds().height() / 2.0f});
- // Draw border and ticks.
- solid_path.addRect(SkRect::MakeXYWH(bounds().x(), bounds().y(),
- bounds().width(), bounds().height()));
- const SkScalar tick_length = 3;
- // Vertical interval ticks (drawn horizontally).
- if (vertical_ticks_interval_ > 0) {
- float tick_bottom_offset = vertical_ticks_interval_;
- while (tick_bottom_offset <= 1) {
- // Skip 50%.
- if (fabs(tick_bottom_offset - .5) > 0.01) {
- const SkScalar line_y = (1 - tick_bottom_offset) * bounds().height();
- solid_path.moveTo({0, line_y});
- solid_path.lineTo({tick_length, line_y});
- solid_path.moveTo({bounds().width() - tick_length, line_y});
- solid_path.lineTo({static_cast<SkScalar>(bounds().width()), line_y});
- }
- tick_bottom_offset += vertical_ticks_interval_;
- }
- }
- // Horizontal interval ticks (drawn vertically).
- if (horizontal_points_number_ > 0 && horizontal_ticks_interval_ > 0) {
- // Add one more tick if graph width is not a multiple of tick width.
- const int h_ticks =
- horizontal_points_number_ / horizontal_ticks_interval_ +
- (horizontal_points_number_ % horizontal_ticks_interval_ ? 1 : 0);
- // Interval between ticks in pixels.
- const SkScalar tick_per_pixels = bounds().width() /
- (float)horizontal_points_number_ *
- horizontal_ticks_interval_;
- for (int i = 1; i < h_ticks; ++i) {
- const SkScalar line_x = bounds().width() - tick_per_pixels * i;
- solid_path.moveTo({line_x, 0});
- solid_path.lineTo({line_x, tick_length});
- solid_path.moveTo({line_x, bounds().height() - tick_length});
- solid_path.lineTo({line_x, static_cast<SkScalar>(bounds().height())});
- }
- }
- cc::PaintFlags flags;
- flags.setAntiAlias(true);
- flags.setBlendMode(SkBlendMode::kSrc);
- flags.setStyle(cc::PaintFlags::kStroke_Style);
- flags.setStrokeWidth(kHUDGraphReferenceLineWidth);
- flags.setColor(color_);
- canvas->DrawPath(solid_path, flags);
- const SkScalar intervals[] = {5, 3};
- flags.setPathEffect(SkDashPathEffect::Make(
- intervals, sizeof(intervals) / sizeof(intervals[0]), /*phase=*/0));
- canvas->DrawPath(dotted_path, flags);
- }
- void ReferenceLines::SetTopLabel(float top) {
- top_ = top;
- right_top_label_->SetText(GenerateLabelText(top_, y_unit_));
- right_middle_label_->SetText(
- GenerateLabelText((top_ - bottom_) / 2, y_unit_));
- // This might trigger label resize.
- InvalidateLayout();
- }
- void ReferenceLines::SetBottomLabel(float bottom) {
- bottom_ = bottom;
- right_bottom_label_->SetText(GenerateLabelText(bottom_, y_unit_));
- right_middle_label_->SetText(
- GenerateLabelText((top_ - bottom_) / 2, y_unit_));
- // This might trigger label resize.
- InvalidateLayout();
- }
- void ReferenceLines::SetLeftLabel(float left) {
- left_ = left;
- left_bottom_label_->SetText(GenerateLabelText(left_, x_unit_));
- // This might trigger label resize.
- InvalidateLayout();
- }
- void ReferenceLines::SetVerticalTicksInterval(float interval) {
- interval == std::abs(interval) >= 1 ? 0 : std::abs(interval);
- if (interval == vertical_ticks_interval_)
- return;
- vertical_ticks_interval_ = interval;
- }
- } // namespace hud_display
- } // namespace ash
|