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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java

Issue 2670083002: [Download Home] Displaying offline page bundle per day (Closed)
Patch Set: comments Created 3 years, 10 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.widget; 5 package org.chromium.chrome.browser.widget;
6 6
7 import android.os.AsyncTask; 7 import android.os.AsyncTask;
8 import android.support.v7.widget.RecyclerView; 8 import android.support.v7.widget.RecyclerView;
9 import android.support.v7.widget.RecyclerView.Adapter; 9 import android.support.v7.widget.RecyclerView.Adapter;
10 import android.support.v7.widget.RecyclerView.ViewHolder; 10 import android.support.v7.widget.RecyclerView.ViewHolder;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 mTextView.setText(builder); 142 mTextView.setText(builder);
143 } 143 }
144 } 144 }
145 145
146 protected static class BasicViewHolder extends RecyclerView.ViewHolder { 146 protected static class BasicViewHolder extends RecyclerView.ViewHolder {
147 public BasicViewHolder(View itemView) { 147 public BasicViewHolder(View itemView) {
148 super(itemView); 148 super(itemView);
149 } 149 }
150 } 150 }
151 151
152 protected static class SubsectionHeaderViewHolder extends RecyclerView.ViewH older {
153 private View mView;
154
155 public SubsectionHeaderViewHolder(View itemView) {
156 super(itemView);
157 mView = itemView;
158 }
159
160 public View getView() {
161 return mView;
162 }
163 }
164
152 /** 165 /**
153 * A bucket of items with the same date. 166 * A bucket of items with the same date.
154 */ 167 */
155 protected static class ItemGroup { 168 public static class ItemGroup {
156 private final Date mDate; 169 private final Date mDate;
157 private final List<TimedItem> mItems = new ArrayList<>(); 170 private final List<TimedItem> mItems = new ArrayList<>();
158 171
159 /** Index of the header, relative to the full list. Must be set only on ce.*/ 172 /** Index of the header, relative to the full list. Must be set only on ce.*/
160 private int mIndex; 173 private int mIndex;
161 174
162 private boolean mIsSorted; 175 private boolean mIsSorted;
163 private boolean mIsListHeader; 176 private boolean mIsListHeader;
164 private boolean mIsListFooter; 177 private boolean mIsListFooter;
165 178
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 if (index == 0 || mIsListHeader || mIsListFooter) return null; 233 if (index == 0 || mIsListHeader || mIsListFooter) return null;
221 234
222 sortIfNeeded(); 235 sortIfNeeded();
223 return mItems.get(index - 1); 236 return mItems.get(index - 1);
224 } 237 }
225 238
226 /** 239 /**
227 * Rather than sorting the list each time a new item is added, the list is sorted when 240 * Rather than sorting the list each time a new item is added, the list is sorted when
228 * something requires a correct ordering of the items. 241 * something requires a correct ordering of the items.
229 */ 242 */
230 private void sortIfNeeded() { 243 protected void sortIfNeeded() {
231 if (mIsSorted) return; 244 if (mIsSorted) return;
232 mIsSorted = true; 245 mIsSorted = true;
233 246
234 Collections.sort(mItems, new Comparator<TimedItem>() { 247 Collections.sort(mItems, new Comparator<TimedItem>() {
235 @Override 248 @Override
236 public int compare(TimedItem lhs, TimedItem rhs) { 249 public int compare(TimedItem lhs, TimedItem rhs) {
237 // More recent items are listed first. Ideally we'd use Lon g.compare, but that 250 return compareItem(lhs, rhs);
238 // is an API level 19 call for some inexplicable reason.
239 long timeDelta = lhs.getTimestamp() - rhs.getTimestamp();
240 if (timeDelta > 0) {
241 return -1;
242 } else if (timeDelta == 0) {
243 return 0;
244 } else {
245 return 1;
246 }
247 } 251 }
248 }); 252 });
249 } 253 }
254
255 protected int compareItem(TimedItem lhs, TimedItem rhs) {
256 // More recent items are listed first. Ideally we'd use Long.compar e, but that
257 // is an API level 19 call for some inexplicable reason.
258 long timeDelta = lhs.getTimestamp() - rhs.getTimestamp();
259 if (timeDelta > 0) {
260 return -1;
261 } else if (timeDelta == 0) {
262 return 0;
263 } else {
264 return 1;
265 }
266 }
250 } 267 }
251 268
252 // Cached async tasks to get the two Calendar objects, which are used when c omparing dates. 269 // Cached async tasks to get the two Calendar objects, which are used when c omparing dates.
253 private static final AsyncTask<Void, Void, Calendar> sCal1 = createCalendar( ); 270 private static final AsyncTask<Void, Void, Calendar> sCal1 = createCalendar( );
254 private static final AsyncTask<Void, Void, Calendar> sCal2 = createCalendar( ); 271 private static final AsyncTask<Void, Void, Calendar> sCal2 = createCalendar( );
255 272
256 public static final int TYPE_FOOTER = -2; 273 public static final int TYPE_FOOTER = -2;
257 public static final int TYPE_HEADER = -1; 274 public static final int TYPE_HEADER = -1;
258 public static final int TYPE_DATE = 0; 275 public static final int TYPE_DATE = 0;
259 public static final int TYPE_NORMAL = 1; 276 public static final int TYPE_NORMAL = 1;
277 public static final int TYPE_SUBSECTION_HEADER = 2;
260 278
261 private int mSize; 279 private int mSize;
262 private boolean mHasListHeader; 280 private boolean mHasListHeader;
263 private boolean mHasListFooter; 281 private boolean mHasListFooter;
264 282
265 private SortedSet<ItemGroup> mGroups = new TreeSet<>(new Comparator<ItemGrou p>() { 283 private SortedSet<ItemGroup> mGroups = new TreeSet<>(new Comparator<ItemGrou p>() {
266 @Override 284 @Override
267 public int compare(ItemGroup lhs, ItemGroup rhs) { 285 public int compare(ItemGroup lhs, ItemGroup rhs) {
268 if (lhs == rhs) return 0; 286 if (lhs == rhs) return 0;
269 287
(...skipping 30 matching lines...) Expand all
300 /** 318 /**
301 * Creates a {@link DateViewHolder} in the given view parent. 319 * Creates a {@link DateViewHolder} in the given view parent.
302 * @see #onCreateViewHolder(ViewGroup, int) 320 * @see #onCreateViewHolder(ViewGroup, int)
303 */ 321 */
304 protected DateViewHolder createDateViewHolder(ViewGroup parent) { 322 protected DateViewHolder createDateViewHolder(ViewGroup parent) {
305 return new DateViewHolder(LayoutInflater.from(parent.getContext()).infla te( 323 return new DateViewHolder(LayoutInflater.from(parent.getContext()).infla te(
306 getTimedItemViewResId(), parent, false)); 324 getTimedItemViewResId(), parent, false));
307 } 325 }
308 326
309 /** 327 /**
328 * Creates a {@link ViewHolder} for a subsection in the given view parent.
329 * @see #onCreateViewHolder(ViewGroup, int)
330 */
331 protected SubsectionHeaderViewHolder createSubsectionHeader(ViewGroup parent ) {
332 return null;
333 }
334
335 /**
336 * Helper function to determine whether an item is a subsection header.
337 * @param timedItem The item
338 * @return Whether the item is a subsection header.
339 */
340 protected boolean isSubsectionHeader(TimedItem timedItem) {
341 return false;
342 }
343
344 /**
310 * Binds the {@link ViewHolder} with the given {@link TimedItem}. 345 * Binds the {@link ViewHolder} with the given {@link TimedItem}.
311 * @see #onBindViewHolder(ViewHolder, int) 346 * @see #onBindViewHolder(ViewHolder, int)
312 */ 347 */
313 protected abstract void bindViewHolderForTimedItem(ViewHolder viewHolder, Ti medItem item); 348 protected abstract void bindViewHolderForTimedItem(ViewHolder viewHolder, Ti medItem item);
314 349
315 /** 350 /**
351 * Binds the {@link SubsectionHeaderViewHolder} with the given {@link TimedI tem}.
352 * @see #onBindViewHolder(ViewHolder, int)
353 */
354 protected void bindViewHolderForSubsectionHeader(
355 SubsectionHeaderViewHolder holder, TimedItem timedItem) {}
356
357 /**
316 * Gets the resource id of the view showing the date header. 358 * Gets the resource id of the view showing the date header.
317 * Contract for subclasses: this view should be a {@link TextView}. 359 * Contract for subclasses: this view should be a {@link TextView}.
318 */ 360 */
319 protected abstract int getTimedItemViewResId(); 361 protected abstract int getTimedItemViewResId();
320 362
321 /** 363 /**
322 * Loads a list of {@link TimedItem}s to this adapter. Previous data will no t be removed. Call 364 * Loads a list of {@link TimedItem}s to this adapter. Previous data will no t be removed. Call
323 * {@link #clear(boolean)} to remove previous items. 365 * {@link #clear(boolean)} to remove previous items.
324 */ 366 */
325 public void loadItems(List<? extends TimedItem> timedItems) { 367 public void loadItems(List<? extends TimedItem> timedItems) {
326 for (TimedItem timedItem : timedItems) { 368 for (TimedItem timedItem : timedItems) {
327 Date date = new Date(timedItem.getTimestamp()); 369 Date date = new Date(timedItem.getTimestamp());
328 boolean found = false; 370 boolean found = false;
329 for (ItemGroup group : mGroups) { 371 for (ItemGroup group : mGroups) {
330 if (group.isSameDay(date)) { 372 if (group.isSameDay(date)) {
331 found = true; 373 found = true;
332 group.addItem(timedItem); 374 group.addItem(timedItem);
333 mSize++; 375 mSize++;
334 break; 376 break;
335 } 377 }
336 } 378 }
337 if (!found) { 379 if (!found) {
338 // Create a new ItemGroup with the date for the new item. This i ncreases the 380 // Create a new ItemGroup with the date for the new item. This i ncreases the
339 // size by two because we add new views for the date and the ite m itself. 381 // size by two because we add new views for the date and the ite m itself.
340 ItemGroup newGroup = new ItemGroup(timedItem.getTimestamp()); 382 ItemGroup newGroup = createGroup(timedItem.getTimestamp());
341 newGroup.addItem(timedItem); 383 newGroup.addItem(timedItem);
342 mGroups.add(newGroup); 384 mGroups.add(newGroup);
343 mSize += 2; 385 mSize += 2;
344 } 386 }
345 } 387 }
346 388
347 setGroupPositions(); 389 setGroupPositions();
348 notifyDataSetChanged(); 390 notifyDataSetChanged();
349 } 391 }
350 392
351 /** 393 /**
394 * Creates and returns an item group for a given day.
395 * @param timestamp A time stamp from which the date is determined.
gone 2017/02/17 19:21:16 timestamp.
shaktisahu 2017/02/17 19:55:10 Done.
396 * @return The item group.
397 */
398 protected ItemGroup createGroup(long timestamp) {
399 return new ItemGroup(timestamp);
400 }
401
402 /**
352 * Tells each group where they start in the list. 403 * Tells each group where they start in the list.
353 */ 404 */
354 private void setGroupPositions() { 405 private void setGroupPositions() {
355 int startIndex = 0; 406 int startIndex = 0;
356 for (ItemGroup group : mGroups) { 407 for (ItemGroup group : mGroups) {
357 group.resetPosition(); 408 group.resetPosition();
358 group.setPosition(startIndex); 409 group.setPosition(startIndex);
359 startIndex += group.size(); 410 startIndex += group.size();
360 } 411 }
361 } 412 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 */ 501 */
451 public Pair<Date, TimedItem> getItemAt(int position) { 502 public Pair<Date, TimedItem> getItemAt(int position) {
452 Pair<ItemGroup, Integer> pair = getGroupAt(position); 503 Pair<ItemGroup, Integer> pair = getGroupAt(position);
453 ItemGroup group = pair.first; 504 ItemGroup group = pair.first;
454 return new Pair<>(group.mDate, group.getItemAt(pair.second)); 505 return new Pair<>(group.mDate, group.getItemAt(pair.second));
455 } 506 }
456 507
457 @Override 508 @Override
458 public final int getItemViewType(int position) { 509 public final int getItemViewType(int position) {
459 Pair<ItemGroup, Integer> pair = getGroupAt(position); 510 Pair<ItemGroup, Integer> pair = getGroupAt(position);
511 ItemGroup group = pair.first;
460 if (pair.second == TYPE_HEADER) { 512 if (pair.second == TYPE_HEADER) {
461 return TYPE_HEADER; 513 return TYPE_HEADER;
462 } else if (pair.second == TYPE_FOOTER) { 514 } else if (pair.second == TYPE_FOOTER) {
463 return TYPE_FOOTER; 515 return TYPE_FOOTER;
464 } else if (pair.second == 0) { 516 } else if (pair.second == 0) {
465 return TYPE_DATE; 517 return TYPE_DATE;
518 } else if (isSubsectionHeader(group.getItemAt(pair.second))) {
519 return TYPE_SUBSECTION_HEADER;
466 } else { 520 } else {
467 return TYPE_NORMAL; 521 return TYPE_NORMAL;
468 } 522 }
469 } 523 }
470 524
471 @Override 525 @Override
472 public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, in t viewType) { 526 public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, in t viewType) {
473 if (viewType == TYPE_DATE) { 527 if (viewType == TYPE_DATE) {
474 return createDateViewHolder(parent); 528 return createDateViewHolder(parent);
475 } else if (viewType == TYPE_NORMAL) { 529 } else if (viewType == TYPE_NORMAL) {
476 return createViewHolder(parent); 530 return createViewHolder(parent);
477 } else if (viewType == TYPE_HEADER) { 531 } else if (viewType == TYPE_HEADER) {
478 return createHeader(parent); 532 return createHeader(parent);
479 } else if (viewType == TYPE_FOOTER) { 533 } else if (viewType == TYPE_FOOTER) {
480 return createFooter(parent); 534 return createFooter(parent);
535 } else if (viewType == TYPE_SUBSECTION_HEADER) {
536 return createSubsectionHeader(parent);
481 } 537 }
482 assert false; 538 assert false;
483 return null; 539 return null;
484 } 540 }
485 541
486 @Override 542 @Override
487 public final void onBindViewHolder(RecyclerView.ViewHolder holder, int posit ion) { 543 public final void onBindViewHolder(RecyclerView.ViewHolder holder, int posit ion) {
488 Pair<Date, TimedItem> pair = getItemAt(position); 544 Pair<Date, TimedItem> pair = getItemAt(position);
489 if (holder instanceof DateViewHolder) { 545 if (holder instanceof DateViewHolder) {
490 ((DateViewHolder) holder).setDate(pair.first); 546 ((DateViewHolder) holder).setDate(pair.first);
547 } else if (holder instanceof SubsectionHeaderViewHolder) {
548 bindViewHolderForSubsectionHeader((SubsectionHeaderViewHolder) holde r, pair.second);
491 } else if (!(holder instanceof BasicViewHolder)) { 549 } else if (!(holder instanceof BasicViewHolder)) {
492 bindViewHolderForTimedItem(holder, pair.second); 550 bindViewHolderForTimedItem(holder, pair.second);
493 } 551 }
494 } 552 }
495 553
496 @Override 554 @Override
497 public final int getItemCount() { 555 public final int getItemCount() {
498 return mSize; 556 return mSize;
499 } 557 }
500 558
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 long dayOfYear = calendar.get(Calendar.DAY_OF_YEAR); 614 long dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
557 long year = calendar.get(Calendar.YEAR); 615 long year = calendar.get(Calendar.YEAR);
558 return (year << 16) + dayOfYear; 616 return (year << 16) + dayOfYear;
559 } 617 }
560 618
561 /** 619 /**
562 * Compares two {@link Date}s. Note if you already have two {@link Calendar} objects, use 620 * Compares two {@link Date}s. Note if you already have two {@link Calendar} objects, use
563 * {@link #compareCalendar(Calendar, Calendar)} instead. 621 * {@link #compareCalendar(Calendar, Calendar)} instead.
564 * @return 0 if date1 and date2 are in the same day; 1 if date1 is before da te2; -1 otherwise. 622 * @return 0 if date1 and date2 are in the same day; 1 if date1 is before da te2; -1 otherwise.
565 */ 623 */
566 private static int compareDate(Date date1, Date date2) { 624 protected static int compareDate(Date date1, Date date2) {
567 Pair<Calendar, Calendar> pair = getCachedCalendars(); 625 Pair<Calendar, Calendar> pair = getCachedCalendars();
568 Calendar cal1 = pair.first, cal2 = pair.second; 626 Calendar cal1 = pair.first, cal2 = pair.second;
569 cal1.setTime(date1); 627 cal1.setTime(date1);
570 cal2.setTime(date2); 628 cal2.setTime(date2);
571 return compareCalendar(cal1, cal2); 629 return compareCalendar(cal1, cal2);
572 } 630 }
573 631
574 /** 632 /**
575 * @return 0 if cal1 and cal2 are in the same day; 1 if cal1 happens before cal2; -1 otherwise. 633 * @return 0 if cal1 and cal2 are in the same day; 1 if cal1 happens before cal2; -1 otherwise.
576 */ 634 */
(...skipping 30 matching lines...) Expand all
607 */ 665 */
608 private static AsyncTask<Void, Void, Calendar> createCalendar() { 666 private static AsyncTask<Void, Void, Calendar> createCalendar() {
609 return new AsyncTask<Void, Void, Calendar>() { 667 return new AsyncTask<Void, Void, Calendar>() {
610 @Override 668 @Override
611 protected Calendar doInBackground(Void... unused) { 669 protected Calendar doInBackground(Void... unused) {
612 return Calendar.getInstance(); 670 return Calendar.getInstance();
613 } 671 }
614 }.execute(); 672 }.execute();
615 } 673 }
616 } 674 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698