View Javadoc

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 				// do nothing, the window will disappear on its own.
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 		// shouldn't be called as strings are shown
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 }