title: Can we draw a circle that uses Path object? [in arguments, like drawPath()]
body: <p>I have typed a program which draws on Canvas.</p>
  <p>It provides a popup menu which gives 3 Drawing tools as options:</p>
  <ol>
  <li><p>Draw line while scratching over screen</p>
  </li>
  <li><p>Draw line based on start and end points on screen</p>
  </li>
  <li><p>Draw a circle</p>
  </li>
  </ol>
  <p>Further, there are options such as:</p>
  <ol>
  <li><p>Clear</p>
  </li>
  <li><p>Undo</p>
  </li>
  </ol>
  <p>While performing undo on lines, there's no issue at all because both are based on path. (Uses <code>List&lt;Path&gt;</code>).
  But here starts the problem. The circle is drawn using Point object. So the issues are:</p>
  <ol>
  <li><strong>I cannot make Android distinguish - the order of drawing lines and circles.</strong> Eg: I draw 5 lines, followed by 5 circles (or
  alternatively). There's no intelligence currently to follow their
  order of drawing. Hence undoing canvas with lines and circles drawn
  together leads to mess up.</li>
  <li><strong>The current code (not meditated upon in depth yet) needs 2 clicks to undo a circle instead of 1.</strong></li>
  </ol>
  <p>Code shared below (is complex). I tried to dedicate a class to each drawing tool (line,circle) - it worked - except - it didn't draw anything on the Canvas. So, all packed in 1 class back again.</p>
  <p>Code:</p>
  <pre><code>package com.example.orbit_.undofortouch;
  
  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.Paint;
  import android.graphics.Path;
  import android.graphics.Point;
  import android.os.Bundle;
  import android.util.AttributeSet;
  import android.util.Log;
  import android.view.MenuItem;
  import android.view.MotionEvent;
  import android.view.View;
  import android.widget.Button;
  import android.widget.LinearLayout;
  import android.widget.PopupMenu;
  import android.widget.Toast;
  
  
  import java.util.ArrayList;
  import java.util.List;
  
  public class MainActivity extends Activity {
  
      Button b1, b2, b3;
      PopupMenu popup;
      int dtool;
      boolean touch,circle;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearLayout2);
          final DrawPanel dp = new DrawPanel(this);
          linearLayout.addView(dp);
  
          b1 = (Button) findViewById(R.id.button1);
          b1.setOnClickListener(new View.OnClickListener() {
  
              @Override
              public void onClick(View v) {
                  dp.Clear();
              }
          });
  
          b2 = (Button) findViewById(R.id.button2);
          b2.setOnClickListener(new View.OnClickListener() {
  
              @Override
              public void onClick(View v) {
                  dp.Undo();
              }
          });
  
          b3 = (Button) findViewById(R.id.button3);
          b3.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
  
                  popup = new PopupMenu(MainActivity.this, v);
                  popup.getMenuInflater().inflate(R.menu.menu_main, popup.getMenu());
  
                  popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
  
                      public boolean onMenuItemClick(MenuItem item) {
                          switch (item.getItemId()) {
                              case R.id.touch:
                                  dtool = 1;
                                  break;
                              case R.id.line:
                                  dtool = 2;
                                  break;
                              case R.id.circle:
                                  dtool = 3;
                                  break;
                          }
  
                          Log.v(&quot;EDITL:&quot;, &quot;Drawtool:&quot;.concat(String.valueOf(item.getTitle())));
  
                          Toast.makeText(MainActivity.this,&quot;Clicked popup menu item &quot; + item.getTitle(),Toast.LENGTH_SHORT).show();
                          return true;
                      }
  
                  });
                  popup.show();
              }
          });
  
     }
  
  
  
  
  class DrawPanel extends View implements View.OnTouchListener {
  
      Bitmap bmp;
  
      Canvas canvas;
      List&lt;Path&gt; paths, undone;
      List&lt;Point&gt; circlePoints,removeCircles;
      Paint paint;
      Path path;
      Point point;
  
      public DrawPanel(Context context, AttributeSet attributeSet, int defStyle) {
          super(context, attributeSet, defStyle);
      }
  
      public DrawPanel(Context context) {
          super(context);
          paint = new Paint();
          path = new Path();
          paths = new ArrayList&lt;&gt;();
          undone = new ArrayList&lt;&gt;();
          circlePoints = new ArrayList&lt;&gt;();
          removeCircles = new ArrayList&lt;&gt;();
  
          canvas = new Canvas();
  
          this.setOnTouchListener(this);
  
          paint.setStrokeWidth(3);
          paint.setColor(Color.BLACK);
          paint.setStyle(Paint.Style.STROKE);
          paint.setDither(true);
          paint.setAntiAlias(true);
          paint.setStrokeCap(Paint.Cap.ROUND);
          paint.setStrokeJoin(Paint.Join.ROUND);
  
  
  
          bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.desert);
          touch=false;
          circle=false;
  
      }
  
      @Override
      protected void onSizeChanged(int w, int h, int oldw, int oldh) {
          super.onSizeChanged(w, h, oldw, oldh);
      }
  
  
      @Override
      protected void onDraw(Canvas canvas) {
  
          for (Path p : paths)
              canvas.drawPath(p, paint);
  
          if (touch)
              canvas.drawPath(path, paint);
          touch = false;
          Log.v(&quot;Inside onDraw&quot;,&quot;Circle is&quot;.concat(String.valueOf(circle)));
  
              for (Point p : circlePoints)
                  canvas.drawCircle(p.x, p.y, 5, paint);
  
  
      }
  
  
      float mX, mY,mx,my;
      final float TOUCH_TOLERANCE = 0;
  
  
  
      private void touch_start(float x, float y) {
          undone.clear();
          Log.v(&quot;ONTOUCH:&quot;, &quot;Inside DOWN&quot;.concat(&quot;DOWN-X---:&quot;).concat(String.valueOf(x)).concat(&quot;**DOWN-Y---:&quot;).concat(String.valueOf(y)));
          path.reset();
          path.moveTo(x, y);
          mX = x;
          mY = y;
          mx = x;
          my = y;
      }
  
      private void touch_up() {
          paths.add(path);
          path = new Path();
      }
  
      private void touch_move(float x, float y) {
          path.moveTo(mX, mY);
          Log.v(&quot;ONTOUCH:&quot;, &quot;Inside MOVE&quot;.concat(&quot;mX:&quot;).concat(String.valueOf(mX)).concat(&quot;mY:&quot;).concat(String.valueOf(mY)));
          Log.v(&quot;ONTOUCH:&quot;, &quot;Inside MOVE&quot;.concat(&quot;MOVE-X---:&quot;).concat(String.valueOf(x)).concat(&quot;**MOVE-Y---:&quot;).concat(String.valueOf(y)));
          float dx = Math.abs(x - mX);
          float dy = Math.abs(y - mY);
          if (dx &gt;= TOUCH_TOLERANCE || dy &gt;= TOUCH_TOLERANCE) {
              path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
              mX = x;
              mY = y;
          }
  
          path.lineTo(mX, mY);
  
          Log.v(&quot;MOVE:&quot;, &quot; PATH ADDED &amp; New Created&quot;);
  
  
      }
  
  
  
  
      @Override
      public boolean onTouch(View v, MotionEvent event) {
  
          float x = event.getX();
          float y = event.getY();
  
          switch (dtool) {
  
              case 1:
                  touch=true;
                  Touch(v, event, x, y);
                  break;
  
              case 2:
                  Line(v,event,x,y);
                  break;
  
              case 3:
                  Circle(v,event,x,y);
                  break;
  
          }
          Log.v(&quot;ONTOUCH:&quot;, &quot;OUTSIDE CASE&quot;);
          return true;
      }
  
      public void Line(View v, MotionEvent event, float x, float y) {
          switch (event.getAction()) {
  
              case MotionEvent.ACTION_DOWN:
                  touch_start(x, y);
                  invalidate();
                  break;
  
              case MotionEvent.ACTION_UP:
                  touch_up();
                  invalidate();
                  break;
  
              case MotionEvent.ACTION_MOVE:
                  touch_move(x, y);
                  invalidate();
                  break;
          }
      }
  
      public void Touch(View v, MotionEvent event, float x, float y) {
          switch (event.getAction()) {
  
              case MotionEvent.ACTION_DOWN:
                  touch_start(x, y);
                  invalidate();
                  canvas.drawPath(path, paint);
                  break;
  
              case MotionEvent.ACTION_UP:
                  touch_up();
                  invalidate();
                  canvas.drawPath(path, paint);
                  break;
  
              case MotionEvent.ACTION_MOVE:
                  touch_move(x, y);
                  invalidate();
  
                  break;
          }
      }
  
      public void Circle(View v, MotionEvent event, float x, float y)
      {   point = new Point();
          point.x = (int)x;
          point.y = (int)y;
          path.moveTo(x,y);
          circle=true;
         if(event.getAction()==MotionEvent.ACTION_DOWN) {
  
             circlePoints.add(new Point(Math.round(point.x), Math.round(point.y)));
             invalidate();
             Log.v(&quot;Circle&quot;, &quot;Inside Circle&quot;);
             circlePoints.add(point);
              paths.add(path);
             
         }
      }
  
      public void Clear() {
          paths.clear(); //Needs to be experimented
          path.reset();
          invalidate();
      }
  
      public void Undo() {
          if (paths.size() &gt; 0) {
              undone.add(paths.remove(paths.size() - 1));
              invalidate();
          }
          else if(circlePoints.size()&gt;0)
          {
              removeCircles.add(circlePoints.remove(circlePoints.size()-1));
              invalidate();
          }
      }
    }
  }
  </code></pre>
  <p>XML Layout Code:</p>
  <pre><code>&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      android:layout_width=&quot;fill_parent&quot;
      android:layout_height=&quot;fill_parent&quot;
      android:orientation=&quot;vertical&quot; &gt;
  
  
      &lt;LinearLayout
          android:id=&quot;@+id/linearLayout2&quot;
          android:layout_width=&quot;match_parent&quot;
          android:layout_height=&quot;match_parent&quot;
          android:orientation=&quot;vertical&quot;
          android:layout_weight=&quot;0&quot;
          android:layout_gravity=&quot;top&quot;&gt;
  
  
      &lt;/LinearLayout&gt;
  
      &lt;Button
          android:layout_width=&quot;wrap_content&quot;
          android:layout_height=&quot;wrap_content&quot;
          android:text=&quot;Undo&quot;
          android:id=&quot;@+id/button2&quot;
          android:layout_gravity=&quot;right&quot;
          android:layout_marginTop=&quot;-50dp&quot; /&gt;
  
      &lt;Button
          android:id=&quot;@+id/button1&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:layout_height=&quot;wrap_content&quot;
          android:text=&quot;Clear&quot;
          android:layout_gravity=&quot;center_vertical|bottom&quot;
          android:layout_marginTop=&quot;-50dp&quot;
          android:enabled=&quot;true&quot; /&gt;
  
      &lt;Button
          android:layout_width=&quot;wrap_content&quot;
          android:layout_height=&quot;wrap_content&quot;
          android:text=&quot;Tools&quot;
          android:id=&quot;@+id/button3&quot;
          android:layout_gravity=&quot;center_horizontal&quot;
          android:layout_weight=&quot;0&quot;
          android:layout_marginTop=&quot;-50dp&quot; /&gt;
  
  &lt;/LinearLayout&gt;
  </code></pre>
  <p>XML Main Menu code:</p>
  <pre><code>&lt;menu xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      xmlns:tools=&quot;http://schemas.android.com/tools&quot; tools:context=&quot;.MainActivity&quot;&gt;
  
      &lt;item
          android:id=&quot;@+id/touch&quot;
          android:title=&quot;Touch&quot;/&gt;
      &lt;item
          android:id=&quot;@+id/circle&quot;
          android:title=&quot;Circle&quot;/&gt;
      &lt;item
          android:id=&quot;@+id/line&quot;
          android:title=&quot;Line&quot;/&gt;
  
  
  
  &lt;/menu&gt;
  </code></pre>