blob: 7cb8cefa00a30a0bd9bbdea3ab1e059309a1326e [file] [log] [blame]
package org.sflphone.model;
import org.sflphone.R;
import org.sflphone.adapters.ContactPictureTask;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.Shader;
import android.view.MotionEvent;
public abstract class Bubble {
// A Bitmap object that is going to be passed to the BitmapShader
protected Bitmap externalBMP;
protected PointF pos = new PointF();
protected RectF bounds;
public float target_scale = 1.f;
protected float radius;
protected float scale = 1.f;
protected float density = 1.f;
public PointF speed = new PointF(0, 0);
public PointF last_speed = new PointF();
public PointF attractor = null;
ActionDrawer act;
public boolean isUser;
public boolean dragged = false;
public boolean markedToDie = false;
public long last_drag;
public boolean expanded; // determine if we draw the buttons around the bubble
protected Bitmap saved_photo;
public interface actions {
int OUT_OF_BOUNDS = -1;
int NOTHING = 0;
int HOLD = 1;
int RECORD = 2;
int HANGUP = 3;
int MESSAGE = 4;
int TRANSFER = 5;
int MUTE = 6;
}
protected Context mContext;
public void setAttractor(PointF attractor) {
this.attractor = attractor;
}
public Bubble(Context context, CallContact contact, float x, float y, float size) {
mContext = context;
pos.set(x, y);
radius = size / 2; // 10 is the white stroke
saved_photo = getContactPhoto(context, contact, (int) size);
generateBitmap();
attractor = new PointF(x, y);
isUser = false;
}
protected void generateBitmap() {
int w = saved_photo.getWidth(), h = saved_photo.getHeight();
if (w > h) {
w = h;
} else if (h > w) {
h = w;
}
externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
BitmapShader shader;
shader = new BitmapShader(saved_photo, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setDither(true);
paint.setAntiAlias(true);
paint.setShader(shader);
Canvas internalCanvas = new Canvas(externalBMP);
internalCanvas.drawCircle(w / 2, h / 2, w / 2, paint);
Paint whiteStroke = new Paint();
whiteStroke.setStyle(Style.STROKE);
whiteStroke.setStrokeWidth(8);
if (expanded) {
whiteStroke.setColor(mContext.getResources().getColor(R.color.sfl_action_blue));
} else {
whiteStroke.setColor(Color.WHITE);
}
whiteStroke.setDither(true);
whiteStroke.setAntiAlias(true);
internalCanvas.drawCircle(w / 2, h / 2, w / 2 - 4, whiteStroke);
bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
}
protected Bitmap getContactPhoto(Context context, CallContact contact, int size) {
if (contact.getPhoto_id() > 0) {
return ContactPictureTask.loadContactPhoto(context.getContentResolver(), contact.getId());
} else {
return ContactPictureTask.decodeSampledBitmapFromResource(context.getResources(), R.drawable.ic_contact_picture, (int) size, (int) size);
}
}
public Bitmap getBitmap() {
return externalBMP;
}
public RectF getBounds() {
return bounds;
}
public abstract void set(float x, float y, float s);
public float getPosX() {
return pos.x;
}
public float getPosY() {
return pos.y;
}
public void setPos(float x, float y) {
set(x, y, scale);
}
public PointF getPos() {
return pos;
}
public float getScale() {
return scale;
}
public void setScale(float s) {
set(pos.x, pos.y, s);
}
public abstract int getRadius();
/**
* Point intersection test.
*/
boolean intersects(float x, float y) {
float dx = x - pos.x;
float dy = y - pos.y;
return dx * dx + dy * dy < getRadius() * getRadius();
}
/**
* Other circle intersection test.
*/
boolean intersects(float x, float y, float radius) {
float dx = x - pos.x, dy = y - pos.y;
float tot_radius = getRadius() + radius;
return dx * dx + dy * dy < tot_radius * tot_radius;
}
public void setDensity(float density) {
this.density = density;
}
public abstract void expand(int width, int height);
public void retract() {
expanded = false;
generateBitmap();
}
public boolean isOnBorder(float w, float h) {
return (bounds.left < 0 || bounds.right > w || bounds.top < 0 || bounds.bottom > h);
}
/**
* Always return the normal radius of the bubble
*
* @return
*/
public float getRetractedRadius() {
return radius;
}
public abstract boolean getHoldStatus();
public abstract boolean getRecordStatus();
public abstract Bitmap getDrawerBitmap();
public abstract RectF getDrawerBounds();
protected abstract class ActionDrawer {
int mWidth, mHeight;
RectF bounds;
Bitmap img;
Paint mLines;
Paint mBackgroundPaint;
Paint mButtonPaint;
Paint mSelector;
public ActionDrawer(int w, int h) {
mWidth = w;
mHeight = h;
bounds = new RectF(0, 0, 0, 0);
mButtonPaint = new Paint();
mBackgroundPaint = new Paint();
mBackgroundPaint.setColor(mContext.getResources().getColor(R.color.sfl_blue_9));
mLines = new Paint();
mLines.setAntiAlias(true);
mLines.setStrokeWidth(2);
mLines.setColor(mContext.getResources().getColor(R.color.transparent_grey));
mSelector = new Paint();
mSelector.setStyle(Style.FILL);
mSelector.setColor(mContext.getResources().getColor(R.color.sfl_dark_blue));
}
/**
* When the bubble is expanded we need to check on wich action button the user tap
*
* @param x
* @param y
* @return
*/
public abstract int getAction(float x, float y);
public void setBounds(float f, float y, float g, float h) {
bounds.set(f, y, g, h);
}
public abstract void generateBitmap(int action);
public RectF getDrawerBounds() {
return bounds;
}
public void setBounds(RectF bounds) {
this.bounds = bounds;
}
public Bitmap getBitmap() {
return img;
}
public int getWidth() {
return mWidth;
}
public int getHeight() {
return mHeight;
}
public void adjustBounds(float x, float y) {
}
}
public ActionDrawer getDrawer() {
return act;
}
public void setDrawer(ActionDrawer a) {
act = a;
}
public abstract String getName();
public abstract boolean callIDEquals(String call);
public abstract String getCallID();
public boolean isConference() {
return false;
}
public abstract boolean onDown(MotionEvent event);
}