Skip to content

Commit

Permalink
Extract ChipView from SuggestionChipView
Browse files Browse the repository at this point in the history
- Extract ChipView as a general view used to show a chip UI. General UI
  logics are extracted from SuggestionChipView to ChipView.
- Assistant suggestion related logics are preserved in
  SuggestionChipView.

Bug: b:272370530
Test: Build passes.
Change-Id: I2f7991846d616c1ffc4f6850a8e0d1c3a96e86c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4355875
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Commit-Queue: Tao Wu <wutao@chromium.org>
Reviewed-by: Tao Wu <wutao@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1119771}
  • Loading branch information
Yuki Awano authored and Chromium LUCI CQ committed Mar 21, 2023
1 parent ff94b74 commit c7c2cae
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 215 deletions.
2 changes: 2 additions & 0 deletions ash/assistant/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ source_set("ui") {
"main_stage/assistant_ui_element_view_factory.h",
"main_stage/assistant_zero_state_view.cc",
"main_stage/assistant_zero_state_view.h",
"main_stage/chip_view.cc",
"main_stage/chip_view.h",
"main_stage/element_animator.cc",
"main_stage/element_animator.h",
"main_stage/suggestion_chip_view.cc",
Expand Down
1 change: 1 addition & 0 deletions ash/assistant/ui/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ include_rules = [
"+net/base",
"+third_party/skia/include/core",
"+ui",
"+url/gurl.h",

# Abseil is allowed by default, but some features are banned. See
# //styleguide/c++/c++-features.md.
Expand Down
181 changes: 181 additions & 0 deletions ash/assistant/ui/main_stage/chip_view.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/assistant/ui/main_stage/chip_view.h"

#include <string>

#include "ash/assistant/ui/assistant_ui_constants.h"
#include "ash/assistant/ui/assistant_view_ids.h"
#include "ash/style/ash_color_id.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_provider.h"

namespace ash {
namespace {
// Appearance.
constexpr int kStrokeWidthDip = 1;
constexpr int kFocusedStrokeWidthDip = 2;

constexpr int kIconMarginDip = 8;
constexpr int kChipPaddingDip = 16;
constexpr int kPreferredHeightDip = 32;
} // namespace

ChipView::ChipView() {
// Focus.
// 1. Dark light mode is OFF
// We change background color of a suggestion chip view. No focus ring is
// used.
// 2. Dark light mode is ON
// We use focus ring. No background color change with focus.
SetFocusBehavior(FocusBehavior::ALWAYS);
SetInstallFocusRingOnFocus(true);

views::FocusRing* focus_ring = views::FocusRing::Get(this);
focus_ring->SetColorId(ui::kColorAshFocusRing);
focus_ring->SetHaloThickness(kFocusedStrokeWidthDip);
focus_ring->SetHaloInset(0.0f);

// Path is used for the focus ring, i.e. path is not necessary for dark and
// light mode flag off case. But we always install this as it shouldn't be a
// problem even if we provide the path to the UI framework.
const int radius = views::LayoutProvider::Get()->GetCornerRadiusMetric(
views::Emphasis::kMaximum, size());
views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), radius);

// Layout.
layout_manager_ = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal,
gfx::Insets::TLBR(0, kChipPaddingDip, 0, kChipPaddingDip),
kIconMarginDip));
layout_manager_->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);

// Icon.
icon_view_ = AddChildView(std::make_unique<views::ImageView>());
icon_view_->SetImageSize(gfx::Size(kIconSizeDip, kIconSizeDip));
icon_view_->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip));
icon_view_->SetVisible(false);

// Text.
text_view_ = AddChildView(std::make_unique<views::Label>());
text_view_->SetID(kSuggestionChipViewLabel);
text_view_->SetAutoColorReadabilityEnabled(false);
text_view_->SetSubpixelRenderingEnabled(false);
const gfx::FontList& font_list = assistant::ui::GetDefaultFontList();
text_view_->SetFontList(font_list.Derive(
/*size_delta=*/1, font_list.GetFontStyle(), gfx::Font::Weight::MEDIUM));
}

ChipView::~ChipView() = default;

