1 /***
2 * Ambient - A music player for the Android platform
3 Copyright (C) 2007 Martin Vysny
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package sk.baka.ambient.activity.main.cb;
20
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.concurrent.CopyOnWriteArrayList;
28
29 import sk.baka.ambient.AmbientApplication;
30 import sk.baka.ambient.R;
31 import sk.baka.ambient.collection.CategoryEnum;
32 import sk.baka.ambient.collection.CategoryItem;
33 import sk.baka.ambient.collection.CollectionException;
34 import sk.baka.ambient.collection.CollectionUtils;
35 import sk.baka.ambient.collection.ICollection;
36 import sk.baka.ambient.collection.TrackMetadataBean;
37 import sk.baka.ambient.commons.Interval;
38
39 /***
40 * Performs the criteria selection.
41 *
42 * @author Martin Vysny
43 */
44 final class CategoryManager implements IContentManager {
45 /***
46 * Browse through these categories. First item in the list is the category
47 * currently being browsed.
48 */
49 private final List<CategoryEnum> categoriesToShow;
50
51 /***
52 * The parent category to display the data from. May be <code>null</code>
53 * if no category item has yet been selected.
54 */
55 private final CategoryItem parent;
56
57 /***
58 * Previous category manager. If <code>null</code> then
59 * {@link GroupingManager} is the previous one.
60 */
61 private final CategoryManager previous;
62
63 /***
64 * Creates new manager.
65 *
66 * @param categories
67 * browse through these categories.
68 */
69 CategoryManager(final CategoryEnum[] categories) {
70 super();
71 this.categoriesToShow = Arrays.asList(categories);
72 previous = null;
73 parent = null;
74 }
75
76 /***
77 * Creates new manager.
78 *
79 * @param previous
80 * Previous category manager. If <code>null</code> then
81 * {@link GroupingManager} is the previous one.
82 * @param parent
83 * The parent category to display the data from. May be
84 * <code>null</code> if no category item has yet been selected.
85 * @param categoriesToShow
86 * Browse through these categories. First item in the list is the
87 * category currently being browsed.
88 */
89 private CategoryManager(final CategoryManager previous,
90 final CategoryItem parent, final List<CategoryEnum> categoriesToShow) {
91 super();
92 this.categoriesToShow = categoriesToShow;
93 this.previous = previous;
94 this.parent = parent;
95 }
96
97 public boolean canReturnTracks() {
98 return true;
99 }
100
101 public List<String> getDisplayableContent() {
102 return displayableCategoriesShown;
103 }
104
105 /***
106 * The manager is currently showing these categories.
107 */
108 private volatile List<CategoryItem> categoriesShown;
109
110 /***
111 * The manager is currently showing these categories.
112 */
113 private volatile List<String> displayableCategoriesShown;
114
115 public List<TrackMetadataBean> getTracks(Interval highlight)
116 throws CollectionException, InterruptedException {
117
118
119 final Set<TrackMetadataBean> presentTracks = new HashSet<TrackMetadataBean>();
120 final List<TrackMetadataBean> result = new ArrayList<TrackMetadataBean>();
121 final List<CategoryItem> categories = categoriesShown.subList(
122 highlight.start, highlight.end + 1);
123 for (final CategoryItem ci : categories) {
124 if (Thread.currentThread().isInterrupted()) {
125 return null;
126 }
127 final List<TrackMetadataBean> tracks = collection.getTracks(ci);
128 tracks.removeAll(presentTracks);
129 presentTracks.addAll(tracks);
130 result.addAll(tracks);
131 }
132 CollectionUtils.sortByAlbumOrder(result);
133 return result;
134 }
135
136 public void uninitialize() {
137 categoriesShown = null;
138 displayableCategoriesShown = null;
139 }
140
141 public IContentManager goBack() {
142 if (previous != null) {
143 return previous;
144 }
145 return new GroupingManager();
146 }
147
148 private volatile ICollection collection;
149
150 private volatile boolean isYear = false;
151
152 public boolean initialize(boolean isYear, final ICollection collection)
153 throws CollectionException, InterruptedException {
154 previouslyActivated = null;
155 if ((categoriesShown != null) && (getCurrent() != CategoryEnum.Album)) {
156 return false;
157 }
158 this.isYear = isYear;
159 this.collection = collection;
160 final List<CategoryItem> list = collection.getCategoryList(
161 getCurrent(), parent, null, isYear);
162 categoriesShown = new CopyOnWriteArrayList<CategoryItem>(list);
163 final boolean albumYear = isYear
164 && (getCurrent() == CategoryEnum.Album);
165 final List<String> displayableList = new ArrayList<String>();
166 for (final CategoryItem item : list) {
167 final String caption = albumYear ? item.getDisplayableYear() + "-"
168 + item.getDisplayableName() : item.getDisplayableName();
169 displayableList.add(caption);
170 }
171 displayableCategoriesShown = Collections
172 .unmodifiableList(new CopyOnWriteArrayList<String>(
173 displayableList));
174 return true;
175 }
176
177 private CategoryItem previouslyActivated;
178
179 public IContentManager itemActivated(int i) {
180 previouslyActivated = categoriesShown.get(i);
181 if (categoriesToShow.size() > 1) {
182 final CategoryManager clone = new CategoryManager(previous, parent,
183 categoriesToShow);
184 return new CategoryManager(clone, previouslyActivated,
185 categoriesToShow.subList(1, categoriesToShow.size()));
186 }
187 return new TrackManager(this, previouslyActivated);
188 }
189
190 /***
191 * Returns currently shown category.
192 *
193 * @return the category being currently shown.
194 */
195 public CategoryEnum getCurrent() {
196 return categoriesToShow.get(0);
197 }
198
199 public int getIndexOfPreviouslyActivatedItem(IContentManager contentManager) {
200 final CategoryItem prev = ((CategoryManager) contentManager).previouslyActivated;
201 return categoriesShown.indexOf(prev);
202 }
203
204 public String getSelectedItemName() {
205 if (previouslyActivated != null) {
206 return previouslyActivated.getDisplayableName();
207 }
208 final CategoryEnum cat = getCurrent();
209 final StringBuilder builder = new StringBuilder();
210 if ((cat == CategoryEnum.Album) && isYear) {
211 builder.append(AmbientApplication.getInstance().getString(
212 R.string.year));
213 builder.append('-');
214 }
215 builder.append(AmbientApplication.getInstance().getString(
216 cat.displayableNameId));
217 return builder.toString();
218 }
219 }