* #23663 Integrated new drawing in App (check action bar icon)
diff --git a/src/com/savoirfairelinux/sflphone/client/BubblesViewActivity.java b/src/com/savoirfairelinux/sflphone/client/BubblesViewActivity.java
new file mode 100644
index 0000000..a59c46a
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/client/BubblesViewActivity.java
@@ -0,0 +1,36 @@
+package com.savoirfairelinux.sflphone.client;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.savoirfairelinux.sflphone.R;
+import com.savoirfairelinux.sflphone.model.BubblesView;
+
+public class BubblesViewActivity extends Activity 
+{
+    
+    BubblesView view;
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.bubbleview_layout);
+        
+        Button b = (Button) findViewById(R.id.add_bubble);
+        view = (BubblesView) findViewById(R.id.main_view);
+        
+        b.setOnClickListener(new OnClickListener() {
+            
+            @Override
+            public void onClick(View v) {
+                view.addBubble();
+                
+            }
+        });
+
+    }
+}
\ No newline at end of file
diff --git a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
index 41650e5..fff2097 100644
--- a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
+++ b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
@@ -306,15 +306,18 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        Log.i("SFLphone", "onOptionsItemSelected " + item.getItemId());
-        if (item.getItemId() != 0) {
-            // When the button is clicked, launch an activity through this intent
+        Log.i(TAG, "onOptionsItemSelected " + item.getItemId());
+        switch(item.getItemId()){
+        case R.id.menu_settings :
             Intent launchPreferencesIntent = new Intent().setClass(this, SFLPhonePreferenceActivity.class);
-
-            // Make it a subactivity so we know when it returns
             startActivityForResult(launchPreferencesIntent, REQUEST_CODE_PREFERENCES);
+            break;
+        case R.id.menu_custom_draw:
+            Intent launchNewInterfaceIntent = new Intent().setClass(this, BubblesViewActivity.class);
+            startActivityForResult(launchNewInterfaceIntent, 0);
+            break;
         }
-
+        
         return super.onOptionsItemSelected(item);
     }
 
