1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
// 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.
#include "chrome/browser/ui/tabs/tab_style.h"
#include <array>
#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;
// The standard tab width is 232 DIP, excluding separators and overlap.
constexpr int kTabWidth = 232;
} // namespace
TabStyle::~TabStyle() = default;
int TabStyle::GetStandardHeight() const {
return GetLayoutConstant(TAB_STRIP_HEIGHT);
}
int TabStyle::GetStandardWidth(const bool is_split) const {
if (is_split) {
// Split tabs appear as half width with one bottom extension. They also must
// include half the tab overlap as the tabs fill the space between them.
return kTabWidth / 2 + GetBottomCornerRadius() + GetTabOverlap() / 2;
} else {
// The full width includes two extensions with the bottom corner radius.
return kTabWidth + 2 * GetBottomCornerRadius();
}
}
int TabStyle::GetPinnedWidth(const bool is_split) const {
constexpr int kTabPinnedContentWidth = 24;
const int standard_pinned_width = kTabPinnedContentWidth +
GetContentsInsets().left() +
GetContentsInsets().right();
if (is_split) {
// Split tabs will recoup half of the tab overlap to reduce extra
// whitespace.
return standard_pinned_width - GetTabOverlap() / 2;
}
return standard_pinned_width;
}
int TabStyle::GetMinimumActiveWidth(const bool is_split) 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));
}
if (is_split) {
// Only have one set of horizontal padding between tabs in an active split.
return min_active_width - kChromeRefreshTabHorizontalPadding / 2;
}
return min_active_width;
}
int TabStyle::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 TabStyle::GetTopCornerRadius() const {
return 10;
}
int TabStyle::GetBottomCornerRadius() const {
return 12;
}
int TabStyle::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 TabStyle::GetPreviewImageSize() const {
constexpr float kTabHoverCardPreviewImageAspectRatio = 16.0f / 9.0f;
const int width = GetStandardWidth(/*is_split*/ false);
return gfx::Size(width, width / kTabHoverCardPreviewImageAspectRatio);
}
gfx::Size TabStyle::GetSeparatorSize() const {
return gfx::Size(kChromeRefreshSeparatorThickness,
kChromeRefreshSeparatorHeight);
}
gfx::Insets TabStyle::GetSeparatorMargins() const {
return gfx::Insets::TLBR(GetLayoutConstant(TAB_STRIP_PADDING),
kChromeRefreshSeparatorHorizontalMargin,
GetLayoutConstant(TAB_STRIP_PADDING),
kChromeRefreshSeparatorHorizontalMargin);
}
int TabStyle::GetSeparatorCornerRadius() const {
return GetSeparatorSize().width() / 2;
}
int TabStyle::GetDragHandleExtension(int height) const {
return 6;
}
SkColor TabStyle::GetTabBackgroundColor(
const TabSelectionState state,
const bool hovered,
const bool frame_active,
const ui::ColorProvider& color_provider) const {
switch (state) {
case TabStyle::TabSelectionState::kActive: {
constexpr std::array<ui::ColorId, 2> kActiveColorIds = {
kColorTabBackgroundActiveFrameInactive,
kColorTabBackgroundActiveFrameActive};
return color_provider.GetColor(kActiveColorIds[frame_active]);
}
case TabStyle::TabSelectionState::kSelected: {
constexpr std::array<std::array<ui::ColorId, 2>, 2> kSelectedColorIds = {
{{kColorTabBackgroundSelectedFrameInactive,
kColorTabBackgroundSelectedFrameActive},
{kColorTabBackgroundSelectedHoverFrameInactive,
kColorTabBackgroundSelectedHoverFrameActive}}};
return color_provider.GetColor(kSelectedColorIds[hovered][frame_active]);
}
case TabStyle::TabSelectionState::kInactive: {
constexpr std::array<std::array<ui::ColorId, 2>, 2> kInactiveColorIds = {
{{kColorTabBackgroundInactiveFrameInactive,
kColorTabBackgroundInactiveFrameActive},
{kColorTabBackgroundInactiveHoverFrameInactive,
kColorTabBackgroundInactiveHoverFrameActive}}};
return color_provider.GetColor(kInactiveColorIds[hovered][frame_active]);
}
default:
NOTREACHED();
}
}
gfx::Insets TabStyle::GetContentsInsets() const {
return gfx::Insets::TLBR(
kChromeRefreshTabVerticalPadding + GetLayoutConstant(TAB_STRIP_PADDING),
GetBottomCornerRadius() + kChromeRefreshTabHorizontalPadding,
kChromeRefreshTabVerticalPadding + GetLayoutConstant(TAB_STRIP_PADDING),
GetBottomCornerRadius() + kChromeRefreshTabHorizontalPadding);
}
float TabStyle::GetSelectedTabOpacity() const {
return kDefaultSelectedTabOpacity;
}
// static
const TabStyle* TabStyle::Get() {
static TabStyle* const tab_style = static_cast<TabStyle*>(new TabStyle());
return tab_style;
}
|