Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkItemsAdapter.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.enhancedbookmarks;
6
7 import android.content.Context;
8 import android.support.v7.widget.RecyclerView;
9 import android.support.v7.widget.RecyclerView.ViewHolder;
10 import android.view.LayoutInflater;
11 import android.view.View;
12 import android.view.View.OnClickListener;
13 import android.view.View.OnLongClickListener;
14 import android.view.ViewGroup;
15 import android.widget.Checkable;
16
17 import com.google.android.apps.chrome.R;
18
19 import org.chromium.base.annotations.SuppressFBWarnings;
20 import org.chromium.chrome.browser.BookmarksBridge.BookmarkItem;
21 import org.chromium.chrome.browser.BookmarksBridge.BookmarkModelObserver;
22 import org.chromium.chrome.browser.enhanced_bookmarks.EnhancedBookmarksBridge.Fi ltersObserver;
23 import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkPromoHeader .PromoHeaderShowingChangeListener;
24 import org.chromium.chrome.browser.util.MathUtils;
25 import org.chromium.components.bookmarks.BookmarkId;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 /**
31 * BaseAdapter for EnhancedBookmarkItemsContainer. It manages bookmarks to list there.
32 */
33 class EnhancedBookmarkItemsAdapter extends RecyclerView.Adapter<RecyclerView.Vie wHolder> implements
34 EnhancedBookmarkUIObserver, PromoHeaderShowingChangeListener {
35
36 /**
37 * An abstraction for the common functionalities for {@link EnhancedBookmark Folder} and
38 * {@link EnhancedBookmarkItem}
39 */
40 public interface BookmarkGrid extends OnClickListener, Checkable {
41 /**
42 * Sets the bookmarkId the object is holding. Corresponding UI changes m ight occur.
43 */
44 public void setBookmarkId(BookmarkId id);
45
46 /**
47 * @return The bookmark that the object is holding.
48 */
49 public BookmarkId getBookmarkId();
50 }
51
52 public static final int PROMO_HEADER_GRID = 0;
53 public static final int FOLDER_VIEW_GRID = 1;
54 public static final int PADDING_VIEW = 2;
55 public static final int BOOKMARK_VIEW_GRID = 3;
56
57 // Have different view types for list and grid modes, in order to force the recycler not reuse
58 // the same tiles across the two modes.
59 public static final int PROMO_HEADER_LIST = 4;
60 public static final int FOLDER_VIEW_LIST = 5;
61 public static final int DIVIDER_LIST = 6;
62 public static final int BOOKMARK_VIEW_LIST = 7;
63
64 private EnhancedBookmarkDelegate mDelegate;
65 private Context mContext;
66 private EnhancedBookmarkPromoHeader mPromoHeaderManager;
67 private ItemFactory mItemFactory;
68 private List<BookmarkId> mFolders = new ArrayList<BookmarkId>();
69 private List<BookmarkId> mBookmarks = new ArrayList<BookmarkId>();
70
71 // These are used to track placeholder invisible view between folder items a nd bookmark items,
72 // to align the beginning of the bookmark items to be the first column.
73 // In list mode, this variable represents the presence of the divider, eithe r 1 or 0.
74 private int mEmptyViewCount;
75 private int mColumnCount = 1;
76
77 private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObse rver() {
78 @Override
79 public void bookmarkNodeChanged(BookmarkItem node) {
80 int position = getPositionForBookmark(node.getId());
81 if (position >= 0) notifyItemChanged(position);
82 }
83
84 @Override
85 public void bookmarkNodeRemoved(BookmarkItem parent, int oldIndex, Bookm arkItem node,
86 boolean isDoingExtensiveChanges) {
87 if (node.isFolder()) {
88 mDelegate.notifyStateChange(EnhancedBookmarkItemsAdapter.this);
89 } else {
90 int deletedPosition = getPositionForBookmark(node.getId());
91 if (deletedPosition >= 0) {
92 removeItem(deletedPosition);
93 }
94 }
95 }
96
97 @Override
98 public void bookmarkModelChanged() {
99 mDelegate.notifyStateChange(EnhancedBookmarkItemsAdapter.this);
100 }
101 };
102
103 private FiltersObserver mFiltersObserver = new FiltersObserver() {
104 @Override
105 public void onFiltersChanged() {
106 if (mDelegate.getCurrentState() == EnhancedBookmarkDelegate.STATE_FI LTER) {
107 mDelegate.notifyStateChange(EnhancedBookmarkItemsAdapter.this);
108 }
109 }
110 };
111
112 EnhancedBookmarkItemsAdapter(Context context) {
113 mContext = context;
114 }
115
116 /**
117 * @return Whether the first item is header.
118 */
119 boolean isHeader(int position) {
120 int type = getItemViewType(position);
121 return type == PROMO_HEADER_GRID || type == PROMO_HEADER_LIST;
122 }
123
124 /**
125 * Set folders and bookmarks to show. Will trigger animation provided by ite m animator.
126 * @param folders This can be null if there is no folders to show.
127 */
128 void setBookmarks(List<BookmarkId> folders, List<BookmarkId> bookmarks) {
129 if (folders == null) folders = new ArrayList<BookmarkId>();
130 notifyItemRangeRemoved(0, getItemCount());
131 mFolders = folders;
132 mBookmarks = bookmarks;
133 updateEmptyViewCount();
134 notifyItemRangeInserted(0, getItemCount());
135 }
136
137 /**
138 * Set number of columns. This information will be used to align the startin g position of
139 * bookmarks to be the beginning of the row.
140 *
141 * This is a hacky responsibility violation, since adapter shouldn't care ab out the way items
142 * are presented in the UI. However, there is no other easy way to do this c orrectly with
143 * GridView.
144 */
145 void setNumColumns(int columnNumber) {
146 if (mColumnCount == columnNumber) return;
147 mColumnCount = columnNumber;
148 updateDataset();
149 }
150
151 /**
152 * If called, recycler view will be brutally reset and no animation will be shown.
153 */
154 void updateDataset() {
155 updateEmptyViewCount();
156 notifyDataSetChanged();
157 }
158
159 private void updateEmptyViewCount() {
160 if (mDelegate.isListModeEnabled()) mEmptyViewCount = mFolders.size() > 0 ? 1 : 0;
161 else mEmptyViewCount = MathUtils.positiveModulo(-mFolders.size(), mColum nCount);
162 }
163
164 private int getHeaderItemsCount() {
165 // In listview a promo header carries a divider below it.
166 if (mPromoHeaderManager.isShowing()) {
167 return mDelegate.isListModeEnabled() ? 2 : 1;
168 }
169 return 0;
170 }
171
172 @Override
173 public int getItemCount() {
174 return getHeaderItemsCount() + mFolders.size() + mEmptyViewCount + mBook marks.size();
175 }
176
177 /**
178 * @return The position of the given bookmark in adapter. Will return -1 if not found.
179 */
180 int getPositionForBookmark(BookmarkId bookmark) {
181 assert bookmark != null;
182 int position = -1;
183 for (int i = 0; i < getItemCount(); i++) {
184 if (bookmark.equals(getItem(i))) {
185 position = i;
186 break;
187 }
188 }
189 return position;
190 }
191
192 BookmarkId getItem(int position) {
193 switch(getItemViewType(position)) {
194 case PROMO_HEADER_GRID:
195 case PROMO_HEADER_LIST:
196 return null;
197 case FOLDER_VIEW_GRID:
198 case FOLDER_VIEW_LIST:
199 return mFolders.get(position - getHeaderItemsCount());
200 case PADDING_VIEW:
201 case DIVIDER_LIST:
202 return null;
203 case BOOKMARK_VIEW_GRID:
204 case BOOKMARK_VIEW_LIST:
205 return mBookmarks.get(
206 position - getHeaderItemsCount() - mFolders.size() - mEm ptyViewCount);
207 default:
208 assert false;
209 return null;
210 }
211 }
212
213 void removeItem(int position) {
214 switch(getItemViewType(position)) {
215 case PROMO_HEADER_GRID:
216 case PROMO_HEADER_LIST:
217 assert false : "Promo header remove should be handled in PromoHe aderManager.";
218 break;
219 case FOLDER_VIEW_GRID:
220 case FOLDER_VIEW_LIST:
221 mFolders.remove(position - getHeaderItemsCount());
222 notifyItemRemoved(position);
223 break;
224 case PADDING_VIEW:
225 case DIVIDER_LIST:
226 assert false : "Cannot remove a padding view or a divider";
227 break;
228 case BOOKMARK_VIEW_GRID:
229 case BOOKMARK_VIEW_LIST:
230 mBookmarks.remove(
231 position
232 - getHeaderItemsCount()
233 - mFolders.size()
234 - mEmptyViewCount);
235 notifyItemRemoved(position);
236 break;
237 default:
238 assert false;
239 }
240 }
241
242 @Override
243 public int getItemViewType(int position) {
244 int i = position;
245
246 if (mPromoHeaderManager.isShowing()) {
247 if (mDelegate.isListModeEnabled()) {
248 if (i == 0) return PROMO_HEADER_LIST;
249 if (i == 1) return DIVIDER_LIST;
250 } else {
251 if (i == 0) return PROMO_HEADER_GRID;
252 }
253 }
254 i -= getHeaderItemsCount();
255
256 if (i < mFolders.size()) {
257 return mDelegate.isListModeEnabled() ? FOLDER_VIEW_LIST : FOLDER_VIE W_GRID;
258 }
259 i -= mFolders.size();
260
261 if (i < mEmptyViewCount) {
262 if (mDelegate.isListModeEnabled()) return DIVIDER_LIST;
263 else return PADDING_VIEW;
264 }
265 i -= mEmptyViewCount;
266
267 if (i < mBookmarks.size()) {
268 return mDelegate.isListModeEnabled() ? BOOKMARK_VIEW_LIST : BOOKMARK _VIEW_GRID;
269 }
270
271 assert false : "Invalid position requested";
272 return -1;
273 }
274
275 @Override
276 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
277 switch (viewType) {
278 case PROMO_HEADER_GRID:
279 case PROMO_HEADER_LIST:
280 return mPromoHeaderManager.createHolder(parent, mDelegate.isList ModeEnabled());
281 case FOLDER_VIEW_GRID:
282 case FOLDER_VIEW_LIST:
283 EnhancedBookmarkFolder folder = mItemFactory.createBookmarkFolde r(parent);
284 folder.setDelegate(mDelegate);
285 return new ItemViewHolder(folder, mDelegate);
286 case PADDING_VIEW:
287 // Padding views are empty place holders that will be set invisi ble.
288 return new ViewHolder(new View(parent.getContext())) {};
289 case DIVIDER_LIST:
290 return new ViewHolder(LayoutInflater.from(parent.getContext()).i nflate(
291 R.layout.eb_list_divider, parent, false)) {};
292 case BOOKMARK_VIEW_GRID:
293 case BOOKMARK_VIEW_LIST:
294 EnhancedBookmarkItem item = mItemFactory.createBookmarkItem(pare nt);
295 item.onEnhancedBookmarkDelegateInitialized(mDelegate);
296 return new ItemViewHolder(item, mDelegate);
297 default:
298 assert false;
299 return null;
300 }
301 }
302
303 @SuppressFBWarnings("BC_UNCONFIRMED_CAST")
304 @Override
305 public void onBindViewHolder(ViewHolder holder, int position) {
306 BookmarkId id = getItem(position);
307 switch (getItemViewType(position)) {
308 case PROMO_HEADER_GRID:
309 case PROMO_HEADER_LIST:
310 break;
311 case FOLDER_VIEW_GRID:
312 case FOLDER_VIEW_LIST:
313 ((ItemViewHolder) holder).setBookmarkId(id);
314 break;
315 case PADDING_VIEW:
316 case DIVIDER_LIST:
317 break;
318 case BOOKMARK_VIEW_GRID:
319 case BOOKMARK_VIEW_LIST:
320 ((ItemViewHolder) holder).setBookmarkId(id);
321 break;
322 default:
323 assert false : "View type not supported!";
324 }
325 }
326
327 // PromoHeaderShowingChangeListener implementation.
328
329 @Override
330 public void onPromoHeaderShowingChanged(boolean isShowing) {
331 if (isShowing) {
332 notifyItemInserted(0);
333 } else {
334 // TODO(kkimlabs): Ideally we want to animate by |notifyItemRemoved| but the default
335 // animation looks broken for this promo header for some reason.
336 notifyDataSetChanged();
337 }
338 }
339
340 // EnhancedBookmarkUIObserver implementations.
341
342 @Override
343 public void onEnhancedBookmarkDelegateInitialized(EnhancedBookmarkDelegate d elegate) {
344 mDelegate = delegate;
345 mDelegate.addUIObserver(this);
346 mDelegate.getModel().addModelObserver(mBookmarkModelObserver);
347 mDelegate.getModel().addFiltersObserver(mFiltersObserver);
348
349 mItemFactory = mDelegate.isListModeEnabled()
350 ? new ListItemFactory() : new GridItemFactory();
351
352 mPromoHeaderManager = new EnhancedBookmarkPromoHeader(mContext, this);
353 }
354
355 @Override
356 public void onDestroy() {
357 mDelegate.removeUIObserver(this);
358 mDelegate.getModel().removeModelObserver(mBookmarkModelObserver);
359 mDelegate.getModel().removeFiltersObserver(mFiltersObserver);
360
361 mPromoHeaderManager.destroy();
362 }
363
364 @Override
365 public void onAllBookmarksStateSet() {
366 setBookmarks(null, mDelegate.getModel().getAllBookmarkIDsOrderedByCreati onDate());
367 }
368
369 @Override
370 public void onFolderStateSet(BookmarkId folder) {
371 setBookmarks(mDelegate.getModel().getChildIDs(folder, true, false),
372 mDelegate.getModel().getChildIDs(folder, false, true));
373 }
374
375 @Override
376 public void onFilterStateSet(String filter) {
377 setBookmarks(null, mDelegate.getModel().getBookmarksForFilter(filter));
378 }
379
380 @Override
381 public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {}
382
383 @Override
384 public void onListModeChange(boolean isListModeEnabled) {
385 if (isListModeEnabled) {
386 setNumColumns(1);
387 mItemFactory = new EnhancedBookmarkItemsAdapter.ListItemFactory();
388 } else {
389 mItemFactory = new EnhancedBookmarkItemsAdapter.GridItemFactory();
390 }
391 updateDataset();
392 }
393
394 private static class ItemViewHolder extends RecyclerView.ViewHolder implemen ts OnClickListener,
395 OnLongClickListener {
396 private EnhancedBookmarkDelegate mDelegate;
397 private BookmarkGrid mGrid;
398
399 public ItemViewHolder(View view, EnhancedBookmarkDelegate delegate) {
400 super(view);
401 mGrid = (BookmarkGrid) view;
402 mDelegate = delegate;
403 view.setOnClickListener(this);
404 view.setOnLongClickListener(this);
405 }
406
407 public void setBookmarkId(BookmarkId id) {
408 mGrid.setBookmarkId(id);
409 mGrid.setChecked(mDelegate.isBookmarkSelected(mGrid.getBookmarkId()) );
410 }
411
412 @Override
413 public boolean onLongClick(View v) {
414 mGrid.setChecked(mDelegate.toggleSelectionForBookmark(mGrid.getBookm arkId()));
415 return true;
416 }
417
418 @Override
419 public void onClick(View v) {
420 if (mDelegate.isSelectionEnabled()) onLongClick(v);
421 else mGrid.onClick(itemView);
422 }
423 }
424
425 /**
426 * Factory interface to get the correct views to show.
427 */
428 private interface ItemFactory {
429 EnhancedBookmarkItem createBookmarkItem(ViewGroup parent);
430 EnhancedBookmarkFolder createBookmarkFolder(ViewGroup parent);
431 }
432
433 private static class GridItemFactory implements ItemFactory {
434 @Override
435 public EnhancedBookmarkItem createBookmarkItem(ViewGroup parent) {
436 return (EnhancedBookmarkItem) LayoutInflater.from(parent.getContext( )).inflate(
437 R.layout.eb_grid_item, parent, false);
438 }
439
440 @Override
441 public EnhancedBookmarkFolder createBookmarkFolder(ViewGroup parent) {
442 return (EnhancedBookmarkFolder) LayoutInflater.from(
443 parent.getContext()).inflate(R.layout.eb_grid_folder, parent , false);
444 }
445 }
446
447 private static class ListItemFactory implements ItemFactory {
448 @Override
449 public EnhancedBookmarkItem createBookmarkItem(ViewGroup parent) {
450 return (EnhancedBookmarkItem) LayoutInflater.from(parent.getContext( )).inflate(
451 R.layout.eb_list_item, parent, false);
452 }
453
454 @Override
455 public EnhancedBookmarkFolder createBookmarkFolder(ViewGroup parent) {
456 return (EnhancedBookmarkFolder) LayoutInflater.from(
457 parent.getContext()).inflate(R.layout.eb_list_folder, parent , false);
458 }
459 }
460 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698