// 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/graph_page_view_base.h" #include "ash/hud_display/hud_constants.h" #include "ash/hud_display/hud_properties.h" #include "ash/hud_display/legend.h" #include "ash/hud_display/reference_lines.h" #include "ash/hud_display/solid_source_background.h" #include "base/bind.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/canvas.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/border.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/window/vector_icons/vector_icons.h" namespace ash { namespace hud_display { namespace { constexpr int kMinMaxButtonIconSize = 10; constexpr int kMinMaxButtonBorder = 5; // ImageButton with underline class MinMaxButton : public views::ImageButton { public: METADATA_HEADER(MinMaxButton); explicit MinMaxButton(views::Button::PressedCallback callback) : views::ImageButton(callback) { SetBorder(views::CreateEmptyBorder(kMinMaxButtonBorder)); SetBackground(std::make_unique(kHUDLegendBackground, /*radius=*/0)); SetProperty(kHUDClickHandler, HTCLIENT); SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY); } MinMaxButton(const MinMaxButton&) = delete; MinMaxButton& operator=(const MinMaxButton&) = delete; ~MinMaxButton() override = default; protected: // ImageButton void PaintButtonContents(gfx::Canvas* canvas) override { views::ImageButton::PaintButtonContents(canvas); SkPath path; path.moveTo(0, height()); path.lineTo(height(), width()); cc::PaintFlags flags; flags.setAntiAlias(true); flags.setBlendMode(SkBlendMode::kSrc); flags.setStyle(cc::PaintFlags::kStroke_Style); flags.setStrokeWidth(1); flags.setColor(kHUDDefaultColor); canvas->DrawPath(path, flags); } }; BEGIN_METADATA(MinMaxButton, views::ImageButton) END_METADATA void SetMinimizeIconToButton(views::ImageButton* button) { button->SetImage( views::Button::ButtonState::STATE_NORMAL, gfx::CreateVectorIcon(views::kWindowControlMinimizeIcon, kMinMaxButtonIconSize, kHUDDefaultColor)); } void SetRestoreIconToButton(views::ImageButton* button) { button->SetImage( views::Button::ButtonState::STATE_NORMAL, gfx::CreateVectorIcon(views::kWindowControlRestoreIcon, kMinMaxButtonIconSize, kHUDDefaultColor)); } } // namespace BEGIN_METADATA(GraphPageViewBase, views::View) END_METADATA GraphPageViewBase::GraphPageViewBase() { DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_); // There are two overlaid children: reference lines and legend container. SetLayoutManager(std::make_unique()); // |ReferenceLines| object is added after this object is fully initialized, // but it should be located under control elements (or they will never receive // events). This way we need to create a separate container for it. reference_lines_container_ = AddChildView(std::make_unique()); reference_lines_container_->SetLayoutManager( std::make_unique()); // Legend is floating in its own container. Invisible border of // kLegendPositionOffset makes it float on top of the graph. constexpr int kLegendPositionOffset = 20; legend_container_ = AddChildView(std::make_unique()); legend_container_ ->SetLayoutManager(std::make_unique( views::BoxLayout::Orientation::kVertical)) ->set_cross_axis_alignment(views::BoxLayout::CrossAxisAlignment::kStart); legend_container_->SetBorder(views::CreateEmptyBorder(kLegendPositionOffset)); legend_container_->SetVisible(false); legend_min_max_button_ = legend_container_->AddChildView( std::make_unique(base::BindRepeating( &GraphPageViewBase::OnButtonPressed, base::Unretained(this)))); legend_min_max_button_->SetTooltipText(u"Trigger graph legend"); SetMinimizeIconToButton(legend_min_max_button_); } GraphPageViewBase::~GraphPageViewBase() { DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_); } void GraphPageViewBase::OnButtonPressed() { if (legend_->GetVisible()) { legend_->SetVisible(false); SetRestoreIconToButton(legend_min_max_button_); } else { legend_->SetVisible(true); SetMinimizeIconToButton(legend_min_max_button_); } } void GraphPageViewBase::CreateLegend( const std::vector& entries) { DCHECK(!legend_); legend_ = legend_container_->AddChildView(std::make_unique(entries)); legend_container_->SetVisible(true); } ReferenceLines* GraphPageViewBase::CreateReferenceLines( 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) { DCHECK(reference_lines_container_->children().empty()); return reference_lines_container_->AddChildView( std::make_unique( left, top, right, bottom, x_unit, y_unit, horizontal_points_number, horizontal_ticks_interval, vertical_ticks_interval)); } void GraphPageViewBase::RefreshLegendValues() { if (legend_) legend_->RefreshValues(); } } // namespace hud_display } // namespace ash