diff --git a/src/com/savoirfairelinux/sflphone/model/Bubble.java b/src/com/savoirfairelinux/sflphone/model/Bubble.java
new file mode 100644
index 0000000..55d7375
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/model/Bubble.java
@@ -0,0 +1,206 @@
+package com.savoirfairelinux.sflphone.model;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.graphics.Region;
+
+import com.savoirfairelinux.sflphone.R;
+
+public class Bubble extends Shape2d {
+
+    // Create a paint for the fill
+    private Paint mPaintPath, mBitmapPaint;
+
+    public Paint getmPaintPath() {
+        return mPaintPath;
+    }
+
+    public Paint getmBitmapPaint() {
+        return mBitmapPaint;
+    }
+
+    private float radius;
+
+    // A Bitmap object that is going to be passed to the BitmapShader
+    private Bitmap internalBMP, externalBMP;
+
+    public Bitmap getExternalBMP() {
+        return externalBMP;
+    }
+
+    Canvas internalCanvas;
+
+    // Two floats to store the touch position
+    private float posX;
+    private float posY;
+    Path path;
+
+    private RectF region;
+
+    private RectF bounds;
+
+    public RectF getBounds() {
+        return bounds;
+    }
+
+    public Path getPath() {
+        return path;
+    }
+
+    private Bubble(Context c, float X, float Y, float rad, int resID) {
+        posX = X;
+        posY = Y;
+
+        // Initialize the bitmap object by loading an image from the resources folder
+        if (resID != -1) {
+            internalBMP = BitmapFactory.decodeResource(c.getResources(), resID);
+        } else {
+            internalBMP = BitmapFactory.decodeResource(c.getResources(), R.drawable.ic_contact_picture);
+        }
+        internalBMP = Bitmap.createScaledBitmap(internalBMP, (int) rad, (int) rad, false);
+        externalBMP = Bitmap.createBitmap(internalBMP.getWidth(), internalBMP.getHeight(), Bitmap.Config.ARGB_8888);
+
+        radius = externalBMP.getWidth() / 2;
+        path = new Path();
+
+        path.addCircle(radius, radius, radius, Path.Direction.CW);
+
+        bounds = new RectF(posX - radius, posY - radius, posX + radius, posY + radius);
+
+        mPaintPath = new Paint();
+        mPaintPath.setARGB(255, 200, 200, 200);
+        mPaintPath.setStyle(Paint.Style.FILL_AND_STROKE);
+        mPaintPath.setAntiAlias(true);
+
+        mBitmapPaint = new Paint();
+        mBitmapPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
+
+        internalCanvas = new Canvas(externalBMP);
+        internalCanvas.clipPath(path, Region.Op.INTERSECT);
+        internalCanvas.drawPath(path, mPaintPath);
+
+        RectF tmp = new RectF(0, 0, externalBMP.getWidth(), externalBMP.getHeight());
+        internalCanvas.drawBitmap(internalBMP, null, tmp, mBitmapPaint);
+
+    }
+
+    public float getPosX() {
+        return posX;
+    }
+
+    public void setPosX(float X) {
+        if (X + radius <= region.right && X - radius >= region.left)
+            this.posX = X;
+
+        path.reset();
+        path.addCircle(posX, posY, radius, Path.Direction.CW);
+        bounds.left = posX - radius;
+        bounds.right = posX + radius;
+    }
+
+    public void setPosY(float Y) {
+        if (Y + radius <= region.bottom && Y - radius >= region.top)
+            this.posY = Y;
+
+        path.reset();
+        path.addCircle(posX, posY, radius, Path.Direction.CW);
+        bounds.top = posY - radius;
+        bounds.bottom = posY + radius;
+    }
+
+    public float getPosY() {
+        return posY;
+    }
+
+    public float getRadius() {
+        return radius;
+    }
+
+    @Override
+    public String toString() {
+        String str = "Bounds :" + getLeft() + " " + getRight() + " " + getTop() + " " + getBottom() + " " + getHeight() + " " + getWidth() + " "
+                + posX + " " + posY;
+        return str;
+    }
+
+    /**
+     * A more readable way to create balls than using a 5 param constructor of all numbers.
+     */
+    public static class Builder {
+        private Context mContext;
+        private float mX = -1;
+        private float mY = -1;
+        private float mRadiusPixels = -1;
+        private int resID = -1;
+
+        public void setResID(int resID) {
+            this.resID = resID;
+        }
+
+        public Builder(Context c) {
+            mContext = c;
+        }
+
+        public Bubble create() {
+
+            if (mX < 0) {
+                throw new IllegalStateException("X must be set");
+            }
+            if (mY < 0) {
+                throw new IllegalStateException("Y must be stet");
+            }
+            if (mRadiusPixels <= 0) {
+                throw new IllegalStateException("radius must be set");
+            }
+            return new Bubble(mContext, mX, mY, mRadiusPixels, resID);
+        }
+
+        public Builder setX(float x) {
+            mX = x;
+            return this;
+        }
+
+        public Builder setY(float y) {
+            mY = y;
+            return this;
+        }
+
+        public Builder setRadiusPixels(float pixels) {
+            mRadiusPixels = pixels;
+            return this;
+        }
+    }
+
+    @Override
+    public float getLeft() {
+        return posX - radius;
+    }
+
+    @Override
+    public float getRight() {
+        return posX + radius;
+    }
+
+    @Override
+    public float getTop() {
+        return posY - radius;
+    }
+
+    @Override
+    public float getBottom() {
+        return posY + radius;
+    }
+
+    public void setRegion(int w, int h) {
+        region = new RectF(0, 0, w, h);
+
+    }
+
+}
diff --git a/src/com/savoirfairelinux/sflphone/model/BubblesView.java b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
new file mode 100644
index 0000000..4c35710
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
@@ -0,0 +1,100 @@
+package com.savoirfairelinux.sflphone.model; // 41 Post - Created by DimasTheDriver on May/24/2012 . Part of the 'Android - rendering a Path with a Bitmap fill' post. http://www.41post.com/?p=4766

+

+import java.util.ArrayList;

+

+import com.savoirfairelinux.sflphone.R;

+

+import android.content.Context;

+import android.graphics.Canvas;

+import android.graphics.Color;

+import android.graphics.Paint;

+import android.util.AttributeSet;

+import android.util.Log;

