blob: 05229c9cc7bad73cb96fbfd413a3ae5dffd6a96c [file] [log] [blame]
alisionfe9cf712013-05-03 17:26:08 -04001package com.savoirfairelinux.sflphone.model;
2
3import android.content.Context;
4import android.graphics.Bitmap;
5import android.graphics.BitmapFactory;
6import android.graphics.Canvas;
alision2ec64f92013-06-17 17:28:58 -04007import android.graphics.Color;
alisionfe9cf712013-05-03 17:26:08 -04008import android.graphics.Paint;
Adrien Béraud25fc4092013-05-06 15:28:39 +10009import android.graphics.PointF;
alisionfe9cf712013-05-03 17:26:08 -040010import android.graphics.PorterDuff.Mode;
11import android.graphics.PorterDuffXfermode;
12import android.graphics.RectF;
alision34673e62013-06-25 14:40:07 -040013import android.util.Log;
alisionfe9cf712013-05-03 17:26:08 -040014
15import com.savoirfairelinux.sflphone.R;
Alexandre Lision6e8931e2013-09-19 16:49:34 -040016import com.savoirfairelinux.sflphone.adapters.ContactPictureTask;
alisionfe9cf712013-05-03 17:26:08 -040017
alision2ec64f92013-06-17 17:28:58 -040018public class Bubble {
alision806e18e2013-06-21 15:30:17 -040019
alision2ec64f92013-06-17 17:28:58 -040020 // A Bitmap object that is going to be passed to the BitmapShader
21 private Bitmap internalBMP, externalBMP;
alisionfe9cf712013-05-03 17:26:08 -040022
alision806e18e2013-06-21 15:30:17 -040023 public SipCall associated_call;
alision2ec64f92013-06-17 17:28:58 -040024 private PointF pos = new PointF();
25 private RectF bounds;
26 public float target_scale = 1.f;
27 private float radius;
28 private float scale = 1.f;
29 private float density = 1.f;
30 public PointF speed = new PointF(0, 0);
31 public PointF last_speed = new PointF();
32 public PointF attractor = null;
alisionfe9cf712013-05-03 17:26:08 -040033
alision2ec64f92013-06-17 17:28:58 -040034 public boolean dragged = false;
Alexandre Lision6deda412013-09-25 13:21:22 -040035
Alexandre Lision0edf18c2013-09-23 17:35:50 -040036 public boolean markedToDie = false;
alision2ec64f92013-06-17 17:28:58 -040037 public long last_drag;
38 public boolean expanded; // determine if we draw the buttons around the bubble
39 private Bitmap saved_photo;
alision729b0a22013-07-02 11:57:33 -040040 private float expanded_radius;
alision4a0eb092013-05-07 13:52:03 -040041
alision2ec64f92013-06-17 17:28:58 -040042 public void setAttractor(PointF attractor) {
43 this.attractor = attractor;
44 }
Adrien Béraude0ef0c22013-05-18 01:56:27 +100045
alision34673e62013-06-25 14:40:07 -040046 public Bubble(Context context, SipCall call, float x, float y, float size) {
47
48 Bitmap photo = null;
49 if (call.getContact().getPhoto_id() > 0) {
Alexandre Lision6e8931e2013-09-19 16:49:34 -040050 photo = ContactPictureTask.loadContactPhoto(context.getContentResolver(), call.getContact().getId());
alision34673e62013-06-25 14:40:07 -040051 } else {
52 photo = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_contact_picture);
53 }
54
alision2ec64f92013-06-17 17:28:58 -040055 saved_photo = photo;
56 internalBMP = Bitmap.createScaledBitmap(photo, (int) size, (int) size, false);
alision91d28592013-07-02 14:33:53 -040057 internalBMP.setHasAlpha(true);
alision806e18e2013-06-21 15:30:17 -040058 associated_call = call;
alision2ec64f92013-06-17 17:28:58 -040059 pos.set(x, y);
alision34673e62013-06-25 14:40:07 -040060 radius = internalBMP.getWidth() / 2;
alision729b0a22013-07-02 11:57:33 -040061 expanded_radius = (float) (size * 1.5);
alision2ec64f92013-06-17 17:28:58 -040062 bounds = new RectF(pos.x - radius, pos.y - radius, pos.x + radius, pos.y + radius);
63 attractor = new PointF(x, y);
alisionfe9cf712013-05-03 17:26:08 -040064
alision2ec64f92013-06-17 17:28:58 -040065 Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
66 circlePaint.setStyle(Paint.Style.FILL);
alision34673e62013-06-25 14:40:07 -040067 Bitmap circle = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -040068 Canvas circle_drawer = new Canvas(circle);
alision34673e62013-06-25 14:40:07 -040069 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
alisionfe9cf712013-05-03 17:26:08 -040070
alision34673e62013-06-25 14:40:07 -040071 externalBMP = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -040072 Canvas canvas = new Canvas(externalBMP);
alisionfe9cf712013-05-03 17:26:08 -040073
alision2ec64f92013-06-17 17:28:58 -040074 circlePaint.setFilterBitmap(false);
75 canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
alisionfe9cf712013-05-03 17:26:08 -040076
alision2ec64f92013-06-17 17:28:58 -040077 circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
78 canvas.drawBitmap(circle, 0, 0, circlePaint);
79 }
Adrien Béraud25fc4092013-05-06 15:28:39 +100080
alision2ec64f92013-06-17 17:28:58 -040081 public Bitmap getBitmap() {
82 return externalBMP;
83 }
alisionfe9cf712013-05-03 17:26:08 -040084
alision2ec64f92013-06-17 17:28:58 -040085 public RectF getBounds() {
86 return bounds;
87 }
Adrien Béraud33268882013-05-18 03:41:15 +100088
alision2ec64f92013-06-17 17:28:58 -040089 public void set(float x, float y, float s) {
90 scale = s;
91 pos.x = x;
92 pos.y = y;
93 float rad = scale * getRadius() * density;
94 bounds.set(pos.x - rad, pos.y - rad, pos.x + rad, pos.y + rad);
95 }
Adrien Béraud25fc4092013-05-06 15:28:39 +100096
alision2ec64f92013-06-17 17:28:58 -040097 public float getPosX() {
98 return pos.x;
99 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000100
alision2ec64f92013-06-17 17:28:58 -0400101 public float getPosY() {
102 return pos.y;
103 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000104
alision2ec64f92013-06-17 17:28:58 -0400105 public void setPos(float x, float y) {
106 set(x, y, scale);
107 }
alisionfe9cf712013-05-03 17:26:08 -0400108
alision2ec64f92013-06-17 17:28:58 -0400109 public PointF getPos() {
110 return pos;
111 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000112
alision2ec64f92013-06-17 17:28:58 -0400113 public float getScale() {
114 return scale;
115 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000116
alision2ec64f92013-06-17 17:28:58 -0400117 public void setScale(float s) {
118 set(pos.x, pos.y, s);
119 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000120
alision2ec64f92013-06-17 17:28:58 -0400121 public float getRadius() {
122 return expanded ? expanded_radius : radius;
123 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000124
alision2ec64f92013-06-17 17:28:58 -0400125 /**
126 * Point intersection test.
127 */
128 boolean intersects(float x, float y) {
alision34673e62013-06-25 14:40:07 -0400129 float dx = x - pos.x;
130 float dy = y - pos.y;
alision50fa0722013-06-25 17:29:44 -0400131
alision34673e62013-06-25 14:40:07 -0400132 return dx * dx + dy * dy < getRadius() * density * getRadius() * density;
alision2ec64f92013-06-17 17:28:58 -0400133 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000134
alision2ec64f92013-06-17 17:28:58 -0400135 /**
136 * Other circle intersection test.
137 */
138 boolean intersects(float x, float y, float radius) {
139 float dx = x - pos.x, dy = y - pos.y;
140 float tot_radius = getRadius() + radius;
141 return dx * dx + dy * dy < tot_radius * tot_radius;
142 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000143
alision2ec64f92013-06-17 17:28:58 -0400144 public void setDensity(float density) {
145 this.density = density;
146 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000147
alision729b0a22013-07-02 11:57:33 -0400148 public void expand() {
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +1000149
alision2ec64f92013-06-17 17:28:58 -0400150 expanded = true;
151 internalBMP = Bitmap.createScaledBitmap(saved_photo, (int) (2 * radius), (int) (2 * radius), false);
alision2ec64f92013-06-17 17:28:58 -0400152
153 bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
154
155 Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
alision34673e62013-06-25 14:40:07 -0400156 circlePaint.setAntiAlias(true);
157 circlePaint.setDither(true);
alision2ec64f92013-06-17 17:28:58 -0400158 circlePaint.setStyle(Paint.Style.FILL);
alision34673e62013-06-25 14:40:07 -0400159 circlePaint.setColor(Color.RED);
160
161 Bitmap circle = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -0400162 Canvas circle_drawer = new Canvas(circle);
alision34673e62013-06-25 14:40:07 -0400163 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
alision2ec64f92013-06-17 17:28:58 -0400164
alision34673e62013-06-25 14:40:07 -0400165 Canvas canvas = new Canvas(internalBMP);
alision2ec64f92013-06-17 17:28:58 -0400166 circlePaint.setFilterBitmap(false);
alision34673e62013-06-25 14:40:07 -0400167 canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
168
169 circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
170 canvas.drawBitmap(circle, 0, 0, circlePaint);
171 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
172
173 externalBMP = Bitmap.createBitmap((int) (getRadius() * 2), (int) (getRadius() * 2), Bitmap.Config.ARGB_8888);
174 Canvas canvasf = new Canvas(externalBMP);
alision2ec64f92013-06-17 17:28:58 -0400175
176 Paint mPaintPath = new Paint(Paint.ANTI_ALIAS_FLAG);
177 mPaintPath.setStyle(Paint.Style.FILL);
alision34673e62013-06-25 14:40:07 -0400178 mPaintPath.setColor(0xAA000000);
alision2ec64f92013-06-17 17:28:58 -0400179
alision34673e62013-06-25 14:40:07 -0400180 Paint fatality = new Paint(Paint.ANTI_ALIAS_FLAG);
181 fatality.setAntiAlias(true);
182 fatality.setDither(true);
183 fatality.setStyle(Paint.Style.FILL);
alision2ec64f92013-06-17 17:28:58 -0400184
alision34673e62013-06-25 14:40:07 -0400185 canvasf.drawOval(new RectF(0, 0, getRadius() * 2, getRadius() * 2), mPaintPath); // background with buttons
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400186
alision465ceba2013-07-04 09:24:30 -0400187 int[] allpixels = new int[internalBMP.getHeight() * internalBMP.getWidth()];
188
189 internalBMP.getPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
190 for (int i = 0; i < internalBMP.getHeight() * internalBMP.getWidth(); i++) {
191 // Log.i("Bubble", "allpixels[i]:"+allpixels[i]);
192 if (allpixels[i] == Color.BLACK) {
alision465ceba2013-07-04 09:24:30 -0400193 allpixels[i] = 0xAA000000;
194 }
195 }
196 internalBMP.setPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400197
alision34673e62013-06-25 14:40:07 -0400198 canvasf.drawBitmap(internalBMP, (float) (getRadius() - radius), (float) (getRadius() - radius), fatality);
alision2ec64f92013-06-17 17:28:58 -0400199
200 }
201
202 public void retract() {
203 expanded = false;
204 internalBMP = Bitmap.createScaledBitmap(saved_photo, (int) (2 * radius), (int) (2 * radius), false);
alision2ec64f92013-06-17 17:28:58 -0400205
206 bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
207
208 Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
alision34673e62013-06-25 14:40:07 -0400209 circlePaint.setAntiAlias(true);
210 circlePaint.setDither(true);
alision2ec64f92013-06-17 17:28:58 -0400211 circlePaint.setStyle(Paint.Style.FILL);
alision2ec64f92013-06-17 17:28:58 -0400212
alision34673e62013-06-25 14:40:07 -0400213 Bitmap circle = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
214 Canvas circle_drawer = new Canvas(circle);
215 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
216
217 externalBMP = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -0400218 Canvas canvas = new Canvas(externalBMP);
219
220 circlePaint.setFilterBitmap(false);
221 canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
222
223 circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
224 canvas.drawBitmap(circle, 0, 0, circlePaint);
225
226 }
alisiondf1dac92013-06-27 17:35:53 -0400227
228 /**
229 * Compare bubbles based on call ID
230 */
231 @Override
232 public boolean equals(Object c) {
233 if (c instanceof Bubble && ((Bubble) c).associated_call.getCallId().contentEquals(associated_call.getCallId())) {
234 return true;
235 }
236 return false;
237
238 }
alision34673e62013-06-25 14:40:07 -0400239
240 /**
Alexandre Lisionc51ccb12013-09-11 16:00:30 -0400241 * When the bubble is expanded we need to check on wich action button the user tap
alision34673e62013-06-25 14:40:07 -0400242 *
243 * @param x
244 * @param y
245 * @return
246 */
247 public int getAction(float x, float y) {
248 float relativeX = x - pos.x + externalBMP.getWidth() / 2;
249 float relativeY = y - pos.y + externalBMP.getHeight() / 2;
alision91d28592013-07-02 14:33:53 -0400250
Alexandre Lision6deda412013-09-25 13:21:22 -0400251 // Log.i("Bubble", "relativeX:" + relativeX);
252 // Log.i("Bubble", "relativeY:" + relativeY);
253 //
254 // Log.i("Bubble", "pos.x:" + pos.x);
255 // Log.i("Bubble", "pos.y:" + pos.y);
256 //
257 // Log.i("Bubble", "externalBMP.getWidth():" + externalBMP.getWidth());
258 // Log.i("Bubble", "externalBMP.getHeight():" + externalBMP.getHeight());
alision34673e62013-06-25 14:40:07 -0400259
260 // Hold - Left
261 if (relativeX < externalBMP.getWidth() / 3 && relativeY > externalBMP.getHeight() / 3) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400262 Log.i("Bubble", "Holding");
alision34673e62013-06-25 14:40:07 -0400263 return 1;
264 }
alision91d28592013-07-02 14:33:53 -0400265
alision34673e62013-06-25 14:40:07 -0400266 // Record - Right
267 if (relativeX > externalBMP.getWidth() * 2 / 3 && relativeY > externalBMP.getHeight() / 3) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400268 Log.i("Bubble", "Record");
alision34673e62013-06-25 14:40:07 -0400269 return 2;
270 }
alision91d28592013-07-02 14:33:53 -0400271
alision34673e62013-06-25 14:40:07 -0400272 // Transfer - Bottom
273 if (relativeY > externalBMP.getHeight() * 2 / 3) {
Alexandre Lision6deda412013-09-25 13:21:22 -0400274 Log.i("Bubble", "Transfer");
alision34673e62013-06-25 14:40:07 -0400275 return 3;
276 }
277 return 0;
278 }
alision729b0a22013-07-02 11:57:33 -0400279
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400280 public boolean isOnBorder(float w, float h) {
281 return (bounds.left < 0 || bounds.right > w || bounds.top < 0 || bounds.bottom > h);
282 }
283
alision729b0a22013-07-02 11:57:33 -0400284 /**
285 * Always return the normal radius of the bubble
alision91d28592013-07-02 14:33:53 -0400286 *
alision729b0a22013-07-02 11:57:33 -0400287 * @return
288 */
289 public float getRetractedRadius() {
290 return radius;
291 }
292
293 public int getHoldStatus() {
alision91d28592013-07-02 14:33:53 -0400294 if (associated_call.isOnHold())
alision729b0a22013-07-02 11:57:33 -0400295 return R.string.action_call_unhold;
296 else
297 return R.string.action_call_hold;
298 }
299
300 public int getRecordStatus() {
alision91d28592013-07-02 14:33:53 -0400301 if (associated_call.isRecording())
alision729b0a22013-07-02 11:57:33 -0400302 return R.string.action_call_stop_record;
303 else
304 return R.string.action_call_record;
305 }
alisionfe9cf712013-05-03 17:26:08 -0400306}