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  
19  package sk.baka.ambient.activity.main;
20  
21  import sk.baka.ambient.ActionsEnum;
22  import sk.baka.ambient.AmbientApplication;
23  import sk.baka.ambient.R;
24  import sk.baka.ambient.activity.ZoomActivity;
25  import sk.baka.ambient.playerservice.PlayerStateEnum;
26  import sk.baka.ambient.views.ContainedPopupWindow;
27  import sk.baka.ambient.views.Iconify;
28  import sk.baka.ambient.views.KeyEventHandler;
29  import sk.baka.ambient.views.ViewUtils;
30  import sk.baka.ambient.views.gesturelist.GesturesListView;
31  import android.content.Intent;
32  import android.view.KeyEvent;
33  import android.view.Menu;
34  import android.view.MenuItem;
35  import android.view.MotionEvent;
36  import android.widget.TextView;
37  
38  /***
39   * Handles activities from the {@link MainActivity} menu.
40   * 
41   * @author Martin Vysny
42   */
43  final class MenuHandler extends KeyEventHandler {
44  	private AbstractListController resizingController = null;
45  
46  	private boolean waitingForTrackballUp = false;
47  	private boolean isCenterUpDownCombo = false;
48  	private boolean wasOnlyCenterPressed = false;
49  
50  	private final MainActivity mainActivity;
51  
52  	/***
53  	 * Creates new handler instance.
54  	 * 
55  	 * @param mainActivity
56  	 *            owner activity
57  	 */
58  	MenuHandler(MainActivity mainActivity) {
59  		super();
60  		this.mainActivity = mainActivity;
61  	}
62  
63  	@Override
64  	protected boolean onKey(int keyCode, int count, KeyEvent event) {
65  		if (resizingController != null) {
66  			return handleResize(keyCode);
67  		}
68  		if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
69  			if (keyDownHandled.isEmpty() && !wasOnlyCenterPressed) {
70  				isCenterUpDownCombo = true;
71  				wasOnlyCenterPressed = true;
72  			}
73  		} else {
74  			wasOnlyCenterPressed = false;
75  		}
76  		// special handling is needed. If Center+Up/Down is pressed then do
77  		// not report it.
78  		if (isCenterUpDownCombo) {
79  			if (keyCode == KeyEvent.KEYCODE_DPAD_UP
80  					|| keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
81  				moveFocus(keyCode == KeyEvent.KEYCODE_DPAD_UP);
82  			}
83  			return true;
84  		}
85  		return false;
86  	}
87  
88  	@Override
89  	protected void keyUp(int keyCode, KeyEvent event) {
90  		if (wasOnlyCenterPressed) {
91  			isCenterUpDownCombo = false;
92  			// only the Center key was pressed. Report it.
93  			final KeyEvent e = new KeyEvent(KeyEvent.ACTION_DOWN,
94  					KeyEvent.KEYCODE_DPAD_CENTER);
95  			mainActivity.dispatchKeyEvent(e);
96  			keyDownHandled.put(KeyEvent.KEYCODE_DPAD_CENTER, false);
97  			wasOnlyCenterPressed = false;
98  		}
99  		if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
100 			wasOnlyCenterPressed = false;
101 			isCenterUpDownCombo = false;
102 		}
103 	}
104 
105 	/***
106 	 * Moves focus to next view.
107 	 * 
108 	 * @param up
109 	 *            moves the focus up if <code>true</code>, moves the focus down
110 	 *            otherwise.
111 	 * @return <code>true</code> if the focus was moved
112 	 */
113 	private boolean moveFocus(final boolean up) {
114 		return moveFocus(mainActivity.getCurrentFocus(), up);
115 	}
116 
117 	private boolean handleResize(int keyCode) {
118 		switch (keyCode) {
119 		case KeyEvent.KEYCODE_DPAD_DOWN:
120 			resizingController.resize(20);
121 			popup.updatePos();
122 			return true;
123 		case KeyEvent.KEYCODE_DPAD_UP:
124 			resizingController.resize(-20);
125 			popup.updatePos();
126 			return true;
127 		case KeyEvent.KEYCODE_ENTER:
128 		case KeyEvent.KEYCODE_DPAD_CENTER:
129 		case KeyEvent.KEYCODE_DPAD_LEFT:
130 		case KeyEvent.KEYCODE_DPAD_RIGHT:
131 			cancelResize();
132 			return true;
133 		default:
134 			cancelResize();
135 		}
136 		return false;
137 	}
138 
139 	/***
140 	 * Cancels the resizing operation.
141 	 */
142 	public void cancelResize() {
143 		resizingController = null;
144 		waitingForTrackballUp = false;
145 		if (popup != null) {
146 			popup.dismiss();
147 			popup = null;
148 		}
149 	}
150 
151 	/***
152 	 * See {@link MainActivity#dispatchTrackballEvent(MotionEvent)}
153 	 * 
154 	 * @param ev
155 	 *            event
156 	 * @return boolean
157 	 */
158 	boolean dispatchTrackballEvent(MotionEvent ev) {
159 		if (resizingController != null) {
160 			if (waitingForTrackballUp) {
161 				if (ViewUtils.isPenUp(ev)) {
162 					cancelResize();
163 				}
164 			} else if (ev.getAction() == MotionEvent.ACTION_DOWN) {
165 				waitingForTrackballUp = true;
166 			} else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
167 				resizingController.resize((int) (ev.getY() * 20));
168 				popup.updatePos();
169 			}
170 			return true;
171 		}
172 		return false;
173 	}
174 
175 	private ContainedPopupWindow popup = null;
176 
177 	/***
178 	 * Starts the controller resizing if available.
179 	 */
180 	public void startResizing() {
181 		waitingForTrackballUp = false;
182 		final AbstractController c = mainActivity.controllers
183 				.getVisibleController();
184 		if (c instanceof AbstractListController) {
185 			resizingController = (AbstractListController) c;
186 			final GesturesListView view = resizingController.listView;
187 			popup = new ContainedPopupWindow(view,
188 					new ContainedPopupWindow.IPlaceable() {
189 						public int[] getCoordinates(ContainedPopupWindow popup,
190 								CharSequence text, TextView textView) {
191 							return new int[] { 0, view.getLayoutParams().height };
192 						}
193 					});
194 			popup.setText(Iconify.iconify(mainActivity,
195 					R.string.resizeTaskWindow));
196 		}
197 	}
198 
199 	/***
200 	 * {@link MainActivity#onPrepareOptionsMenu(Menu)}
201 	 * 
202 	 * @param menu
203 	 *            menu
204 	 */
205 	void onPrepareOptionsMenu(Menu menu) {
206 		final AmbientApplication app = AmbientApplication.getInstance();
207 		menu.removeGroup(0);
208 		MenuItem item = menu.add(Menu.NONE, 0, 0, R.string.zoom);
209 		item.setIcon(android.R.drawable.btn_plus);
210 		final boolean playing = app.getPlaylist().getPlaybackState() == PlayerStateEnum.Playing;
211 		item = menu.add(Menu.NONE, 1, 1, playing ? R.string.pause
212 				: R.string.play);
213 		item.setIcon(playing ? R.drawable.pause48 : R.drawable.play48);
214 		final AbstractController c = mainActivity.controllers
215 				.getVisibleController();
216 		if (c instanceof AbstractListController) {
217 			item = menu.add(Menu.NONE, 2, 2, ActionsEnum.ResizeKeypad.caption);
218 			item.setIcon(ActionsEnum.ResizeKeypad.icon);
219 		}
220 		if (mainActivity.getCurrentFocus() instanceof GesturesListView) {
221 			item = menu.add(Menu.NONE, 3, 3, ActionsEnum.DpadSearch.caption);
222 			item.setIcon(ActionsEnum.DpadSearch.icon);
223 		}
224 	}
225 
226 	/***
227 	 * {@link MainActivity#onOptionsItemSelected(MenuItem)}
228 	 * 
229 	 * @param item
230 	 *            item
231 	 * @return boolean
232 	 */
233 	boolean onOptionsItemSelected(MenuItem item) {
234 		final AmbientApplication app = AmbientApplication.getInstance();
235 		switch (item.getItemId()) {
236 		case 0:
237 			final Intent intent = new Intent(mainActivity, ZoomActivity.class);
238 			mainActivity.startActivity(intent);
239 			return true;
240 		case 1:
241 			switch (app.getPlaylist().getPlaybackState()) {
242 			case Paused:
243 				app.getPlaylist().pause();
244 				break;
245 			case Playing:
246 				app.getPlaylist().pause();
247 				break;
248 			case Stopped:
249 				app.getPlaylist().play();
250 				break;
251 			}
252 			return true;
253 		case 2:
254 			startResizing();
255 			return true;
256 		case 3:
257 			mainActivity.activateAction(ActionsEnum.DpadSearch, false);
258 			return true;
259 		}
260 		return false;
261 	}
262 }