blob: ea6292d2df8ea3c7985defffe1e8cf7d52a488d1 [file] [log] [blame]
alisioncc7bb422013-06-06 15:31:39 -04001/*
2 * Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3 *
4 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
5 * Adrien Béraud <adrien.beraud@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Additional permission under GNU GPL version 3 section 7:
22 *
23 * If you modify this program, or any covered work, by linking or
24 * combining it with the OpenSSL project's OpenSSL library (or a
25 * modified version of that library), containing parts covered by the
26 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
27 * grants you additional permission to convey the resulting work.
28 * Corresponding Source for a non-source form of such a combination
29 * shall include the source code for the parts of OpenSSL used as well
30 * as that of the covered work.
31 */
32
Alexandre Lision064e1e02013-10-01 16:18:42 -040033package org.sflphone.model;
alisionfe9cf712013-05-03 17:26:08 -040034
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +100035import java.util.List;
36
Alexandre Lision064e1e02013-10-01 16:18:42 -040037import org.sflphone.R;
Alexandre Lision064e1e02013-10-01 16:18:42 -040038import org.sflphone.fragments.CallFragment;
39
alisionfe9cf712013-05-03 17:26:08 -040040import android.content.Context;
41import android.graphics.Canvas;
Adrien Béraud33268882013-05-18 03:41:15 +100042import android.graphics.Paint;
Adrien Béraud6bbce912013-05-24 00:48:13 +100043import android.graphics.Paint.Align;
Alexandre Lision23628c12013-09-24 11:17:05 -040044import android.graphics.Paint.Style;
Alexandre Lision68855472013-10-10 16:20:46 -040045import android.graphics.PixelFormat;
Alexandre Lision0edf18c2013-09-23 17:35:50 -040046import android.graphics.RectF;
Adrien Béraud04463092013-05-06 14:17:22 +100047import android.os.Handler;
48import android.os.Message;
Alexandre Lision68855472013-10-10 16:20:46 -040049import android.os.RemoteException;
alisionfe9cf712013-05-03 17:26:08 -040050import android.util.AttributeSet;
51import android.util.Log;
alision58356b72013-06-03 17:13:36 -040052import android.view.GestureDetector;
53import android.view.GestureDetector.OnGestureListener;
alisionfe9cf712013-05-03 17:26:08 -040054import android.view.MotionEvent;
Adrien Béraud04463092013-05-06 14:17:22 +100055import android.view.SurfaceHolder;
56import android.view.SurfaceView;
alisionfe9cf712013-05-03 17:26:08 -040057import android.view.View;
Adrien Béraud04463092013-05-06 14:17:22 +100058import android.view.View.OnTouchListener;
alisionfe9cf712013-05-03 17:26:08 -040059
alision2cb99562013-05-30 17:02:20 -040060public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
61 private static final String TAG = BubblesView.class.getSimpleName();
alisionfe9cf712013-05-03 17:26:08 -040062
alision2cb99562013-05-30 17:02:20 -040063 private BubblesThread thread = null;
64 private BubbleModel model;
alisionfe9cf712013-05-03 17:26:08 -040065
alision34673e62013-06-25 14:40:07 -040066 private Paint black_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
67 private Paint white_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Adrien Béraud6bbce912013-05-24 00:48:13 +100068
alisione38001f2013-06-04 14:14:39 -040069 private GestureDetector gDetector;
70
alision2cb99562013-05-30 17:02:20 -040071 private float density;
72 private float textDensity;
Adrien Béraud33268882013-05-18 03:41:15 +100073
alision2cb99562013-05-30 17:02:20 -040074 private boolean dragging_bubble = false;
Adrien Béraudc9c424d2013-05-30 17:47:35 +100075
alision34673e62013-06-25 14:40:07 -040076 private CallFragment callback;
77
alision2cb99562013-05-30 17:02:20 -040078 public BubblesView(Context context, AttributeSet attrs) {
79 super(context, attrs);
alisionfe9cf712013-05-03 17:26:08 -040080
alision2cb99562013-05-30 17:02:20 -040081 density = getResources().getDisplayMetrics().density;
82 textDensity = getResources().getDisplayMetrics().scaledDensity;
Adrien Béraud6bbce912013-05-24 00:48:13 +100083
alision2cb99562013-05-30 17:02:20 -040084 SurfaceHolder holder = getHolder();
85 holder.addCallback(this);
alisionfe9cf712013-05-03 17:26:08 -040086
Alexandre Lision68855472013-10-10 16:20:46 -040087 this.setZOrderOnTop(true); // necessary
88 this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
alision2cb99562013-05-30 17:02:20 -040089 // create thread only; it's started in surfaceCreated()
90 createThread();
alisionfe9cf712013-05-03 17:26:08 -040091
alision2cb99562013-05-30 17:02:20 -040092 setOnTouchListener(this);
93 setFocusable(true);
Adrien Béraud33268882013-05-18 03:41:15 +100094
alision34673e62013-06-25 14:40:07 -040095 black_name_paint.setTextSize(18 * textDensity);
96 black_name_paint.setColor(0xFF303030);
97 black_name_paint.setTextAlign(Align.CENTER);
98
99 white_name_paint.setTextSize(18 * textDensity);
100 white_name_paint.setColor(0xFFEEEEEE);
101 white_name_paint.setTextAlign(Align.CENTER);
alision58356b72013-06-03 17:13:36 -0400102
103 gDetector = new GestureDetector(getContext(), new MyOnGestureListener());
alision2cb99562013-05-30 17:02:20 -0400104 }
alisionfe9cf712013-05-03 17:26:08 -0400105
alision2cb99562013-05-30 17:02:20 -0400106 private void createThread() {
107 if (thread != null)
108 return;
109 thread = new BubblesThread(getHolder(), getContext(), new Handler() {
110 @Override
111 public void handleMessage(Message m) {
112 /*
113 * mStatusText.setVisibility(m.getData().getInt("viz")); mStatusText.setText(m.getData().getString("text"));
114 */
115 }
116 });
117 if (model != null)
118 thread.setModel(model);
119 }
alisionfe9cf712013-05-03 17:26:08 -0400120
alision2cb99562013-05-30 17:02:20 -0400121 public void setModel(BubbleModel model) {
122 this.model = model;
123 thread.setModel(model);
124 }
alisionfe9cf712013-05-03 17:26:08 -0400125
alision2cb99562013-05-30 17:02:20 -0400126 /*
127 * @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (!hasWindowFocus) { thread.pause(); } }
128 */
alisionfe9cf712013-05-03 17:26:08 -0400129
alision2cb99562013-05-30 17:02:20 -0400130 @Override
131 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
132 Log.w(TAG, "surfaceChanged " + width + "-" + height);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400133 if (height < model.height) // probably showing the keyboard, don't move!
Alexandre Lision84208a32013-09-25 13:18:37 -0400134 return;
135
alision2cb99562013-05-30 17:02:20 -0400136 thread.setSurfaceSize(width, height);
137 }
alisionfe9cf712013-05-03 17:26:08 -0400138
alision2cb99562013-05-30 17:02:20 -0400139 /*
140 * Callback invoked when the Surface has been created and is ready to be used.
141 */
142 @Override
143 public void surfaceCreated(SurfaceHolder holder) {
144 // start the thread here so that we don't busy-wait in run()
145 // waiting for the surface to be created
146 createThread();
alisionfe9cf712013-05-03 17:26:08 -0400147
alision2cb99562013-05-30 17:02:20 -0400148 Log.w(TAG, "surfaceCreated");
149 thread.setRunning(true);
150 thread.start();
151 }
alisionfe9cf712013-05-03 17:26:08 -0400152
alision2cb99562013-05-30 17:02:20 -0400153 /*
154 * Callback invoked when the Surface has been destroyed and must no longer be touched. WARNING: after this method returns, the Surface/Canvas must
155 * never be touched again!
156 */
157 @Override
158 public void surfaceDestroyed(SurfaceHolder holder) {
159 // we have to tell thread to shut down & wait for it to finish, or else
160 // it might touch the Surface after we return and explode
161 Log.w(TAG, "surfaceDestroyed");
162 boolean retry = true;
163 thread.setRunning(false);
alision1005ba12013-06-19 13:52:44 -0400164 thread.setPaused(false);
alision2cb99562013-05-30 17:02:20 -0400165 while (retry) {
166 try {
alision1005ba12013-06-19 13:52:44 -0400167 Log.w(TAG, "joining...");
alision2cb99562013-05-30 17:02:20 -0400168 thread.join();
169 retry = false;
170 } catch (InterruptedException e) {
171 }
172 }
alision1005ba12013-06-19 13:52:44 -0400173 Log.w(TAG, "done");
alision2cb99562013-05-30 17:02:20 -0400174 thread = null;
175 }
alisionfe9cf712013-05-03 17:26:08 -0400176
alision2cb99562013-05-30 17:02:20 -0400177 public boolean isDraggingBubble() {
178 return dragging_bubble;
179 }
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000180
alision2cb99562013-05-30 17:02:20 -0400181 class BubblesThread extends Thread {
182 private boolean running = false;
183 private SurfaceHolder surfaceHolder;
alisione38001f2013-06-04 14:14:39 -0400184 public Boolean suspendFlag = false;
alisionfe9cf712013-05-03 17:26:08 -0400185
alision2cb99562013-05-30 17:02:20 -0400186 BubbleModel model = null;
alisionfe9cf712013-05-03 17:26:08 -0400187
alision2cb99562013-05-30 17:02:20 -0400188 public BubblesThread(SurfaceHolder holder, Context context, Handler handler) {
189 surfaceHolder = holder;
190 }
alisionfe9cf712013-05-03 17:26:08 -0400191
alision2cb99562013-05-30 17:02:20 -0400192 public void setModel(BubbleModel model) {
193 this.model = model;
194 }
alisionfe9cf712013-05-03 17:26:08 -0400195
alision2cb99562013-05-30 17:02:20 -0400196 @Override
197 public void run() {
198 while (running) {
199 Canvas c = null;
200 try {
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000201
alisione38001f2013-06-04 14:14:39 -0400202 if (suspendFlag) {
203 synchronized (this) {
204 while (suspendFlag) {
205 try {
206 wait();
207 } catch (InterruptedException e) {
208 // TODO Auto-generated catch block
209 e.printStackTrace();
210 }
211 }
212 }
213 } else {
alisione38001f2013-06-04 14:14:39 -0400214 c = surfaceHolder.lockCanvas(null);
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000215
alisione38001f2013-06-04 14:14:39 -0400216 // for the case the surface is destroyed while already in the loop
217 if (c == null || model == null)
218 continue;
219
220 synchronized (surfaceHolder) {
221 // Log.w(TAG, "Thread doDraw");
222 model.update();
223 doDraw(c);
224 }
alision2cb99562013-05-30 17:02:20 -0400225 }
alisione38001f2013-06-04 14:14:39 -0400226
alision2cb99562013-05-30 17:02:20 -0400227 } finally {
228 if (c != null)
229 surfaceHolder.unlockCanvasAndPost(c);
230 }
231 }
232 }
Adrien Béraud04463092013-05-06 14:17:22 +1000233
alisione38001f2013-06-04 14:14:39 -0400234 public void setPaused(boolean wantToPause) {
235 synchronized (this) {
236 suspendFlag = wantToPause;
237 notify();
238 }
239 }
240
alision2cb99562013-05-30 17:02:20 -0400241 public void setRunning(boolean b) {
242 running = b;
243 }
Adrien Béraud04463092013-05-06 14:17:22 +1000244
alision2cb99562013-05-30 17:02:20 -0400245 public void setSurfaceSize(int width, int height) {
246 synchronized (surfaceHolder) {
247 if (model != null) {
248 model.width = width;
249 model.height = height;
250 }
251 }
252 }
Adrien Béraud04463092013-05-06 14:17:22 +1000253
alision2cb99562013-05-30 17:02:20 -0400254 /**
255 * I got multiple IndexOutOfBoundsException, when switching calls. //FIXME
256 *
257 * @param canvas
258 */
259 private void doDraw(Canvas canvas) {
Adrien Béraud04463092013-05-06 14:17:22 +1000260
alision2cb99562013-05-30 17:02:20 -0400261 synchronized (model) {
262 List<Bubble> bubbles = model.getBubbles();
263 List<Attractor> attractors = model.getAttractors();
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400264
265 Paint tryMe = new Paint();
266
Alexandre Lision40954dc2013-10-09 15:24:03 -0400267 canvas.drawColor(getResources().getColor(R.color.sfl_light_blue));
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400268
269 if (dragging_bubble) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400270 Paint p = new Paint();
271 p.setDither(true);
Alexandre Lision23628c12013-09-24 11:17:05 -0400272 p.setColor(getResources().getColor(R.color.holo_red_light));
Alexandre Lision23628c12013-09-24 11:17:05 -0400273 p.setStyle(Style.STROKE);
Alexandre Lision23628c12013-09-24 11:17:05 -0400274 p.setStrokeWidth(20);
Alexandre Lision23628c12013-09-24 11:17:05 -0400275 canvas.drawRect(new RectF(10, 10, model.width - 10, model.height - 10), p);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400276 }
277
278 tryMe.setStyle(Paint.Style.STROKE);
279 tryMe.setColor(getResources().getColor(R.color.darker_gray));
280 tryMe.setXfermode(null);
281 canvas.drawCircle(model.width / 2, model.height / 2, model.width / 2 - getResources().getDimension(R.dimen.bubble_size), tryMe);
282
alision2cb99562013-05-30 17:02:20 -0400283 try {
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +1000284
alision2cb99562013-05-30 17:02:20 -0400285 for (int i = 0, n = attractors.size(); i < n; i++) {
286 Attractor a = attractors.get(i);
287 canvas.drawBitmap(a.getBitmap(), null, a.getBounds(), null);
288 }
Adrien Béraud33268882013-05-18 03:41:15 +1000289
alision2cb99562013-05-30 17:02:20 -0400290 for (int i = 0, n = bubbles.size(); i < n; i++) {
291 Bubble b = bubbles.get(i);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400292 if (b.expanded) {
alision465ceba2013-07-04 09:24:30 -0400293 continue;
294 }
alision2cb99562013-05-30 17:02:20 -0400295 canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400296 canvas.drawText(b.getName(), b.getPosX(), (float) (b.getPosY() - b.getRetractedRadius() * 1.2 * density), getNamePaint(b));
alision34673e62013-06-25 14:40:07 -0400297 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400298
alision34673e62013-06-25 14:40:07 -0400299 Bubble first_plan = getExpandedBubble();
300 if (first_plan != null) {
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400301
Alexandre Lision40954dc2013-10-09 15:24:03 -0400302 if (first_plan.getDrawerBitmap() != null) {
303 canvas.drawBitmap(first_plan.getDrawerBitmap(), null, first_plan.getDrawerBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400304 }
alision34673e62013-06-25 14:40:07 -0400305 canvas.drawBitmap(first_plan.getBitmap(), null, first_plan.getBounds(), null);
Alexandre Lision40954dc2013-10-09 15:24:03 -0400306 // canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),
307 // (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));
alisiondf1dac92013-06-27 17:35:53 -0400308
alision2cb99562013-05-30 17:02:20 -0400309 }
310
311 } catch (IndexOutOfBoundsException e) {
312 Log.e(TAG, e.toString());
313 }
314 }
315 }
alision34673e62013-06-25 14:40:07 -0400316
317 }
318
319 private Paint getNamePaint(Bubble b) {
alision50fa0722013-06-25 17:29:44 -0400320 if (b.expanded) {
321 white_name_paint.setTextSize(15 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400322 return white_name_paint;
alision50fa0722013-06-25 17:29:44 -0400323 }
324 black_name_paint.setTextSize(18 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400325 return black_name_paint;
alision2cb99562013-05-30 17:02:20 -0400326 }
Adrien Béraud04463092013-05-06 14:17:22 +1000327
alisione38001f2013-06-04 14:14:39 -0400328 @Override
329 public boolean onTouch(View v, MotionEvent event) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400330 // Log.w(TAG, "onTouch " + event.getAction());
alisione38001f2013-06-04 14:14:39 -0400331
332 int action = event.getActionMasked();
333
334 if (action == MotionEvent.ACTION_UP) {
335 if (thread.suspendFlag) {
336 Log.i(TAG, "Relaunch drawing thread");
337 thread.setPaused(false);
338 }
339
340 List<Bubble> bubbles = model.getBubbles();
341 final int n_bubbles = bubbles.size();
342 for (int i = 0; i < n_bubbles; i++) {
343 Bubble b = bubbles.get(i);
344 if (b.dragged) {
345 b.dragged = false;
346 b.target_scale = 1.f;
Alexandre Lisionfdef8852013-09-24 13:32:38 -0400347 if (b.isOnBorder(model.width, model.height) && !b.expanded) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400348 b.markedToDie = true;
Alexandre Lision68855472013-10-10 16:20:46 -0400349
350 try {
351 if (b.isConference())
352 callback.mCallbacks.getService().hangUpConference(b.getCallID());
353 else
354 callback.mCallbacks.getService().hangUp(b.getCallID());
355
356 } catch (RemoteException e) {
357 e.printStackTrace();
358 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400359 }
alisione38001f2013-06-04 14:14:39 -0400360 }
361 }
362 dragging_bubble = false;
363 } else if (action != MotionEvent.ACTION_DOWN && !isDraggingBubble() && !thread.suspendFlag) {
364
365 Log.i(TAG, "Not dragging thread should be stopped");
366 thread.setPaused(true);
367 // thread.holdDrawing();
368 }
369
370 return gDetector.onTouchEvent(event);
371 }
372
alision34673e62013-06-25 14:40:07 -0400373 private Bubble getExpandedBubble() {
374 List<Bubble> bubbles = model.getBubbles();
375 final int n_bubbles = bubbles.size();
376 for (int i = 0; i < n_bubbles; i++) {
377 Bubble b = bubbles.get(i);
378 if (b.expanded) {
379 return b;
380 }
381 }
382 return null;
383 }
alision2ec64f92013-06-17 17:28:58 -0400384
alisiondf1dac92013-06-27 17:35:53 -0400385 public void restartDrawing() {
386 if (thread != null && thread.suspendFlag) {
387 Log.i(TAG, "Relaunch drawing thread");
388 thread.setPaused(false);
389 }
390 }
391
392 public void setFragment(CallFragment callFragment) {
393 callback = callFragment;
394
395 }
396
397 public void stopThread() {
398 if (thread != null && thread.suspendFlag) {
399 Log.i(TAG, "Stop drawing thread");
400 thread.setRunning(false);
401 thread.setPaused(false);
402 }
403
404 }
405
alision58356b72013-06-03 17:13:36 -0400406 class MyOnGestureListener implements OnGestureListener {
407 @Override
408 public boolean onDown(MotionEvent event) {
409 List<Bubble> bubbles = model.getBubbles();
410 final int n_bubbles = bubbles.size();
alision2ec64f92013-06-17 17:28:58 -0400411 Bubble expand = getExpandedBubble();
Alexandre Lision40954dc2013-10-09 15:24:03 -0400412 Log.d("Main", "onDown");
alision34673e62013-06-25 14:40:07 -0400413 if (expand != null) {
Alexandre Lision68855472013-10-10 16:20:46 -0400414 Log.d("Main", "getAction");
Alexandre Lision40954dc2013-10-09 15:24:03 -0400415 switch (expand.getDrawer().getAction(event.getX(), event.getY())) {
416 case Bubble.actions.NOTHING:
alision34673e62013-06-25 14:40:07 -0400417 expand.retract();
Alexandre Lision40954dc2013-10-09 15:24:03 -0400418 break;
419 case Bubble.actions.HOLD:
Alexandre Lision68855472013-10-10 16:20:46 -0400420
421 try {
422 if (expand.getHoldStatus()) {
423
424 if (expand.isConference())
425 callback.mCallbacks.getService().unholdConference(expand.getCallID());
426 else
427 callback.mCallbacks.getService().unhold(expand.getCallID());
428 } else {
429 if (expand.isConference())
430 callback.mCallbacks.getService().holdConference(expand.getCallID());
431 else
432 callback.mCallbacks.getService().hold(expand.getCallID());
433
434 }
435 } catch (Exception e) {
436 e.printStackTrace();
alision34673e62013-06-25 14:40:07 -0400437 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400438
439 break;
440 case Bubble.actions.RECORD:
Alexandre Lision68855472013-10-10 16:20:46 -0400441 try {
442 callback.mCallbacks.getService().toggleRecordingCall(expand.getCallID());
443 } catch (RemoteException e1) {
444 e1.printStackTrace();
445 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400446 break;
447 case Bubble.actions.MESSAGE:
448 // TODO
449 break;
450
451 case Bubble.actions.HANGUP:
Alexandre Lision68855472013-10-10 16:20:46 -0400452 try {
453 if (expand.isConference())
454 callback.mCallbacks.getService().hangUpConference(expand.getCallID());
455 else
456 callback.mCallbacks.getService().hangUp(expand.getCallID());
457 } catch (RemoteException e) {
458 e.printStackTrace();
459 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400460 break;
461
462 case Bubble.actions.TRANSFER:
463 callback.makeTransfer((BubbleContact) expand);
464 break;
alision34673e62013-06-25 14:40:07 -0400465 }
466 return true;
alision2ec64f92013-06-17 17:28:58 -0400467 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400468
Alexandre Lision6deda412013-09-25 13:21:22 -0400469 // Log.d("Main", "onDown");
alision58356b72013-06-03 17:13:36 -0400470 for (int i = 0; i < n_bubbles; i++) {
471 Bubble b = bubbles.get(i);
alision34673e62013-06-25 14:40:07 -0400472 if (b.intersects(event.getX(), event.getY()) && !b.expanded) {
alision58356b72013-06-03 17:13:36 -0400473 b.dragged = true;
474 b.last_drag = System.nanoTime();
475 b.setPos(event.getX(), event.getY());
476 b.target_scale = .8f;
477 dragging_bubble = true;
478 }
479 }
480 return true;
481 }
alision2ec64f92013-06-17 17:28:58 -0400482
alision58356b72013-06-03 17:13:36 -0400483 @Override
484 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400485 // Log.d("Main", "onFling");
alision58356b72013-06-03 17:13:36 -0400486 return true;
487 }
488
489 @Override
490 public void onLongPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400491 // Log.d("Main", "onLongPress");
alision2ec64f92013-06-17 17:28:58 -0400492 if (isDraggingBubble()) {
493 Bubble b = getDraggedBubble(e);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400494 b.expand(model.width, model.height);
alision2ec64f92013-06-17 17:28:58 -0400495 }
496 }
497
alision2ec64f92013-06-17 17:28:58 -0400498 private Bubble getDraggedBubble(MotionEvent e) {
499 List<Bubble> bubbles = model.getBubbles();
500 final int n_bubbles = bubbles.size();
501 for (int i = 0; i < n_bubbles; i++) {
502 Bubble b = bubbles.get(i);
503 if (b.intersects(e.getX(), e.getY())) {
504 return b;
505 }
506 }
507 return null;
alision58356b72013-06-03 17:13:36 -0400508 }
509
510 @Override
511 public boolean onScroll(MotionEvent e1, MotionEvent event, float distanceX, float distanceY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400512 // Log.d("Main", "onScroll");
alision58356b72013-06-03 17:13:36 -0400513 List<Bubble> bubbles = model.getBubbles();
514 final int n_bubbles = bubbles.size();
515 long now = System.nanoTime();
516 for (int i = 0; i < n_bubbles; i++) {
517 Bubble b = bubbles.get(i);
518 if (b.dragged) {
519 float x = event.getX(), y = event.getY();
520 float dt = (float) ((now - b.last_drag) / 1000000000.);
521 float dx = x - b.getPosX(), dy = y - b.getPosY();
522 b.last_drag = now;
alision58356b72013-06-03 17:13:36 -0400523 b.setPos(event.getX(), event.getY());
alision58356b72013-06-03 17:13:36 -0400524 b.speed.x = dx / dt;
525 b.speed.y = dy / dt;
alision58356b72013-06-03 17:13:36 -0400526 // }
527 return true;
528 }
529 }
530 return true;
531 }
532
533 @Override
534 public void onShowPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400535 // Log.d("Main", "onShowPress");
alision58356b72013-06-03 17:13:36 -0400536
537 }
538
539 @Override
540 public boolean onSingleTapUp(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400541 // Log.d("Main", "onSingleTapUp");
alision58356b72013-06-03 17:13:36 -0400542 return true;
543 }
544 }
alisionfe9cf712013-05-03 17:26:08 -0400545}