blob: 0f1e5c46255a11d9962abb55642f9352089b94fa [file] [log] [blame]
// Copyright 2017 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/views/chrome_layout_provider.h"
#include <algorithm>
#include "base/feature_list.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "components/omnibox/common/omnibox_features.h"
#include "ui/base/pointer/touch_ui_controller.h"
#include "ui/gfx/shadow_value.h"
namespace {
ChromeLayoutProvider* g_chrome_layout_provider = nullptr;
} // namespace
ChromeLayoutProvider::ChromeLayoutProvider() {
DCHECK_EQ(nullptr, g_chrome_layout_provider);
g_chrome_layout_provider = this;
}
ChromeLayoutProvider::~ChromeLayoutProvider() {
DCHECK_EQ(this, g_chrome_layout_provider);
g_chrome_layout_provider = nullptr;
}
// static
ChromeLayoutProvider* ChromeLayoutProvider::Get() {
// Check to avoid downcasting a base LayoutProvider.
DCHECK_EQ(g_chrome_layout_provider, views::LayoutProvider::Get());
return static_cast<ChromeLayoutProvider*>(views::LayoutProvider::Get());
}
// static
std::unique_ptr<views::LayoutProvider>
ChromeLayoutProvider::CreateLayoutProvider() {
return std::make_unique<ChromeLayoutProvider>();
}
gfx::Insets ChromeLayoutProvider::GetInsetsMetric(int metric) const {
DCHECK_LT(metric, views::VIEWS_INSETS_MAX);
const bool touch_ui = ui::TouchUiController::Get()->touch_ui();
switch (metric) {
case views::INSETS_DIALOG:
case views::INSETS_DIALOG_SUBSECTION: {
return gfx::Insets::VH(20, 20);
}
case views::INSETS_DIALOG_FOOTNOTE: {
return gfx::Insets::TLBR(10, 20, 15, 20);
}
case views::INSETS_CHECKBOX_RADIO_BUTTON: {
gfx::Insets insets = LayoutProvider::GetInsetsMetric(metric);
// Checkboxes and radio buttons should be aligned flush to the left edge.
return gfx::Insets::TLBR(insets.top(), 0, insets.bottom(),
insets.right());
}
case views::INSETS_VECTOR_IMAGE_BUTTON:
return gfx::Insets(4);
case views::InsetsMetric::INSETS_LABEL_BUTTON:
return touch_ui ? gfx::Insets::VH(8, 8)
: LayoutProvider::GetInsetsMetric(metric);
case INSETS_BOOKMARKS_BAR_BUTTON:
return touch_ui ? gfx::Insets::VH(8, 10) : gfx::Insets(6);
case INSETS_TOAST:
return gfx::Insets::VH(0, 16);
case INSETS_OMNIBOX_PILL_BUTTON:
if (!touch_ui) {
return gfx::Insets::VH(4, 8);
} else {
return touch_ui ? gfx::Insets::VH(8, 16) : gfx::Insets::VH(5, 12);
}
case INSETS_PAGE_INFO_HOVER_BUTTON: {
const gfx::Insets insets =
LayoutProvider::GetInsetsMetric(views::INSETS_LABEL_BUTTON);
const int horizontal_padding = 20;
// Hover button in page info requires double the height compared to the
// label button because it behaves like a menu control.
return gfx::Insets::VH(insets.height(), horizontal_padding);
}
case INSETS_RECENT_ACTIVITY_IMAGE_MARGIN:
return gfx::Insets::TLBR(0, 12, 0, 16);
case INSETS_TASK_MANAGER:
return gfx::Insets::TLBR(4, 20, 20, 20);
case INSETS_PAGE_INFO_FOOTER_BUTTON:
return gfx::Insets::VH(12, 20);
default:
return LayoutProvider::GetInsetsMetric(metric);
}
}
int ChromeLayoutProvider::GetDistanceMetric(int metric) const {
DCHECK_GE(metric, views::VIEWS_DISTANCE_START);
DCHECK_LT(metric, views::VIEWS_DISTANCE_MAX);
if (metric < views::VIEWS_DISTANCE_END) {
return LayoutProvider::GetDistanceMetric(metric);
}
switch (static_cast<ChromeDistanceMetric>(metric)) {
case DISTANCE_CONTENT_LIST_VERTICAL_SINGLE:
return 4;
case DISTANCE_CONTENT_LIST_VERTICAL_MULTI:
return 8;
case DISTANCE_EXTENSIONS_MENU_WIDTH:
return kMediumDialogWidth;
case DISTANCE_EXTENSIONS_MENU_BUTTON_ICON_SIZE:
return 20;
case DISTANCE_EXTENSIONS_MENU_BUTTON_ICON_SMALL_SIZE:
return 16;
case DISTANCE_EXTENSIONS_MENU_EXTENSION_ICON_SIZE:
return 28;
case DISTANCE_EXTENSIONS_MENU_ICON_SPACING:
return (GetDistanceMetric(DISTANCE_EXTENSIONS_MENU_EXTENSION_ICON_SIZE) -
GetDistanceMetric(DISTANCE_EXTENSIONS_MENU_BUTTON_ICON_SIZE)) /
2;
case DISTANCE_EXTENSIONS_MENU_BUTTON_MARGIN:
return 12;
case DISTANCE_EXTENSIONS_MENU_LABEL_ICON_SPACING:
return 4;
case DISTANCE_RELATED_CONTROL_HORIZONTAL_SMALL:
return 16;
case DISTANCE_RELATED_CONTROL_VERTICAL_SMALL:
return 8;
case DISTANCE_BUTTON_MINIMUM_WIDTH:
return GetDistanceMetric(views::DISTANCE_DIALOG_BUTTON_MINIMUM_WIDTH);
case DISTANCE_RELATED_LABEL_HORIZONTAL_LIST:
return 8;
case DISTANCE_SUBSECTION_HORIZONTAL_INDENT:
return 0;
case DISTANCE_TOAST_CONTROL_VERTICAL:
return 8;
case DISTANCE_TOAST_LABEL_VERTICAL:
return 12;
case DISTANCE_UNRELATED_CONTROL_HORIZONTAL_LARGE:
return 16;
case DISTANCE_UNRELATED_CONTROL_VERTICAL_LARGE:
return 16;
case DISTANCE_STANDALONE_BUBBLE_PREFERRED_WIDTH:
return kMediumDialogWidth;
case DISTANCE_BETWEEN_PRIMARY_AND_SECONDARY_LABELS_HORIZONTAL:
return 24;
case DISTANCE_OMNIBOX_CELL_VERTICAL_PADDING:
return 12;
case DISTANCE_OMNIBOX_TWO_LINE_CELL_VERTICAL_PADDING:
return 4;
case DISTANCE_SIDE_PANEL_HEADER_VECTOR_ICON_SIZE:
return 16;
case DISTANCE_SIDE_PANEL_HEADER_BUTTON_MINIMUM_SIZE:
return 20;
case DISTANCE_SIDE_PANEL_HEADER_INTERIOR_MARGIN_HORIZONTAL:
return 4;
case DISTANCE_HORIZONTAL_SEPARATOR_PADDING_PAGE_INFO_VIEW:
return 20;
case DISTANCE_INFOBAR_HORIZONTAL_ICON_LABEL_PADDING:
return 16;
case DISTANCE_INFOBAR_HEIGHT:
// Spec says height of button should be 36dp, vertical padding on both
// top and bottom should be 8dp.
return 36 + 2 * 8;
case DISTANCE_PERMISSION_PROMPT_HORIZONTAL_ICON_LABEL_PADDING:
return 8;
case DISTANCE_RICH_HOVER_BUTTON_ICON_HORIZONTAL:
return 8;
case DISTANCE_TASK_MANAGER_SEARCH_BAR_ICON_AND_BUTTON_HORIZONTAL_SPACING:
return 4;
case DISTANCE_TASK_MANAGER_SEARCH_ICON_SIZE:
return 20;
case DISTANCE_TASK_MANAGER_SEARCH_BAR_MIN_WIDTH:
return 160;
case DISTANCE_TASK_MANAGER_SEARCH_BAR_MIN_HEIGHT:
return 36;
case DISTANCE_TASK_MANAGER_TAB_HEIGHT:
return 54;
case DISTANCE_TOAST_BUBBLE_BETWEEN_CHILD_SPACING:
case DISTANCE_TOAST_BUBBLE_BROWSER_WINDOW_MARGIN:
return 4;
case DISTANCE_TOAST_BUBBLE_BETWEEN_LABEL_ACTION_BUTTON_SPACING:
case DISTANCE_TOAST_BUBBLE_BETWEEN_LABEL_MENU_BUTTON_SPACING:
return 16;
case DISTANCE_TOAST_BUBBLE_HEIGHT:
return 48;
case DISTANCE_TOAST_BUBBLE_HEIGHT_ACTION_BUTTON:
return 36;
case DISTANCE_TOAST_BUBBLE_HEIGHT_CONTENT:
return 24;
case DISTANCE_TOAST_BUBBLE_ICON_SIZE:
case DISTANCE_TOAST_BUBBLE_MENU_ICON_SIZE:
return 20;
case DISTANCE_TOAST_BUBBLE_LEADING_ICON_SIDE_MARGINS:
return 2;
case DISTANCE_TOAST_BUBBLE_MARGIN_LEFT:
return 12;
case DISTANCE_TOAST_BUBBLE_MARGIN_RIGHT_ACTION_BUTTON:
return 6;
case DISTANCE_TOAST_BUBBLE_MARGIN_RIGHT_CLOSE_BUTTON:
case DISTANCE_TOAST_BUBBLE_MARGIN_RIGHT_MENU_BUTTON:
return 10;
case DISTANCE_TOAST_BUBBLE_MARGIN_RIGHT_LABEL:
return 16;
case DISTANCE_RECENT_ACTIVITY_AVATAR_SIZE:
return 32;
case DISTANCE_RECENT_ACTIVITY_AVATAR_FALLBACK_SIZE:
return 24;
case DISTANCE_RECENT_ACTIVITY_FAVICON_CONTAINER_RADIUS:
return 9;
case DISTANCE_RECENT_ACTIVITY_FAVICON_CONTAINER_BORDER_WIDTH:
return 2;
case DISTANCE_RECENT_ACTIVITY_FAVICON_CONTAINER_PADDING:
return 4;
case DISTANCE_RECENT_ACTIVITY_FAVICON_CONTAINER_OFFSET_FROM_AVATAR:
return 2;
case DISTANCE_RECENT_ACTIVITY_CONTAINER_RADIUS:
return 8;
case DISTANCE_RECENT_ACTIVITY_CONTAINER_VERTICAL_MARGIN:
return 10;
case DISTANCE_RECENT_ACTIVITY_CONTAINER_VERTICAL_PADDING:
return 6;
case DISTANCE_RECENT_ACTIVITY_ROW_VERTICAL_PADDING:
return 6;
case DISTANCE_ACCOUNT_INFO_ROW_AVATAR_EMAIL:
return 8;
case DISTANCE_COLLABORATION_MESSAGING_AVATAR_FALLBACK_ICON_PADDING:
return 2;
case DISTANCE_COLLABORATION_MESSAGING_AVATAR_FALLBACK_ICON_BORDER_SIZE:
return 1;
case DISTANCE_TEXTFIELD_ACCOUNT_CARD_VERTICAL:
return 4;
case DISTANCE_FEATURE_FIRST_RUN_INFO_BOX_ICON_SIZE:
return 16;
case DISTANCE_FEATURE_FIRST_RUN_INFO_BOX_PADDING:
return 12;
case DISTANCE_FEATURE_FIRST_RUN_INFO_BOX_ROUNDED_BORDER_RADIUS:
return 12;
case DISTANCE_FEATURE_FIRST_RUN_INFO_BOX_VERTICAL:
return 1;
}
NOTREACHED();
}
int ChromeLayoutProvider::GetSnappedDialogWidth(int min_width) const {
for (int snap_point :
{kSmallDialogWidth, kMediumDialogWidth, kLargeDialogWidth}) {
if (min_width <= snap_point) {
return snap_point;
}
}
return ((min_width + 15) / 16) * 16;
}
const views::TypographyProvider& ChromeLayoutProvider::GetTypographyProvider()
const {
return typography_provider_;
}
bool ChromeLayoutProvider::ShouldShowWindowIcon() const {
return false;
}