Commit bd90941e authored by Toni Barzic's avatar Toni Barzic Committed by Commit Bot

app list: Suggestion chip container should respect app list margins

Makes the suggestion chip container respect 1/16 (or 1/12 for smaller
screen width) horizontal margin. This ensures that at least 3 chips are
shown - if the minimum number of chips does not fit the margins, their
width is reduced by using box layout flexing.

BUG=1010236

Change-Id: I4ee0d85ce5ac263de1fc583ba7bdaa926b5344ac
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1836453
Commit-Queue: Toni Baržić <tbarzic@chromium.org>
Reviewed-by: default avatarAlex Newcomer <newcomer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702602}
parent 82a95e87
......@@ -2903,7 +2903,7 @@ TEST_F(AppListViewTest, EnsurePageSwitcherFitsAppsGridMargin) {
ash::features::kEnableBackgroundBlur},
{});
const gfx::Size window_size = gfx::Size(600, 800);
const gfx::Size window_size = gfx::Size(400, 800);
gfx::NativeView parent = GetContext();
parent->SetBounds(gfx::Rect(window_size));
......@@ -2915,12 +2915,12 @@ TEST_F(AppListViewTest, EnsurePageSwitcherFitsAppsGridMargin) {
const int expected_vertical_margin =
(window_size.height() - ShelfHeight()) / 16;
// The horizontal margin is selected so the page switcher fits the margin
// space (note that 600 / 16, which is how the margin is normally calculated
// space (note that 400 / 12, which is how the margin is normally calculated
// is smaller than the width required by page switcher).
VerifyAppsContainerLayout(window_size, 4 /*column_count*/, 5 /*row_count*/,
40 /*expected_horizontal_margin*/,
expected_vertical_margin,
88 /*expected_item_size*/);
80 /*expected_item_size*/);
}
// Verifies that the vertical spacing between items in apps grid has an upper
......
......@@ -64,6 +64,17 @@ constexpr float kSuggestionChipOpacityEndProgress = 1;
// The app list transition progress value for fullscreen state.
constexpr float kAppListFullscreenProgressValue = 2.0;
// Returns ideal horizontal padding for apps container with provided contents
// bounds.
int GetContainerHorizontalPaddingForBounds(const gfx::Rect& bounds) {
const int horizontal_margin_ratio =
(app_list_features::IsScalableAppListEnabled() &&
bounds.width() <= kAppsGridMarginSmallWidthThreshold)
? kAppsGridMarginRatioForSmallWidth
: kAppsGridMarginRatio;
return bounds.width() / horizontal_margin_ratio;
}
} // namespace
// static
......@@ -278,6 +289,10 @@ void AppsContainerView::Layout() {
contents_view_->app_list_view()->GetAppListTransitionProgress(
AppListView::kProgressFlagNone)));
chip_container_rect.set_height(kSuggestionChipContainerHeight);
if (app_list_features::IsScalableAppListEnabled()) {
chip_container_rect.Inset(GetContainerHorizontalPaddingForBounds(rect),
0);
}
suggestion_chip_container_view_->SetBoundsRect(chip_container_rect);
// Leave the same available bounds for the apps grid view in both
......@@ -479,13 +494,8 @@ const gfx::Insets& AppsContainerView::CalculateMarginsForAvailableBounds(
calculate_margin(ideal_vertical_margin, available_height,
min_grid_size.height(), max_grid_size.height());
const int horizontal_margin_ratio =
(app_list_features::IsScalableAppListEnabled() &&
available_bounds.width() < kAppsGridMarginSmallWidthThreshold)
? kAppsGridMarginRatioForSmallWidth
: kAppsGridMarginRatio;
const int ideal_horizontal_margin =
available_bounds.width() / horizontal_margin_ratio;
GetContainerHorizontalPaddingForBounds(available_bounds);
const int horizontal_margin =
calculate_margin(ideal_horizontal_margin, available_bounds.width(),
min_grid_size.width(), max_grid_size.width());
......
......@@ -28,6 +28,11 @@ namespace {
// The spacing between chips.
constexpr int kChipSpacing = 8;
// The minimum allowed number of suggestion chips shown in the container
// (provided that the suggestoin chip results contain at least than number of
// items).
constexpr int kMinimumSuggestionChipNumber = 3;
bool IsPolicySuggestionChip(const SearchResult& result) {
return result.display_location() ==
ash::SearchResultDisplayLocation::kSuggestionChipContainer &&
......@@ -61,11 +66,9 @@ SuggestionChipContainerView::SuggestionChipContainerView(
layer()->SetFillsBoundsOpaquely(false);
DCHECK(contents_view);
views::BoxLayout* layout_manager =
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
kChipSpacing));
layout_manager->set_main_axis_alignment(
layout_manager_ = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), kChipSpacing));
layout_manager_->set_main_axis_alignment(
views::BoxLayout::MainAxisAlignment::kCenter);
for (size_t i = 0; i < static_cast<size_t>(
......@@ -166,19 +169,73 @@ void SuggestionChipContainerView::Layout() {
// Only show the chips that fit in this view's contents bounds.
int total_width = 0;
const int max_width = GetContentsBounds().width();
bool has_hidden_chip = false;
std::vector<views::View*> shown_chips;
for (auto* chip : suggestion_chip_views_) {
if (!chip->result())
break;
layout_manager_->ClearFlexForView(chip);
if (!chip->result()) {
chip->SetVisible(false);
continue;
}
const gfx::Size size = chip->GetPreferredSize();
if (size.width() + total_width > max_width) {
if (has_hidden_chip ||
(size.width() + total_width > max_width &&
shown_chips.size() >= kMinimumSuggestionChipNumber)) {
chip->SetVisible(false);
} else {
chip->SetVisible(true);
chip->SetSize(size);
has_hidden_chip = true;
continue;
}
chip->SetVisible(true);
shown_chips.push_back(chip);
total_width += (total_width == 0 ? 0 : kChipSpacing) + size.width();
}
// If current suggestion chip width is over the max value, reduce the width by
// flexing views whose width is above average for the available space.
if (total_width > max_width && shown_chips.size() > 0) {
// Remove spacing between chips from total width to get the width available
// to visible suggestion chip views.
int available_width = std::max(
0, max_width - (kMinimumSuggestionChipNumber - 1) * kChipSpacing);
std::vector<views::View*> views_to_flex;
views_to_flex.swap(shown_chips);
// Do not flex views whose width is below average available width per chip,
// as flexing those would actually increase their size. Repeat this until
// there are no more views to remove from consideration for flexing
// (removing a view increases the average available space for the remaining
// views, so another view's size might fit into the remaining space).
for (size_t i = 0; i < kMinimumSuggestionChipNumber - 1; ++i) {
if (views_to_flex.empty())
break;
std::vector<views::View*> next_views_to_flex;
const int avg_width = available_width / views_to_flex.size();
for (auto* view : views_to_flex) {
gfx::Size view_size = view->GetPreferredSize();
if (view_size.width() <= avg_width) {
available_width -= view_size.width();
} else {
next_views_to_flex.push_back(view);
}
}
if (views_to_flex.size() == next_views_to_flex.size())
break;
views_to_flex.swap(next_views_to_flex);
}
// Flex the views that are left over.
for (auto* view : views_to_flex)
layout_manager_->SetFlexForView(view, 1);
}
views::View::Layout();
}
......
......@@ -38,8 +38,8 @@ class SuggestionChipContainerView : public SearchResultContainerView {
void OnTabletModeChanged(bool started);
private:
ContentsView* contents_view_ = nullptr; // Not owned
views::BoxLayout* layout_manager_ = nullptr; // Not owned
std::vector<SearchResultSuggestionChipView*> suggestion_chip_views_; // Owned
......
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