gfx::Size ChipView::CalculatePreferredSize() const {
const int preferred_width = views::View::CalculatePreferredSize().width();
return gfx::Size(preferred_width, GetHeightForWidth(preferred_width));
}

int ChipView::GetHeightForWidth(int width) const {
return kPreferredHeightDip;
}

void ChipView::ChildVisibilityChanged(views::View* child) {
// When icon visibility is modified we need to update layout padding.
if (child == icon_view_) {
const int padding_left_dip =
icon_view_->GetVisible() ? kIconMarginDip : kChipPaddingDip;
layout_manager_->set_inside_border_insets(
gfx::Insets::TLBR(0, padding_left_dip, 0, kChipPaddingDip));
}
PreferredSizeChanged();
}

bool ChipView::OnKeyPressed(const ui::KeyEvent& event) {
if (event.key_code() == ui::VKEY_SPACE) {
return false;
}
return Button::OnKeyPressed(event);
}

void ChipView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
Button::OnBoundsChanged(previous_bounds);

// If there is no change in height, we don't need to do anything as the code
// below is to update corner radius values.
if (height() == previous_bounds.height()) {
return;
}

const int radius = views::LayoutProvider::Get()->GetCornerRadiusMetric(
views::Emphasis::kMaximum, size());

// Only set the border if a ColorProvider is available. Otherwise, we cannot
// compute the stroke color.
auto* color_provider = GetColorProvider();
if (color_provider) {
SetBorder(views::CreateRoundedRectBorder(
kStrokeWidthDip, radius,
color_provider->GetColor(kColorAshSeparatorColor)));
}

views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), radius);
}

void ChipView::OnThemeChanged() {
views::Button::OnThemeChanged();

raw_ptr<ui::ColorProvider> color_provider = GetColorProvider();
if (!color_provider) {
DCHECK(false) << "ColorProvider should not be null";
return;
}

text_view_->SetEnabledColor(
color_provider->GetColor(kColorAshSuggestionChipViewTextView));
const int radius = views::LayoutProvider::Get()->GetCornerRadiusMetric(
views::Emphasis::kMaximum, size());
SetBorder(views::CreateRoundedRectBorder(
kStrokeWidthDip, radius,
color_provider->GetColor(kColorAshSeparatorColor)));
}

void ChipView::SetIcon(const gfx::ImageSkia& icon) {
icon_view_->SetImage(icon);
MakeIconVisible();
}

void ChipView::MakeIconVisible() {
icon_view_->SetVisible(true);
}

gfx::ImageSkia ChipView::GetIcon() const {
return icon_view_->GetImage();
}

void ChipView::SetText(const std::u16string& text) {
text_view_->SetText(text);
SetAccessibleName(text);
}

const std::u16string& ChipView::GetText() const {
return text_view_->GetText();
}

BEGIN_METADATA(ChipView, views::Button)
END_METADATA

} // namespace ash
52 changes: 52 additions & 0 deletions ash/assistant/ui/main_stage/chip_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_ASSISTANT_UI_MAIN_STAGE_CHIP_VIEW_H_
#define ASH_ASSISTANT_UI_MAIN_STAGE_CHIP_VIEW_H_

#include "base/component_export.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"

namespace ash {

class COMPONENT_EXPORT(ASSISTANT_UI) ChipView : public views::Button {
public:
static constexpr int kIconSizeDip = 16;

ChipView();
~ChipView() override;

// views::View:
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int width) const override;
void ChildVisibilityChanged(views::View* child) override;
bool OnKeyPressed(const ui::KeyEvent& event) override;
void OnThemeChanged() override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;

// Make `icon_view_` visible to secure layout space for it. Use this method to
// avoid layout shift after downloading an icon image from the Web.
void MakeIconVisible();
void SetIcon(const gfx::ImageSkia& icon);
gfx::ImageSkia GetIcon() const;

void SetText(const std::u16string& text);
const std::u16string& GetText() const;

METADATA_HEADER(ChipView);

private:
raw_ptr<views::BoxLayout> layout_manager_;
raw_ptr<views::ImageView> icon_view_;
raw_ptr<views::Label> text_view_;
};

} // namespace ash

#endif // ASH_ASSISTANT_UI_MAIN_STAGE_CHIP_VIEW_H_

0 comments on commit c7c2cae

Please sign in to comment.