blob: b7b3ac39851d96ed777ee593b9a9dfaa80db3a34 [file] [log] [blame]
alisioncc7bb422013-06-06 15:31:39 -04001/*
Alexandre Lisionc1024c02014-01-06 11:12:53 -05002 * Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
alisioncc7bb422013-06-06 15:31:39 -04003 *
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 Lision940a9db2013-11-19 17:12:02 -050046import android.graphics.PorterDuff.Mode;
47import android.graphics.PorterDuffXfermode;
Alexandre Lision0edf18c2013-09-23 17:35:50 -040048import android.graphics.RectF;
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;
Alexandre Lision8ad39592013-11-21 13:23:58 -050073
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;
Alexandre Lisionf30ff852013-12-09 17:08:40 -0500109 thread = new BubblesThread(getHolder(), getContext());
alision2cb99562013-05-30 17:02:20 -0400110 if (model != null)
111 thread.setModel(model);
112 }
alisionfe9cf712013-05-03 17:26:08 -0400113
alision2cb99562013-05-30 17:02:20 -0400114 public void setModel(BubbleModel model) {
115 this.model = model;
116 thread.setModel(model);
117 }
alisionfe9cf712013-05-03 17:26:08 -0400118
alision2cb99562013-05-30 17:02:20 -0400119 /*
120 * @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (!hasWindowFocus) { thread.pause(); } }
121 */
alisionfe9cf712013-05-03 17:26:08 -0400122
alision2cb99562013-05-30 17:02:20 -0400123 @Override
124 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
125 Log.w(TAG, "surfaceChanged " + width + "-" + height);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400126 if (height < model.height) // probably showing the keyboard, don't move!
Alexandre Lision84208a32013-09-25 13:18:37 -0400127 return;
128
alision2cb99562013-05-30 17:02:20 -0400129 thread.setSurfaceSize(width, height);
130 }
alisionfe9cf712013-05-03 17:26:08 -0400131
alision2cb99562013-05-30 17:02:20 -0400132 /*
133 * Callback invoked when the Surface has been created and is ready to be used.
134 */
135 @Override
136 public void surfaceCreated(SurfaceHolder holder) {
137 // start the thread here so that we don't busy-wait in run()
138 // waiting for the surface to be created
139 createThread();
alisionfe9cf712013-05-03 17:26:08 -0400140
alision2cb99562013-05-30 17:02:20 -0400141 Log.w(TAG, "surfaceCreated");
142 thread.setRunning(true);
143 thread.start();
144 }
alisionfe9cf712013-05-03 17:26:08 -0400145
alision2cb99562013-05-30 17:02:20 -0400146 /*
147 * Callback invoked when the Surface has been destroyed and must no longer be touched. WARNING: after this method returns, the Surface/Canvas must
148 * never be touched again!
149 */
150 @Override
151 public void surfaceDestroyed(SurfaceHolder holder) {
152 // we have to tell thread to shut down & wait for it to finish, or else
153 // it might touch the Surface after we return and explode
154 Log.w(TAG, "surfaceDestroyed");
155 boolean retry = true;
156 thread.setRunning(false);
alision1005ba12013-06-19 13:52:44 -0400157 thread.setPaused(false);
alision2cb99562013-05-30 17:02:20 -0400158 while (retry) {
159 try {
alision1005ba12013-06-19 13:52:44 -0400160 Log.w(TAG, "joining...");
alision2cb99562013-05-30 17:02:20 -0400161 thread.join();
162 retry = false;
163 } catch (InterruptedException e) {
164 }
165 }
alision1005ba12013-06-19 13:52:44 -0400166 Log.w(TAG, "done");
alision2cb99562013-05-30 17:02:20 -0400167 thread = null;
168 }
alisionfe9cf712013-05-03 17:26:08 -0400169
alision2cb99562013-05-30 17:02:20 -0400170 public boolean isDraggingBubble() {
171 return dragging_bubble;
172 }
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000173
alision2cb99562013-05-30 17:02:20 -0400174 class BubblesThread extends Thread {
175 private boolean running = false;
176 private SurfaceHolder surfaceHolder;
alisione38001f2013-06-04 14:14:39 -0400177 public Boolean suspendFlag = false;
alisionfe9cf712013-05-03 17:26:08 -0400178
alision2cb99562013-05-30 17:02:20 -0400179 BubbleModel model = null;
alisionfe9cf712013-05-03 17:26:08 -0400180
Alexandre Lisionf30ff852013-12-09 17:08:40 -0500181 public BubblesThread(SurfaceHolder holder, Context context) {
alision2cb99562013-05-30 17:02:20 -0400182 surfaceHolder = holder;
183 }
alisionfe9cf712013-05-03 17:26:08 -0400184
alision2cb99562013-05-30 17:02:20 -0400185 public void setModel(BubbleModel model) {
186 this.model = model;
187 }
alisionfe9cf712013-05-03 17:26:08 -0400188
alision2cb99562013-05-30 17:02:20 -0400189 @Override
190 public void run() {
191 while (running) {
192 Canvas c = null;
193 try {
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000194
alisione38001f2013-06-04 14:14:39 -0400195 if (suspendFlag) {
196 synchronized (this) {
197 while (suspendFlag) {
198 try {
199 wait();
200 } catch (InterruptedException e) {
201 // TODO Auto-generated catch block
202 e.printStackTrace();
203 }
204 }
205 }
206 } else {
alisione38001f2013-06-04 14:14:39 -0400207 c = surfaceHolder.lockCanvas(null);
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000208
alisione38001f2013-06-04 14:14:39 -0400209 // for the case the surface is destroyed while already in the loop
210 if (c == null || model == null)
211 continue;
212
213 synchronized (surfaceHolder) {
214 // Log.w(TAG, "Thread doDraw");
215 model.update();
216 doDraw(c);
217 }
alision2cb99562013-05-30 17:02:20 -0400218 }
alisione38001f2013-06-04 14:14:39 -0400219
alision2cb99562013-05-30 17:02:20 -0400220 } finally {
221 if (c != null)
222 surfaceHolder.unlockCanvasAndPost(c);
223 }
224 }
225 }
Adrien Béraud04463092013-05-06 14:17:22 +1000226
alisione38001f2013-06-04 14:14:39 -0400227 public void setPaused(boolean wantToPause) {
228 synchronized (this) {
229 suspendFlag = wantToPause;
230 notify();
231 }
232 }
233
alision2cb99562013-05-30 17:02:20 -0400234 public void setRunning(boolean b) {
235 running = b;
236 }
Adrien Béraud04463092013-05-06 14:17:22 +1000237
alision2cb99562013-05-30 17:02:20 -0400238 public void setSurfaceSize(int width, int height) {
239 synchronized (surfaceHolder) {
240 if (model != null) {
241 model.width = width;
242 model.height = height;
243 }
244 }
245 }
Adrien Béraud04463092013-05-06 14:17:22 +1000246
alision2cb99562013-05-30 17:02:20 -0400247 /**
Alexandre Lision8ad39592013-11-21 13:23:58 -0500248 * got multiple IndexOutOfBoundsException, when switching calls. //FIXME
alision2cb99562013-05-30 17:02:20 -0400249 *
250 * @param canvas
251 */
252 private void doDraw(Canvas canvas) {
Adrien Béraud04463092013-05-06 14:17:22 +1000253
alision2cb99562013-05-30 17:02:20 -0400254 synchronized (model) {
255 List<Bubble> bubbles = model.getBubbles();
256 List<Attractor> attractors = model.getAttractors();
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400257
258 Paint tryMe = new Paint();
Alexandre Lision8ad39592013-11-21 13:23:58 -0500259
Alexandre Lision940a9db2013-11-19 17:12:02 -0500260 Paint paint = new Paint();
261 paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
262 canvas.drawPaint(paint);
263 paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400264
Alexandre Lision8ad39592013-11-21 13:23:58 -0500265 // canvas.drawColor(Color.LTGRAY);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400266
267 if (dragging_bubble) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400268 Paint p = new Paint();
269 p.setDither(true);
Alexandre Lision23628c12013-09-24 11:17:05 -0400270 p.setColor(getResources().getColor(R.color.holo_red_light));
Alexandre Lision23628c12013-09-24 11:17:05 -0400271 p.setStyle(Style.STROKE);
Alexandre Lision23628c12013-09-24 11:17:05 -0400272 p.setStrokeWidth(20);
Alexandre Lision23628c12013-09-24 11:17:05 -0400273 canvas.drawRect(new RectF(10, 10, model.width - 10, model.height - 10), p);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400274 }
275
276 tryMe.setStyle(Paint.Style.STROKE);
277 tryMe.setColor(getResources().getColor(R.color.darker_gray));
278 tryMe.setXfermode(null);
279 canvas.drawCircle(model.width / 2, model.height / 2, model.width / 2 - getResources().getDimension(R.dimen.bubble_size), tryMe);
280
alision2cb99562013-05-30 17:02:20 -0400281 try {
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +1000282
alision2cb99562013-05-30 17:02:20 -0400283 for (int i = 0, n = attractors.size(); i < n; i++) {
284 Attractor a = attractors.get(i);
285 canvas.drawBitmap(a.getBitmap(), null, a.getBounds(), null);
286 }
Adrien Béraud33268882013-05-18 03:41:15 +1000287
alision2cb99562013-05-30 17:02:20 -0400288 for (int i = 0, n = bubbles.size(); i < n; i++) {
289 Bubble b = bubbles.get(i);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400290 if (b.expanded) {
alision465ceba2013-07-04 09:24:30 -0400291 continue;
292 }
alision2cb99562013-05-30 17:02:20 -0400293 canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400294 canvas.drawText(b.getName(), b.getPosX(), (float) (b.getPosY() - b.getRetractedRadius() * 1.2 * density), getNamePaint(b));
alision34673e62013-06-25 14:40:07 -0400295 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400296
alision34673e62013-06-25 14:40:07 -0400297 Bubble first_plan = getExpandedBubble();
298 if (first_plan != null) {
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400299
Alexandre Lision40954dc2013-10-09 15:24:03 -0400300 if (first_plan.getDrawerBitmap() != null) {
301 canvas.drawBitmap(first_plan.getDrawerBitmap(), null, first_plan.getDrawerBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400302 }
alision34673e62013-06-25 14:40:07 -0400303 canvas.drawBitmap(first_plan.getBitmap(), null, first_plan.getBounds(), null);
Alexandre Lision40954dc2013-10-09 15:24:03 -0400304 // canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),
305 // (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));
alisiondf1dac92013-06-27 17:35:53 -0400306
alision2cb99562013-05-30 17:02:20 -0400307 }
308
309 } catch (IndexOutOfBoundsException e) {
310 Log.e(TAG, e.toString());
311 }
312 }
313 }
alision34673e62013-06-25 14:40:07 -0400314
315 }
316
317 private Paint getNamePaint(Bubble b) {
alision50fa0722013-06-25 17:29:44 -0400318 if (b.expanded) {
319 white_name_paint.setTextSize(15 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400320 return white_name_paint;
alision50fa0722013-06-25 17:29:44 -0400321 }
322 black_name_paint.setTextSize(18 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400323 return black_name_paint;
alision2cb99562013-05-30 17:02:20 -0400324 }
Adrien Béraud04463092013-05-06 14:17:22 +1000325
alisione38001f2013-06-04 14:14:39 -0400326 @Override
327 public boolean onTouch(View v, MotionEvent event) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400328 // Log.w(TAG, "onTouch " + event.getAction());
alisione38001f2013-06-04 14:14:39 -0400329
330 int action = event.getActionMasked();
331
Alexandre Lision1888bf32013-10-31 09:51:41 -0400332 if (gDetector.onTouchEvent(event))
333 return true;
334
alisione38001f2013-06-04 14:14:39 -0400335 if (action == MotionEvent.ACTION_UP) {
336 if (thread.suspendFlag) {
337 Log.i(TAG, "Relaunch drawing thread");
338 thread.setPaused(false);
339 }
340
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400341 Bubble expand = getExpandedBubble();
342 if (expand != null) {
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400343 switch (expand.getDrawer().getAction(event.getX(), event.getY())) {
344 case Bubble.actions.OUT_OF_BOUNDS:
345 expand.retract();
346 break;
347 case Bubble.actions.HOLD:
348
349 try {
350 if (expand.getHoldStatus()) {
351
352 if (expand.isConference())
353 callback.mCallbacks.getService().unholdConference(expand.getCallID());
354 else
355 callback.mCallbacks.getService().unhold(expand.getCallID());
356 } else {
357 if (expand.isConference())
358 callback.mCallbacks.getService().holdConference(expand.getCallID());
359 else
360 callback.mCallbacks.getService().hold(expand.getCallID());
361
362 }
363 } catch (Exception e) {
364 e.printStackTrace();
365 }
366
367 return true;
368 case Bubble.actions.RECORD:
369 try {
Alexandre Lision3874e552013-11-04 17:20:12 -0500370 boolean isRecording = callback.mCallbacks.getService().toggleRecordingCall(expand.getCallID());
371 ((BubbleUser) expand).associated_call.setRecording(isRecording);
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400372 } catch (RemoteException e1) {
373 e1.printStackTrace();
374 }
375 return true;
376 case Bubble.actions.MESSAGE:
377 // TODO
378 return true;
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400379 case Bubble.actions.MUTE:
Alexandre Lisionc9fca9e2013-11-08 15:21:18 -0500380 try {
381 callback.mCallbacks.getService().setMuted(!((BubbleUser) expand).getMute());
382 ((BubbleUser) expand).toggleMute();
383 } catch (RemoteException e1) {
384 e1.printStackTrace();
385 }
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400386 return true;
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400387 case Bubble.actions.HANGUP:
388 try {
389 if (expand.isConference())
390 callback.mCallbacks.getService().hangUpConference(expand.getCallID());
391 else
392 callback.mCallbacks.getService().hangUp(expand.getCallID());
393 } catch (RemoteException e) {
394 e.printStackTrace();
395 }
396 return true;
397
398 case Bubble.actions.TRANSFER:
399 callback.makeTransfer((BubbleContact) expand);
400 return true;
401 case Bubble.actions.NOTHING:
402 break;
403 }
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400404
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400405 }
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400406
alisione38001f2013-06-04 14:14:39 -0400407 List<Bubble> bubbles = model.getBubbles();
408 final int n_bubbles = bubbles.size();
409 for (int i = 0; i < n_bubbles; i++) {
410 Bubble b = bubbles.get(i);
411 if (b.dragged) {
412 b.dragged = false;
413 b.target_scale = 1.f;
Alexandre Lisionfdef8852013-09-24 13:32:38 -0400414 if (b.isOnBorder(model.width, model.height) && !b.expanded) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400415 b.markedToDie = true;
Alexandre Lision68855472013-10-10 16:20:46 -0400416
417 try {
418 if (b.isConference())
419 callback.mCallbacks.getService().hangUpConference(b.getCallID());
420 else
421 callback.mCallbacks.getService().hangUp(b.getCallID());
422
423 } catch (RemoteException e) {
424 e.printStackTrace();
425 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400426 }
alisione38001f2013-06-04 14:14:39 -0400427 }
428 }
429 dragging_bubble = false;
430 } else if (action != MotionEvent.ACTION_DOWN && !isDraggingBubble() && !thread.suspendFlag) {
431
432 Log.i(TAG, "Not dragging thread should be stopped");
433 thread.setPaused(true);
434 // thread.holdDrawing();
435 }
436
Alexandre Lision1888bf32013-10-31 09:51:41 -0400437 return true;
alisione38001f2013-06-04 14:14:39 -0400438 }
439
alision34673e62013-06-25 14:40:07 -0400440 private Bubble getExpandedBubble() {
441 List<Bubble> bubbles = model.getBubbles();
442 final int n_bubbles = bubbles.size();
443 for (int i = 0; i < n_bubbles; i++) {
444 Bubble b = bubbles.get(i);
445 if (b.expanded) {
446 return b;
447 }
448 }
449 return null;
450 }
alision2ec64f92013-06-17 17:28:58 -0400451
alisiondf1dac92013-06-27 17:35:53 -0400452 public void restartDrawing() {
453 if (thread != null && thread.suspendFlag) {
454 Log.i(TAG, "Relaunch drawing thread");
455 thread.setPaused(false);
456 }
457 }
458
459 public void setFragment(CallFragment callFragment) {
460 callback = callFragment;
461
462 }
463
464 public void stopThread() {
465 if (thread != null && thread.suspendFlag) {
466 Log.i(TAG, "Stop drawing thread");
Alexandre Lision666b3772013-10-28 17:42:48 -0400467 thread.setPaused(true);
alisiondf1dac92013-06-27 17:35:53 -0400468 }
469
470 }
471
alision58356b72013-06-03 17:13:36 -0400472 class MyOnGestureListener implements OnGestureListener {
473 @Override
474 public boolean onDown(MotionEvent event) {
475 List<Bubble> bubbles = model.getBubbles();
Alexandre Lision1888bf32013-10-31 09:51:41 -0400476
Alexandre Lision8fdcf2b2013-10-30 16:06:51 -0400477 Bubble target = getExpandedBubble();
Alexandre Lision1888bf32013-10-31 09:51:41 -0400478 if (target != null) {
Alexandre Lision8fdcf2b2013-10-30 16:06:51 -0400479 target.onDown(event);
480 return true;
481 }
Alexandre Lision68855472013-10-10 16:20:46 -0400482
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400483 for (int i = 0; i < bubbles.size(); i++) {
alision58356b72013-06-03 17:13:36 -0400484 Bubble b = bubbles.get(i);
Alexandre Lision1888bf32013-10-31 09:51:41 -0400485 if (b.onDown(event))
486 dragging_bubble = true;
alision58356b72013-06-03 17:13:36 -0400487 }
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400488
alision58356b72013-06-03 17:13:36 -0400489 return true;
490 }
alision2ec64f92013-06-17 17:28:58 -0400491
alision58356b72013-06-03 17:13:36 -0400492 @Override
493 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400494 // Log.d("Main", "onFling");
Alexandre Lision1888bf32013-10-31 09:51:41 -0400495 return false;
alision58356b72013-06-03 17:13:36 -0400496 }
497
498 @Override
499 public void onLongPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400500 // Log.d("Main", "onLongPress");
Alexandre Lision1888bf32013-10-31 09:51:41 -0400501
alision2ec64f92013-06-17 17:28:58 -0400502 }
503
alision2ec64f92013-06-17 17:28:58 -0400504 private Bubble getDraggedBubble(MotionEvent e) {
505 List<Bubble> bubbles = model.getBubbles();
506 final int n_bubbles = bubbles.size();
507 for (int i = 0; i < n_bubbles; i++) {
508 Bubble b = bubbles.get(i);
509 if (b.intersects(e.getX(), e.getY())) {
510 return b;
511 }
512 }
513 return null;
alision58356b72013-06-03 17:13:36 -0400514 }
515
516 @Override
517 public boolean onScroll(MotionEvent e1, MotionEvent event, float distanceX, float distanceY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400518 // Log.d("Main", "onScroll");
alision58356b72013-06-03 17:13:36 -0400519 List<Bubble> bubbles = model.getBubbles();
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400520
alision58356b72013-06-03 17:13:36 -0400521 long now = System.nanoTime();
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400522 for (int i = 0; i < bubbles.size(); i++) {
alision58356b72013-06-03 17:13:36 -0400523 Bubble b = bubbles.get(i);
524 if (b.dragged) {
525 float x = event.getX(), y = event.getY();
526 float dt = (float) ((now - b.last_drag) / 1000000000.);
527 float dx = x - b.getPosX(), dy = y - b.getPosY();
528 b.last_drag = now;
alision58356b72013-06-03 17:13:36 -0400529 b.setPos(event.getX(), event.getY());
alision58356b72013-06-03 17:13:36 -0400530 b.speed.x = dx / dt;
531 b.speed.y = dy / dt;
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400532
Alexandre Lision1888bf32013-10-31 09:51:41 -0400533 return false;
alision58356b72013-06-03 17:13:36 -0400534 }
535 }
536 return true;
537 }
538
539 @Override
540 public void onShowPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400541 // Log.d("Main", "onShowPress");
alision58356b72013-06-03 17:13:36 -0400542
543 }
544
545 @Override
546 public boolean onSingleTapUp(MotionEvent e) {
Alexandre Lision1888bf32013-10-31 09:51:41 -0400547 if (isDraggingBubble() && callback.getConference().isOnGoing()) {
548 Bubble b = getDraggedBubble(e);
549 b.expand(model.width, model.height);
Alexandre Lision1a682572013-11-01 11:21:17 -0400550 dragging_bubble = false;
Alexandre Lision1888bf32013-10-31 09:51:41 -0400551 }
552 return false;
553
alision58356b72013-06-03 17:13:36 -0400554 }
555 }
alisionfe9cf712013-05-03 17:26:08 -0400556}