Skip to content
Snippets Groups Projects
Commit c9c424d6 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

Bubbles cleanup and bug fixes.

parent 0c9bd8fe
No related branches found
No related tags found
No related merge requests found
......@@ -30,7 +30,7 @@ shall include the source code for the parts of OpenSSL used as well
as that of the covered work.
-->
<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
<com.savoirfairelinux.sflphone.views.CallPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/slidingpanelayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
......@@ -45,4 +45,4 @@ as that of the covered work.
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SlidingPaneLayout>
\ No newline at end of file
</com.savoirfairelinux.sflphone.views.CallPaneLayout>
\ No newline at end of file
This diff is collapsed.
......@@ -61,10 +61,12 @@ public class CallFragment extends Fragment {
static final String TAG = "CallFragment";
static final float BUBBLE_SIZE = 100;
static final float BUBBLE_SIZE = 75;
static final float ATTRACTOR_SIZE = 40;
private SipCall mCall;
private ViewGroup rootView;
private BubblesView view;
private BubbleModel model;
private PointF screenCenter;
......@@ -175,6 +177,8 @@ public class CallFragment extends Fragment {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
//rootView.requestDisallowInterceptTouchEvent(true);
mCallbacks = (Callbacks) activity;
}
......@@ -182,11 +186,13 @@ public class CallFragment extends Fragment {
public void onDetach() {
super.onDetach();
mCallbacks = sDummyCallbacks;
//rootView.requestDisallowInterceptTouchEvent(false);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false);
rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false);
//rootView.requestDisallowInterceptTouchEvent(true);
view = (BubblesView) rootView.findViewById(R.id.main_view);
view.setModel(model);
......@@ -225,36 +231,20 @@ public class CallFragment extends Fragment {
private void initNormalStateDisplay() {
Log.i(TAG, "Start normal display");
// TODO off-thread image loading
Bubble contact_bubble = getBubbleFor(mCall.getContacts().get(0), screenCenter.x, screenCenter.y);
Bubble me = getBubbleFor(myself, screenCenter.x, screenCenter.y * 3 / 2);
/* contact_bubble.setPos(screenCenter.x, screenCenter.y);
me.setPos(screenCenter.x, screenCenter.y * 3 / 2);*/
/*if (mCall.getContacts().get(0).getPhoto_id() > 0) {
Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), mCall.getContacts().get(0).getId());
contact_bubble = new Bubble(screenCenter.x, screenCenter.y, 150, photo);
} else {
contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y / 2 , 150, R.drawable.ic_contact_picture);
}
me = new Bubble(getActivity(), screenCenter.x, screenCenter.y * 3 / 2, 150, R.drawable.ic_contact_picture);
*/
model.clearAttractors();
model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), 20, new Attractor.Callback() {
model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), ATTRACTOR_SIZE, new Attractor.Callback() {
@Override
public void onBubbleSucked(Bubble b) {
public boolean onBubbleSucked(Bubble b) {
Log.w(TAG, "Bubble sucked ! ");
mCallbacks.onCallEnded(mCall);
bubbleRemoved(b);
return true;
}
}, hangup_icon));
/* contact_bubble.contact = mCall.getContacts().get(0);
me.contact = myself;
model.addBubble(contact_bubble);
model.addBubble(me);
contacts.put(mCall.getContacts().get(0), contact_bubble);
contacts.put(myself, me);*/
}
private void initIncomingCallDisplay() {
......@@ -264,16 +254,19 @@ public class CallFragment extends Fragment {
contacts.put(mCall.getContacts().get(0), contact_bubble);
model.clearAttractors();
model.addAttractor(new Attractor(new PointF(3 * metrics.widthPixels / 4, metrics.heightPixels / 4), 20, new Attractor.Callback() {
model.addAttractor(new Attractor(new PointF(4 * metrics.widthPixels / 5, screenCenter.y), ATTRACTOR_SIZE, new Attractor.Callback() {
@Override
public void onBubbleSucked(Bubble b) {
public boolean onBubbleSucked(Bubble b) {
mCallbacks.onCallAccepted(mCall);
return false;
}
}, call_icon));
model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 4, metrics.heightPixels / 4), 20, new Attractor.Callback() {
model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 5, screenCenter.y), ATTRACTOR_SIZE, new Attractor.Callback() {
@Override
public void onBubbleSucked(Bubble b) {
public boolean onBubbleSucked(Bubble b) {
mCallbacks.onCallRejected(mCall);
bubbleRemoved(b);
return true;
}
}, hangup_icon));
}
......@@ -284,17 +277,15 @@ public class CallFragment extends Fragment {
Bubble contact_bubble = getBubbleFor(mCall.getContacts().get(0), screenCenter.x, screenCenter.y);
model.clearAttractors();
model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), 20, new Attractor.Callback() {
model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), 40, new Attractor.Callback() {
@Override
public void onBubbleSucked(Bubble b) {
public boolean onBubbleSucked(Bubble b) {
Log.w(TAG, "Bubble sucked ! ");
mCallbacks.onCallEnded(mCall);
bubbleRemoved(b);
return true;
}
}, hangup_icon));
/*contact_bubble.contact = mCall.getContacts().get(0);
model.addBubble(contact_bubble);
contacts.put(mCall.getContacts().get(0), contact_bubble);*/
}
/**
......@@ -313,6 +304,7 @@ public class CallFragment extends Fragment {
return contact_bubble;
}
// TODO off-thread image loading
if (contact.getPhoto_id() > 0) {
Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), mCall.getContacts().get(0).getId());
contact_bubble = new Bubble(x, y, BUBBLE_SIZE, photo);
......@@ -327,6 +319,17 @@ public class CallFragment extends Fragment {
return contact_bubble;
}
/**
* Should be called when a bubble is removed from the model
*/
void bubbleRemoved(Bubble b) {
if(b.contact == null) {
return;
}
contacts.remove(b.contact);
}
public void changeCallState(String callID, String newState) {
Log.w(TAG, "Changing call state of "+callID);
......@@ -340,4 +343,9 @@ public class CallFragment extends Fragment {
}
}
public boolean draggingBubble()
{
return view == null ? false : view.isDraggingBubble();
}
}
......@@ -9,7 +9,14 @@ import android.graphics.RectF;
public class Attractor {
public interface Callback {
public void onBubbleSucked(Bubble b);
/**
* Called when a bubble is on the "active" zone of the attractor.
*
* @param b The bubble that is on the attractor.
* @return true if the bubble should be removed from the model, false otherwise.
*/
public boolean onBubbleSucked(Bubble b);
}
final PointF pos;
......@@ -20,9 +27,9 @@ public class Attractor {
private final RectF bounds = new RectF();
public Attractor(PointF pos, float radius, Callback callback, Bitmap img) {
public Attractor(PointF pos, float size, Callback callback, Bitmap img) {
this.pos = pos;
this.radius = radius;
this.radius = size/2;
this.callback = callback;
this.img = img;
}
......
......@@ -37,36 +37,32 @@ public class Bubble
this.attractor = attractor;
}
public Bubble(float x, float y, float rad, Bitmap photo) {
internalBMP = photo;
pos.set(x, y);
internalBMP = Bitmap.createScaledBitmap(internalBMP, (int) rad, (int) rad, false);
public Bubble(float x, float y, float size, Bitmap photo) {
internalBMP = Bitmap.createScaledBitmap(photo, (int) size, (int) size, false);
int w = internalBMP.getWidth(), h = internalBMP.getHeight();
externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
pos.set(x, y);
radius = w / 2;
bounds = new RectF(pos.x - radius, pos.y - radius, pos.x + radius, pos.y + radius);
attractor = new PointF(x, y);
radius = externalBMP.getWidth() / 2;
Path path = new Path();
path.addCircle(radius, radius, radius, Path.Direction.CW);
bounds = new RectF(pos.x - radius, pos.y - radius, pos.x + radius, pos.y + radius);
Paint mPaintPath = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintPath.setStyle(Paint.Style.FILL);
mPaintPath.setAntiAlias(true);
Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setStyle(Paint.Style.FILL);
Bitmap circle = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas circle_drawer = new Canvas(circle);
circle_drawer.drawOval(new RectF(0, 0, w, h), mPaintPath);
circle_drawer.drawOval(new RectF(0, 0, w, h), circlePaint);
attractor = new PointF(x, y);
mPaintPath.setFilterBitmap(false);
externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(externalBMP);
circlePaint.setFilterBitmap(false);
canvas.drawBitmap(internalBMP, 0, 0, circlePaint);
Canvas internalCanvas = new Canvas(externalBMP);
internalCanvas.drawBitmap(internalBMP, 0, 0, mPaintPath);
mPaintPath.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
internalCanvas.drawBitmap(circle, 0, 0, mPaintPath);
circlePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawBitmap(circle, 0, 0, circlePaint);
}
public Bubble(float x, float y, float rad, Context c, int resID) {
......@@ -87,10 +83,7 @@ public class Bubble
pos.x = x;
pos.y = y;
float rad = scale*radius*density;
bounds.left = pos.x - rad;
bounds.right = pos.x + rad;
bounds.top = pos.y - rad;
bounds.bottom = pos.y + rad;
bounds.set(pos.x-rad, pos.y-rad, pos.x+rad, pos.y+rad);
}
public float getPosX() {
......
......@@ -101,7 +101,8 @@ public class BubbleModel
PointF attractor_pos = b.attractor;
float attractor_dist = (attractor_pos.x-bx)*(attractor_pos.x-bx) + (attractor_pos.y-by)*(attractor_pos.x-by);
for(Attractor t : attractors) {
for(int j=0; j<attr_n; j++) {
Attractor t = attractors.get(j);
float dx = t.pos.x-bx, dy = t.pos.y-by;
float adist = dx*dx + dy*dy;
if(adist < attractor_dist) {
......@@ -163,9 +164,13 @@ public class BubbleModel
b.setPos((float)(bx+dx), (float)(by+dy));
if(attractor != null && attractor_dist < attractor_dist_suck*attractor_dist_suck) {
attractor.callback.onBubbleSucked(b);
bubbles.remove(b);
n--;
b.dragged = false;
if(attractor.callback.onBubbleSucked(b)) {
bubbles.remove(b);
n--;
} else {
b.target_scale = 1.f;
}
}
}
......
......@@ -30,6 +30,8 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback,
private float density;
private float textDensity;
private boolean dragging_bubble = false;
public BubblesView(Context context, AttributeSet attrs)
{
super(context, attrs);
......@@ -48,7 +50,7 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback,
attractor_paint.setColor(Color.RED);
//attractor_paint.set
name_paint.setTextSize(18*textDensity);
name_paint.setTextSize(18 * textDensity);
name_paint.setColor(0xFF303030);
name_paint.setTextAlign(Align.CENTER);
}
......@@ -140,53 +142,60 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback,
final int n_bubbles = bubbles.size();
if (action == MotionEvent.ACTION_DOWN) {
for(int i=0; i<n_bubbles; i++) {
for (int i = 0; i < n_bubbles; i++) {
Bubble b = bubbles.get(i);
if (b.intersects(event.getX(), event.getY())) {
b.dragged = true;
b.last_drag = System.nanoTime();
b.setPos(event.getX(), event.getY());
b.target_scale = .8f;
dragging_bubble = true;
}
}
} else if (action == MotionEvent.ACTION_MOVE) {
long now = System.nanoTime();
for(int i=0; i<n_bubbles; i++) {
for (int i = 0; i < n_bubbles; i++) {
Bubble b = bubbles.get(i);
if (b.dragged) {
float x = event.getX(), y = event.getY();
float dt = (float) ((now-b.last_drag)/1000000000.);
float dt = (float) ((now - b.last_drag) / 1000000000.);
float dx = x - b.getPosX(), dy = y - b.getPosY();
b.last_drag = now;
b.setPos(event.getX(), event.getY());
/*int hn = event.getHistorySize() - 2;
Log.w(TAG, "event.getHistorySize() : " + event.getHistorySize());
if(hn > 0) {
Log.w(TAG, "event.getHistorySize() : " + event.getHistorySize());
if(hn > 0) {
float dx = x-event.getHistoricalX(hn);
float dy = y-event.getHistoricalY(hn);
float dt = event.getHistoricalEventTime(hn)/1000.f;*/
b.speed.x = dx/dt;
b.speed.y = dy/dt;
b.speed.x = dx / dt;
b.speed.y = dy / dt;
//Log.w(TAG, "onTouch dx:" + b.speed.x + " dy:" + b.speed.y);
//}
return true;
}
}
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
for(int i=0; i<n_bubbles; i++) {
for (int i = 0; i < n_bubbles; i++) {
Bubble b = bubbles.get(i);
if (b.dragged) {
b.dragged = false;
b.target_scale = 1.f;
}
}
dragging_bubble = false;
}
}
return true;
}
public boolean isDraggingBubble()
{
return dragging_bubble;
}
class BubblesThread extends Thread
{
private boolean running = false;
......@@ -251,17 +260,15 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback,
List<Bubble> bubbles = model.getBubbles();
List<Attractor> attractors = model.getAttractors();
for (int i=0, n=attractors.size(); i < n; i++) {
for (int i = 0, n = attractors.size(); i < n; i++) {
Attractor a = attractors.get(i);
//canvas.drawCircle(a.pos.x, a.pos.y, 10, attractor_paint);
canvas.drawBitmap(a.getBitmap(), null, a.getBounds(), null);
}
for (int i=0, n=bubbles.size(); i<n; i++) {
for (int i = 0, n = bubbles.size(); i < n; i++) {
Bubble b = bubbles.get(i);
//RectF bounds = new RectF(b.getBounds());
canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
canvas.drawText(b.contact.getmDisplayName(), b.getPosX(), b.getPosY()-50*density, name_paint);
canvas.drawText(b.contact.getmDisplayName(), b.getPosX(), b.getPosY() - 50 * density, name_paint);
}
}
}
......
package com.savoirfairelinux.sflphone.views;
import android.content.Context;
import android.support.v4.widget.SlidingPaneLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.savoirfairelinux.sflphone.fragments.CallFragment;
public class CallPaneLayout extends SlidingPaneLayout
{
public CallFragment curFragment = null;
public CallPaneLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public CallPaneLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{
if(curFragment!=null && curFragment.draggingBubble()) {
return false;
}
return super.onInterceptTouchEvent(event);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment