Commit 1e0e2ff5 authored by Alexander Alekseev's avatar Alexander Alekseev Committed by Commit Bot

[Ash HUD] Make debug HUD more touch-friendly and add tabbed interface.

This Cl permanently exposes HUD controls and adds tabbed controls as a
preparation to adding more data.

Tabbed UI:

https://screenshot.googleplex.com/uQSuqEps8s8.png - First tab active.
https://screenshot.googleplex.com/YdMcrG74OiP.png - Second tab active.
https://screenshot.googleplex.com/7t5ZSVU2fWB.png - Third tab active.
https://screenshot.googleplex.com/MtoB750fA4C.png - Settings UI.

Bug: 1075612
Change-Id: Ic5101f302b071e060ab54de6f8fb6b510e0250ff
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2348337
Commit-Queue: Alexander Alekseev <alemate@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797733}
parent d5a7ba9d
...@@ -469,12 +469,16 @@ component("ash") { ...@@ -469,12 +469,16 @@ component("ash") {
"hud_display/hud_constants.h", "hud_display/hud_constants.h",
"hud_display/hud_display.cc", "hud_display/hud_display.cc",
"hud_display/hud_display.h", "hud_display/hud_display.h",
"hud_display/hud_header_view.cc",
"hud_display/hud_header_view.h",
"hud_display/hud_properties.cc", "hud_display/hud_properties.cc",
"hud_display/hud_properties.h", "hud_display/hud_properties.h",
"hud_display/hud_settings_view.cc", "hud_display/hud_settings_view.cc",
"hud_display/hud_settings_view.h", "hud_display/hud_settings_view.h",
"hud_display/memory_status.cc", "hud_display/memory_status.cc",
"hud_display/memory_status.h", "hud_display/memory_status.h",
"hud_display/tab_strip.cc",
"hud_display/tab_strip.h",
"ime/ime_controller_impl.cc", "ime/ime_controller_impl.cc",
"ime/ime_controller_impl.h", "ime/ime_controller_impl.h",
"ime/ime_mode_indicator_view.cc", "ime/ime_mode_indicator_view.cc",
......
...@@ -12,6 +12,33 @@ namespace hud_display { ...@@ -12,6 +12,33 @@ namespace hud_display {
constexpr SkAlpha kHUDAlpha = 204; // = 0.8 * 255 constexpr SkAlpha kHUDAlpha = 204; // = 0.8 * 255
// Use light orange color.
constexpr SkColor kHUDDefaultColor =
SkColorSetARGB(kHUDAlpha, 0xFF, 0xB2, 0x66);
constexpr SkColor kHUDBackground = SkColorSetARGB(kHUDAlpha, 17, 17, 17);
// Radius of rounded corners for tabs.
// Must be be divisible by 3 to make kTabOverlayWidth integer.
constexpr int kTabOverlayCornerRadius = 9;
// Border around settings icon in the settings button.
constexpr int kSettingsIconBorder = 5;
// Settings button icon size.
constexpr int kHUDSettingsIconSize = 18;
// Visible border inside the HUDDisplayView rectangle around contents.
// HUDDisplayView does not use insets itself. Children substitute this inset
// where needed.
constexpr int kHUDInset = 5;
// HUD display modes.
enum class DisplayModes {
MEMORY_DISPLAY,
DEFAULT = MEMORY_DISPLAY
};
} // namespace hud_display } // namespace hud_display
} // namespace ash } // namespace ash
......
This diff is collapsed.
...@@ -5,19 +5,18 @@ ...@@ -5,19 +5,18 @@
#ifndef ASH_HUD_DISPLAY_HUD_DISPLAY_H_ #ifndef ASH_HUD_DISPLAY_HUD_DISPLAY_H_
#define ASH_HUD_DISPLAY_HUD_DISPLAY_H_ #define ASH_HUD_DISPLAY_HUD_DISPLAY_H_
#include "ash/hud_display/hud_constants.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_delegate.h"
namespace views {
class ImageButton;
}
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
class GraphsContainerView; class GraphsContainerView;
class HUDHeaderView;
class HUDSettingsView; class HUDSettingsView;
class HUDTabButton;
// HUDDisplayView class can be used to display a system monitoring overview. // HUDDisplayView class can be used to display a system monitoring overview.
class HUDDisplayView : public views::WidgetDelegateView, class HUDDisplayView : public views::WidgetDelegateView,
...@@ -25,21 +24,11 @@ class HUDDisplayView : public views::WidgetDelegateView, ...@@ -25,21 +24,11 @@ class HUDDisplayView : public views::WidgetDelegateView,
public: public:
METADATA_HEADER(HUDDisplayView); METADATA_HEADER(HUDDisplayView);
// Default HUDDisplayView height.
static constexpr size_t kDefaultHUDHeight = 300;
// Border width inside the HUDDisplayView rectangle around contents.
static constexpr size_t kHUDInset = 5;
HUDDisplayView(); HUDDisplayView();
~HUDDisplayView() override;
HUDDisplayView(const HUDDisplayView&) = delete; HUDDisplayView(const HUDDisplayView&) = delete;
HUDDisplayView& operator=(const HUDDisplayView&) = delete; HUDDisplayView& operator=(const HUDDisplayView&) = delete;
// view:: ~HUDDisplayView() override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
// WidgetDelegate: // WidgetDelegate:
views::ClientView* CreateClientView(views::Widget* widget) override; views::ClientView* CreateClientView(views::Widget* widget) override;
...@@ -58,10 +47,13 @@ class HUDDisplayView : public views::WidgetDelegateView, ...@@ -58,10 +47,13 @@ class HUDDisplayView : public views::WidgetDelegateView,
// of the children. // of the children.
int NonClientHitTest(const gfx::Point& point); int NonClientHitTest(const gfx::Point& point);
// Changes UI display mode.
void TabButtonPressed(const HUDTabButton* tab_button);
private: private:
GraphsContainerView* graphs_container_ = nullptr; // not owned HUDHeaderView* header_view_ = nullptr; // not owned
HUDSettingsView* settings_view_ = nullptr; // not owned GraphsContainerView* graphs_container_ = nullptr; // not owned
views::ImageButton* settings_trigger_button_ = nullptr; // not owned HUDSettingsView* settings_view_ = nullptr; // not owned
SEQUENCE_CHECKER(ui_sequence_checker_); SEQUENCE_CHECKER(ui_sequence_checker_);
}; };
......
// 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/hud_header_view.h"
#include "ash/hud_display/hud_constants.h"
#include "ash/hud_display/hud_display.h"
#include "ash/hud_display/hud_properties.h"
#include "ash/hud_display/tab_strip.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/skia_util.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_manager.h"
namespace ash {
namespace hud_display {
namespace {
// Basically views::SolidBackground with SkBlendMode::kSrc paint mode.
class SolidSourceBackground : public views::Background {
public:
// Background will have top rounded corners with |top_rounding_radius|.
SolidSourceBackground(SkColor color, SkScalar top_rounding_radius)
: top_rounding_radius_(top_rounding_radius) {
SetNativeControlColor(color);
}
SolidSourceBackground(const SolidSourceBackground&) = delete;
SolidSourceBackground& operator=(const SolidSourceBackground&) = delete;
~SolidSourceBackground() override = default;
// views::Background
void Paint(gfx::Canvas* canvas, views::View* view) const override {
if (top_rounding_radius_ == 0) {
// Fill the background. Note that we don't constrain to the bounds as
// canvas is already clipped for us.
canvas->DrawColor(get_color(), SkBlendMode::kSrc);
} else {
const SkScalar circle_size = top_rounding_radius_ * 2;
const int right_edge = view->width();
const int bottom_edge = view->height();
SkPath path;
path.moveTo(0, bottom_edge);
/* |false| will draw straight line to the start of the arc */
path.arcTo({0, 0, circle_size, circle_size}, -180, 90, false);
path.arcTo({right_edge - circle_size, 0, right_edge, circle_size}, -90,
90, false);
path.lineTo(right_edge, bottom_edge);
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setBlendMode(SkBlendMode::kSrc);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(get_color());
canvas->DrawPath(path, flags);
}
}
private:
SkScalar top_rounding_radius_;
};
// Draws bottom left rounded background triangle.
class BottomLeftOuterBackground : public views::Background {
public:
// Background will have left bottom rounded corner with |top_rounding_radius|.
BottomLeftOuterBackground(SkColor color, SkScalar top_rounding_radius)
: inner_radius_(top_rounding_radius) {
SetNativeControlColor(color);
}
BottomLeftOuterBackground(const BottomLeftOuterBackground&) = delete;
BottomLeftOuterBackground& operator=(const BottomLeftOuterBackground&) =
delete;
~BottomLeftOuterBackground() override = default;
// views::Background
void Paint(gfx::Canvas* canvas, views::View* view) const override {
const SkScalar circle_size = inner_radius_ * 2;
const int bottom_edge = view->height();
SkPath path;
path.moveTo(0, bottom_edge);
/* |false| will draw straight line to the start of the arc */
path.arcTo({0, bottom_edge - circle_size, circle_size, bottom_edge}, 90, 90,
false);
path.lineTo(0, bottom_edge);
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setBlendMode(SkBlendMode::kSrc);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(get_color());
canvas->DrawPath(path, flags);
}
private:
SkScalar inner_radius_;
};
// ImageButton with underline
class SettingsButton : public views::ImageButton {
public:
METADATA_HEADER(SettingsButton);
explicit SettingsButton(views::ButtonListener* listener)
: views::ImageButton(listener) {
SetImage(views::Button::ButtonState::STATE_NORMAL,
gfx::CreateVectorIcon(vector_icons::kSettingsIcon,
kHUDSettingsIconSize, kHUDDefaultColor));
SetBorder(views::CreateEmptyBorder(gfx::Insets(kSettingsIconBorder)));
SetProperty(kHUDClickHandler, HTCLIENT);
}
SettingsButton(const SettingsButton&) = delete;
SettingsButton& operator=(const SettingsButton&) = delete;
~SettingsButton() 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(SettingsButton)
METADATA_PARENT_CLASS(ImageButton)
END_METADATA()
// Basically FillLayout that matches host size to the given data view.
// Padding will take the rest of the host view to the right.
class HUDHeaderLayout : public views::LayoutManager {
public:
HUDHeaderLayout(const views::View* data_view, views::View* padding)
: data_view_(data_view), padding_(padding) {}
HUDHeaderLayout(const HUDHeaderLayout&) = delete;
HUDHeaderLayout& operator=(const HUDHeaderLayout&) = delete;
~HUDHeaderLayout() override = default;
// views::LayoutManager:
void Layout(views::View* host) override;
gfx::Size GetPreferredSize(const views::View* host) const override;
private:
const views::View* data_view_;
views::View* padding_;
};
gfx::Size HUDHeaderLayout::GetPreferredSize(const views::View* host) const {
return data_view_->GetPreferredSize() + padding_->GetPreferredSize();
}
void HUDHeaderLayout::Layout(views::View* host) {
// Assume there are only 3 child views (data, background and padding).
DCHECK_EQ(host->children().size(), 3U);
const gfx::Size preferred_size = data_view_->GetPreferredSize();
for (auto* child : host->children()) {
if (child != padding_) {
child->SetPosition({0, 0});
child->SetSize(preferred_size);
}
}
// Layout padding
padding_->SetPosition({preferred_size.width(), 0});
padding_->SetSize({host->width() - preferred_size.width(), host->height()});
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// HUDHeaderView
BEGIN_METADATA(HUDHeaderView)
METADATA_PARENT_CLASS(View)
END_METADATA()
HUDHeaderView::HUDHeaderView(HUDDisplayView* hud) {
// Header is rendered as horizontal container with three children:
// background, buttons container and padding.
// Header should have background under the buttons area only.
// To achieve this we have buttons container view to calculate total width,
// and special layout manager that matches size of the background view to the
// size of the buttons.
//
// There is additional "padding" view an the end to draw bottom inner
// rounded piece of background.
views::View* header_background =
AddChildView(std::make_unique<views::View>());
header_background->SetBackground(std::make_unique<SolidSourceBackground>(
kHUDBackground, kTabOverlayCornerRadius));
views::View* header_buttons = AddChildView(std::make_unique<views::View>());
header_buttons
->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal))
->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStretch);
// Header does not have margin between header and data.
// Data has its top margin (kHUDGraphsInset).
header_buttons->SetBorder(views::CreateEmptyBorder(
gfx::Insets(kHUDInset, kHUDInset, 0, kHUDInset)));
// Add buttons and tab strip.
header_buttons->AddChildView(std::make_unique<SettingsButton>(hud));
tab_strip_ = header_buttons->AddChildView(std::make_unique<HUDTabStrip>(hud));
// Padding will take the rest of the header and draw bottom inner left
// background padding.
views::View* padding = AddChildView(std::make_unique<views::View>());
padding->SetBackground(std::make_unique<BottomLeftOuterBackground>(
kHUDBackground, kTabOverlayCornerRadius));
SetLayoutManager(std::make_unique<HUDHeaderLayout>(header_buttons, padding));
}
HUDHeaderView::~HUDHeaderView() = default;
} // namespace hud_display
} // namespace ash
// 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.
#ifndef ASH_HUD_DISPLAY_HUD_HEADER_VIEW_H_
#define ASH_HUD_DISPLAY_HUD_HEADER_VIEW_H_
#include "ui/views/view.h"
namespace ash {
namespace hud_display {
class HUDDisplayView;
class HUDTabStrip;
// HUDHeaderView renders header (with buttons and tabs) of the HUD.
class HUDHeaderView : public views::View {
public:
METADATA_HEADER(HUDHeaderView);
explicit HUDHeaderView(HUDDisplayView* hud);
HUDHeaderView(const HUDHeaderView&) = delete;
HUDHeaderView& operator=(const HUDHeaderView&) = delete;
~HUDHeaderView() override;
HUDTabStrip* tab_strip() { return tab_strip_; }
private:
HUDTabStrip* tab_strip_ = nullptr; // not owned
};
} // namespace hud_display
} // namespace ash
#endif // ASH_HUD_DISPLAY_HUD_HEADER_VIEW_H_
...@@ -79,26 +79,23 @@ BEGIN_METADATA(HUDSettingsView) ...@@ -79,26 +79,23 @@ BEGIN_METADATA(HUDSettingsView)
METADATA_PARENT_CLASS(View) METADATA_PARENT_CLASS(View)
END_METADATA() END_METADATA()
constexpr SkColor HUDSettingsView::kDefaultColor;
HUDSettingsView::HUDSettingsView() { HUDSettingsView::HUDSettingsView() {
SetVisible(false); SetVisible(false);
auto layout_manager = std::make_unique<views::BoxLayout>( views::BoxLayout* layout_manager =
views::BoxLayout::Orientation::kVertical); SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
layout_manager->set_cross_axis_alignment( layout_manager->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStart); views::BoxLayout::CrossAxisAlignment::kStart);
SetLayoutManager(std::move(layout_manager)); SetBorder(views::CreateSolidBorder(1, kHUDDefaultColor));
SetBorder(views::CreateSolidBorder(1, kDefaultColor));
auto add_checkbox = [](HUDSettingsView* self, auto add_checkbox = [](HUDSettingsView* self,
const base::string16& text) -> views::Checkbox* { const base::string16& text) -> views::Checkbox* {
auto checkbox = std::make_unique<views::Checkbox>(text, self); views::Checkbox* checkbox =
views::Checkbox* result = checkbox.get(); self->AddChildView(std::make_unique<views::Checkbox>(text, self));
checkbox->SetEnabledTextColors(kDefaultColor); checkbox->SetEnabledTextColors(kHUDDefaultColor);
checkbox->SetProperty(kHUDClickHandler, HTCLIENT); checkbox->SetProperty(kHUDClickHandler, HTCLIENT);
self->AddChildView(std::move(checkbox)); return checkbox;
return result;
}; };
checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>( checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>(
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <vector> #include <vector>
#include "ash/hud_display/hud_constants.h" #include "ash/hud_display/hud_constants.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/view.h" #include "ui/views/view.h"
...@@ -22,10 +21,6 @@ class HUDSettingsView : public views::ButtonListener, public views::View { ...@@ -22,10 +21,6 @@ class HUDSettingsView : public views::ButtonListener, public views::View {
public: public:
METADATA_HEADER(HUDSettingsView); METADATA_HEADER(HUDSettingsView);
// Use light orange color.
static constexpr SkColor kDefaultColor =
SkColorSetARGB(kHUDAlpha, 0xFF, 0xB2, 0x66);
HUDSettingsView(); HUDSettingsView();
~HUDSettingsView() override; ~HUDSettingsView() override;
......
// 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/tab_strip.h"
#include <cmath>
#include "ash/hud_display/hud_display.h"
#include "ash/hud_display/hud_properties.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/layout/layout_manager.h"
namespace ash {
namespace hud_display {
namespace {
// The width in pixels of overlaying adjacent tabs. Must be even number.
constexpr int kTabOverlayWidth = 2 * kTabOverlayCornerRadius / 3;
// Border around tab text (tab overlay width will be added to this).
constexpr int kTabTitleBorder = 3;
class HUDTabStripLayout : public views::LayoutManager {
public:
HUDTabStripLayout() = default;
HUDTabStripLayout(const HUDTabStripLayout&) = delete;
HUDTabStripLayout& operator=(const HUDTabStripLayout&) = delete;
~HUDTabStripLayout() override = default;
// views::LayoutManager:
void Layout(views::View* host) override;
gfx::Size GetPreferredSize(const views::View* host) const override;
};
gfx::Size HUDTabStripLayout::GetPreferredSize(const views::View* host) const {
gfx::Size result;
for (const auto* child : host->children()) {
const gfx::Size child_preferred = child->GetPreferredSize();
// Tab strip is always horizontal.
result.set_width(result.width() + child_preferred.width() -
kTabOverlayWidth);
result.set_height(std::max(result.height(), child_preferred.height()));
}
// Assume all children have equal left and right border, which is used to
// overlay the tabs. Add one overlay width to compensate one edge.
if (host->children().size())
result.set_width(result.width() + kTabOverlayWidth);
// Add right padding equal to the padding of the settings icon.
result.set_width(result.width() + kSettingsIconBorder);
return result;
}
void HUDTabStripLayout::Layout(views::View* host) {
// Assume all children have equal left and right border, which is used to
// overlay the tabs.
int left_offset = 0;
for (auto* child : host->children()) {
const gfx::Size preferred = child->GetPreferredSize();
const gfx::Size child_size({preferred.width(), host->height()});
child->SetSize(child_size);
child->SetPosition({left_offset, 0});
left_offset += child_size.width() - kTabOverlayWidth;
}
}
} // namespace
BEGIN_METADATA(HUDTabButton)
METADATA_PARENT_CLASS(LabelButton)
END_METADATA()
HUDTabButton::HUDTabButton(Style style,
HUDTabStrip* tab_strip,
const DisplayModes display_mode,
const base::string16& text)
: views::LabelButton(tab_strip, text),
style_(style),
display_mode_(display_mode) {
SetHorizontalAlignment(gfx::ALIGN_CENTER);
SetEnabledTextColors(kHUDDefaultColor);
SetProperty(kHUDClickHandler, HTCLIENT);
SetBorder(views::CreateEmptyBorder(
kSettingsIconBorder, kTabOverlayWidth + kTabTitleBorder,
kSettingsIconBorder, kTabOverlayWidth + kTabTitleBorder));
}
void HUDTabButton::SetStyle(Style style) {
if (style_ == style)
return;
style_ = style;
SchedulePaint();
}
void HUDTabButton::PaintButtonContents(gfx::Canvas* canvas) {
// Horizontal offset from tab {0,0} where two tab arcs cross.
constexpr int kTabArcCrossedX = kTabOverlayWidth / 2;
// Reduce kTabArcCrossedX by one pixel when calculating partial arc so that
// the pixels along kTabArcCrossedX vertical line are drawn by full arc only.
static const float kTabPartialArcAngle =
90 - 180 *
asinf((kTabOverlayCornerRadius - kTabArcCrossedX + 1) /
(float)kTabOverlayCornerRadius) /
M_PI;
const int kCircleSize = kTabOverlayCornerRadius * 2;
const int right_edge = width();
const int bottom_edge = height();
SkPath path;
// Draw left vertical line and arc
if (style_ == Style::RIGHT) {
/* |true| - move to the start of the arc */
path.arcTo({0, 0, kCircleSize, kCircleSize}, -90 - kTabPartialArcAngle,
kTabPartialArcAngle, true);
} else {
if (style_ == Style::LEFT) {
// Draw bottom line from the right edge. Adjust for 2 pixels crossing the
// right vertical line.
path.moveTo(right_edge - kTabOverlayWidth / 2 - 2, bottom_edge);
path.lineTo(0, bottom_edge);
} else {
// No bottom line. Just move to the start of the vertical line.
path.moveTo(0, bottom_edge);
}
/* |false| will draw straight line to the start of the arc */
path.arcTo({0, 0, kCircleSize - 1, kCircleSize}, -180, 90, false);
}
// Draw top line, right arc and right vertical line
if (style_ == Style::LEFT) {
/* |false| will draw straight line to the start of the arc */
path.arcTo({right_edge - kCircleSize, 0, right_edge, kCircleSize}, -90,
kTabPartialArcAngle, false);
} else {
/* |false| will draw straight line to the start of the arc */
path.arcTo({right_edge - kCircleSize, 0, right_edge, kCircleSize}, -90, 90,
false);
path.lineTo(right_edge, bottom_edge);
if (style_ == Style::RIGHT) {
// Draw bottom line to the left edge. Adjust for 2 pixels crossing the
// left vertical line.
path.lineTo(kTabOverlayWidth / 2 + 2, bottom_edge);
}
}
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(HUDTabStrip)
METADATA_PARENT_CLASS(View)
END_METADATA()
HUDTabStrip::HUDTabStrip(HUDDisplayView* hud) : hud_(hud) {
SetLayoutManager(std::make_unique<HUDTabStripLayout>());
}
HUDTabStrip::~HUDTabStrip() = default;
HUDTabButton* HUDTabStrip::AddTabButton(HUDDisplayView* hud,
const DisplayModes display_mode,
const base::string16& label) {
// Make first tab active by default.
HUDTabButton* tab_button = AddChildView(std::make_unique<HUDTabButton>(
tabs_.size() ? HUDTabButton::Style::RIGHT : HUDTabButton::Style::ACTIVE,
this, display_mode, label));
tabs_.push_back(tab_button);
return tab_button;
}
void HUDTabStrip::ButtonPressed(views::Button* sender,
const ui::Event& /*event*/) {
for (const auto* tab : tabs_) {
if (tab == sender) {
hud_->TabButtonPressed(tab);
return;
}
}
NOTREACHED();
}
void HUDTabStrip::ActivateTab(const views::View* active_tab_button) {
// True if we find given active tab.
bool found = false;
for (HUDTabButton* tab : tabs_) {
if (found) {
tab->SetStyle(HUDTabButton::Style::RIGHT);
continue;
}
if (tab == active_tab_button) {
found = true;
tab->SetStyle(HUDTabButton::Style::ACTIVE);
continue;
}
tab->SetStyle(HUDTabButton::Style::LEFT);
}
DCHECK(found);
}
} // namespace hud_display
} // namespace ash
// 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.
#ifndef ASH_HUD_DISPLAY_TAB_STRIP_H_
#define ASH_HUD_DISPLAY_TAB_STRIP_H_
#include "ash/hud_display/hud_constants.h"
#include "base/strings/string16.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/metadata/metadata_header_macros.h"
namespace gfx {
class Canvas;
}
namespace views {
class View;
}
namespace ash {
namespace hud_display {
class HUDDisplayView;
class HUDTabStrip;
class HUDTabButton : public views::LabelButton {
public:
// Defines tab paint style.
enum class Style {
LEFT, // Tab to the left of the active tab.
ACTIVE, // Active tab.
RIGHT // Tab to the right of the active tab.
};
METADATA_HEADER(HUDTabButton);
HUDTabButton(Style style,
HUDTabStrip* tab_strip,
const DisplayModes display_mode,
const base::string16& text);
HUDTabButton(const HUDTabButton&) = delete;
HUDTabButton& operator=(const HUDTabButton&) = delete;
~HUDTabButton() override = default;
void SetStyle(Style style);
DisplayModes display_mode() const { return display_mode_; }
protected:
// views::LabelButton:
void PaintButtonContents(gfx::Canvas* canvas) override;
private:
Style style_ = Style::LEFT;
// Tab activation sends this display mode to the HUD.
DisplayModes display_mode_ = DisplayModes::DEFAULT;
};
class HUDTabStrip : public views::View, public views::ButtonListener {
public:
METADATA_HEADER(HUDTabStrip);
explicit HUDTabStrip(HUDDisplayView* hud);
HUDTabStrip(const HUDTabStrip&) = delete;
HUDTabStrip& operator=(const HUDTabStrip&) = delete;
~HUDTabStrip() override;
HUDTabButton* AddTabButton(HUDDisplayView* hud,
const DisplayModes display_mode,
const base::string16& label);
// views::ButtonListener
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// Mark tabs around the active one need repaint to modify borders.
void ActivateTab(const views::View* active_tab_button);
private:
HUDDisplayView* hud_;
std::vector<HUDTabButton*> tabs_; // Ordered list of child tabs.
};
} // namespace hud_display
} // namespace ash
#endif // ASH_HUD_DISPLAY_TAB_STRIP_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment