Commit a4347263 authored by Tetsui Ohkubo's avatar Tetsui Ohkubo Committed by Commit Bot

Implement custom detailed view back button.

This CL changes the back button of a detailed view to have custom shape
following the UX spec.

To do this, this CL splits CustomShapeButton from CollapseButton, and
derives CollapseButton and BackButton from CustomShapeButton.

Screenshot: http://screen/Lkuj2DJCYHP
UX spec: http://shortn/_N5oGsw6QZ0

TEST=manual
BUG=850396

Change-Id: I08554db7e78e710e96dd670917d612dbadee5ccb
Reviewed-on: https://chromium-review.googlesource.com/1096813Reviewed-by: default avatarYoshiki Iguchi <yoshiki@chromium.org>
Commit-Queue: Tetsui Ohkubo <tetsui@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567101}
parent 10cdb9da
......@@ -188,6 +188,7 @@ constexpr int kUnifiedTopShortcutButtonDefaultSpacing = 16;
constexpr int kUnifiedTopShortcutButtonMinSpacing = 4;
// Constants used in the title row of a detailed view in UnifiedSystemTray.
constexpr gfx::Insets kUnifiedDetailedViewTitlePadding(0, 0, 0, 16);
constexpr int kUnifiedDetailedViewTitleRowHeight = 64;
} // namespace ash
......
......@@ -24,94 +24,64 @@ namespace ash {
namespace {
// TODO(tetsui): Remove when the asset is arrived.
const int kCollapseIconSize = 20;
SkPath CreateCollapseButtonPath(const gfx::Rect& bounds) {
SkPath path;
SkScalar bottom_radius = SkIntToScalar(kTrayItemSize / 2);
SkScalar radii[8] = {
0, 0, 0, 0, bottom_radius, bottom_radius, bottom_radius, bottom_radius};
path.addRoundRect(gfx::RectToSkRect(bounds), radii);
return path;
}
// Ink drop mask that masks non-standard shape of CollapseButton.
class CollapseButtonInkDropMask : public views::InkDropMask {
// Ink drop mask that masks non-standard shape of CustomShapeButton.
class CustomShapeInkDropMask : public views::InkDropMask {
public:
CollapseButtonInkDropMask(const gfx::Size& layer_size);
CustomShapeInkDropMask(const gfx::Size& layer_size,
const CustomShapeButton* button);
private:
// InkDropMask:
void OnPaintLayer(const ui::PaintContext& context) override;
DISALLOW_COPY_AND_ASSIGN(CollapseButtonInkDropMask);
const CustomShapeButton* const button_;
DISALLOW_COPY_AND_ASSIGN(CustomShapeInkDropMask);
};
CollapseButtonInkDropMask::CollapseButtonInkDropMask(
const gfx::Size& layer_size)
: views::InkDropMask(layer_size) {}
CustomShapeInkDropMask::CustomShapeInkDropMask(const gfx::Size& layer_size,
const CustomShapeButton* button)
: views::InkDropMask(layer_size), button_(button) {}
void CollapseButtonInkDropMask::OnPaintLayer(const ui::PaintContext& context) {
void CustomShapeInkDropMask::OnPaintLayer(const ui::PaintContext& context) {
cc::PaintFlags flags;
flags.setAlpha(255);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setAntiAlias(true);
ui::PaintRecorder recorder(context, layer()->size());
recorder.canvas()->DrawPath(CreateCollapseButtonPath(layer()->bounds()),
recorder.canvas()->DrawPath(button_->CreateCustomShapePath(layer()->bounds()),
flags);
}
} // namespace
CollapseButton::CollapseButton(views::ButtonListener* listener)
CustomShapeButton::CustomShapeButton(views::ButtonListener* listener)
: ImageButton(listener) {
UpdateIcon(true /* expanded */);
SetImageAlignment(HorizontalAlignment::ALIGN_CENTER,
VerticalAlignment::ALIGN_BOTTOM);
SetTooltipText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_COLLAPSE));
SetBorder(views::CreateEmptyBorder(
gfx::Insets((kTrayItemSize - kCollapseIconSize) / 2)));
TrayPopupUtils::ConfigureTrayPopupButton(this);
}
CollapseButton::~CollapseButton() = default;
void CollapseButton::UpdateIcon(bool expanded) {
gfx::ImageSkia icon =
gfx::CreateVectorIcon(kNotificationCenterCollapseIcon, kCollapseIconSize,
kUnifiedMenuIconColor);
if (!expanded)
icon = gfx::ImageSkiaOperations::CreateRotatedImage(
icon, SkBitmapOperations::ROTATION_180_CW);
SetImage(views::Button::STATE_NORMAL, icon);
}
gfx::Size CollapseButton::CalculatePreferredSize() const {
return gfx::Size(kTrayItemSize, kTrayItemSize * 3 / 2);
}
int CollapseButton::GetHeightForWidth(int width) const {
return CalculatePreferredSize().height();
}
CustomShapeButton::~CustomShapeButton() = default;
void CollapseButton::PaintButtonContents(gfx::Canvas* canvas) {
void CustomShapeButton::PaintButtonContents(gfx::Canvas* canvas) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setColor(kUnifiedMenuButtonColor);
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->DrawPath(CreateCollapseButtonPath(GetLocalBounds()), flags);
canvas->DrawPath(CreateCustomShapePath(GetLocalBounds()), flags);
views::ImageButton::PaintButtonContents(canvas);
}
std::unique_ptr<views::InkDrop> CollapseButton::CreateInkDrop() {
std::unique_ptr<views::InkDrop> CustomShapeButton::CreateInkDrop() {
return TrayPopupUtils::CreateInkDrop(this);
}
std::unique_ptr<views::InkDropRipple> CollapseButton::CreateInkDropRipple()
std::unique_ptr<views::InkDropRipple> CustomShapeButton::CreateInkDropRipple()
const {
return TrayPopupUtils::CreateInkDropRipple(
TrayPopupInkDropStyle::FILL_BOUNDS, this,
......@@ -119,13 +89,49 @@ std::unique_ptr<views::InkDropRipple> CollapseButton::CreateInkDropRipple()
}
std::unique_ptr<views::InkDropHighlight>
CollapseButton::CreateInkDropHighlight() const {
CustomShapeButton::CreateInkDropHighlight() const {
return TrayPopupUtils::CreateInkDropHighlight(
TrayPopupInkDropStyle::FILL_BOUNDS, this, kUnifiedMenuIconColor);
}
std::unique_ptr<views::InkDropMask> CollapseButton::CreateInkDropMask() const {
return std::make_unique<CollapseButtonInkDropMask>(size());
std::unique_ptr<views::InkDropMask> CustomShapeButton::CreateInkDropMask()
const {
return std::make_unique<CustomShapeInkDropMask>(size(), this);
}
CollapseButton::CollapseButton(views::ButtonListener* listener)
: CustomShapeButton(listener) {
UpdateIcon(true /* expanded */);
SetImageAlignment(HorizontalAlignment::ALIGN_CENTER,
VerticalAlignment::ALIGN_BOTTOM);
SetTooltipText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_COLLAPSE));
SetBorder(views::CreateEmptyBorder(
gfx::Insets((kTrayItemSize - kCollapseIconSize) / 2)));
}
CollapseButton::~CollapseButton() = default;
void CollapseButton::UpdateIcon(bool expanded) {
gfx::ImageSkia icon =
gfx::CreateVectorIcon(kNotificationCenterCollapseIcon, kCollapseIconSize,
kUnifiedMenuIconColor);
if (!expanded)
icon = gfx::ImageSkiaOperations::CreateRotatedImage(
icon, SkBitmapOperations::ROTATION_180_CW);
SetImage(views::Button::STATE_NORMAL, icon);
}
gfx::Size CollapseButton::CalculatePreferredSize() const {
return gfx::Size(kTrayItemSize, kTrayItemSize * 3 / 2);
}
SkPath CollapseButton::CreateCustomShapePath(const gfx::Rect& bounds) const {
SkPath path;
SkScalar bottom_radius = SkIntToScalar(kTrayItemSize / 2);
SkScalar radii[8] = {
0, 0, 0, 0, bottom_radius, bottom_radius, bottom_radius, bottom_radius};
path.addRoundRect(gfx::RectToSkRect(bounds), radii);
return path;
}
} // namespace ash
......@@ -9,27 +9,43 @@
namespace ash {
// Abstract base class of buttons that have custom shape with Material Design
// ink drop.
class CustomShapeButton : public views::ImageButton {
public:
explicit CustomShapeButton(views::ButtonListener* listener);
~CustomShapeButton() override;
// Return the custom shape for the button in SkPath.
virtual SkPath CreateCustomShapePath(const gfx::Rect& bounds) const = 0;
// views::ImageButton:
void PaintButtonContents(gfx::Canvas* canvas) override;
std::unique_ptr<views::InkDrop> CreateInkDrop() override;
std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
const override;
std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
private:
DISALLOW_COPY_AND_ASSIGN(CustomShapeButton);
};
// Collapse button shown in TopShortcutsView with TopShortcutButtons.
// UnifiedSystemTrayBubble will support collapsed state where the height of the
// bubble is smaller, and some rows and labels will be omitted.
// By pressing the button, the state of the bubble will be toggled.
class CollapseButton : public views::ImageButton {
class CollapseButton : public CustomShapeButton {
public:
CollapseButton(views::ButtonListener* listener);
explicit CollapseButton(views::ButtonListener* listener);
~CollapseButton() override;
// Change the icon for the |expanded| state.
void UpdateIcon(bool expanded);
// views::ImageButton:
// CustomShapeButton:
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int width) const override;
void PaintButtonContents(gfx::Canvas* canvas) override;
std::unique_ptr<views::InkDrop> CreateInkDrop() override;
std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
const override;
std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
SkPath CreateCustomShapePath(const gfx::Rect& bounds) const override;
private:
DISALLOW_COPY_AND_ASSIGN(CollapseButton);
......
......@@ -9,9 +9,11 @@
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_popup_item_style.h"
#include "ash/system/tray/tray_popup_utils.h"
#include "ash/system/unified/collapse_button.h"
#include "ash/system/unified/top_shortcut_button.h"
#include "ash/system/unified/unified_system_tray_controller.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/separator.h"
......@@ -21,6 +23,9 @@ namespace ash {
namespace {
// TODO(tetsui): Remove when the asset is arrived.
const int kBackIconSize = 20;
void ConfigureTitleTriView(TriView* tri_view, TriView::Container container) {
std::unique_ptr<views::BoxLayout> layout;
......@@ -52,6 +57,40 @@ void ConfigureTitleTriView(TriView* tri_view, TriView::Container container) {
gfx::Size(0, kUnifiedDetailedViewTitleRowHeight));
}
class BackButton : public CustomShapeButton {
public:
BackButton(views::ButtonListener* listener) : CustomShapeButton(listener) {
SetImage(views::Button::STATE_NORMAL,
gfx::CreateVectorIcon(kSystemMenuArrowBackIcon, kBackIconSize,
kUnifiedMenuIconColor));
SetImageAlignment(HorizontalAlignment::ALIGN_RIGHT,
VerticalAlignment::ALIGN_MIDDLE);
SetTooltipText(
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_PREVIOUS_MENU));
SetBorder(views::CreateEmptyBorder(
gfx::Insets((kTrayItemSize - kBackIconSize) / 2)));
}
~BackButton() override = default;
// CustomShapeButton:
gfx::Size CalculatePreferredSize() const override {
return gfx::Size(kTrayItemSize * 3 / 2, kTrayItemSize);
}
SkPath CreateCustomShapePath(const gfx::Rect& bounds) const override {
SkPath path;
SkScalar bottom_radius = SkIntToScalar(kTrayItemSize / 2);
SkScalar radii[8] = {
0, 0, bottom_radius, bottom_radius, bottom_radius, bottom_radius, 0, 0};
path.addRoundRect(gfx::RectToSkRect(bounds), radii);
return path;
}
private:
DISALLOW_COPY_AND_ASSIGN(BackButton);
};
} // namespace
UnifiedDetailedViewDelegate::UnifiedDetailedViewDelegate(
......@@ -91,7 +130,8 @@ TriView* UnifiedDetailedViewDelegate::CreateTitleRow(int string_id) {
tri_view->AddView(TriView::Container::CENTER, label);
tri_view->SetContainerVisible(TriView::Container::END, false);
tri_view->SetBorder(views::CreateEmptyBorder(kUnifiedTopShortcutPadding));
tri_view->SetBorder(
views::CreateEmptyBorder(kUnifiedDetailedViewTitlePadding));
return tri_view;
}
......@@ -106,9 +146,7 @@ views::View* UnifiedDetailedViewDelegate::CreateTitleSeparator() {
views::Button* UnifiedDetailedViewDelegate::CreateBackButton(
views::ButtonListener* listener) {
// TODO(tetsui): Implement custom back button derived from CollapseButton.
return new TopShortcutButton(listener, kSystemMenuArrowBackIcon,
IDS_ASH_STATUS_TRAY_PREVIOUS_MENU);
return new BackButton(listener);
}
views::Button* UnifiedDetailedViewDelegate::CreateInfoButton(
......
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