Commit 2df35f29 authored by Shakti Sahu's avatar Shakti Sahu Committed by Commit Bot

Download Home : Decoupled SelectionDelegate from list item view

Removed using SelectableItemView in download home. Instead properties for
selected and selectionModeActive will be set into the ListItem from the mediator.

Bug: 850600, 868205
Change-Id: I36d98b4f7cfde8d6c8a93adae091cd8024b14e3c
Reviewed-on: https://chromium-review.googlesource.com/1150810Reviewed-by: default avatarTheresa <twellington@chromium.org>
Commit-Queue: Shakti Sahu <shaktisahu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580249}
parent 7398fb38
...@@ -29,6 +29,17 @@ ...@@ -29,6 +29,17 @@
app:layout_gravity="center_vertical" app:layout_gravity="center_vertical"
app:chrometint="@color/dark_mode_tint" /> app:chrometint="@color/dark_mode_tint" />
<org.chromium.chrome.browser.download.home.view.SelectionView
android:id="@+id/selection"
android:layout_width="@dimen/download_manager_generic_thumbnail_size"
android:layout_height="@dimen/download_manager_generic_thumbnail_size"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_column="0"
app:layout_row="0"
app:layout_rowSpan="2"
app:layout_gravity="center_vertical" />
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
style="@style/DownloadItemText" style="@style/DownloadItemText"
......
...@@ -21,14 +21,12 @@ ...@@ -21,14 +21,12 @@
android:layout_gravity="center" android:layout_gravity="center"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<org.chromium.chrome.browser.widget.TintedImageView <org.chromium.chrome.browser.download.home.view.SelectionView
android:id="@+id/selection" android:id="@+id/selection"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:layout_gravity="start|top" android:layout_gravity="start|top"
android:layout_marginStart="6dp" android:layout_marginStart="6dp"
android:layout_marginTop="6dp" android:layout_marginTop="6dp"/>
android:visibility="gone"
app:chrometint="@color/dark_mode_tint"/>
</FrameLayout> </FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<org.chromium.chrome.browser.widget.TintedImageView
android:id="@+id/check"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"
android:background="@drawable/list_item_icon_modern_bg"
android:visibility="gone"
app:chrometint="@color/white_mode_tint"
app:layout_gravity="center"
tools:ignore="ContentDescription" />
<org.chromium.chrome.browser.widget.TintedImageView
android:id="@+id/circle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@null"
android:src="@drawable/download_circular_selector_transparent"
android:visibility="gone"
app:chrometint="@null"
tools:ignore="ContentDescription"/>
</merge>
...@@ -46,12 +46,39 @@ class DateOrderedListMediator { ...@@ -46,12 +46,39 @@ class DateOrderedListMediator {
private final OfflineItemSource mSource; private final OfflineItemSource mSource;
private final DateOrderedListMutator mListMutator; private final DateOrderedListMutator mListMutator;
private final ThumbnailProvider mThumbnailProvider; private final ThumbnailProvider mThumbnailProvider;
private final MediatorSelectionObserver mSelectionObserver;
private final OffTheRecordOfflineItemFilter mOffTheRecordFilter; private final OffTheRecordOfflineItemFilter mOffTheRecordFilter;
private final DeleteUndoOfflineItemFilter mDeleteUndoFilter; private final DeleteUndoOfflineItemFilter mDeleteUndoFilter;
private final TypeOfflineItemFilter mTypeFilter; private final TypeOfflineItemFilter mTypeFilter;
private final SearchOfflineItemFilter mSearchFilter; private final SearchOfflineItemFilter mSearchFilter;
/**
* A selection observer that correctly updates the selection state for each item in the list.
*/
private class MediatorSelectionObserver
implements SelectionDelegate.SelectionObserver<ListItem> {
private final SelectionDelegate<ListItem> mSelectionDelegate;
public MediatorSelectionObserver(SelectionDelegate<ListItem> delegate) {
mSelectionDelegate = delegate;
mSelectionDelegate.addObserver(this);
}
@Override
public void onSelectionStateChange(List<ListItem> selectedItems) {
for (int i = 0; i < mModel.size(); i++) {
ListItem item = mModel.get(i);
boolean selected = mSelectionDelegate.isItemSelected(item);
item.showSelectedAnimation = selected && !item.selected;
item.selected = selected;
mModel.setItem(i, item);
}
mModel.dispatchLastEvent();
mModel.getProperties().setSelectionModeActive(mSelectionDelegate.isSelectionEnabled());
}
}
/** /**
* Creates an instance of a DateOrderedListMediator that will push {@code provider} into * Creates an instance of a DateOrderedListMediator that will push {@code provider} into
* {@code model}. * {@code model}.
...@@ -86,6 +113,7 @@ class DateOrderedListMediator { ...@@ -86,6 +113,7 @@ class DateOrderedListMediator {
mThumbnailProvider = new ThumbnailProviderImpl( mThumbnailProvider = new ThumbnailProviderImpl(
((ChromeApplication) ContextUtils.getApplicationContext()).getReferencePool()); ((ChromeApplication) ContextUtils.getApplicationContext()).getReferencePool());
mSelectionObserver = new MediatorSelectionObserver(selectionDelegate);
mModel.getProperties().setEnableItemAnimations(true); mModel.getProperties().setEnableItemAnimations(true);
mModel.getProperties().setOpenCallback(mProvider::openItem); mModel.getProperties().setOpenCallback(mProvider::openItem);
...@@ -95,7 +123,7 @@ class DateOrderedListMediator { ...@@ -95,7 +123,7 @@ class DateOrderedListMediator {
mModel.getProperties().setShareCallback(item -> {}); mModel.getProperties().setShareCallback(item -> {});
mModel.getProperties().setRemoveCallback(this::onDeleteItem); mModel.getProperties().setRemoveCallback(this::onDeleteItem);
mModel.getProperties().setVisualsProvider(this::getVisuals); mModel.getProperties().setVisualsProvider(this::getVisuals);
mModel.getProperties().setSelectionDelegate(selectionDelegate); mModel.getProperties().setSelectionCallback(selectionDelegate::toggleSelectionForItem);
} }
/** Tears down this mediator. */ /** Tears down this mediator. */
......
...@@ -16,6 +16,12 @@ import java.util.Date; ...@@ -16,6 +16,12 @@ import java.util.Date;
public abstract class ListItem { public abstract class ListItem {
public final long stableId; public final long stableId;
/** Indicates that we are in multi-select mode and the item is currently selected. */
public boolean selected;
/** Whether animation should be shown for the recent change in selection state for this item. */
public boolean showSelectedAnimation;
/** Creates a {@link ListItem} instance. */ /** Creates a {@link ListItem} instance. */
ListItem(long stableId) { ListItem(long stableId) {
this.stableId = stableId; this.stableId = stableId;
......
...@@ -6,7 +6,6 @@ package org.chromium.chrome.browser.download.home.list; ...@@ -6,7 +6,6 @@ package org.chromium.chrome.browser.download.home.list;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.chrome.browser.modelutil.PropertyObservable; import org.chromium.chrome.browser.modelutil.PropertyObservable;
import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItem;
import org.chromium.components.offline_items_collection.OfflineItemVisuals; import org.chromium.components.offline_items_collection.OfflineItemVisuals;
import org.chromium.components.offline_items_collection.VisualsCallback; import org.chromium.components.offline_items_collection.VisualsCallback;
...@@ -41,6 +40,8 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop ...@@ -41,6 +40,8 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop
static final PropertyKey CALLBACK_CANCEL = new PropertyKey(); static final PropertyKey CALLBACK_CANCEL = new PropertyKey();
static final PropertyKey CALLBACK_SHARE = new PropertyKey(); static final PropertyKey CALLBACK_SHARE = new PropertyKey();
static final PropertyKey CALLBACK_REMOVE = new PropertyKey(); static final PropertyKey CALLBACK_REMOVE = new PropertyKey();
static final PropertyKey CALLBACK_SELECTION = new PropertyKey();
static final PropertyKey SELECTION_MODE_ACTIVE = new PropertyKey();
// Utility properties. // Utility properties.
static final PropertyKey PROVIDER_VISUALS = new PropertyKey(); static final PropertyKey PROVIDER_VISUALS = new PropertyKey();
...@@ -49,14 +50,15 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop ...@@ -49,14 +50,15 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop
} }
private boolean mEnableItemAnimations; private boolean mEnableItemAnimations;
private boolean mSelectionModeActive;
private Callback<OfflineItem> mOpenCallback; private Callback<OfflineItem> mOpenCallback;
private Callback<OfflineItem> mPauseCallback; private Callback<OfflineItem> mPauseCallback;
private Callback<OfflineItem> mResumeCallback; private Callback<OfflineItem> mResumeCallback;
private Callback<OfflineItem> mCancelCallback; private Callback<OfflineItem> mCancelCallback;
private Callback<OfflineItem> mShareCallback; private Callback<OfflineItem> mShareCallback;
private Callback<OfflineItem> mRemoveCallback; private Callback<OfflineItem> mRemoveCallback;
private Callback<ListItem> mSelectionCallback;
private VisualsProvider mVisualsProvider; private VisualsProvider mVisualsProvider;
private SelectionDelegate<ListItem> mSelectionDelegate;
/** Sets whether or not item animations should be enabled. */ /** Sets whether or not item animations should be enabled. */
public void setEnableItemAnimations(boolean enableItemAnimations) { public void setEnableItemAnimations(boolean enableItemAnimations) {
...@@ -70,6 +72,18 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop ...@@ -70,6 +72,18 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop
return mEnableItemAnimations; return mEnableItemAnimations;
} }
/** Sets whether or not selection mode is currently active. */
public void setSelectionModeActive(boolean selectionModeActive) {
if (mSelectionModeActive == selectionModeActive) return;
mSelectionModeActive = selectionModeActive;
notifyPropertyChanged(PropertyKey.SELECTION_MODE_ACTIVE);
}
/** @return Whether or not selection mode is currently active. */
public boolean getSelectionModeActive() {
return mSelectionModeActive;
}
/** Sets the callback for when a UI action should open a {@link OfflineItem}. */ /** Sets the callback for when a UI action should open a {@link OfflineItem}. */
public void setOpenCallback(Callback<OfflineItem> callback) { public void setOpenCallback(Callback<OfflineItem> callback) {
if (mOpenCallback == callback) return; if (mOpenCallback == callback) return;
...@@ -154,13 +168,15 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop ...@@ -154,13 +168,15 @@ public class ListPropertyModel extends PropertyObservable<ListPropertyModel.Prop
return mVisualsProvider; return mVisualsProvider;
} }
/** Sets the selection delegate to handle selection of list items. */ /** Sets the callback for when an {@link ListItem} is selected or deselected on the UI. */
public void setSelectionDelegate(SelectionDelegate<ListItem> selectionDelegate) { public void setSelectionCallback(Callback<ListItem> callback) {
mSelectionDelegate = selectionDelegate; if (mSelectionCallback == callback) return;
mSelectionCallback = callback;
notifyPropertyChanged(PropertyKey.CALLBACK_SELECTION);
} }
/** @return The selection delegate to handle multiple item selections. */ /** @return The callback to trigger when a UI action selects or deselects a {@link ListItem}. */
public SelectionDelegate<ListItem> getSelectionDelegate() { public Callback<ListItem> getSelectionCallback() {
return mSelectionDelegate; return mSelectionCallback;
} }
} }
...@@ -33,7 +33,9 @@ class ListPropertyViewBinder ...@@ -33,7 +33,9 @@ class ListPropertyViewBinder
|| propertyKey == ListPropertyModel.PropertyKey.CALLBACK_CANCEL || propertyKey == ListPropertyModel.PropertyKey.CALLBACK_CANCEL
|| propertyKey == ListPropertyModel.PropertyKey.CALLBACK_SHARE || propertyKey == ListPropertyModel.PropertyKey.CALLBACK_SHARE
|| propertyKey == ListPropertyModel.PropertyKey.CALLBACK_REMOVE || propertyKey == ListPropertyModel.PropertyKey.CALLBACK_REMOVE
|| propertyKey == ListPropertyModel.PropertyKey.PROVIDER_VISUALS) { || propertyKey == ListPropertyModel.PropertyKey.PROVIDER_VISUALS
|| propertyKey == ListPropertyModel.PropertyKey.CALLBACK_SELECTION
|| propertyKey == ListPropertyModel.PropertyKey.SELECTION_MODE_ACTIVE) {
view.getAdapter().notifyItemChanged(0, view.getAdapter().getItemCount()); view.getAdapter().notifyItemChanged(0, view.getAdapter().getItemCount());
} }
} }
......
...@@ -4,11 +4,9 @@ ...@@ -4,11 +4,9 @@
package org.chromium.chrome.browser.download.home.list.holder; package org.chromium.chrome.browser.download.home.list.holder;
import android.content.res.ColorStateList;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
import android.support.v4.graphics.drawable.RoundedBitmapDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
import android.support.v7.content.res.AppCompatResources; import android.support.v7.content.res.AppCompatResources;
...@@ -19,10 +17,10 @@ import android.widget.ImageView; ...@@ -19,10 +17,10 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.download.DownloadUtils;
import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.ListItem;
import org.chromium.chrome.browser.download.home.list.ListPropertyModel; import org.chromium.chrome.browser.download.home.list.ListPropertyModel;
import org.chromium.chrome.browser.download.home.list.UiUtils; import org.chromium.chrome.browser.download.home.list.UiUtils;
import org.chromium.chrome.browser.download.home.view.SelectionView;
import org.chromium.chrome.browser.widget.TintedImageView; import org.chromium.chrome.browser.widget.TintedImageView;
import org.chromium.components.offline_items_collection.OfflineItemVisuals; import org.chromium.components.offline_items_collection.OfflineItemVisuals;
...@@ -31,9 +29,6 @@ import org.chromium.components.offline_items_collection.OfflineItemVisuals; ...@@ -31,9 +29,6 @@ import org.chromium.components.offline_items_collection.OfflineItemVisuals;
public class GenericViewHolder extends ThumbnailAwareViewHolder { public class GenericViewHolder extends ThumbnailAwareViewHolder {
private static final int INVALID_ID = -1; private static final int INVALID_ID = -1;
private final ColorStateList mCheckedIconForegroundColorList;
private final AnimatedVectorDrawableCompat mCheckDrawable;
private final TextView mTitle; private final TextView mTitle;
private final TextView mCaption; private final TextView mCaption;
private final TintedImageView mThumbnailView; private final TintedImageView mThumbnailView;
...@@ -61,11 +56,6 @@ public class GenericViewHolder extends ThumbnailAwareViewHolder { ...@@ -61,11 +56,6 @@ public class GenericViewHolder extends ThumbnailAwareViewHolder {
mTitle = (TextView) itemView.findViewById(R.id.title); mTitle = (TextView) itemView.findViewById(R.id.title);
mCaption = (TextView) itemView.findViewById(R.id.caption); mCaption = (TextView) itemView.findViewById(R.id.caption);
mThumbnailView = (TintedImageView) itemView.findViewById(R.id.thumbnail); mThumbnailView = (TintedImageView) itemView.findViewById(R.id.thumbnail);
mCheckDrawable = AnimatedVectorDrawableCompat.create(
itemView.getContext(), R.drawable.ic_check_googblue_24dp_animated);
mCheckedIconForegroundColorList =
DownloadUtils.getIconForegroundColorList(itemView.getContext());
} }
// ListItemViewHolder implementation. // ListItemViewHolder implementation.
...@@ -89,18 +79,9 @@ public class GenericViewHolder extends ThumbnailAwareViewHolder { ...@@ -89,18 +79,9 @@ public class GenericViewHolder extends ThumbnailAwareViewHolder {
private void updateThumbnailView() { private void updateThumbnailView() {
Resources resources = itemView.getContext().getResources(); Resources resources = itemView.getContext().getResources();
SelectionView selectionView = itemView.findViewById(R.id.selection);
// TODO(shaktisahu): Pass the appropriate value of selection. mThumbnailView.setVisibility(selectionView.isSelected() ? View.GONE : View.VISIBLE);
boolean selected = false; if (mThumbnailBitmap != null) {
if (selected) {
mThumbnailView.setBackgroundResource(R.drawable.list_item_icon_modern_bg);
mThumbnailView.getBackground().setLevel(
resources.getInteger(R.integer.list_item_level_selected));
mThumbnailView.setImageDrawable(mCheckDrawable);
mThumbnailView.setTint(mCheckedIconForegroundColorList);
mCheckDrawable.start();
} else if (mThumbnailBitmap != null) {
assert !mThumbnailBitmap.isRecycled(); assert !mThumbnailBitmap.isRecycled();
mThumbnailView.setBackground(null); mThumbnailView.setBackground(null);
......
...@@ -4,27 +4,18 @@ ...@@ -4,27 +4,18 @@
package org.chromium.chrome.browser.download.home.list.holder; package org.chromium.chrome.browser.download.home.list.holder;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.download.DownloadUtils;
import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.ListItem;
import org.chromium.chrome.browser.download.home.list.ListPropertyModel; import org.chromium.chrome.browser.download.home.list.ListPropertyModel;
import org.chromium.chrome.browser.widget.TintedImageView;
import org.chromium.components.offline_items_collection.OfflineItemVisuals; import org.chromium.components.offline_items_collection.OfflineItemVisuals;
/** A {@link RecyclerView.ViewHolder} specifically meant to display an image {@code OfflineItem}. */ /** A {@link RecyclerView.ViewHolder} specifically meant to display an image {@code OfflineItem}. */
public class ImageViewHolder extends ThumbnailAwareViewHolder { public class ImageViewHolder extends ThumbnailAwareViewHolder {
private final TintedImageView mSelectionImage;
private final ColorStateList mCheckedIconForegroundColorList;
private final AnimatedVectorDrawableCompat mCheckDrawable;
public static org.chromium.chrome.browser.download.home.list.holder.ImageViewHolder create( public static org.chromium.chrome.browser.download.home.list.holder.ImageViewHolder create(
ViewGroup parent) { ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
...@@ -37,11 +28,6 @@ public class ImageViewHolder extends ThumbnailAwareViewHolder { ...@@ -37,11 +28,6 @@ public class ImageViewHolder extends ThumbnailAwareViewHolder {
public ImageViewHolder(View view, int thumbnailSizePx) { public ImageViewHolder(View view, int thumbnailSizePx) {
super(view, thumbnailSizePx, thumbnailSizePx); super(view, thumbnailSizePx, thumbnailSizePx);
mCheckDrawable = AnimatedVectorDrawableCompat.create(
itemView.getContext(), R.drawable.ic_check_googblue_24dp_animated);
mCheckedIconForegroundColorList =
DownloadUtils.getIconForegroundColorList(itemView.getContext());
mSelectionImage = (TintedImageView) itemView.findViewById(R.id.selection);
} }
// ThumbnailAwareViewHolder implementation. // ThumbnailAwareViewHolder implementation.
...@@ -51,39 +37,10 @@ public class ImageViewHolder extends ThumbnailAwareViewHolder { ...@@ -51,39 +37,10 @@ public class ImageViewHolder extends ThumbnailAwareViewHolder {
ListItem.OfflineItemListItem offlineItem = (ListItem.OfflineItemListItem) item; ListItem.OfflineItemListItem offlineItem = (ListItem.OfflineItemListItem) item;
View imageView = itemView.findViewById(R.id.thumbnail); View imageView = itemView.findViewById(R.id.thumbnail);
imageView.setContentDescription(offlineItem.item.title); imageView.setContentDescription(offlineItem.item.title);
updateImageView();
} }
@Override @Override
void onVisualsChanged(ImageView view, OfflineItemVisuals visuals) { void onVisualsChanged(ImageView view, OfflineItemVisuals visuals) {
view.setImageBitmap(visuals == null ? null : visuals.icon); view.setImageBitmap(visuals == null ? null : visuals.icon);
updateImageView();
}
protected void updateImageView() {
Resources resources = itemView.getContext().getResources();
// TODO(shaktisahu): Pass the appropriate value of selection.
boolean selected = false;
boolean selectionModeActive = false;
if (selected) {
mSelectionImage.setVisibility(View.VISIBLE);
mSelectionImage.setBackgroundResource(R.drawable.list_item_icon_modern_bg);
mSelectionImage.getBackground().setLevel(
resources.getInteger(R.integer.list_item_level_selected));
mSelectionImage.setImageDrawable(mCheckDrawable);
mSelectionImage.setTint(mCheckedIconForegroundColorList);
mCheckDrawable.start();
} else if (selectionModeActive) {
mSelectionImage.setVisibility(View.VISIBLE);
mSelectionImage.setBackground(null);
mSelectionImage.setTint(null);
mSelectionImage.setImageResource(R.drawable.download_circular_selector_transparent);
} else {
mSelectionImage.setBackground(null);
mSelectionImage.setTint(null);
mSelectionImage.setVisibility(View.GONE);
}
} }
} }
...@@ -37,6 +37,7 @@ class MoreButtonViewHolder extends ListItemViewHolder implements ListMenuButton. ...@@ -37,6 +37,7 @@ class MoreButtonViewHolder extends ListItemViewHolder implements ListMenuButton.
ListItem.OfflineItemListItem offlineItem = (ListItem.OfflineItemListItem) item; ListItem.OfflineItemListItem offlineItem = (ListItem.OfflineItemListItem) item;
mShareCallback = () -> properties.getShareCallback().onResult(offlineItem.item); mShareCallback = () -> properties.getShareCallback().onResult(offlineItem.item);
mDeleteCallback = () -> properties.getRemoveCallback().onResult(offlineItem.item); mDeleteCallback = () -> properties.getRemoveCallback().onResult(offlineItem.item);
if (mMore != null) mMore.setClickable(!properties.getSelectionModeActive());
} }
// ListMenuButton.Delegate implementation. // ListMenuButton.Delegate implementation.
......
...@@ -12,6 +12,7 @@ import android.widget.ImageView; ...@@ -12,6 +12,7 @@ import android.widget.ImageView;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.ListItem;
import org.chromium.chrome.browser.download.home.list.ListPropertyModel; import org.chromium.chrome.browser.download.home.list.ListPropertyModel;
import org.chromium.chrome.browser.download.home.view.SelectionView;
import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.ContentId;
import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItem;
import org.chromium.components.offline_items_collection.OfflineItemVisuals; import org.chromium.components.offline_items_collection.OfflineItemVisuals;
...@@ -22,6 +23,7 @@ import org.chromium.components.offline_items_collection.VisualsCallback; ...@@ -22,6 +23,7 @@ import org.chromium.components.offline_items_collection.VisualsCallback;
*/ */
abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements VisualsCallback { abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements VisualsCallback {
private final ImageView mThumbnail; private final ImageView mThumbnail;
private final SelectionView mSelectionView;
/** /**
* The {@link ContentId} of the associated thumbnail/request if any. * The {@link ContentId} of the associated thumbnail/request if any.
...@@ -58,6 +60,7 @@ abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements ...@@ -58,6 +60,7 @@ abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements
super(view); super(view);
mThumbnail = (ImageView) view.findViewById(R.id.thumbnail); mThumbnail = (ImageView) view.findViewById(R.id.thumbnail);
mSelectionView = itemView.findViewById(R.id.selection);
mWidthPx = thumbnailWidthPx; mWidthPx = thumbnailWidthPx;
mHeightPx = thumbnailHeightPx; mHeightPx = thumbnailHeightPx;
} }
...@@ -73,9 +76,27 @@ abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements ...@@ -73,9 +76,27 @@ abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements
OfflineItem offlineItem = ((ListItem.OfflineItemListItem) item).item; OfflineItem offlineItem = ((ListItem.OfflineItemListItem) item).item;
// If we're rebinding the same item, ignore the bind. // If we're rebinding the same item, ignore the bind.
if (offlineItem.id.equals(mId)) return; if (offlineItem.id.equals(mId) && !selectionStateHasChanged(properties, item)) {
return;
// TODO(shaktisahu): Add callbacks for selection and open. }
if (mSelectionView != null) {
mSelectionView.setSelectionState(
item.selected, properties.getSelectionModeActive(), item.showSelectedAnimation);
}
itemView.setOnLongClickListener(v -> {
properties.getSelectionCallback().onResult(item);
return true;
});
itemView.setOnClickListener(v -> {
if (mSelectionView != null && mSelectionView.isInSelectionMode()) {
properties.getSelectionCallback().onResult(item);
} else {
properties.getOpenCallback().onResult(offlineItem);
}
});
// Clear any associated bitmap from the thumbnail. // Clear any associated bitmap from the thumbnail.
if (mId != null) onVisualsChanged(mThumbnail, null); if (mId != null) onVisualsChanged(mThumbnail, null);
...@@ -92,6 +113,13 @@ abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements ...@@ -92,6 +113,13 @@ abstract class ThumbnailAwareViewHolder extends MoreButtonViewHolder implements
if (!mIsRequesting) mCancellable = null; if (!mIsRequesting) mCancellable = null;
} }
private boolean selectionStateHasChanged(ListPropertyModel properties, ListItem item) {
if (mSelectionView == null) return false;
return mSelectionView.isSelected() != item.selected
|| mSelectionView.isInSelectionMode() != properties.getSelectionModeActive();
}
// VisualsCallback implementation. // VisualsCallback implementation.
@Override @Override
public void onVisualsAvailable(ContentId id, OfflineItemVisuals visuals) { public void onVisualsAvailable(ContentId id, OfflineItemVisuals visuals) {
......
// 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.download.home.view;
import android.content.Context;
import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.widget.TintedImageView;
/**
* A helper UI widget that provides visual feedback when the selection state of the underlying view
* is changed. The widget represents three distinct states : selected, in selection mode and not
* selected. The caller can define the UI behavior at each of these states by subclassing this view.
*/
public class SelectionView extends FrameLayout {
private final TintedImageView mCheck;
private final TintedImageView mCircle;
private final AnimatedVectorDrawableCompat mCheckDrawable;
private boolean mIsSelected;
private boolean mInSelectionMode;
private boolean mShowSelectedAnimation;
/** Constructor for inflating from XML. */
public SelectionView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.list_selection_handle_view, this, true);
mCheck = (TintedImageView) findViewById(R.id.check);
mCircle = (TintedImageView) findViewById(R.id.circle);
mCheckDrawable = AnimatedVectorDrawableCompat.create(
context, R.drawable.ic_check_googblue_24dp_animated);
}
@Override
public boolean isSelected() {
return mIsSelected;
}
/** @return Whether the selection mode is currently active. */
public boolean isInSelectionMode() {
return mInSelectionMode;
}
/**
* Called to inform the view about its current selection state.
* @param selected Whether the item is currently selected.
* @param inSelectionMode Whether we are currently in active selection mode.
* @param showSelectedAnimation Whether the item was recently selected from an unselected state
* and animation should be shown.
*/
public void setSelectionState(
boolean selected, boolean inSelectionMode, boolean showSelectedAnimation) {
mIsSelected = selected;
mInSelectionMode = inSelectionMode;
mShowSelectedAnimation = showSelectedAnimation;
updateView();
}
private void updateView() {
if (mIsSelected) {
mCheck.setVisibility(VISIBLE);
mCircle.setVisibility(GONE);
mCheck.setImageDrawable(mCheckDrawable);
mCheck.getBackground().setLevel(
getResources().getInteger(R.integer.list_item_level_selected));
if (mShowSelectedAnimation) mCheckDrawable.start();
} else if (mInSelectionMode) {
mCheck.setVisibility(GONE);
mCircle.setVisibility(VISIBLE);
} else {
mCheck.setVisibility(GONE);
mCircle.setVisibility(GONE);
}
}
}
...@@ -500,6 +500,7 @@ chrome_java_sources = [ ...@@ -500,6 +500,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java", "java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java",
"java/src/org/chromium/chrome/browser/download/home/snackbars/DeleteUndoCoordinator.java", "java/src/org/chromium/chrome/browser/download/home/snackbars/DeleteUndoCoordinator.java",
"java/src/org/chromium/chrome/browser/download/home/snackbars/UndoUiUtils.java", "java/src/org/chromium/chrome/browser/download/home/snackbars/UndoUiUtils.java",
"java/src/org/chromium/chrome/browser/download/home/view/SelectionView.java",
"java/src/org/chromium/chrome/browser/download/items/DownloadBlockedOfflineContentProvider.java", "java/src/org/chromium/chrome/browser/download/items/DownloadBlockedOfflineContentProvider.java",
"java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorFactory.java", "java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorFactory.java",
"java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java", "java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java",
......
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