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