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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java

Issue 2396523002: Unify NewTabPageItem and ItemGroup into a single tree-structured interface. (Closed)
Patch Set: review Created 4 years, 2 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.ntp.cards; 5 package org.chromium.chrome.browser.ntp.cards;
6 6
7 import org.chromium.base.VisibleForTesting; 7 import org.chromium.base.VisibleForTesting;
8 import org.chromium.chrome.browser.ntp.snippets.CategoryInt; 8 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
9 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m; 9 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m;
10 import org.chromium.chrome.browser.ntp.snippets.SectionHeader; 10 import org.chromium.chrome.browser.ntp.snippets.SectionHeader;
11 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; 11 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
12 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; 12 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge;
13 13
14 import java.util.ArrayList; 14 import java.util.ArrayList;
15 import java.util.Collections; 15 import java.util.Collections;
16 import java.util.List; 16 import java.util.List;
17 17
18 /** 18 /**
19 * A group of suggestions, with a header, a status card, and a progress indicato r. 19 * A group of suggestions, with a header, a status card, and a progress indicato r.
20 */ 20 */
21 public class SuggestionsSection implements ItemGroup { 21 public class SuggestionsSection extends InnerNode {
22 private final List<SnippetArticle> mSuggestions = new ArrayList<>(); 22 private final List<SnippetArticle> mSuggestions = new ArrayList<>();
23 private final SectionHeader mHeader; 23 private final SectionHeader mHeader;
24 private final StatusItem mStatus; 24 private final StatusItem mStatus;
25 private final ProgressItem mProgressIndicator = new ProgressItem(); 25 private final ProgressItem mProgressIndicator = new ProgressItem();
26 private final ActionItem mMoreButton; 26 private final ActionItem mMoreButton;
27 private final Observer mObserver;
28 private final SuggestionsCategoryInfo mCategoryInfo; 27 private final SuggestionsCategoryInfo mCategoryInfo;
29 28
30 public SuggestionsSection(SuggestionsCategoryInfo info, Observer observer) { 29 public SuggestionsSection(NodeParent parent, SuggestionsCategoryInfo info) {
30 super(parent);
31 mHeader = new SectionHeader(info.getTitle()); 31 mHeader = new SectionHeader(info.getTitle());
32 mCategoryInfo = info; 32 mCategoryInfo = info;
33 mObserver = observer;
34 mMoreButton = new ActionItem(info); 33 mMoreButton = new ActionItem(info);
35 mStatus = StatusItem.createNoSuggestionsItem(info); 34 mStatus = StatusItem.createNoSuggestionsItem(info);
36 } 35 }
37 36
38 @Override 37 @Override
39 public List<NewTabPageItem> getItems() { 38 public List<TreeNode> getChildren() {
40 // Note: Keep this coherent with the various notify** calls on ItemGroup .Observer 39 // Note: Keep this coherent with the various notify** calls on ItemGroup .Observer
41 List<NewTabPageItem> items = new ArrayList<>(); 40 List<TreeNode> items = new ArrayList<>();
42 items.add(mHeader); 41 items.add(mHeader);
43 items.addAll(mSuggestions); 42 items.addAll(mSuggestions);
44 43
45 if (mSuggestions.isEmpty()) items.add(mStatus); 44 if (mSuggestions.isEmpty()) items.add(mStatus);
46 if (mCategoryInfo.hasMoreButton() || mSuggestions.isEmpty()) items.add(m MoreButton); 45 if (mCategoryInfo.hasMoreButton() || mSuggestions.isEmpty()) items.add(m MoreButton);
47 if (mSuggestions.isEmpty()) items.add(mProgressIndicator); 46 if (mSuggestions.isEmpty()) items.add(mProgressIndicator);
48 47
49 return Collections.unmodifiableList(items); 48 return Collections.unmodifiableList(items);
50 } 49 }
51 50
52 public void removeSuggestion(SnippetArticle suggestion) { 51 public void removeSuggestion(SnippetArticle suggestion) {
53 int removedIndex = mSuggestions.indexOf(suggestion); 52 int removedIndex = mSuggestions.indexOf(suggestion);
54 if (removedIndex == -1) return; 53 if (removedIndex == -1) return;
55 54
56 mSuggestions.remove(removedIndex); 55 mSuggestions.remove(removedIndex);
57 if (mMoreButton != null) mMoreButton.setDismissable(!hasSuggestions()); 56 if (mMoreButton != null) mMoreButton.setDismissable(!hasSuggestions());
58 57
59 // Note: Keep this coherent with getItems() 58 // Note: Keep this coherent with getItems()
60 int globalRemovedIndex = removedIndex + 1; // Header has index 0 in the section. 59 int globalRemovedIndex = removedIndex + 1; // Header has index 0 in the section.
61 mObserver.onItemRangeRemoved(this, globalRemovedIndex, 1); 60 notifyItemRemoved(globalRemovedIndex);
62 61
63 // If we still have some suggestions, we are done. Otherwise, we'll have to notify about the 62 // If we still have some suggestions, we are done. Otherwise, we'll have to notify about the
64 // status-related items that are now present. 63 // status-related items that are now present.
65 if (hasSuggestions()) return; 64 if (hasSuggestions()) return;
66 mObserver.onItemRangeInserted(this, globalRemovedIndex, 1); // Status ca rd. 65 notifyItemInserted(globalRemovedIndex); // Status card.
67 if (!mCategoryInfo.hasMoreButton()) { 66 if (!mCategoryInfo.hasMoreButton()) {
68 mObserver.onItemRangeInserted(this, globalRemovedIndex + 1, 1); // A ction card. 67 notifyItemInserted(globalRemovedIndex + 1); // Action card.
69 } 68 }
70 mObserver.onItemRangeInserted(this, globalRemovedIndex + 2, 1); // Progr ess indicator. 69 notifyItemInserted(globalRemovedIndex + 2); // Progress indicator.
71 } 70 }
72 71
73 public void removeSuggestionById(String idWithinCategory) { 72 public void removeSuggestionById(String idWithinCategory) {
74 for (SnippetArticle suggestion : mSuggestions) { 73 for (SnippetArticle suggestion : mSuggestions) {
75 if (suggestion.mIdWithinCategory.equals(idWithinCategory)) { 74 if (suggestion.mIdWithinCategory.equals(idWithinCategory)) {
76 removeSuggestion(suggestion); 75 removeSuggestion(suggestion);
77 return; 76 return;
78 } 77 }
79 } 78 }
80 } 79 }
81 80
82 public boolean hasSuggestions() { 81 public boolean hasSuggestions() {
83 return !mSuggestions.isEmpty(); 82 return !mSuggestions.isEmpty();
84 } 83 }
85 84
86 public int getSuggestionsCount() { 85 public int getSuggestionsCount() {
87 return mSuggestions.size(); 86 return mSuggestions.size();
88 } 87 }
89 88
90 public void setSuggestions(List<SnippetArticle> suggestions, @CategoryStatus Enum int status) { 89 public void setSuggestions(List<SnippetArticle> suggestions, @CategoryStatus Enum int status) {
91 copyThumbnails(suggestions); 90 copyThumbnails(suggestions);
92 91
93 int itemCountBefore = getItems().size(); 92 int itemCountBefore = getItemCount();
94 setStatusInternal(status); 93 setStatusInternal(status);
95 94
96 mSuggestions.clear(); 95 mSuggestions.clear();
97 mSuggestions.addAll(suggestions); 96 mSuggestions.addAll(suggestions);
98 97
99 if (mMoreButton != null) { 98 if (mMoreButton != null) {
100 mMoreButton.setPosition(mSuggestions.size()); 99 mMoreButton.setPosition(mSuggestions.size());
101 mMoreButton.setDismissable(mSuggestions.isEmpty()); 100 mMoreButton.setDismissable(mSuggestions.isEmpty());
102 } 101 }
103 notifySectionChanged(itemCountBefore); 102 notifySectionChanged(itemCountBefore);
104 } 103 }
105 104
106 /** Sets the status for the section. Some statuses can cause the suggestions to be cleared. */ 105 /** Sets the status for the section. Some statuses can cause the suggestions to be cleared. */
107 public void setStatus(@CategoryStatusEnum int status) { 106 public void setStatus(@CategoryStatusEnum int status) {
108 int itemCountBefore = getItems().size(); 107 int itemCountBefore = getItemCount();
109 setStatusInternal(status); 108 setStatusInternal(status);
110 notifySectionChanged(itemCountBefore); 109 notifySectionChanged(itemCountBefore);
111 } 110 }
112 111
113 private void setStatusInternal(@CategoryStatusEnum int status) { 112 private void setStatusInternal(@CategoryStatusEnum int status) {
114 if (!SnippetsBridge.isCategoryStatusAvailable(status)) mSuggestions.clea r(); 113 if (!SnippetsBridge.isCategoryStatusAvailable(status)) mSuggestions.clea r();
115 114
116 mProgressIndicator.setVisible(SnippetsBridge.isCategoryLoading(status)); 115 mProgressIndicator.setVisible(SnippetsBridge.isCategoryLoading(status));
117 } 116 }
118 117
(...skipping 14 matching lines...) Expand all
133 /** 132 /**
134 * The dismiss sibling is an item that should be dismissed at the same time as the provided 133 * The dismiss sibling is an item that should be dismissed at the same time as the provided
135 * one. For example, if we want to dismiss a status card that has a More but ton attached, the 134 * one. For example, if we want to dismiss a status card that has a More but ton attached, the
136 * button is the card's dismiss sibling. This function return the adapter po sition delta to 135 * button is the card's dismiss sibling. This function return the adapter po sition delta to
137 * apply to get to the sibling from the provided item. For the previous exam ple, it would return 136 * apply to get to the sibling from the provided item. For the previous exam ple, it would return
138 * {@code +1}, as the button comes right after the status card. 137 * {@code +1}, as the button comes right after the status card.
139 * 138 *
140 * @return a position delta to apply to the position of the provided item to get the adapter 139 * @return a position delta to apply to the position of the provided item to get the adapter
141 * position of the item to animate. Returns {@code 0} if there is no dismiss sibling. 140 * position of the item to animate. Returns {@code 0} if there is no dismiss sibling.
142 */ 141 */
143 public int getDismissSiblingPosDelta(NewTabPageItem item) { 142 public int getDismissSiblingPosDelta(int position) {
144 // The only dismiss siblings we have so far are the More button and the status card. 143 // The only dismiss siblings we have so far are the More button and the status card.
145 // Exit early if there is no More button. 144 // Exit early if there is no More button.
146 if (mMoreButton == null) return 0; 145 if (mMoreButton == null) return 0;
147 146
148 // When there are suggestions we won't have contiguous status and action items. 147 // When there are suggestions we won't have contiguous status and action items.
149 if (hasSuggestions()) return 0; 148 if (hasSuggestions()) return 0;
150 149
150 TreeNode item = getChildren().get(position);
151
151 // The sibling of the more button is the status card, that should be rig ht above. 152 // The sibling of the more button is the status card, that should be rig ht above.
152 if (item == mMoreButton) return -1; 153 if (item == mMoreButton) return -1;
153 154
154 // The sibling of the status card is the more button when it exists, sho uld be right below. 155 // The sibling of the status card is the more button when it exists, sho uld be right below.
155 if (item == mStatus) return 1; 156 if (item == mStatus) return 1;
156 157
157 return 0; 158 return 0;
158 } 159 }
159 160
160 private void notifySectionChanged(int itemCountBefore) { 161 private void notifySectionChanged(int itemCountBefore) {
161 int itemCountAfter = getItems().size(); 162 int itemCountAfter = getItemCount();
162 163
163 // The header is stable in sections. Don't notify about it. 164 // The header is stable in sections. Don't notify about it.
164 final int startPos = 1; 165 final int startPos = 1;
165 itemCountBefore--; 166 itemCountBefore--;
166 itemCountAfter--; 167 itemCountAfter--;
167 168
168 mObserver.onItemRangeChanged(this, startPos, Math.min(itemCountBefore, i temCountAfter)); 169 notifyItemRangeChanged(startPos, Math.min(itemCountBefore, itemCountAfte r));
169 if (itemCountBefore < itemCountAfter) { 170 if (itemCountBefore < itemCountAfter) {
170 mObserver.onItemRangeInserted( 171 notifyItemRangeInserted(startPos + itemCountBefore, itemCountAfter - itemCountBefore);
171 this, startPos + itemCountBefore, itemCountAfter - itemCount Before);
172 } else if (itemCountBefore > itemCountAfter) { 172 } else if (itemCountBefore > itemCountAfter) {
173 mObserver.onItemRangeRemoved( 173 notifyItemRangeRemoved(startPos + itemCountAfter, itemCountBefore - itemCountAfter);
174 this, startPos + itemCountAfter, itemCountBefore - itemCount After);
175 } 174 }
176 } 175 }
177 176
177 /**
178 * @return The progress indicator.
179 */
180 @VisibleForTesting
181 ProgressItem getProgressItemForTesting() {
182 return mProgressIndicator;
183 }
184
178 @VisibleForTesting 185 @VisibleForTesting
179 ActionItem getActionItem() { 186 ActionItem getActionItem() {
180 return mMoreButton; 187 return mMoreButton;
181 } 188 }
182 189
183 @VisibleForTesting 190 @VisibleForTesting
184 StatusItem getStatusItem() { 191 StatusItem getStatusItem() {
185 return mStatus; 192 return mStatus;
186 } 193 }
187 } 194 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698