blob: b22e0bf22121d3bf2d9c97c48da18feec5c2d596 [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;
alision34673e62013-06-25 14:40:07 -040016import com.savoirfairelinux.sflphone.adapters.ContactPictureLoader;
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;
35 public long last_drag;
36 public boolean expanded; // determine if we draw the buttons around the bubble
37 private Bitmap saved_photo;
alision729b0a22013-07-02 11:57:33 -040038 private float expanded_radius;
alision4a0eb092013-05-07 13:52:03 -040039
alision2ec64f92013-06-17 17:28:58 -040040 public void setAttractor(PointF attractor) {
41 this.attractor = attractor;
42 }
Adrien Béraude0ef0c22013-05-18 01:56:27 +100043
alision34673e62013-06-25 14:40:07 -040044 public Bubble(Context context, SipCall call, float x, float y, float size) {
45
46 Bitmap photo = null;
47 if (call.getContact().getPhoto_id() > 0) {
48 photo = ContactPictureLoader.loadContactPhoto(context.getContentResolver(), call.getContact().getId());
49 } else {
50 photo = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_contact_picture);
51 }
52
alision2ec64f92013-06-17 17:28:58 -040053 saved_photo = photo;
54 internalBMP = Bitmap.createScaledBitmap(photo, (int) size, (int) size, false);
alision91d28592013-07-02 14:33:53 -040055 internalBMP.setHasAlpha(true);
alision806e18e2013-06-21 15:30:17 -040056 associated_call = call;
alision2ec64f92013-06-17 17:28:58 -040057 pos.set(x, y);
alision34673e62013-06-25 14:40:07 -040058 radius = internalBMP.getWidth() / 2;
alision729b0a22013-07-02 11:57:33 -040059 expanded_radius = (float) (size * 1.5);
alision2ec64f92013-06-17 17:28:58 -040060 bounds = new RectF(pos.x - radius, pos.y - radius, pos.x + radius, pos.y + radius);
61 attractor = new PointF(x, y);
alisionfe9cf712013-05-03 17:26:08 -040062
alision2ec64f92013-06-17 17:28:58 -040063 Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
64 circlePaint.setStyle(Paint.Style.FILL);
alision34673e62013-06-25 14:40:07 -040065 Bitmap circle = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -040066 Canvas circle_drawer = new Canvas(circle);
alision34673e62013-06-25 14:40:07 -040067 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
alisionfe9cf712013-05-03 17:26:08 -040068
alision34673e62013-06-25 14:40:07 -040069 externalBMP = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -040070 Canvas canvas = new Canvas(externalBMP);
alisionfe9cf712013-05-03 17:26:08 -040071
alision2ec64f92013-06-17 17:28:58 -040072 circlePaint.setFilterBitmap(false);
73 canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
alisionfe9cf712013-05-03 17:26:08 -040074
alision2ec64f92013-06-17 17:28:58 -040075 circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
76 canvas.drawBitmap(circle, 0, 0, circlePaint);
77 }
Adrien Béraud25fc4092013-05-06 15:28:39 +100078
alision2ec64f92013-06-17 17:28:58 -040079 public Bitmap getBitmap() {
80 return externalBMP;
81 }
alisionfe9cf712013-05-03 17:26:08 -040082
alision2ec64f92013-06-17 17:28:58 -040083 public RectF getBounds() {
84 return bounds;
85 }
Adrien Béraud33268882013-05-18 03:41:15 +100086
alision2ec64f92013-06-17 17:28:58 -040087 public void set(float x, float y, float s) {
88 scale = s;
89 pos.x = x;
90 pos.y = y;
91 float rad = scale * getRadius() * density;
92 bounds.set(pos.x - rad, pos.y - rad, pos.x + rad, pos.y + rad);
93 }
Adrien Béraud25fc4092013-05-06 15:28:39 +100094
alision2ec64f92013-06-17 17:28:58 -040095 public float getPosX() {
96 return pos.x;
97 }
Adrien Béraud25fc4092013-05-06 15:28:39 +100098
alision2ec64f92013-06-17 17:28:58 -040099 public float getPosY() {
100 return pos.y;
101 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000102
alision2ec64f92013-06-17 17:28:58 -0400103 public void setPos(float x, float y) {
104 set(x, y, scale);
105 }
alisionfe9cf712013-05-03 17:26:08 -0400106
alision2ec64f92013-06-17 17:28:58 -0400107 public PointF getPos() {
108 return pos;
109 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000110
alision2ec64f92013-06-17 17:28:58 -0400111 public float getScale() {
112 return scale;
113 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000114
alision2ec64f92013-06-17 17:28:58 -0400115 public void setScale(float s) {
116 set(pos.x, pos.y, s);
117 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000118
alision2ec64f92013-06-17 17:28:58 -0400119 public float getRadius() {
120 return expanded ? expanded_radius : radius;
121 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000122
alision2ec64f92013-06-17 17:28:58 -0400123 /**
124 * Point intersection test.
125 */
126 boolean intersects(float x, float y) {
alision34673e62013-06-25 14:40:07 -0400127 float dx = x - pos.x;
128 float dy = y - pos.y;
alision50fa0722013-06-25 17:29:44 -0400129
alision34673e62013-06-25 14:40:07 -0400130 return dx * dx + dy * dy < getRadius() * density * getRadius() * density;
alision2ec64f92013-06-17 17:28:58 -0400131 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000132
alision2ec64f92013-06-17 17:28:58 -0400133 /**
134 * Other circle intersection test.
135 */
136 boolean intersects(float x, float y, float radius) {
137 float dx = x - pos.x, dy = y - pos.y;
138 float tot_radius = getRadius() + radius;
139 return dx * dx + dy * dy < tot_radius * tot_radius;
140 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000141
alision2ec64f92013-06-17 17:28:58 -0400142 public void setDensity(float density) {
143 this.density = density;
144 }
Adrien Béraud25fc4092013-05-06 15:28:39 +1000145
alision729b0a22013-07-02 11:57:33 -0400146 public void expand() {
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +1000147
alision2ec64f92013-06-17 17:28:58 -0400148 expanded = true;
149 internalBMP = Bitmap.createScaledBitmap(saved_photo, (int) (2 * radius), (int) (2 * radius), false);
alision2ec64f92013-06-17 17:28:58 -0400150
151 bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
152
153 Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
alision34673e62013-06-25 14:40:07 -0400154 circlePaint.setAntiAlias(true);
155 circlePaint.setDither(true);
alision2ec64f92013-06-17 17:28:58 -0400156 circlePaint.setStyle(Paint.Style.FILL);
alision34673e62013-06-25 14:40:07 -0400157 circlePaint.setColor(Color.RED);
158
159 Bitmap circle = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -0400160 Canvas circle_drawer = new Canvas(circle);
alision34673e62013-06-25 14:40:07 -0400161 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
alision2ec64f92013-06-17 17:28:58 -0400162
alision34673e62013-06-25 14:40:07 -0400163 Canvas canvas = new Canvas(internalBMP);
alision2ec64f92013-06-17 17:28:58 -0400164 circlePaint.setFilterBitmap(false);
alision34673e62013-06-25 14:40:07 -0400165 canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
166
167 circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
168 canvas.drawBitmap(circle, 0, 0, circlePaint);
169 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
170
171 externalBMP = Bitmap.createBitmap((int) (getRadius() * 2), (int) (getRadius() * 2), Bitmap.Config.ARGB_8888);
172 Canvas canvasf = new Canvas(externalBMP);
alision2ec64f92013-06-17 17:28:58 -0400173
174 Paint mPaintPath = new Paint(Paint.ANTI_ALIAS_FLAG);
175 mPaintPath.setStyle(Paint.Style.FILL);
alision34673e62013-06-25 14:40:07 -0400176 mPaintPath.setColor(0xAA000000);
alision2ec64f92013-06-17 17:28:58 -0400177
alision34673e62013-06-25 14:40:07 -0400178 Paint fatality = new Paint(Paint.ANTI_ALIAS_FLAG);
179 fatality.setAntiAlias(true);
180 fatality.setDither(true);
181 fatality.setStyle(Paint.Style.FILL);
alision2ec64f92013-06-17 17:28:58 -0400182
alision34673e62013-06-25 14:40:07 -0400183 canvasf.drawOval(new RectF(0, 0, getRadius() * 2, getRadius() * 2), mPaintPath); // background with buttons
alision465ceba2013-07-04 09:24:30 -0400184
185 int[] allpixels = new int[internalBMP.getHeight() * internalBMP.getWidth()];
186
187 internalBMP.getPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
188 for (int i = 0; i < internalBMP.getHeight() * internalBMP.getWidth(); i++) {
189 // Log.i("Bubble", "allpixels[i]:"+allpixels[i]);
190 if (allpixels[i] == Color.BLACK) {
191 Log.i("Bubble", "replacing color");
192 allpixels[i] = 0xAA000000;
193 }
194 }
195 internalBMP.setPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
196
alision34673e62013-06-25 14:40:07 -0400197 canvasf.drawBitmap(internalBMP, (float) (getRadius() - radius), (float) (getRadius() - radius), fatality);
alision2ec64f92013-06-17 17:28:58 -0400198
199 }
200
201 public void retract() {
202 expanded = false;
203 internalBMP = Bitmap.createScaledBitmap(saved_photo, (int) (2 * radius), (int) (2 * radius), false);
alision2ec64f92013-06-17 17:28:58 -0400204
205 bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
206
207 Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
alision34673e62013-06-25 14:40:07 -0400208 circlePaint.setAntiAlias(true);
209 circlePaint.setDither(true);
alision2ec64f92013-06-17 17:28:58 -0400210 circlePaint.setStyle(Paint.Style.FILL);
alision2ec64f92013-06-17 17:28:58 -0400211
alision34673e62013-06-25 14:40:07 -0400212 Bitmap circle = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
213 Canvas circle_drawer = new Canvas(circle);
214 circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
215
216 externalBMP = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
alision2ec64f92013-06-17 17:28:58 -0400217 Canvas canvas = new Canvas(externalBMP);
218
219 circlePaint.setFilterBitmap(false);
220 canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
221
222 circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
223 canvas.drawBitmap(circle, 0, 0, circlePaint);
224
225 }
alisiondf1dac92013-06-27 17:35:53 -0400226
227 /**
228 * Compare bubbles based on call ID
229 */
230 @Override
231 public boolean equals(Object c) {
232 if (c instanceof Bubble && ((Bubble) c).associated_call.getCallId().contentEquals(associated_call.getCallId())) {
233 return true;
234 }
235 return false;
236
237 }
alision34673e62013-06-25 14:40:07 -0400238
239 /**
240 * When bubble is expanded we need to check on wich action button the user tap
241 *
242 * @param x
243 * @param y
244 * @return
245 */
246 public int getAction(float x, float y) {
247 float relativeX = x - pos.x + externalBMP.getWidth() / 2;
248 float relativeY = y - pos.y + externalBMP.getHeight() / 2;
alision91d28592013-07-02 14:33:53 -0400249
250 Log.i("Bubble", "relativeX:" + relativeX);
251 Log.i("Bubble", "relativeY:" + relativeY);
252
253 Log.i("Bubble", "pos.x:" + pos.x);
254 Log.i("Bubble", "pos.y:" + pos.y);
255
256 Log.i("Bubble", "externalBMP.getWidth():" + externalBMP.getWidth());
257 Log.i("Bubble", "externalBMP.getHeight():" + externalBMP.getHeight());
alision34673e62013-06-25 14:40:07 -0400258
259 // Hold - Left
260 if (relativeX < externalBMP.getWidth() / 3 && relativeY > externalBMP.getHeight() / 3) {
261 return 1;
262 }
alision91d28592013-07-02 14:33:53 -0400263
alision34673e62013-06-25 14:40:07 -0400264 // Record - Right
265 if (relativeX > externalBMP.getWidth() * 2 / 3 && relativeY > externalBMP.getHeight() / 3) {
266 return 2;
267 }
alision91d28592013-07-02 14:33:53 -0400268
alision34673e62013-06-25 14:40:07 -0400269 // Transfer - Bottom
270 if (relativeY > externalBMP.getHeight() * 2 / 3) {
271 return 3;
272 }
273 return 0;
274 }
alision729b0a22013-07-02 11:57:33 -0400275
276 /**
277 * Always return the normal radius of the bubble
alision91d28592013-07-02 14:33:53 -0400278 *
alision729b0a22013-07-02 11:57:33 -0400279 * @return
280 */
281 public float getRetractedRadius() {
282 return radius;
283 }
284
285 public int getHoldStatus() {
alision91d28592013-07-02 14:33:53 -0400286 if (associated_call.isOnHold())
alision729b0a22013-07-02 11:57:33 -0400287 return R.string.action_call_unhold;
288 else
289 return R.string.action_call_hold;
290 }
291
292 public int getRecordStatus() {
alision91d28592013-07-02 14:33:53 -0400293 if (associated_call.isRecording())
alision729b0a22013-07-02 11:57:33 -0400294 return R.string.action_call_stop_record;
295 else
296 return R.string.action_call_record;
297 }
alisionfe9cf712013-05-03 17:26:08 -0400298}