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 package sk.baka.ambient.activity.main;
19
20 import java.io.IOException;
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.BitSet;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28
29 import sk.baka.ambient.ActionsEnum;
30 import sk.baka.ambient.AmbientApplication;
31 import sk.baka.ambient.AppState;
32 import sk.baka.ambient.R;
33 import sk.baka.ambient.ZoomEnum;
34 import sk.baka.ambient.commons.Interval;
35 import sk.baka.ambient.commons.ObjectStorage;
36 import sk.baka.ambient.playlist.IPlaylistStrategy;
37 import sk.baka.ambient.views.ButtonBar;
38 import sk.baka.ambient.views.ViewUtils;
39 import sk.baka.ambient.views.gesturelist.GesturesListView;
40 import android.content.Context;
41 import android.content.DialogInterface;
42 import android.view.View;
43 import android.widget.TextView;
44
45 /***
46 * Controls the playlist manager.
47 *
48 * @author Martin Vysny
49 */
50 public final class PlaylistManagerController extends AbstractListController {
51 /***
52 * Creates new playlist manager controller instance.
53 *
54 * @param mainActivity
55 */
56 public PlaylistManagerController(MainActivity mainActivity) {
57 super(R.id.playlistManager, R.id.playlistManagerPlaylists, mainActivity);
58 initButtonBar(R.id.playlistManagerButtons, actions);
59 update(null);
60 }
61
62 @Override
63 public void update(Interval target) {
64 super.update(target);
65 final boolean dynamic = app.getPlaylist().isDynamic();
66 updateDynamic(dynamic);
67 }
68
69 private final List<ActionsEnum> actions = Arrays.asList(
70 ActionsEnum.PlaylistStatic, ActionsEnum.PlaylistDynamic,
71 ActionsEnum.PlaylistClear, ActionsEnum.PlaylistSortByAlbums,
72 ActionsEnum.PlaylistShuffle, ActionsEnum.PlaylistSave);
73
74 @Override
75 protected void onAction(ActionsEnum action) {
76 if (action == ActionsEnum.PlaylistSave) {
77 savePlaylistWizard(mainActivity);
78 }
79 if (action == ActionsEnum.PlaylistStatic) {
80 updateDynamic(false);
81 actions.set(2, ActionsEnum.PlaylistClear);
82 initButtonBar(R.id.playlistManagerButtons, actions);
83 }
84 if (action == ActionsEnum.PlaylistDynamic) {
85 updateDynamic(true);
86 actions.set(2, ActionsEnum.RepopulatePlaylist);
87 initButtonBar(R.id.playlistManagerButtons, actions);
88 }
89 super.onAction(action);
90 }
91
92 /***
93 * Navigates user through a 'save playlist' wizard.
94 *
95 * @param context
96 * the context.
97 */
98 public void savePlaylistWizard(final Context context) {
99 final ViewUtils.OnTextSubmit listener = new ViewUtils.OnTextSubmit() {
100 public void submit(String text) {
101 savePlaylistAs(context, text, true);
102 update(null);
103 }
104
105 public String validate(String text) {
106 return text.length() == 0 ? context
107 .getString(R.string.playlistNameEmpty) : null;
108 }
109
110 public void cancel() {
111
112 }
113 };
114 ViewUtils.showTextEditor(context, context
115 .getString(R.string.lsplaylistSave), null, context
116 .getString(R.string.savePlaylist), context
117 .getString(R.string.savePlaylistAs), listener);
118 }
119
120 private void savePlaylistAs(final Context context, final String name,
121 final boolean askForOverwrite) {
122 final AmbientApplication app = AmbientApplication.getInstance();
123 try {
124 final ObjectStorage ps = app.getPlaylistStorage();
125 if (ps.contains(name) && askForOverwrite) {
126 final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
127 public void onClick(DialogInterface dialog, int which) {
128 savePlaylistAs(context, name, false);
129 }
130 };
131 ViewUtils.showYesNoDialog(context, context
132 .getString(R.string.playlistOverwrite), listener);
133 }
134 final AppState state = new AppState();
135 app.getPlaylist().storeState(state);
136 ps.saveObject(name, (Serializable) state.playlist);
137 } catch (IOException e) {
138 app.error(PlaylistManagerController.class, true, app.getResources()
139 .getString(R.string.lsplaylistErrSave), e);
140 }
141 }
142
143 @Override
144 protected void recomputeListItems() {
145 final List<String> sortedNames = new ArrayList<String>(app
146 .getPlaylistStorage().getNames());
147 Collections.sort(sortedNames);
148 final List<Object> playlistNames = listView.getModel().getModel();
149 playlistNames.clear();
150 playlistNames.addAll(sortedNames);
151 }
152
153 @Override
154 public boolean isReadOnly() {
155 return false;
156 }
157
158 public void itemActivated(int index, Object model) {
159 loadPlaylist((String) model);
160 }
161
162 /***
163 * Loads playlist with given name. Shows an error message when the playlist
164 * failed to be loaded.
165 *
166 * @param name
167 * the name of the playlist.
168 */
169 public void loadPlaylist(final String name) {
170 try {
171 final ObjectStorage ps = app.getPlaylistStorage();
172 final IPlaylistStrategy state = (IPlaylistStrategy) ps
173 .loadObject(name);
174 app.getPlaylist().reinit(state);
175 } catch (final Exception ex) {
176 app.error(PlaylistManagerController.class, true, mainActivity
177 .getString(R.string.lsplaylistErrLoad), ex);
178 }
179 }
180
181 @Override
182 public void removeItems(final Interval remove) {
183 if (remove.isEmpty())
184 return;
185 final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
186 public void onClick(DialogInterface dialog, int which) {
187 final List<Object> toDelete = listView.getModel().getModel()
188 .subList(remove.start, remove.end + 1);
189 final ObjectStorage storage = AmbientApplication.getInstance()
190 .getPlaylistStorage();
191 for (final Object pname : toDelete) {
192 storage.delete((String) pname);
193 }
194 update(null);
195 }
196 };
197 ViewUtils.showYesNoDialog(mainActivity, mainActivity
198 .getString(R.string.playlistDelete), listener);
199 }
200
201 public void update(GesturesListView listView, View itemView, int index,
202 Object model) {
203 final TextView view = (TextView) itemView;
204 if (listView.getHighlight().contains(index)) {
205 view.setBackgroundColor(highlightColor);
206 } else {
207 view.setBackgroundColor(0);
208 }
209 view.setText((String) model);
210 }
211
212 @Override
213 protected void performZoom(final Map<ZoomEnum, Integer> zoom) {
214 super.performZoom(zoom);
215 initButtonBar(R.id.playlistManagerButtons, actions);
216 }
217
218 public String toString(Object model) {
219
220 throw new Error();
221 }
222
223 private void updateDynamic(final boolean dynamic) {
224 final BitSet bs = new BitSet();
225 bs.set(dynamic ? 1 : 0);
226 final ButtonBar b = ((ButtonBar) mainView
227 .findViewById(R.id.playlistManagerButtons));
228 b.highlight(null, bs);
229 }
230 }