1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.android.car.multidisplaytest.draw;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Color;
22 import android.graphics.Paint;
23 import android.graphics.Path;
24 import android.util.AttributeSet;
25 import android.view.MotionEvent;
26 import android.view.View;
27 
28 public class CanvasView extends View {
29     private static final float TOLERANCE = 5.0f;
30 
31     private final Paint mPaint;
32     private final Path mPath;
33     private float mX;
34     private float mY;
35 
CanvasView(Context c, AttributeSet attrs)36     public CanvasView(Context c, AttributeSet attrs) {
37         super(c, attrs);
38 
39         mPath = new Path();
40         mPaint = new Paint();
41         mPaint.setStyle(Paint.Style.STROKE);
42         mPaint.setStrokeJoin(Paint.Join.ROUND);
43         mPaint.setStrokeWidth(4f);
44         mPaint.setColor(Color.WHITE);
45     }
46 
47     @Override
onDraw(Canvas canvas)48     protected void onDraw(Canvas canvas) {
49         super.onDraw(canvas);
50         canvas.drawPath(mPath, mPaint);
51     }
52 
53     @Override
onTouchEvent(MotionEvent event)54     public boolean onTouchEvent(MotionEvent event) {
55         float x = event.getX();
56         float y = event.getY();
57 
58         switch (event.getAction()) {
59             case MotionEvent.ACTION_DOWN:
60                 downTouch(x, y);
61                 invalidate();
62                 break;
63             case MotionEvent.ACTION_MOVE:
64                 moveTouch(x, y);
65                 invalidate();
66                 break;
67             case MotionEvent.ACTION_UP:
68                 upTouch();
69                 invalidate();
70                 break;
71             default:
72                 // No op.
73         }
74         return true;
75     }
76 
clearCanvas()77     public void clearCanvas() {
78         mPath.reset();
79         invalidate();
80     }
81 
moveTouch(float x, float y)82     private void moveTouch(float x, float y) {
83         float dx = Math.abs(x - mX);
84         float dy = Math.abs(y - mY);
85         if (dx >= TOLERANCE || dy >= TOLERANCE) {
86             // use mid-point as the control point of the bezier curve to make a smooth line
87             // eg. when forming curve between three non-aligned consecutive points
88             mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
89             mX = x;
90             mY = y;
91         }
92     }
93 
downTouch(float x, float y)94     private void downTouch(float x, float y) {
95         mPath.moveTo(x, y);
96         mX = x;
97         mY = y;
98     }
99 
upTouch()100     private void upTouch() {
101         mPath.lineTo(mX, mY);
102     }
103 }
104