blob: d48223986946d1d1972388928a83df7abcf82670 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "chrome/browser/ui/tabs/tab_style.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/tabs/features.h"
#include "chrome/browser/ui/ui_features.h"
#include "ui/base/ui_base_features.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/color_utils.h"
#include "ui/views/layout/layout_provider.h"
namespace {
// Thickness in DIPs of the separator painted on the left and right edges of
// the tab.
constexpr int kChromeRefreshSeparatorThickness = 2;
constexpr int kChromeRefreshSeparatorHorizontalMargin = 2;
// TODO (crbug.com/1451400): This constant should be in LayoutConstants.
constexpr int kChromeRefreshSeparatorHeight = 16;
// The padding from the top of the tab to the content area.
constexpr int kChromeRefreshTabVerticalPadding = 6;
constexpr int kChromeRefreshTabHorizontalPadding = 8;
class ChromeRefresh2023TabStyle : public TabStyle {
public:
~ChromeRefresh2023TabStyle() override = default;
int GetStandardWidth() const override;
int GetPinnedWidth() const override;
int GetMinimumActiveWidth() const override;
int GetMinimumInactiveWidth() const override;
int GetTopCornerRadius() const override;
int GetBottomCornerRadius() const override;
int GetTabOverlap() const override;
gfx::Size GetPreviewImageSize() const override;
gfx::Size GetSeparatorSize() const override;
gfx::Insets GetSeparatorMargins() const override;
int GetSeparatorCornerRadius() const override;
int GetDragHandleExtension(int height) const override;
SkColor GetTabBackgroundColor(
TabSelectionState state,
bool hovered,
bool frame_active,
const ui::ColorProvider& color_provider) const override;
gfx::Insets GetContentsInsets() const override;
float GetSelectedTabOpacity() const override;
};
} // namespace
TabStyle::~TabStyle() = default;
int ChromeRefresh2023TabStyle::GetStandardWidth() const {
// The standard tab width is 240 DIP including both separators.
constexpr int kTabWidth = 240;
// The overlap includes one separator, so subtract it here.
return kTabWidth + GetTabOverlap() - GetSeparatorSize().width();
}
int ChromeRefresh2023TabStyle::GetPinnedWidth() const {
constexpr int kTabPinnedContentWidth = 24;
return kTabPinnedContentWidth + GetContentsInsets().left() +
GetContentsInsets().right();
}
int ChromeRefresh2023TabStyle::GetMinimumActiveWidth() const {
const int close_button_size = GetLayoutConstant(TAB_CLOSE_BUTTON_SIZE);
const gfx::Insets insets = GetContentsInsets();
const int min_active_width =
close_button_size + insets.left() + insets.right();
if (base::FeatureList::IsEnabled(tabs::kScrollableTabStrip)) {
return std::max(
min_active_width,
base::GetFieldTrialParamByFeatureAsInt(
tabs::kScrollableTabStrip,
tabs::kMinimumTabWidthFeatureParameterName, min_active_width));
}
return min_active_width;
}
int ChromeRefresh2023TabStyle::GetMinimumInactiveWidth() const {
// Allow tabs to shrink until they appear to be 16 DIP wide excluding
// outer corners.
constexpr int kInteriorWidth = 16;
// The overlap contains the trailing separator that is part of the interior
// width; avoid double-counting it.
int min_inactive_width =
kInteriorWidth - GetSeparatorSize().width() + GetTabOverlap();
if (base::FeatureList::IsEnabled(tabs::kScrollableTabStrip)) {
return std::max(
min_inactive_width,
base::GetFieldTrialParamByFeatureAsInt(
tabs::kScrollableTabStrip,
tabs::kMinimumTabWidthFeatureParameterName, min_inactive_width));
}
return min_inactive_width;
}
int ChromeRefresh2023TabStyle::GetTopCornerRadius() const {
return 10;
}
int ChromeRefresh2023TabStyle::GetBottomCornerRadius() const {
return 12;
}
int ChromeRefresh2023TabStyle::GetTabOverlap() const {
// The overlap removes the width and the margins of the separator.
const float total_separator_width = GetSeparatorMargins().left() +
GetSeparatorSize().width() +
GetSeparatorMargins().right();
return 2 * GetBottomCornerRadius() - total_separator_width;
}
gfx::Size ChromeRefresh2023TabStyle::GetPreviewImageSize() const {
constexpr float kTabHoverCardPreviewImageAspectRatio = 16.0f / 9.0f;
const int width = GetStandardWidth();
return gfx::Size(width, width / kTabHoverCardPreviewImageAspectRatio);
}
gfx::Size ChromeRefresh2023TabStyle::GetSeparatorSize() const {
return gfx::Size(kChromeRefreshSeparatorThickness,
kChromeRefreshSeparatorHeight);
}
gfx::Insets ChromeRefresh2023TabStyle::GetSeparatorMargins() const {
return gfx::Insets::TLBR(GetLayoutConstant(TAB_STRIP_PADDING),
kChromeRefreshSeparatorHorizontalMargin,
GetLayoutConstant(TAB_STRIP_PADDING),
kChromeRefreshSeparatorHorizontalMargin);
}
int ChromeRefresh2023TabStyle::GetSeparatorCornerRadius() const {
return GetSeparatorSize().width() / 2;
}
int ChromeRefresh2023TabStyle::GetDragHandleExtension(int height) const {
return 6;
}
SkColor ChromeRefresh2023TabStyle::GetTabBackgroundColor(
const TabSelectionState state,
const bool hovered,
const bool frame_active,
const ui::ColorProvider& color_provider) const {
switch (state) {
case TabStyle::TabSelectionState::kActive: {
constexpr ui::ColorId kActiveColorIds[2] = {
kColorTabBackgroundActiveFrameInactive,
kColorTabBackgroundActiveFrameActive};
return color_provider.GetColor(kActiveColorIds[frame_active]);
}
case TabStyle::TabSelectionState::kSelected: {
constexpr ui::ColorId kSelectedColorIds[2][2] = {
{kColorTabBackgroundSelectedFrameInactive,
kColorTabBackgroundSelectedFrameActive},
{kColorTabBackgroundSelectedHoverFrameInactive,
kColorTabBackgroundSelectedHoverFrameActive}};
return color_provider.GetColor(kSelectedColorIds[hovered][frame_active]);
}
case TabStyle::TabSelectionState::kInactive: {
constexpr ui::ColorId kInactiveColorIds[2][2] = {
{kColorTabBackgroundInactiveFrameInactive,
kColorTabBackgroundInactiveFrameActive},
{kColorTabBackgroundInactiveHoverFrameInactive,
kColorTabBackgroundInactiveHoverFrameActive}};
return color_provider.GetColor(kInactiveColorIds[hovered][frame_active]);
}
default:
NOTREACHED();
}
}
gfx::Insets ChromeRefresh2023TabStyle::GetContentsInsets() const {
return gfx::Insets::TLBR(
kChromeRefreshTabVerticalPadding + GetLayoutConstant(TAB_STRIP_PADDING),
GetBottomCornerRadius() + kChromeRefreshTabHorizontalPadding,
kChromeRefreshTabVerticalPadding + GetLayoutConstant(TAB_STRIP_PADDING),
GetBottomCornerRadius() + kChromeRefreshTabHorizontalPadding);
}
float ChromeRefresh2023TabStyle::GetSelectedTabOpacity() const {
return kDefaultSelectedTabOpacity;
}
// static
const TabStyle* TabStyle::Get() {
static TabStyle* const tab_style =
static_cast<TabStyle*>(new ChromeRefresh2023TabStyle());
return tab_style;
}