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
77
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
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 }