blob: f5ec01dc8a5096ebefb6477121d8e00baffd82ac [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;
Alexandre Lision940a9db2013-11-19 17:12:02 -050041import android.graphics.Bitmap;
42import android.graphics.BitmapFactory;
alisionfe9cf712013-05-03 17:26:08 -040043import 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 Lision940a9db2013-11-19 17:12:02 -050048import android.graphics.PorterDuff.Mode;
49import android.graphics.PorterDuffXfermode;
Alexandre Lision0edf18c2013-09-23 17:35:50 -040050import android.graphics.RectF;
Adrien Béraud04463092013-05-06 14:17:22 +100051import android.os.Handler;
52import android.os.Message;
Alexandre Lision68855472013-10-10 16:20:46 -040053import android.os.RemoteException;
alisionfe9cf712013-05-03 17:26:08 -040054import android.util.AttributeSet;
55import android.util.Log;
alision58356b72013-06-03 17:13:36 -040056import android.view.GestureDetector;
57import android.view.GestureDetector.OnGestureListener;
alisionfe9cf712013-05-03 17:26:08 -040058import android.view.MotionEvent;
Adrien Béraud04463092013-05-06 14:17:22 +100059import android.view.SurfaceHolder;
60import android.view.SurfaceView;
alisionfe9cf712013-05-03 17:26:08 -040061import android.view.View;
Adrien Béraud04463092013-05-06 14:17:22 +100062import android.view.View.OnTouchListener;
alisionfe9cf712013-05-03 17:26:08 -040063
alision2cb99562013-05-30 17:02:20 -040064public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
65 private static final String TAG = BubblesView.class.getSimpleName();
alisionfe9cf712013-05-03 17:26:08 -040066
alision2cb99562013-05-30 17:02:20 -040067 private BubblesThread thread = null;
68 private BubbleModel model;
alisionfe9cf712013-05-03 17:26:08 -040069
alision34673e62013-06-25 14:40:07 -040070 private Paint black_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
71 private Paint white_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Adrien Béraud6bbce912013-05-24 00:48:13 +100072
alisione38001f2013-06-04 14:14:39 -040073 private GestureDetector gDetector;
74
alision2cb99562013-05-30 17:02:20 -040075 private float density;
76 private float textDensity;
Alexandre Lision940a9db2013-11-19 17:12:02 -050077
78 private Bitmap mBackground;
Adrien Béraud33268882013-05-18 03:41:15 +100079
alision2cb99562013-05-30 17:02:20 -040080 private boolean dragging_bubble = false;
Adrien Béraudc9c424d2013-05-30 17:47:35 +100081
alision34673e62013-06-25 14:40:07 -040082 private CallFragment callback;
83
alision2cb99562013-05-30 17:02:20 -040084 public BubblesView(Context context, AttributeSet attrs) {
85 super(context, attrs);
alisionfe9cf712013-05-03 17:26:08 -040086
Alexandre Lision940a9db2013-11-19 17:12:02 -050087 Bitmap tmp = BitmapFactory.decodeResource(getResources(), R.drawable.bg_72);
88 mBackground = Bitmap.createScaledBitmap(tmp, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels, false);
alision2cb99562013-05-30 17:02:20 -040089 density = getResources().getDisplayMetrics().density;
90 textDensity = getResources().getDisplayMetrics().scaledDensity;
Adrien Béraud6bbce912013-05-24 00:48:13 +100091
alision2cb99562013-05-30 17:02:20 -040092 SurfaceHolder holder = getHolder();
93 holder.addCallback(this);
alisionfe9cf712013-05-03 17:26:08 -040094
Alexandre Lision68855472013-10-10 16:20:46 -040095 this.setZOrderOnTop(true); // necessary
96 this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
alision2cb99562013-05-30 17:02:20 -040097 // create thread only; it's started in surfaceCreated()
98 createThread();
alisionfe9cf712013-05-03 17:26:08 -040099
alision2cb99562013-05-30 17:02:20 -0400100 setOnTouchListener(this);
101 setFocusable(true);
Adrien Béraud33268882013-05-18 03:41:15 +1000102
alision34673e62013-06-25 14:40:07 -0400103 black_name_paint.setTextSize(18 * textDensity);
104 black_name_paint.setColor(0xFF303030);
105 black_name_paint.setTextAlign(Align.CENTER);
106
107 white_name_paint.setTextSize(18 * textDensity);
108 white_name_paint.setColor(0xFFEEEEEE);
109 white_name_paint.setTextAlign(Align.CENTER);
alision58356b72013-06-03 17:13:36 -0400110
111 gDetector = new GestureDetector(getContext(), new MyOnGestureListener());
alision2cb99562013-05-30 17:02:20 -0400112 }
alisionfe9cf712013-05-03 17:26:08 -0400113
alision2cb99562013-05-30 17:02:20 -0400114 private void createThread() {
115 if (thread != null)
116 return;
117 thread = new BubblesThread(getHolder(), getContext(), new Handler() {
118 @Override
119 public void handleMessage(Message m) {
120 /*
121 * mStatusText.setVisibility(m.getData().getInt("viz")); mStatusText.setText(m.getData().getString("text"));
122 */
123 }
124 });
125 if (model != null)
126 thread.setModel(model);
127 }
alisionfe9cf712013-05-03 17:26:08 -0400128
alision2cb99562013-05-30 17:02:20 -0400129 public void setModel(BubbleModel model) {
130 this.model = model;
131 thread.setModel(model);
132 }
alisionfe9cf712013-05-03 17:26:08 -0400133
alision2cb99562013-05-30 17:02:20 -0400134 /*
135 * @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (!hasWindowFocus) { thread.pause(); } }
136 */
alisionfe9cf712013-05-03 17:26:08 -0400137
alision2cb99562013-05-30 17:02:20 -0400138 @Override
139 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
140 Log.w(TAG, "surfaceChanged " + width + "-" + height);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400141 if (height < model.height) // probably showing the keyboard, don't move!
Alexandre Lision84208a32013-09-25 13:18:37 -0400142 return;
143
alision2cb99562013-05-30 17:02:20 -0400144 thread.setSurfaceSize(width, height);
145 }
alisionfe9cf712013-05-03 17:26:08 -0400146
alision2cb99562013-05-30 17:02:20 -0400147 /*
148 * Callback invoked when the Surface has been created and is ready to be used.
149 */
150 @Override
151 public void surfaceCreated(SurfaceHolder holder) {
152 // start the thread here so that we don't busy-wait in run()
153 // waiting for the surface to be created
154 createThread();
alisionfe9cf712013-05-03 17:26:08 -0400155
alision2cb99562013-05-30 17:02:20 -0400156 Log.w(TAG, "surfaceCreated");
157 thread.setRunning(true);
158 thread.start();
159 }
alisionfe9cf712013-05-03 17:26:08 -0400160
alision2cb99562013-05-30 17:02:20 -0400161 /*
162 * Callback invoked when the Surface has been destroyed and must no longer be touched. WARNING: after this method returns, the Surface/Canvas must
163 * never be touched again!
164 */
165 @Override
166 public void surfaceDestroyed(SurfaceHolder holder) {
167 // we have to tell thread to shut down & wait for it to finish, or else
168 // it might touch the Surface after we return and explode
169 Log.w(TAG, "surfaceDestroyed");
170 boolean retry = true;
171 thread.setRunning(false);
alision1005ba12013-06-19 13:52:44 -0400172 thread.setPaused(false);
alision2cb99562013-05-30 17:02:20 -0400173 while (retry) {
174 try {
alision1005ba12013-06-19 13:52:44 -0400175 Log.w(TAG, "joining...");
alision2cb99562013-05-30 17:02:20 -0400176 thread.join();
177 retry = false;
178 } catch (InterruptedException e) {
179 }
180 }
alision1005ba12013-06-19 13:52:44 -0400181 Log.w(TAG, "done");
alision2cb99562013-05-30 17:02:20 -0400182 thread = null;
183 }
alisionfe9cf712013-05-03 17:26:08 -0400184
alision2cb99562013-05-30 17:02:20 -0400185 public boolean isDraggingBubble() {
186 return dragging_bubble;
187 }
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000188
alision2cb99562013-05-30 17:02:20 -0400189 class BubblesThread extends Thread {
190 private boolean running = false;
191 private SurfaceHolder surfaceHolder;
alisione38001f2013-06-04 14:14:39 -0400192 public Boolean suspendFlag = false;
alisionfe9cf712013-05-03 17:26:08 -0400193
alision2cb99562013-05-30 17:02:20 -0400194 BubbleModel model = null;
alisionfe9cf712013-05-03 17:26:08 -0400195
alision2cb99562013-05-30 17:02:20 -0400196 public BubblesThread(SurfaceHolder holder, Context context, Handler handler) {
197 surfaceHolder = holder;
198 }
alisionfe9cf712013-05-03 17:26:08 -0400199
alision2cb99562013-05-30 17:02:20 -0400200 public void setModel(BubbleModel model) {
201 this.model = model;
202 }
alisionfe9cf712013-05-03 17:26:08 -0400203
alision2cb99562013-05-30 17:02:20 -0400204 @Override
205 public void run() {
206 while (running) {
207 Canvas c = null;
208 try {
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000209
alisione38001f2013-06-04 14:14:39 -0400210 if (suspendFlag) {
211 synchronized (this) {
212 while (suspendFlag) {
213 try {
214 wait();
215 } catch (InterruptedException e) {
216 // TODO Auto-generated catch block
217 e.printStackTrace();
218 }
219 }
220 }
221 } else {
alisione38001f2013-06-04 14:14:39 -0400222 c = surfaceHolder.lockCanvas(null);
Adrien Béraud7ed23dc2013-05-06 16:27:24 +1000223
alisione38001f2013-06-04 14:14:39 -0400224 // for the case the surface is destroyed while already in the loop
225 if (c == null || model == null)
226 continue;
227
228 synchronized (surfaceHolder) {
229 // Log.w(TAG, "Thread doDraw");
230 model.update();
231 doDraw(c);
232 }
alision2cb99562013-05-30 17:02:20 -0400233 }
alisione38001f2013-06-04 14:14:39 -0400234
alision2cb99562013-05-30 17:02:20 -0400235 } finally {
236 if (c != null)
237 surfaceHolder.unlockCanvasAndPost(c);
238 }
239 }
240 }
Adrien Béraud04463092013-05-06 14:17:22 +1000241
alisione38001f2013-06-04 14:14:39 -0400242 public void setPaused(boolean wantToPause) {
243 synchronized (this) {
244 suspendFlag = wantToPause;
245 notify();
246 }
247 }
248
alision2cb99562013-05-30 17:02:20 -0400249 public void setRunning(boolean b) {
250 running = b;
251 }
Adrien Béraud04463092013-05-06 14:17:22 +1000252
alision2cb99562013-05-30 17:02:20 -0400253 public void setSurfaceSize(int width, int height) {
254 synchronized (surfaceHolder) {
255 if (model != null) {
256 model.width = width;
257 model.height = height;
258 }
259 }
260 }
Adrien Béraud04463092013-05-06 14:17:22 +1000261
alision2cb99562013-05-30 17:02:20 -0400262 /**
Alexandre Lision940a9db2013-11-19 17:12:02 -0500263 * got multiple IndexOutOfBoundsException, when switching calls. //FIXME
alision2cb99562013-05-30 17:02:20 -0400264 *
265 * @param canvas
266 */
267 private void doDraw(Canvas canvas) {
Adrien Béraud04463092013-05-06 14:17:22 +1000268
alision2cb99562013-05-30 17:02:20 -0400269 synchronized (model) {
270 List<Bubble> bubbles = model.getBubbles();
271 List<Attractor> attractors = model.getAttractors();
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400272
273 Paint tryMe = new Paint();
Alexandre Lision940a9db2013-11-19 17:12:02 -0500274
275 Paint paint = new Paint();
276 paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
277 canvas.drawPaint(paint);
278 paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400279
Alexandre Lision940a9db2013-11-19 17:12:02 -0500280// canvas.drawColor(Color.LTGRAY);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400281
282 if (dragging_bubble) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400283 Paint p = new Paint();
284 p.setDither(true);
Alexandre Lision23628c12013-09-24 11:17:05 -0400285 p.setColor(getResources().getColor(R.color.holo_red_light));
Alexandre Lision23628c12013-09-24 11:17:05 -0400286 p.setStyle(Style.STROKE);
Alexandre Lision23628c12013-09-24 11:17:05 -0400287 p.setStrokeWidth(20);
Alexandre Lision23628c12013-09-24 11:17:05 -0400288 canvas.drawRect(new RectF(10, 10, model.width - 10, model.height - 10), p);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400289 }
290
291 tryMe.setStyle(Paint.Style.STROKE);
292 tryMe.setColor(getResources().getColor(R.color.darker_gray));
293 tryMe.setXfermode(null);
294 canvas.drawCircle(model.width / 2, model.height / 2, model.width / 2 - getResources().getDimension(R.dimen.bubble_size), tryMe);
295
alision2cb99562013-05-30 17:02:20 -0400296 try {
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +1000297
alision2cb99562013-05-30 17:02:20 -0400298 for (int i = 0, n = attractors.size(); i < n; i++) {
299 Attractor a = attractors.get(i);
300 canvas.drawBitmap(a.getBitmap(), null, a.getBounds(), null);
301 }
Adrien Béraud33268882013-05-18 03:41:15 +1000302
alision2cb99562013-05-30 17:02:20 -0400303 for (int i = 0, n = bubbles.size(); i < n; i++) {
304 Bubble b = bubbles.get(i);
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400305 if (b.expanded) {
alision465ceba2013-07-04 09:24:30 -0400306 continue;
307 }
alision2cb99562013-05-30 17:02:20 -0400308 canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400309 canvas.drawText(b.getName(), b.getPosX(), (float) (b.getPosY() - b.getRetractedRadius() * 1.2 * density), getNamePaint(b));
alision34673e62013-06-25 14:40:07 -0400310 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400311
alision34673e62013-06-25 14:40:07 -0400312 Bubble first_plan = getExpandedBubble();
313 if (first_plan != null) {
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400314
Alexandre Lision40954dc2013-10-09 15:24:03 -0400315 if (first_plan.getDrawerBitmap() != null) {
316 canvas.drawBitmap(first_plan.getDrawerBitmap(), null, first_plan.getDrawerBounds(), null);
Alexandre Lision68855472013-10-10 16:20:46 -0400317 }
alision34673e62013-06-25 14:40:07 -0400318 canvas.drawBitmap(first_plan.getBitmap(), null, first_plan.getBounds(), null);
Alexandre Lision40954dc2013-10-09 15:24:03 -0400319 // canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),
320 // (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));
alisiondf1dac92013-06-27 17:35:53 -0400321
alision2cb99562013-05-30 17:02:20 -0400322 }
323
324 } catch (IndexOutOfBoundsException e) {
325 Log.e(TAG, e.toString());
326 }
327 }
328 }
alision34673e62013-06-25 14:40:07 -0400329
330 }
331
332 private Paint getNamePaint(Bubble b) {
alision50fa0722013-06-25 17:29:44 -0400333 if (b.expanded) {
334 white_name_paint.setTextSize(15 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400335 return white_name_paint;
alision50fa0722013-06-25 17:29:44 -0400336 }
337 black_name_paint.setTextSize(18 * b.target_scale * textDensity);
alision34673e62013-06-25 14:40:07 -0400338 return black_name_paint;
alision2cb99562013-05-30 17:02:20 -0400339 }
Adrien Béraud04463092013-05-06 14:17:22 +1000340
alisione38001f2013-06-04 14:14:39 -0400341 @Override
342 public boolean onTouch(View v, MotionEvent event) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400343 // Log.w(TAG, "onTouch " + event.getAction());
alisione38001f2013-06-04 14:14:39 -0400344
345 int action = event.getActionMasked();
346
Alexandre Lision1888bf32013-10-31 09:51:41 -0400347 if (gDetector.onTouchEvent(event))
348 return true;
349
alisione38001f2013-06-04 14:14:39 -0400350 if (action == MotionEvent.ACTION_UP) {
351 if (thread.suspendFlag) {
352 Log.i(TAG, "Relaunch drawing thread");
353 thread.setPaused(false);
354 }
355
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400356 Bubble expand = getExpandedBubble();
357 if (expand != null) {
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400358 switch (expand.getDrawer().getAction(event.getX(), event.getY())) {
359 case Bubble.actions.OUT_OF_BOUNDS:
360 expand.retract();
361 break;
362 case Bubble.actions.HOLD:
363
364 try {
365 if (expand.getHoldStatus()) {
366
367 if (expand.isConference())
368 callback.mCallbacks.getService().unholdConference(expand.getCallID());
369 else
370 callback.mCallbacks.getService().unhold(expand.getCallID());
371 } else {
372 if (expand.isConference())
373 callback.mCallbacks.getService().holdConference(expand.getCallID());
374 else
375 callback.mCallbacks.getService().hold(expand.getCallID());
376
377 }
378 } catch (Exception e) {
379 e.printStackTrace();
380 }
381
382 return true;
383 case Bubble.actions.RECORD:
384 try {
Alexandre Lision3874e552013-11-04 17:20:12 -0500385 boolean isRecording = callback.mCallbacks.getService().toggleRecordingCall(expand.getCallID());
386 ((BubbleUser) expand).associated_call.setRecording(isRecording);
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400387 } catch (RemoteException e1) {
388 e1.printStackTrace();
389 }
390 return true;
391 case Bubble.actions.MESSAGE:
392 // TODO
393 return true;
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400394 case Bubble.actions.MUTE:
Alexandre Lisionc9fca9e2013-11-08 15:21:18 -0500395 try {
396 callback.mCallbacks.getService().setMuted(!((BubbleUser) expand).getMute());
397 ((BubbleUser) expand).toggleMute();
398 } catch (RemoteException e1) {
399 e1.printStackTrace();
400 }
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400401 return true;
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400402 case Bubble.actions.HANGUP:
403 try {
404 if (expand.isConference())
405 callback.mCallbacks.getService().hangUpConference(expand.getCallID());
406 else
407 callback.mCallbacks.getService().hangUp(expand.getCallID());
408 } catch (RemoteException e) {
409 e.printStackTrace();
410 }
411 return true;
412
413 case Bubble.actions.TRANSFER:
414 callback.makeTransfer((BubbleContact) expand);
415 return true;
416 case Bubble.actions.NOTHING:
417 break;
418 }
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400419
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400420 }
Alexandre Lision5cd659e2013-10-29 13:18:23 -0400421
alisione38001f2013-06-04 14:14:39 -0400422 List<Bubble> bubbles = model.getBubbles();
423 final int n_bubbles = bubbles.size();
424 for (int i = 0; i < n_bubbles; i++) {
425 Bubble b = bubbles.get(i);
426 if (b.dragged) {
427 b.dragged = false;
428 b.target_scale = 1.f;
Alexandre Lisionfdef8852013-09-24 13:32:38 -0400429 if (b.isOnBorder(model.width, model.height) && !b.expanded) {
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400430 b.markedToDie = true;
Alexandre Lision68855472013-10-10 16:20:46 -0400431
432 try {
433 if (b.isConference())
434 callback.mCallbacks.getService().hangUpConference(b.getCallID());
435 else
436 callback.mCallbacks.getService().hangUp(b.getCallID());
437
438 } catch (RemoteException e) {
439 e.printStackTrace();
440 }
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400441 }
alisione38001f2013-06-04 14:14:39 -0400442 }
443 }
444 dragging_bubble = false;
445 } else if (action != MotionEvent.ACTION_DOWN && !isDraggingBubble() && !thread.suspendFlag) {
446
447 Log.i(TAG, "Not dragging thread should be stopped");
448 thread.setPaused(true);
449 // thread.holdDrawing();
450 }
451
Alexandre Lision1888bf32013-10-31 09:51:41 -0400452 return true;
alisione38001f2013-06-04 14:14:39 -0400453 }
454
alision34673e62013-06-25 14:40:07 -0400455 private Bubble getExpandedBubble() {
456 List<Bubble> bubbles = model.getBubbles();
457 final int n_bubbles = bubbles.size();
458 for (int i = 0; i < n_bubbles; i++) {
459 Bubble b = bubbles.get(i);
460 if (b.expanded) {
461 return b;
462 }
463 }
464 return null;
465 }
alision2ec64f92013-06-17 17:28:58 -0400466
alisiondf1dac92013-06-27 17:35:53 -0400467 public void restartDrawing() {
468 if (thread != null && thread.suspendFlag) {
469 Log.i(TAG, "Relaunch drawing thread");
470 thread.setPaused(false);
471 }
472 }
473
474 public void setFragment(CallFragment callFragment) {
475 callback = callFragment;
476
477 }
478
479 public void stopThread() {
480 if (thread != null && thread.suspendFlag) {
481 Log.i(TAG, "Stop drawing thread");
Alexandre Lision666b3772013-10-28 17:42:48 -0400482 thread.setPaused(true);
alisiondf1dac92013-06-27 17:35:53 -0400483 }
484
485 }
486
alision58356b72013-06-03 17:13:36 -0400487 class MyOnGestureListener implements OnGestureListener {
488 @Override
489 public boolean onDown(MotionEvent event) {
490 List<Bubble> bubbles = model.getBubbles();
Alexandre Lision1888bf32013-10-31 09:51:41 -0400491
Alexandre Lision8fdcf2b2013-10-30 16:06:51 -0400492 Bubble target = getExpandedBubble();
Alexandre Lision1888bf32013-10-31 09:51:41 -0400493 if (target != null) {
Alexandre Lision8fdcf2b2013-10-30 16:06:51 -0400494 target.onDown(event);
495 return true;
496 }
Alexandre Lision68855472013-10-10 16:20:46 -0400497
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400498 for (int i = 0; i < bubbles.size(); i++) {
alision58356b72013-06-03 17:13:36 -0400499 Bubble b = bubbles.get(i);
Alexandre Lision1888bf32013-10-31 09:51:41 -0400500 if (b.onDown(event))
501 dragging_bubble = true;
alision58356b72013-06-03 17:13:36 -0400502 }
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400503
alision58356b72013-06-03 17:13:36 -0400504 return true;
505 }
alision2ec64f92013-06-17 17:28:58 -0400506
alision58356b72013-06-03 17:13:36 -0400507 @Override
508 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400509 // Log.d("Main", "onFling");
Alexandre Lision1888bf32013-10-31 09:51:41 -0400510 return false;
alision58356b72013-06-03 17:13:36 -0400511 }
512
513 @Override
514 public void onLongPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400515 // Log.d("Main", "onLongPress");
Alexandre Lision1888bf32013-10-31 09:51:41 -0400516
alision2ec64f92013-06-17 17:28:58 -0400517 }
518
alision2ec64f92013-06-17 17:28:58 -0400519 private Bubble getDraggedBubble(MotionEvent e) {
520 List<Bubble> bubbles = model.getBubbles();
521 final int n_bubbles = bubbles.size();
522 for (int i = 0; i < n_bubbles; i++) {
523 Bubble b = bubbles.get(i);
524 if (b.intersects(e.getX(), e.getY())) {
525 return b;
526 }
527 }
528 return null;
alision58356b72013-06-03 17:13:36 -0400529 }
530
531 @Override
532 public boolean onScroll(MotionEvent e1, MotionEvent event, float distanceX, float distanceY) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400533 // Log.d("Main", "onScroll");
alision58356b72013-06-03 17:13:36 -0400534 List<Bubble> bubbles = model.getBubbles();
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400535
alision58356b72013-06-03 17:13:36 -0400536 long now = System.nanoTime();
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400537 for (int i = 0; i < bubbles.size(); i++) {
alision58356b72013-06-03 17:13:36 -0400538 Bubble b = bubbles.get(i);
539 if (b.dragged) {
540 float x = event.getX(), y = event.getY();
541 float dt = (float) ((now - b.last_drag) / 1000000000.);
542 float dx = x - b.getPosX(), dy = y - b.getPosY();
543 b.last_drag = now;
alision58356b72013-06-03 17:13:36 -0400544 b.setPos(event.getX(), event.getY());
alision58356b72013-06-03 17:13:36 -0400545 b.speed.x = dx / dt;
546 b.speed.y = dy / dt;
Alexandre Lisiond9c3f7f2013-10-30 15:20:55 -0400547
Alexandre Lision1888bf32013-10-31 09:51:41 -0400548 return false;
alision58356b72013-06-03 17:13:36 -0400549 }
550 }
551 return true;
552 }
553
554 @Override
555 public void onShowPress(MotionEvent e) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400556 // Log.d("Main", "onShowPress");
alision58356b72013-06-03 17:13:36 -0400557
558 }
559
560 @Override
561 public boolean onSingleTapUp(MotionEvent e) {
Alexandre Lision1888bf32013-10-31 09:51:41 -0400562 if (isDraggingBubble() && callback.getConference().isOnGoing()) {
563 Bubble b = getDraggedBubble(e);
564 b.expand(model.width, model.height);
Alexandre Lision1a682572013-11-01 11:21:17 -0400565 dragging_bubble = false;
Alexandre Lision1888bf32013-10-31 09:51:41 -0400566 }
567 return false;
568
alision58356b72013-06-03 17:13:36 -0400569 }
570 }
alisionfe9cf712013-05-03 17:26:08 -0400571}