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.util.BitSet;
21  import java.util.EnumMap;
22  import java.util.List;
23  import java.util.Map;
24  
25  import sk.baka.ambient.ActionsEnum;
26  import sk.baka.ambient.AmbientApplication;
27  import sk.baka.ambient.ZoomEnum;
28  import sk.baka.ambient.commons.Interval;
29  import sk.baka.ambient.views.ButtonBar;
30  import android.app.Activity;
31  import android.graphics.Point;
32  import android.view.View;
33  import android.view.View.OnClickListener;
34  import android.widget.AdapterView;
35  import android.widget.AdapterView.OnItemClickListener;
36  
37  /***
38   * A base class each controller must extend. Defines common operations.
39   * 
40   * @author Martin Vysny
41   */
42  public abstract class AbstractController {
43  	/***
44  	 * The main view controlled by this controller.
45  	 */
46  	protected View mainView;
47  
48  	/***
49  	 * Reference to the main activity.
50  	 */
51  	protected Activity mainActivity;
52  
53  	/***
54  	 * Creates new controller.
55  	 * 
56  	 * @param mainViewId
57  	 *            the view whose visibility is controlled.
58  	 * @param mainActivity
59  	 *            the activity.
60  	 */
61  	protected AbstractController(final int mainViewId,
62  			final Activity mainActivity) {
63  		super();
64  		this.mainView = mainActivity.findViewById(mainViewId);
65  		if (mainView == null) {
66  			throw new IllegalArgumentException("No view with id " + mainViewId);
67  		}
68  		this.mainActivity = mainActivity;
69  		app = AmbientApplication.getInstance();
70  	}
71  
72  	/***
73  	 * Flips the player visibility - shows it if it is hidden or vice versa.
74  	 */
75  	public final void flipVisibility() {
76  		if (isVisible()) {
77  			hide();
78  		} else {
79  			show();
80  		}
81  	}
82  
83  	/***
84  	 * Checks if the view controlled by this controller is visible.
85  	 * 
86  	 * @return <code>true</code> if visible, <code>false</code> otherwise.
87  	 */
88  	public final boolean isVisible() {
89  		return mainView.getVisibility() == View.VISIBLE;
90  	}
91  
92  	/***
93  	 * Shows the view on screen.
94  	 */
95  	public final void show() {
96  		if (!isVisible()) {
97  			mainView.setVisibility(View.VISIBLE);
98  			visibilityChanged(true);
99  		}
100 	}
101 
102 	/***
103 	 * Invoked when the component visibility changes. By default does nothing.
104 	 * 
105 	 * @param visible
106 	 *            new visibility flag.
107 	 */
108 	protected void visibilityChanged(boolean visible) {
109 		// do nothing by default
110 	}
111 
112 	/***
113 	 * Hides the view and removes it (the {@link View#GONE} functionality).
114 	 */
115 	public final void hide() {
116 		if (isVisible()) {
117 			mainView.setVisibility(View.GONE);
118 			visibilityChanged(false);
119 		}
120 	}
121 
122 	/***
123 	 * Sets the visibility of the view controlled by this controller.
124 	 * 
125 	 * @param visible
126 	 *            if <code>true</code> then the view is made visible, otherwise
127 	 *            it is made GONE.
128 	 */
129 	public final void setVisibility(final boolean visible) {
130 		if (visible) {
131 			show();
132 		} else {
133 			hide();
134 		}
135 	}
136 
137 	/***
138 	 * Called when an action button is pressed. By default invokes main
139 	 * activity. Subclasses can override.
140 	 * 
141 	 * @param action
142 	 *            the action to take
143 	 */
144 	protected void onAction(final ActionsEnum action) {
145 		if (action == ActionsEnum.Refresh) {
146 			update(null);
147 			return;
148 		}
149 		((MainActivity) mainActivity).activateAction(action, cycle);
150 	}
151 
152 	/***
153 	 * If <code>true</code> then random/repeat modes are cycled instead of being
154 	 * activated.
155 	 */
156 	protected boolean cycle = false;
157 
158 	/***
159 	 * The activity button listener.
160 	 */
161 	protected final class Listener implements OnClickListener,
162 			OnItemClickListener {
163 		public void onClick(View arg0) {
164 			final ActionsEnum action = (ActionsEnum) arg0.getTag();
165 			onAction(action);
166 		}
167 
168 		@SuppressWarnings("unchecked")
169 		public void onItemClick(AdapterView parent, View v, int position,
170 				long id) {
171 			final List<? extends ActionsEnum> actions = (List<? extends ActionsEnum>) v
172 					.getTag();
173 			onAction(actions.get(position));
174 		}
175 	}
176 
177 	/***
178 	 * Listens for click actions and activates {@link ActionsEnum} stored in the
179 	 * tag values.
180 	 */
181 	protected final Listener listener = new Listener();
182 
183 	/***
184 	 * Returns the application instance.
185 	 */
186 	protected AmbientApplication app;
187 
188 	/***
189 	 * Reinitializes the underlying view. Used when the view was not updated for
190 	 * a time and is about to be shown on screen. Default implementation does
191 	 * nothing.
192 	 * 
193 	 * @param select
194 	 *            reset selection to this interval.
195 	 */
196 	public void update(final Interval select) {
197 		// do nothing
198 	}
199 
200 	/***
201 	 * Initializes given button bar with buttons. The size is 32x32 (48x48 when
202 	 * hovered) when not zoomed, 48x48 (64x64 when hovered) when zoomed.
203 	 * 
204 	 * @param buttonbarId
205 	 *            the resource id of the {@link ButtonBar} component.
206 	 * @param actions
207 	 *            the list of actions.
208 	 */
209 	protected void initButtonBar(final int buttonbarId,
210 			List<ActionsEnum> actions) {
211 		final boolean buttonsZoomed = ZoomEnum.Buttons.getLevel(zoom) != 0;
212 		initButtonBar(buttonbarId, actions, buttonsZoomed ? new Point(48, 48)
213 				: new Point(32, 32), buttonsZoomed ? new Point(64, 64)
214 				: new Point(48, 48));
215 	}
216 
217 	/***
218 	 * Initializes given button bar with buttons.
219 	 * 
220 	 * @param buttonbarId
221 	 *            the resource id of the {@link ButtonBar} component.
222 	 * @param actions
223 	 *            the list of actions.
224 	 * @param bitmapSize
225 	 *            the size of all buttons.
226 	 * @param hoveredBitmapSize
227 	 *            maximum size of a button when hovered.
228 	 */
229 	protected final void initButtonBar(final int buttonbarId,
230 			List<ActionsEnum> actions, final Point bitmapSize,
231 			final Point hoveredBitmapSize) {
232 		final ButtonBar bar = (ButtonBar) mainView.findViewById(buttonbarId);
233 		bar.listener = listener;
234 		initButtonBar(bar, actions, bitmapSize, hoveredBitmapSize);
235 	}
236 
237 	/***
238 	 * Checks or un-checks given button on the button bar.
239 	 * 
240 	 * @param buttonbarId
241 	 *            the button bar
242 	 * @param actionIndex
243 	 *            the index of the action
244 	 * @param value
245 	 *            the new value.
246 	 */
247 	protected final void checkButton(final int buttonbarId, int actionIndex,
248 			final boolean value) {
249 		final ButtonBar b = (ButtonBar) mainView
250 				.findViewById(buttonbarId);
251 		final BitSet checked = b.getChecked();
252 		checked.set(actionIndex, value);
253 		b.highlight(b.getHighlight(), checked);
254 	}
255 	
256 	/***
257 	 * Initializes given button bar with buttons.
258 	 * 
259 	 * @param bar
260 	 *            the {@link ButtonBar} component.
261 	 * @param actions
262 	 *            the list of actions.
263 	 * @param bitmapSize
264 	 *            the size of all buttons.
265 	 * @param hoveredBitmapSize
266 	 *            maximum size of a button when hovered.
267 	 */
268 	public static final void initButtonBar(final ButtonBar bar,
269 			final List<ActionsEnum> actions, final Point bitmapSize,
270 			final Point hoveredBitmapSize) {
271 		final int[] images = new int[actions.size()];
272 		final int[] captions = new int[actions.size()];
273 		for (int i = 0; i < actions.size(); i++) {
274 			images[i] = actions.get(i).icon;
275 			captions[i] = actions.get(i).caption;
276 		}
277 		bar.setBitmaps(images, captions, bitmapSize, hoveredBitmapSize);
278 		bar.setTag(actions);
279 	}
280 
281 	/***
282 	 * The controller is about to be destroyed. No invocations are performed
283 	 * after this call. The controller should release its resources, stop its
284 	 * activities etc. Make sure that you call {@code super()} if you override
285 	 * this method!
286 	 */
287 	public void destroy() {
288 		mainActivity = null;
289 		mainView = null;
290 	}
291 
292 	/***
293 	 * Checks if this controller was destroyed.
294 	 * 
295 	 * @return <code>true</code> if this controller is destroyed.
296 	 */
297 	protected final boolean isDestroyed() {
298 		return mainActivity == null;
299 	}
300 
301 	@Override
302 	public final boolean equals(Object o) {
303 		if (o == null) {
304 			return false;
305 		}
306 		return getClass().equals(o.getClass());
307 	}
308 
309 	@Override
310 	public final int hashCode() {
311 		return getClass().hashCode();
312 	}
313 
314 	/***
315 	 * Zooms, or un-zooms the controller.
316 	 * 
317 	 * @param zoom
318 	 *            new zoom levels.
319 	 */
320 	public final void zoom(final Map<ZoomEnum,Integer> zoom) {
321 		this.zoom.putAll(zoom);
322 		performZoom(zoom);
323 	}
324 
325 	/***
326 	 * Zooms, or un-zooms the controller.
327 	 * 
328 	 * @param zoom
329 	 *            new zoom levels.
330 	 */
331 	protected abstract void performZoom(final Map<ZoomEnum,Integer> zoom);
332 
333 	private final EnumMap<ZoomEnum,Integer> zoom = ZoomEnum.getMinLevels();
334 
335 	/***
336 	 * Checks if this controller is zoomed.
337 	 * 
338 	 * @return current zoom levels.
339 	 */
340 	protected final EnumMap<ZoomEnum,Integer> getZoom() {
341 		return zoom;
342 	}
343 }