How to perform undo redo on surface view
<p>I am currently work on surface view  for drawing purpose, but am facing a problem that am not performing the undo redo operation on surface view using command pattern. If any one knows about it's then please help.</p>

<p>My code is XML..</p>

<pre><code>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"&gt;

&lt;FrameLayout
     android:id="@+id/frameLayout"
     android:layout_width="fill_parent"
     android:layout_height="430dp"/&gt;
    &lt;LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:gravity="center_horizontal"
        android:layout_gravity="bottom"
        android:background="#c2300f"&gt;
        &lt;Button
            android:id="@+id/buttonUndo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Undo" /&gt;
        &lt;Button
            android:id="@+id/buttonRedo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Redo" /&gt;
        &lt;Button
            android:id="@+id/buttonColor"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Color" /&gt;
    &lt;/LinearLayout&gt;       
   &lt;/LinearLayout&gt;
</code></pre>

<p>Main Activity is ......</p>

<pre><code>package com.example.surfacetuto;

 import android.app.Activity;
 import android.graphics.Paint;
 import android.graphics.Point;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 import android.widget.Toast;

 public class MainActivity extends Activity implements OnClickListener{
DrawingSurface ds;
FrameLayout frm;
Button btnU,btnR,btnC;
int color=0xfff00000;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ds=new DrawingSurface(this);
    setContentView(R.layout.activity_main);

    frm=(FrameLayout)findViewById(R.id.frameLayout);
    frm.addView(ds);

    btnU=(Button)findViewById(R.id.buttonUndo);
    btnR=(Button)findViewById(R.id.buttonRedo);
    btnC=(Button)findViewById(R.id.buttonColor);

    btnU.setOnClickListener(this);
    btnR.setOnClickListener(this);
    btnC.setOnClickListener(this);

    btnU.setEnabled(true);
    btnR.setEnabled(true);
}
@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    switch (v.getId()) {
    case R.id.buttonUndo:
        ds.undo();
        if( ds.hasMoreUndo() == false ){
            btnU.setEnabled( false );
        }
        btnU.setEnabled( true );
        Toast.makeText(getApplicationContext(), "Undo", 0).show();
        break;
    case R.id.buttonRedo:
        ds.redo();
        if( ds.hasMoreRedo() == false ){
            btnR.setEnabled( false );
        }

        btnR.setEnabled( true );
        Toast.makeText(getApplicationContext(), "Redo", 1).show();
        break;
    case R.id.buttonColor:
        Toast.makeText(getApplicationContext(), "Color", 2).show();
        ds.colorNew();

        break;

    default:
        break;
    }
}   
   }
</code></pre>

<p>Drawing Surface class is.....</p>

<pre><code>package com.example.surfacetuto;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {

       Canvas cacheCanvas;
       Bitmap backBuffer;
       int width, height, clientHeight;
       Paint paint;
       Context context;
        SurfaceHolder mHolder;
        protected DrawThread thread;
      private Boolean _run;
      public boolean isDrawing = true;
      private Bitmap mBitmap;
      private CommandManager commandManager;

public DrawingSurface(Context context) {
    super(context);
    this.context = context;
    init();
}
public DrawingSurface(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;      
    init();
}

private void init() {
    mHolder = getHolder();
    mHolder.addCallback(this);
    commandManager = new CommandManager();
    thread = new DrawThread(getHolder());

}
class DrawThread extends  Thread{
    private SurfaceHolder mSurfaceHolder;
    public DrawThread(SurfaceHolder surfaceHolder){
        mSurfaceHolder = surfaceHolder;
    }
    public void setRunning(boolean run) {
        _run = run;
    }
    @Override
    public void run() {
        Canvas canvas = null;
        while (_run){
            if(isDrawing == true){
                try{
                    canvas = mSurfaceHolder.lockCanvas(null);
                    if(mBitmap == null){
                        mBitmap =  Bitmap.createBitmap (100, 100, Bitmap.Config.ARGB_8888);
                    }
                    final Canvas c = new Canvas (mBitmap);
                    c.drawColor(Color.WHITE);
                    canvas.drawColor(Color.WHITE);
                    commandManager.executeAll(c);
                    canvas.drawBitmap (mBitmap, 0,  0,null);
                } finally {
                    mSurfaceHolder.unlockCanvasAndPost(canvas);
                }
                isDrawing = true;
            }

          }

        }
    }
 public void addDrawingPath (DrawingPath drawingPath){
        commandManager.addCommand(drawingPath);
    }

int lastX, lastY, currX, currY;
boolean isDeleting;
@Override
public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);
    int action = event.getAction();
    switch(action &amp; MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        lastX = (int) event.getX();
        lastY = (int) event.getY();
        break;
    case MotionEvent.ACTION_MOVE:
        if(isDeleting) break;

        currX = (int) event.getX();
        currY = (int) event.getY();
        cacheCanvas.drawLine(lastX, lastY, currX, currY, paint);
        lastX = currX;
        lastY = currY;

        break;
    case MotionEvent.ACTION_UP:
        if(isDeleting) isDeleting = false;
        break;
    case MotionEvent.ACTION_POINTER_DOWN:
        cacheCanvas.drawColor(Color.WHITE);
        isDeleting = true;
        break;
    case MotionEvent.ACTION_POINTER_UP:
        break;
    }
    draw(); 
    return true;
}

protected void draw() {

    if(clientHeight==0) {
        clientHeight = getClientHeight();
        height = clientHeight;
        backBuffer = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888);
        cacheCanvas.setBitmap(backBuffer);
        cacheCanvas.drawColor(Color.WHITE);
    }
    Canvas canvas = null;
    try{
        canvas = mHolder.lockCanvas(null);

        canvas.drawBitmap(backBuffer, 0,0, paint);
    }catch(Exception ex){
        ex.printStackTrace();
    }finally{
        if(mHolder!=null)  mHolder.unlockCanvasAndPost(canvas);
    }
}

private int getClientHeight() {
    Rect rect= new Rect();    
    Window window = ((Activity)context).getWindow();     
    window.getDecorView().getWindowVisibleDisplayFrame(rect);     
    int statusBarHeight= rect.top;    
    int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop();     
    int titleBarHeight= contentViewTop - statusBarHeight;
    return ((Activity)context).getWindowManager().getDefaultDisplay().
            getHeight() - statusBarHeight - titleBarHeight;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
}

public void surfaceCreated(SurfaceHolder holder) {


        thread.setRunning(true);
        thread.start();

    width = getWidth();
    height = getHeight();
    cacheCanvas = new Canvas();
    backBuffer = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888); 
    cacheCanvas.setBitmap(backBuffer);
    cacheCanvas.drawColor(Color.WHITE);
    paint = new Paint();
    paint.setColor(Color.BLUE);
    paint.setStrokeWidth(10);
    paint.setStrokeCap(Paint.Cap.ROUND);
    paint.setStrokeJoin(Paint.Join.ROUND);
    draw();

}

public void surfaceDestroyed(SurfaceHolder holder) {
     boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                // we will try it again and again...
            }
        }
}

public void colorNew() {
    // TODO Auto-generated method stub
    paint.setColor(Color.GRAY);
}
public void undo() {
    // TODO Auto-generated method stub
     isDrawing = true;
    commandManager.undo();
}
public void redo() {
    // TODO Auto-generated method stub
     isDrawing = true;
    commandManager.redo();
}
public boolean hasMoreUndo() {
    // TODO Auto-generated method stub
    return commandManager.hasMoreUndo();
}
public boolean hasMoreRedo() {
    // TODO Auto-generated method stub
     return commandManager.hasMoreRedo();
}
  }
</code></pre>
