blob: f30c05e253fe96e5ee2679db7d4912207478d4c1 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.omnibox.suggestions;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Px;
import org.chromium.chrome.browser.omnibox.OmniboxFeatures;
import org.chromium.chrome.browser.omnibox.R;
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
import org.chromium.components.omnibox.GroupsProto.GroupSection;
import org.chromium.components.omnibox.GroupsProto.GroupsInfo;
import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
import org.chromium.ui.modelutil.PropertyModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** Manages the list of DropdownItemViewInfo elements. */
class DropdownItemViewInfoListManager {
private final Context mContext;
private final ModelList mManagedModel;
private int mLayoutDirection;
private @BrandedColorScheme int mBrandedColorScheme;
private List<DropdownItemViewInfo> mSourceViewInfoList;
private final int mListActiveOmniboxTopSmallMargin;
private final int mListActiveOmniboxTopBigMargin;
private final int mListNonActiveOmniboxTopSmallMargin;
private final int mListNonActiveOmniboxTopBigMargin;
DropdownItemViewInfoListManager(@NonNull ModelList managedModel, @NonNull Context context) {
assert managedModel != null : "Must specify a non-null model.";
mContext = context;
mLayoutDirection = View.LAYOUT_DIRECTION_INHERIT;
mBrandedColorScheme = BrandedColorScheme.LIGHT_BRANDED_THEME;
mSourceViewInfoList = Collections.emptyList();
mManagedModel = managedModel;
mListActiveOmniboxTopSmallMargin =
OmniboxResourceProvider.getActiveOmniboxTopSmallMargin(context);
mListActiveOmniboxTopBigMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_list_active_top_big_margin);
mListNonActiveOmniboxTopSmallMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_list_non_active_top_small_margin);
mListNonActiveOmniboxTopBigMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_list_non_active_top_big_margin);
}
/**
* Sets the layout direction to be used for any new suggestion views.
* @see View#setLayoutDirection(int)
*/
void setLayoutDirection(int layoutDirection) {
if (mLayoutDirection == layoutDirection) return;
mLayoutDirection = layoutDirection;
for (int i = 0; i < mSourceViewInfoList.size(); i++) {
PropertyModel model = mSourceViewInfoList.get(i).model;
model.set(SuggestionCommonProperties.LAYOUT_DIRECTION, layoutDirection);
}
}
/**
* Specifies the visual theme to be used by the suggestions.
* @param brandedColorScheme Specifies which {@link BrandedColorScheme} should be used.
*/
void setBrandedColorScheme(@BrandedColorScheme int brandedColorScheme) {
if (mBrandedColorScheme == brandedColorScheme) return;
mBrandedColorScheme = brandedColorScheme;
for (int i = 0; i < mSourceViewInfoList.size(); i++) {
PropertyModel model = mSourceViewInfoList.get(i).model;
model.set(SuggestionCommonProperties.COLOR_SCHEME, brandedColorScheme);
}
}
/** Clear all DropdownItemViewInfo lists. */
void clear() {
mSourceViewInfoList.clear();
mManagedModel.clear();
}
void onNativeInitialized() {}
/**
* Specify the input list of DropdownItemViewInfo elements.
*
* @param sourceList Source list of ViewInfo elements.
* @param groupsInfo Group ID to GroupConfig map carrying group collapsed state information.
*/
void setSourceViewInfoList(
@NonNull List<DropdownItemViewInfo> sourceList, @NonNull GroupsInfo groupsInfo) {
mSourceViewInfoList = sourceList;
final var groupsDetails = groupsInfo.getGroupConfigsMap();
// Build a new list of suggestions. Honor the default collapsed state.
final List<ListItem> suggestionsList = new ArrayList<>();
int deviceType = DeviceFormFactor.isNonMultiDisplayContextOnTablet(mContext)
? SuggestionCommonProperties.FormFactor.TABLET
: SuggestionCommonProperties.FormFactor.PHONE;
DropdownItemViewInfo previousItem = null;
int groupTopMargin = OmniboxResourceProvider.getSuggestionGroupTopMargin(mContext);
int groupBottomMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_group_vertical_smallest_margin);
int suggestionVerticalMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_vertical_margin);
GroupSection previousSection = null;
GroupSection currentSection;
boolean shouldShowModernizeVisualUpdate =
OmniboxFeatures.shouldShowModernizeVisualUpdate(mContext);
boolean previousItemWasHeader = false;
for (int i = 0; i < mSourceViewInfoList.size(); i++) {
final DropdownItemViewInfo item = mSourceViewInfoList.get(i);
final PropertyModel model = item.model;
model.set(SuggestionCommonProperties.LAYOUT_DIRECTION, mLayoutDirection);
model.set(SuggestionCommonProperties.COLOR_SCHEME, mBrandedColorScheme);
model.set(SuggestionCommonProperties.DEVICE_FORM_FACTOR, deviceType);
if (shouldShowModernizeVisualUpdate && item.processor.allowBackgroundRounding()) {
var groupConfig = groupsDetails.get(item.groupId);
currentSection = groupConfig != null ? groupConfig.getSection()
: GroupSection.SECTION_DEFAULT;
var applyRounding = currentSection != previousSection;
int topMargin;
if (previousItemWasHeader) {
topMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_group_vertical_margin);
} else {
topMargin = applyRounding ? groupTopMargin : suggestionVerticalMargin;
}
var bottomMargin = applyRounding ? groupBottomMargin : suggestionVerticalMargin;
model.set(DropdownCommonProperties.BG_TOP_CORNER_ROUNDED, applyRounding);
// Do not have margin for the first suggestion, otherwise the first suggestion will
// have a big gap with the Omnibox.
model.set(DropdownCommonProperties.TOP_MARGIN,
previousItem == null
? getSuggestionListTopMargin(item.processor.getViewTypeId())
: topMargin);
if (previousItem != null) {
previousItem.model.set(
DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED, applyRounding);
previousItem.model.set(DropdownCommonProperties.BOTTOM_MARGIN, bottomMargin);
}
previousItem = item;
previousSection = currentSection;
}
previousItemWasHeader = item.processor.getViewTypeId() == OmniboxSuggestionUiType.HEADER
&& shouldShowModernizeVisualUpdate
&& (OmniboxFeatures.shouldShowSmallestMargins()
|| OmniboxFeatures.shouldShowSmallerMargins());
suggestionsList.add(item);
}
// round the bottom corners of the last suggestion.
if (previousItem != null) {
previousItem.model.set(DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED, true);
}
mManagedModel.set(suggestionsList);
}
/**
* Return the top margin for the suggestion list in pixel size.
* The padding size between the Omnibox and the top suggestion is dependent on the top
* suggestion type and variations of the experiment:
* 1. If the type is EDIT_URL_SUGGESTION, being an integral part of the Search Ready Omnibox
* appears closer to the Omnibox.
* 2. Everything else is spaced farther away, keeping the same distance between the Omnibox and
* the Top suggestion as the distance between individual Suggestion sections.
*
* @param firstSuggestionUiType The type of the first suggestion.
*/
private @Px int getSuggestionListTopMargin(@OmniboxSuggestionUiType int firstSuggestionUiType) {
if (firstSuggestionUiType == OmniboxSuggestionUiType.EDIT_URL_SUGGESTION) {
return OmniboxFeatures.shouldShowSmallerMargins() ? mListActiveOmniboxTopSmallMargin
: 0;
}
if (OmniboxFeatures.shouldShowActiveColorOnOmnibox()) {
if (OmniboxFeatures.shouldShowSmallestMargins()) {
return 0;
} else if (OmniboxFeatures.shouldShowSmallBottomMargin()
|| OmniboxFeatures.shouldShowSmallerMargins()) {
return mListActiveOmniboxTopSmallMargin;
} else {
return mListActiveOmniboxTopBigMargin;
}
} else {
if (OmniboxFeatures.shouldShowSmallBottomMargin()) {
return mListNonActiveOmniboxTopSmallMargin;
} else {
return mListNonActiveOmniboxTopBigMargin;
}
}
}
}