blob: 5766f1a08e7ded3d5a1cd3e4a35f164c4e8cb55f [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.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.LayoutManager;
import org.chromium.base.TraceEvent;
import org.chromium.base.metrics.TimingMetric;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
/** ModelListAdapter for OmniboxSuggestionsDropdown (RecyclerView version). */
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public class OmniboxSuggestionsDropdownAdapter extends SimpleRecyclerViewAdapter {
private int mSelectedItem = RecyclerView.NO_POSITION;
private LayoutManager mLayoutManager;
private int mNumSessionViewsCreated;
private int mNumSessionViewsBound;
OmniboxSuggestionsDropdownAdapter(ModelList data) {
super(data);
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView view) {
super.onAttachedToRecyclerView(view);
mLayoutManager = view.getLayoutManager();
mSelectedItem = RecyclerView.NO_POSITION;
}
/* package */ void recordSessionMetrics() {
if (mNumSessionViewsBound > 0) {
SuggestionsMetrics.recordSuggestionViewReuseStats(mNumSessionViewsCreated,
100 * (mNumSessionViewsBound - mNumSessionViewsCreated)
/ mNumSessionViewsBound);
}
mNumSessionViewsCreated = 0;
mNumSessionViewsBound = 0;
}
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
if (holder == null || holder.itemView == null) return;
holder.itemView.setSelected(false);
}
/**
* @return Index of the currently highlighted view.
*/
int getSelectedViewIndex() {
return mSelectedItem;
}
/** @return Currently selected view. */
@Nullable
View getSelectedView() {
if (mLayoutManager == null) return null;
if (mSelectedItem < 0 || mSelectedItem >= getItemCount()) return null;
View currentSelectedView = mLayoutManager.findViewByPosition(mSelectedItem);
if (currentSelectedView != null) {
return currentSelectedView;
}
mSelectedItem = RecyclerView.NO_POSITION;
return null;
}
/** Ensures selection is reset to beginning of the list. */
void resetSelection() {
setSelectedViewIndex(RecyclerView.NO_POSITION);
}
/**
* Move focus to another view.
*
* @param index end index.
*/
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public boolean setSelectedViewIndex(int index) {
if (mLayoutManager == null) return false;
if (index != RecyclerView.NO_POSITION && (index < 0 || index >= getItemCount())) {
return false;
}
View previousSelectedView = mLayoutManager.findViewByPosition(mSelectedItem);
if (previousSelectedView != null) {
previousSelectedView.setSelected(false);
}
mSelectedItem = index;
mLayoutManager.scrollToPosition(index);
View currentSelectedView = mLayoutManager.findViewByPosition(index);
if (currentSelectedView != null) {
currentSelectedView.setSelected(true);
}
return true;
}
@Override
// extend this
protected View createView(ViewGroup parent, int viewType) {
// This skips measuring Adapter.CreateViewHolder, which is final, but it capture
// the creation of a view holder.
try (TraceEvent tracing =
TraceEvent.scoped("OmniboxSuggestionsList.CreateView", "type:" + viewType);
TimingMetric metric = SuggestionsMetrics.recordSuggestionViewCreateTime()) {
return super.createView(parent, viewType);
}
}
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
mNumSessionViewsCreated++;
return super.onCreateViewHolder(parent, viewType);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
mNumSessionViewsBound++;
super.onBindViewHolder(holder, position);
}
}