+import android.view.MotionEvent;

+import android.view.View;

+

+public class BubblesView extends View {

+

+    private static final String TAG = BubblesView.class.getSimpleName();

+

+    ArrayList<Bubble> listBubbles;

+

+    Paint paint;

+

+    private int width;

+

+    private int height;

+

+    public BubblesView(Context context, AttributeSet attrs) {

+        super(context, attrs);

+

+        listBubbles = new ArrayList<Bubble>();

+        Bubble.Builder builder = new Bubble.Builder(getContext());

+        builder.setRadiusPixels(200).setX(200).setY(300).setResID(R.drawable.me);

+        listBubbles.add(builder.create());

+

+        builder.setRadiusPixels(200).setX(200).setY(700).setResID(R.drawable.callee);

+        listBubbles.add(builder.create());

+        // This View can receive focus, so it can react to touch events.

+        this.setFocusable(true);

+

+        paint = new Paint();

+

+        paint.setStyle(Paint.Style.FILL);

+        paint.setColor(Color.BLACK);

+        paint.setAntiAlias(true);

+        paint.setStrokeWidth(3);

+

+    }

+

+    @Override

+    public boolean onTouchEvent(MotionEvent event) {

+        // Store the position of the touch event at 'posX' and 'posY'

+        if (event.getAction() == MotionEvent.ACTION_MOVE) {

+

+            for (Bubble b : listBubbles) {

+                if (b.isPointWithin(event.getX(), event.getY())) {

+                    b.setPosX(event.getX());

+                    b.setPosY(event.getY());

+                    invalidate();

+                    return true;

+                }

+            }

+

+        }

+        return true;

+    }

+

+    @Override

+    public void onSizeChanged(int w, int h, int oldw, int oldh) {

+        super.onSizeChanged(w, h, oldw, oldh);

+        width = w;

+        height = h;

+        Log.i(TAG, "New Width " + w);

+        Log.i(TAG, "New Heigth " + h);

+        for (Bubble b : listBubbles) {

+            b.setRegion(w, h);

+        }

+        invalidate();

+    }

+

+    @Override

+    protected void onDraw(Canvas canvas) {

+

+        canvas.drawColor(Color.GRAY);

+        // canvas.drawLine(a.getPosX(), a.getPosY(), b.getPosX(), b.getPosY(), paint);

+

+        for (Bubble b : listBubbles) {

+            canvas.drawBitmap(b.getExternalBMP(), null, b.getBounds(), null);

+        }

+

+    }

+

+    public void addBubble() {

+        Bubble.Builder builder = new Bubble.Builder(getContext());

+        builder.setRadiusPixels(200).setX(200).setY(300);

+        listBubbles.add(builder.create());

+        listBubbles.get(listBubbles.size()-1).setRegion(width, height);

+        invalidate();

+    }

+}

diff --git a/src/com/savoirfairelinux/sflphone/model/Shape2d.java b/src/com/savoirfairelinux/sflphone/model/Shape2d.java
new file mode 100644
index 0000000..06cee4e
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/model/Shape2d.java
@@ -0,0 +1,41 @@
+package com.savoirfairelinux.sflphone.model;
+
+public abstract class Shape2d {
+
+    public abstract float getLeft();
+    public abstract float getRight();
+    public abstract float getTop();
+    public abstract float getBottom();
+
+    /**
+     * @param other Another 2d shape
+     * @return Whether this shape is intersecting with the other.
+     */
+    public boolean isIntersecting(Shape2d other) {
+        return getLeft() <= other.getRight() && getRight() >= other.getLeft()
+                && getTop() <= other.getBottom() && getBottom() >= other.getTop();
+    }
+
+    /**
+     * @param x An x coordinate
+     * @param y A y coordinate
+     * @return Whether the point is within this shape
+     */
+    public boolean isPointWithin(float x, float y) {
+        return (x > getLeft() && x < getRight()
+                && y > getTop() && y < getBottom());
+
+    }
+
+    public float getArea() {
+        return getHeight() * getWidth();
+    }
+
+    public float getHeight() {
+        return getBottom() - getTop();
+    }
+
+    public float getWidth () {
+        return getRight() - getLeft();
+    }
+}
\ No newline at end of file