blob: 7673224584a4d21de2f6c705ef86e586506529ee [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;
38import org.sflphone.client.CallActivity;
39import org.sflphone.fragments.CallFragment;
Alexandre Lision68855472013-10-10 16:20:46 -040040import org.sflphone.model.SipCall.state;
Alexandre Lision064e1e02013-10-01 16:18:42 -040041
alisionfe9cf712013-05-03 17:26:08 -040042import android.content.Context;
43import android.graphics.Canvas;
Adrien Béraud33268882013-05-18 03:41:15 +100044import android.graphics.Paint;
Adrien Béraud6bbce912013-05-24 00:48:13 +100045import android.graphics.Paint.Align;
Alexandre Lision23628c12013-09-24 11:17:05 -040046import android.graphics.Paint.Style;
Alexandre Lision68855472013-10-10 16:20:46 -040047import android.graphics.PixelFormat;
Alexandre Lision0edf18c2013-09-23 17:35:50 -040048import android.graphics.RectF;
Adrien Béraud04463092013-05-06 14:17:22 +100049import android.os.Handler;
50import android.os.Message;
Alexandre Lision68855472013-10-10 16:20:46 -040051import android.os.RemoteException;
alisionfe9cf712013-05-03 17:26:08 -040052import android.util.AttributeSet;
53import android.util.Log;
alision58356b72013-06-03 17:13:36 -040054import android.view.GestureDetector;
55import android.view.GestureDetector.OnGestureListener;
alisionfe9cf712013-05-03 17:26:08 -040056import android.view.MotionEvent;
Adrien Béraud04463092013-05-06 14:17:22 +100057import android.view.SurfaceHolder;
58import android.view.SurfaceView;
alisionfe9cf712013-05-03 17:26:08 -040059import android.view.View;
Adrien Béraud04463092013-05-06 14:17:22 +100060import android.view.View.OnTouchListener;
alisionfe9cf712013-05-03 17:26:08 -040061
alision2cb99562013-05-30 17:02:20 -040062public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
63 private static final String TAG = BubblesView.class.getSimpleName();
alisionfe9cf712013-05-03 17:26:08 -040064
alision2cb99562013-05-30 17:02:20 -040065 private BubblesThread thread = null;
66 private BubbleModel model;
alisionfe9cf712013-05-03 17:26:08 -040067
alision34673e62013-06-25 14:40:07 -040068 private Paint black_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
69 private Paint white_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Adrien Béraud6bbce912013-05-24 00:48:13 +100070
alisione38001f2013-06-04 14:14:39 -040071 private GestureDetector gDetector;
72
alision2cb99562013-05-30 17:02:20 -040073 private float density;
74 private float textDensity;
Adrien Béraud33268882013-05-18 03:41:15 +100075
alision2cb99562013-05-30 17:02:20 -040076 private boolean dragging_bubble = false;
Adrien Béraudc9c424d2013-05-30 17:47:35 +100077
alision34673e62013-06-25 14:40:07 -040078 private CallFragment callback;
79
alision2cb99562013-05-30 17:02:20 -040080 public BubblesView(Context context, AttributeSet attrs) {
81 super(context, attrs);
alisionfe9cf712013-05-03 17:26:08 -040082
alision2cb99562013-05-30 17:02:20 -040083 density = getResources().getDisplayMetrics().density;
84 textDensity = getResources().getDisplayMetrics().scaledDensity;
Adrien Béraud6bbce912013-05-24 00:48:13 +100085
alision2cb99562013-05-30 17:02:20 -040086 SurfaceHolder holder = getHolder();
87 holder.addCallback(this);
alisionfe9cf712013-05-03 17:26:08 -040088
Alexandre Lision68855472013-10-10 16:20:46 -040089 this.setZOrderOnTop(true); // necessary
90 this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
alision2cb99562013-05-30 17:02:20 -040091 // create thread only; it's started in surfaceCreated()
92 createThread();
alisionfe9cf712013-05-03 17:26:08 -040093
alision2cb99562013-05-30 17:02:20 -040094 setOnTouchListener(this);
95 setFocusable(true);
Adrien Béraud33268882013-05-18 03:41:15 +100096
alision34673e62013-06-25 14:40:07 -040097 black_name_paint.setTextSize(18 * textDensity);
98 black_name_paint.setColor(0xFF303030);
99 black_name_paint.setTextAlign(Align.CENTER);
100
101 white_name_paint.setTextSize(18 * textDensity);
102 white_name_paint.setColor(0xFFEEEEEE);
103 white_name_paint.setTextAlign(Align.CENTER);
alision58356b72013-06-03 17:13:36 -0400104
105 gDetector = new GestureDetector(getContext(), new MyOnGestureListener());
alision2cb99562013-05-30 17:02:20 -0400106 }
alisionfe9cf712013-05-03 17:26:08 -0400107
alision2cb99562013-05-30 17:02:20 -0400108 private void createThread() {
109 if (thread != null)
110 return;
111 thread = new BubblesThread(getHolder(), getContext(), new Handler() {
112 @Override
113 public void handleMessage(Message m) {
114 /*
115 * mStatusText.setVisibility(m.getData().getInt("viz")); mStatusText.setText(m.getData().getString("text"));
116 */
117 }
118 });
119 if (model != null)
120 thread.setModel(model);
121 }
alisionfe9cf712013-05-03 17:26:08 -0400122
alision2cb99562013-05-30 17:02:20 -0400123 public void setModel(BubbleModel model) {
124 this.model = model;
125 thread.setModel(model);
126 }
alisionfe9cf712013-05-03 17:26:08 -0400127
alision2cb99562013-05-30 17:02:20 -0400128 /*
129 * @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (!hasWindowFocus) { thread.pause(); } }
130 */
alisionfe9cf712013-05-03 17:26:08 -0400131
alision2cb99562013-05-30 17:02:20 -0400132 @Override
133 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
134 Log.w(TAG, "surfaceChanged " + width + "-" + height);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400135 if (height < model.height) // probably showing the keyboard, don't move!
Alexandre Lision84208a32013-09-25 13:18:37 -0400136 return;
137
alision2cb99562013-05-30 17:02:20 -0400138 thread.setSurfaceSize(width, height);
139 }
alisionfe9cf712013-05-03 17:26:08 -0400140
alision2cb99562013-05-30 17:02:20 -0400141 /*
142 * Callback invoked when the Surface has been created and is ready to be used.
143 */
144 @Override
145 public void surfaceCreated(SurfaceHolder holder) {
146 // start the thread here so that we don't busy-wait in run()
147 // waiting for the surface to be created
148 createThread();
alisionfe9cf712013-05-03 17:26:08 -0400149
alision2cb99562013-05-30 17:02:20 -0400150 Log.w(TAG, "surfaceCreated");
151 thread.setRunning(true);
152 thread.start();
153 }
alisionfe9cf712013-05-03 17:26:08 -0400154
alision2cb99562013-05-30 17:02:20 -0400155 /*
156 * Callback invoked when the Surface has been destroyed and must no longer be touched. WARNING: after this method returns, the Surface/Canvas must
157 * never be touched again!
158 */
159 @Override
160 public void surfaceDestroyed(SurfaceHolder holder) {
161 // we have to tell thread to shut down & wait for it to finish, or else
162 // it might touch the Surface after we return and explode
163 Log.w(TAG, "surfaceDestroyed");
164 boolean retry = true;
165 thread.setRunning(false);
alision1005ba12013-06-19 13:52:44 -0400166 thread.setPaused(false);
alision2cb99562013-05-30 17:02:20 -0400167 while (retry) {
168 try {
alision1005ba12013-06-19 13:52:44 -0400169 Log.w(TAG, "joining...");
alision2cb99562013-05-30 17:02:20 -0400170 thread.join();
171 retry = false;
172 } catch (InterruptedException e) {
173 }
174 }
alision1005ba12013-06-19 13:52:44 -0400175 Log.w(TAG, "done");
alision2cb99562013-05-30 17:02:20 -0400176 thread = null;
177 }
alisionfe9cf712013-05-03 17:26:08 -0400178
alision2cb99562013-05-30 17:02:20 -0400179 public boolean isDraggingBubble() {
180 return dragging_bubble;
181 }
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000182
alision2cb99562013-05-30 17:02:20 -0400183 class BubblesThread extends Thread {
184 private boolean running = false;
185 private SurfaceHolder surfaceHolder;
alisione38001f2013-06-04 14:14:39 -0400186 public Boolean suspendFlag = false;
alisionfe9cf712013-05-03 17:26:08 -0400187
alision2cb99562013-05-30 17:02:20 -0400188 BubbleModel model = null;
alisionfe9cf712013-05-03 17:26:08 -0400189
alision2cb99562013-05-30 17:02:20 -0400190 public BubblesThread(SurfaceHolder holder, Context context, Handler handler) {
191 surfaceHolder = holder;
192 }
alisionfe9cf712013-05-03 17:26:08 -0400193
alision2cb99562013-05-30 17:02:20 -0400194 public void setModel(BubbleModel model) {
195 this.model = model;
196 }
alisionfe9cf712013-05-03 17:26:08 -0400197
alision2cb99562013-05-30 17:02:20 -0400198 @Override
199 public void run() {
200 while (running) {
201 Canvas c = null;
202 try {
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000203
alisione38001f2013-06-04 14:14:39 -0400204 if (suspendFlag) {
205 synchronized (this) {
206 while (suspendFlag) {
207 try {
208 wait();
209 } catch (InterruptedException e) {
210 // TODO Auto-generated catch block
211 e.printStackTrace();
212 }
213 }
214 }
215 } else {
alisione38001f2013-06-04 14:14:39 -0400216 c = surfaceHolder.lockCanvas(null);
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000217
alisione38001f2013-06-04 14:14:39 -0400218 // for the case the surface is destroyed while already in the loop
219 if (c == null || model == null)
220 continue;
221
222 synchronized (surfaceHolder) {
223 // Log.w(TAG, "Thread doDraw");
224 model.update();
225 doDraw(c);
226 }
alision2cb99562013-05-30 17:02:20 -0400227 }
alisione38001f2013-06-04 14:14:39 -0400228
alision2cb99562013-05-30 17:02:20 -0400229 } finally {
230 if (c != null)
231 surfaceHolder.unlockCanvasAndPost(c);
232 }
233 }
234 }
Adrien Béraud04463092013-05-06 14:17:22 +1000235
alisione38001f2013-06-04 14:14:39 -0400236 public void setPaused(boolean wantToPause) {
237 synchronized (this) {
238 suspendFlag = wantToPause;
239 notify();
240 }
241 }
242
alision2cb99562013-05-30 17:02:20 -0400243 public void setRunning(boolean b) {
244 running = b;
245 }
Adrien Béraud04463092013-05-06 14:17:22 +1000246
alision2cb99562013-05-30 17:02:20 -0400247 public void setSurfaceSize(int width, int height) {
248 synchronized (surfaceHolder) {
249 if (model != null) {
250 model.width = width;
251 model.height = height;
252 }
253 }
254 }
Adrien Béraud04463092013-05-06 14:17:22 +1000255
alision2cb99562013-05-30 17:02:20 -0400256 /**
257 * I got multiple IndexOutOfBoundsException, when switching calls. //FIXME
258 *
259 * @param canvas
260 */
261 private void doDraw(Canvas canvas) {
Adrien Béraud04463092013-05-06 14:17:22 +1000262
alision2cb99562013-05-30 17:02:20 -0400263 synchronized (model) {
264 List<Bubble> bubbles = model.getBubbles();
265 List<Attractor> attractors = model.getAttractors();
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400266
267 Paint tryMe = new Paint();
268
Alexandre Lision40954dc2013-10-09 15:24:03 -0400269 canvas.drawColor(getResources().getColor(R.color.sfl_light_blue));
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400270
271 if (dragging_bubble) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400272 Paint p = new Paint();
273 p.setDither(true);
Alexandre Lision23628c12013-09-24 11:17:05 -0400274 p.setColor(getResources().getColor(R.color.holo_red_light));
Alexandre Lision23628c12013-09-24 11:17:05 -0400275 p.setStyle(Style.STROKE);
Alexandre Lision23628c12013-09-24 11:17:05 -0400276 p.setStrokeWidth(20);
Alexandre Lision23628c12013-09-24 11:17:05 -0400277 canvas.drawRect(new RectF(10, 10, model.width - 10, model.height - 10), p);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400278 }
279
280 tryMe.setStyle(Paint.Style.STROKE);
281 tryMe.setColor(getResources().getColor(R.color.darker_gray));
282 tryMe.setXfermode(null);
283 canvas.drawCircle(model.width / 2, model.height / 2, model.width / 2 - getResources().getDimension(R.dimen.bubble_size), tryMe);
284
alision2cb99562013-05-30 17:02:20 -0400285 try {
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +1000286
alision2cb99562013-05-30 17:02:20 -0400287 for (int i = 0, n = attractors.size(); i < n; i++) {
288 Attractor a = attractors.get(i);
289 canvas.drawBitmap(a.getBitmap(), null, a.getBounds(), null);
290 }
Adrien Béraud33268882013-05-18 03:41:15 +1000291
alision2cb99562013-05-30 17:02:20 -0400292 for (int i = 0, n = bubbles.size(); i < n; i++) {
293 Bubble b = bubbles.get(i);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400294 if (b.expanded) {
alision465ceba2013-07-04 09:24:30 -0400295 continue;
296 }
alision2cb99562013-05-30 17:02:20 -0400297 canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400298 canvas.drawText(b.getName(), b.getPosX(), (float) (b.getPosY() - b.getRetractedRadius() * 1.2 * density), getNamePaint(b));
alision34673e62013-06-25 14:40:07 -0400299 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400300
alision34673e62013-06-25 14:40:07 -0400301 Bubble first_plan = getExpandedBubble();
302 if (first_plan != null) {
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400303
Alexandre Lision40954dc2013-10-09 15:24:03 -0400304 if (first_plan.getDrawerBitmap() != null) {
305 canvas.drawBitmap(first_plan.getDrawerBitmap(), null, first_plan.getDrawerBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400306 }
alision34673e62013-06-25 14:40:07 -0400307 canvas.drawBitmap(first_plan.getBitmap(), null, first_plan.getBounds(), null);
Alexandre Lision40954dc2013-10-09 15:24:03 -0400308 // canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),
309 // (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));
alisiondf1dac92013-06-27 17:35:53 -0400310
alision2cb99562013-05-30 17:02:20 -0400311 }
312
313 } catch (IndexOutOfBoundsException e) {
314 Log.e(TAG, e.toString());
315 }
316 }
317 }
alision34673e62013-06-25 14:40:07 -0400318
319 }
320
321 private Paint getNamePaint(Bubble b) {
alision50fa0722013-06-25 17:29:44 -0400322 if (b.expanded) {
323 white_name_paint.setTextSize(15 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400324 return white_name_paint;
alision50fa0722013-06-25 17:29:44 -0400325 }
326 black_name_paint.setTextSize(18 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400327 return black_name_paint;
alision2cb99562013-05-30 17:02:20 -0400328 }
Adrien Béraud04463092013-05-06 14:17:22 +1000329
alisione38001f2013-06-04 14:14:39 -0400330 @Override
331 public boolean onTouch(View v, MotionEvent event) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400332 // Log.w(TAG, "onTouch " + event.getAction());
alisione38001f2013-06-04 14:14:39 -0400333
334 int action = event.getActionMasked();
335
336 if (action == MotionEvent.ACTION_UP) {
337 if (thread.suspendFlag) {
338 Log.i(TAG, "Relaunch drawing thread");
339 thread.setPaused(false);
340 }
341
342 List<Bubble> bubbles = model.getBubbles();
343 final int n_bubbles = bubbles.size();
344 for (int i = 0; i < n_bubbles; i++) {
345 Bubble b = bubbles.get(i);
346 if (b.dragged) {
347 b.dragged = false;
348 b.target_scale = 1.f;
Alexandre Lisionfdef8852013-09-24 13:32:38 -0400349 if (b.isOnBorder(model.width, model.height) && !b.expanded) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400350 b.markedToDie = true;
Alexandre Lision68855472013-10-10 16:20:46 -0400351
352 try {
353 if (b.isConference())
354 callback.mCallbacks.getService().hangUpConference(b.getCallID());
355 else
356 callback.mCallbacks.getService().hangUp(b.getCallID());
357
358 } catch (RemoteException e) {
359 e.printStackTrace();
360 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400361 }
alisione38001f2013-06-04 14:14:39 -0400362 }
363 }
364 dragging_bubble = false;
365 } else if (action != MotionEvent.ACTION_DOWN && !isDraggingBubble() && !thread.suspendFlag) {
366
367 Log.i(TAG, "Not dragging thread should be stopped");
368 thread.setPaused(true);
369 // thread.holdDrawing();
370 }
371
372 return gDetector.onTouchEvent(event);
373 }
374
alision34673e62013-06-25 14:40:07 -0400375 private Bubble getExpandedBubble() {
376 List<Bubble> bubbles = model.getBubbles();
377 final int n_bubbles = bubbles.size();
378 for (int i = 0; i < n_bubbles; i++) {
379 Bubble b = bubbles.get(i);
380 if (b.expanded) {
381 return b;
382 }
383 }
384 return null;
385 }
alision2ec64f92013-06-17 17:28:58 -0400386
alisiondf1dac92013-06-27 17:35:53 -0400387 public void restartDrawing() {
388 if (thread != null && thread.suspendFlag) {
389 Log.i(TAG, "Relaunch drawing thread");
390 thread.setPaused(false);
391 }
392 }
393
394 public void setFragment(CallFragment callFragment) {
395 callback = callFragment;
396
397 }
398
399 public void stopThread() {
400 if (thread != null && thread.suspendFlag) {
401 Log.i(TAG, "Stop drawing thread");
402 thread.setRunning(false);
403 thread.setPaused(false);
404 }
405
406 }
407
alision58356b72013-06-03 17:13:36 -0400408 class MyOnGestureListener implements OnGestureListener {
409 @Override
410 public boolean onDown(MotionEvent event) {
411 List<Bubble> bubbles = model.getBubbles();
412 final int n_bubbles = bubbles.size();
alision2ec64f92013-06-17 17:28:58 -0400413 Bubble expand = getExpandedBubble();
Alexandre Lision40954dc2013-10-09 15:24:03 -0400414 Log.d("Main", "onDown");
alision34673e62013-06-25 14:40:07 -0400415 if (expand != null) {
Alexandre Lision68855472013-10-10 16:20:46 -0400416 Log.d("Main", "getAction");
Alexandre Lision40954dc2013-10-09 15:24:03 -0400417 switch (expand.getDrawer().getAction(event.getX(), event.getY())) {
418 case Bubble.actions.NOTHING:
alision34673e62013-06-25 14:40:07 -0400419 expand.retract();
Alexandre Lision40954dc2013-10-09 15:24:03 -0400420 break;
421 case Bubble.actions.HOLD:
Alexandre Lision68855472013-10-10 16:20:46 -0400422
423 try {
424 if (expand.getHoldStatus()) {
425
426 if (expand.isConference())
427 callback.mCallbacks.getService().unholdConference(expand.getCallID());
428 else
429 callback.mCallbacks.getService().unhold(expand.getCallID());
430 } else {
431 if (expand.isConference())
432 callback.mCallbacks.getService().holdConference(expand.getCallID());
433 else
434 callback.mCallbacks.getService().hold(expand.getCallID());
435
436 }
437 } catch (Exception e) {
438 e.printStackTrace();
alision34673e62013-06-25 14:40:07 -0400439 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400440
441 break;
442 case Bubble.actions.RECORD:
Alexandre Lision68855472013-10-10 16:20:46 -0400443 try {
444 callback.mCallbacks.getService().toggleRecordingCall(expand.getCallID());
445 } catch (RemoteException e1) {
446 e1.printStackTrace();
447 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400448 break;
449 case Bubble.actions.MESSAGE:
450 // TODO
451 break;
452
453 case Bubble.actions.HANGUP:
Alexandre Lision68855472013-10-10 16:20:46 -0400454 try {
455 if (expand.isConference())
456 callback.mCallbacks.getService().hangUpConference(expand.getCallID());
457 else
458 callback.mCallbacks.getService().hangUp(expand.getCallID());
459 } catch (RemoteException e) {
460 e.printStackTrace();
461 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400462 break;
463
464 case Bubble.actions.TRANSFER:
465 callback.makeTransfer((BubbleContact) expand);
466 break;
alision34673e62013-06-25 14:40:07 -0400467 }
468 return true;
alision2ec64f92013-06-17 17:28:58 -0400469 }
Alexandre Lision40954dc2013-10-09 15:24:03 -0400470
Alexandre Lision6deda412013-09-25 13:21:22 -0400471 // Log.d("Main", "onDown");
alision58356b72013-06-03 17:13:36 -0400472 for (int i = 0; i < n_bubbles; i++) {
473 Bubble b = bubbles.get(i);
alision34673e62013-06-25 14:40:07 -0400474 if (b.intersects(event.getX(), event.getY()) && !b.expanded) {
alision58356b72013-06-03 17:13:36 -0400475 b.dragged = true;
476 b.last_drag = System.nanoTime();
477 b.setPos(event.getX(), event.getY());
478 b.target_scale = .8f;
479 dragging_bubble = true;
480 }
481 }
482 return true;
483 }
alision2ec64f92013-06-17 17:28:58 -0400484
alision58356b72013-06-03 17:13:36 -0400485 @Override
486 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400487 // Log.d("Main", "onFling");
alision58356b72013-06-03 17:13:36 -0400488 return true;
489 }
490
491 @Override
492 public void onLongPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400493 // Log.d("Main", "onLongPress");
alision2ec64f92013-06-17 17:28:58 -0400494 if (isDraggingBubble()) {
495 Bubble b = getDraggedBubble(e);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400496 b.expand(model.width, model.height);
alision2ec64f92013-06-17 17:28:58 -0400497 }
498 }
499
alision2ec64f92013-06-17 17:28:58 -0400500 private Bubble getDraggedBubble(MotionEvent e) {
501 List<Bubble> bubbles = model.getBubbles();
502 final int n_bubbles = bubbles.size();
503 for (int i = 0; i < n_bubbles; i++) {
504 Bubble b = bubbles.get(i);
505 if (b.intersects(e.getX(), e.getY())) {
506 return b;
507 }
508 }
509 return null;
alision58356b72013-06-03 17:13:36 -0400510 }
511
512 @Override
513 public boolean onScroll(MotionEvent e1, MotionEvent event, float distanceX, float distanceY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400514 // Log.d("Main", "onScroll");
alision58356b72013-06-03 17:13:36 -0400515 List<Bubble> bubbles = model.getBubbles();
516 final int n_bubbles = bubbles.size();
517 long now = System.nanoTime();
518 for (int i = 0; i < n_bubbles; i++) {
519 Bubble b = bubbles.get(i);
520 if (b.dragged) {
521 float x = event.getX(), y = event.getY();
522 float dt = (float) ((now - b.last_drag) / 1000000000.);
523 float dx = x - b.getPosX(), dy = y - b.getPosY();
524 b.last_drag = now;
alision58356b72013-06-03 17:13:36 -0400525 b.setPos(event.getX(), event.getY());
alision58356b72013-06-03 17:13:36 -0400526 b.speed.x = dx / dt;
527 b.speed.y = dy / dt;
alision58356b72013-06-03 17:13:36 -0400528 // }
529 return true;
530 }
531 }
532 return true;
533 }
534
535 @Override
536 public void onShowPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400537 // Log.d("Main", "onShowPress");
alision58356b72013-06-03 17:13:36 -0400538
539 }
540
541 @Override
542 public boolean onSingleTapUp(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400543 // Log.d("Main", "onSingleTapUp");
alision58356b72013-06-03 17:13:36 -0400544 return true;
545 }
546 }
alisionfe9cf712013-05-03 17:26:08 -0400547}