blob: d78b6dfdf8c5eeb271fcd57855cf758a3efda5c5 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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.explore_sites;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.AttributeSet;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.widget.GridLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.modelutil.PropertyKey;
import org.chromium.chrome.browser.modelutil.PropertyModel;
import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor;
import org.chromium.chrome.browser.native_page.ContextMenuManager;
import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.widget.RoundedIconGenerator;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.ui.base.PageTransition;
import org.chromium.ui.mojom.WindowOpenDisposition;
import java.util.ArrayList;
import java.util.List;
/**
* View for a category name and site tiles.
*/
public class ExploreSitesCategoryCardView extends LinearLayout {
private static final int MAX_TILE_COUNT = 8;
private static final int TITLE_LINES = 1;
private TextView mTitleView;
private GridLayout mTileView;
private RoundedIconGenerator mIconGenerator;
private ContextMenuManager mContextMenuManager;
private NativePageNavigationDelegate mNavigationDelegate;
private Profile mProfile;
private List<PropertyModelChangeProcessor<PropertyModel, ExploreSitesTileView, PropertyKey>>
mModelChangeProcessors;
private class CategoryCardInteractionDelegate
implements ContextMenuManager.Delegate, OnClickListener, OnCreateContextMenuListener {
private String mSiteUrl;
public CategoryCardInteractionDelegate(String siteUrl) {
mSiteUrl = siteUrl;
}
@Override
public void onClick(View view) {
mNavigationDelegate.openUrl(WindowOpenDisposition.CURRENT_TAB,
new LoadUrlParams(getUrl(), PageTransition.AUTO_BOOKMARK));
}
@Override
public void onCreateContextMenu(
ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
mContextMenuManager.createContextMenu(menu, v, this);
}
@Override
public void openItem(int windowDisposition) {
mNavigationDelegate.openUrl(
windowDisposition, new LoadUrlParams(getUrl(), PageTransition.AUTO_BOOKMARK));
}
@Override
public void removeItem() {} // TODO(chili): Add removal method.
@Override
public String getUrl() {
return mSiteUrl;
}
@Override
public boolean isItemSupported(@ContextMenuManager.ContextMenuItemId int menuItemId) {
if (menuItemId == ContextMenuManager.ContextMenuItemId.LEARN_MORE) {
return false;
}
return true;
}
@Override
public void onContextMenuCreated(){};
}
private class ExploreSitesSiteViewBinder
implements PropertyModelChangeProcessor
.ViewBinder<PropertyModel, ExploreSitesTileView, PropertyKey> {
@Override
public void bind(PropertyModel model, ExploreSitesTileView view, PropertyKey key) {
if (key == ExploreSitesSite.ICON_KEY) {
view.updateIcon(model.get(ExploreSitesSite.ICON_KEY),
model.get(ExploreSitesSite.TITLE_KEY));
} else if (key == ExploreSitesSite.TITLE_KEY) {
view.setTitle(model.get(ExploreSitesSite.TITLE_KEY), TITLE_LINES);
} else if (key == ExploreSitesSite.URL_KEY) {
// Attach click handlers.
CategoryCardInteractionDelegate interactionDelegate =
new CategoryCardInteractionDelegate(model.get(ExploreSitesSite.URL_KEY));
view.setOnClickListener(interactionDelegate);
view.setOnCreateContextMenuListener(interactionDelegate);
}
}
}
public ExploreSitesCategoryCardView(Context context, AttributeSet attrs) {
super(context, attrs);
mModelChangeProcessors = new ArrayList<>(MAX_TILE_COUNT);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTitleView = findViewById(R.id.category_title);
mTileView = findViewById(R.id.category_sites);
}
public void setCategory(ExploreSitesCategory category, RoundedIconGenerator iconGenerator,
ContextMenuManager contextMenuManager, NativePageNavigationDelegate navigationDelegate,
Profile profile) {
mIconGenerator = iconGenerator;
mContextMenuManager = contextMenuManager;
mNavigationDelegate = navigationDelegate;
mProfile = profile;
updateTitle(category.getTitle());
updateTileViews(category.getSites());
}
public void updateTitle(String categoryTitle) {
mTitleView.setText(categoryTitle);
}
public void updateTileViews(List<ExploreSitesSite> sites) {
// Clear observers.
for (PropertyModelChangeProcessor<PropertyModel, ExploreSitesTileView, PropertyKey>
observer : mModelChangeProcessors) {
observer.destroy();
}
mModelChangeProcessors.clear();
// Remove extra tiles if too many.
if (mTileView.getChildCount() > sites.size()) {
mTileView.removeViews(sites.size(), mTileView.getChildCount() - sites.size());
}
// Maximum number of sites to show.
int tileMax = Math.min(MAX_TILE_COUNT, sites.size());
// Add tiles if too few
if (mTileView.getChildCount() < tileMax) {
for (int i = mTileView.getChildCount(); i < tileMax; i++) {
mTileView.addView(LayoutInflater.from(getContext())
.inflate(R.layout.explore_sites_tile_view, mTileView,
/* attachToRoot = */ false));
}
}
// Initialize all the non-empty tiles again to update.
for (int i = 0; i < tileMax; i++) {
ExploreSitesTileView tileView = (ExploreSitesTileView) mTileView.getChildAt(i);
final PropertyModel site = sites.get(i).getModel();
tileView.initialize(mIconGenerator);
mModelChangeProcessors.add(PropertyModelChangeProcessor.create(
site, tileView, new ExploreSitesSiteViewBinder()));
// Fetch icon if not present already.
if (site.get(ExploreSitesSite.ICON_KEY) == null) {
ExploreSitesBridge.getSiteImage(mProfile, site.get(ExploreSitesSite.ID_KEY),
(Bitmap icon) -> site.set(ExploreSitesSite.ICON_KEY, icon));
}
}
}
}