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 android.systemui.cts; 18 19 import android.graphics.Canvas; 20 import android.graphics.Color; 21 import android.graphics.ColorFilter; 22 import android.graphics.CornerPathEffect; 23 import android.graphics.DashPathEffect; 24 import android.graphics.Insets; 25 import android.graphics.Paint; 26 import android.graphics.Path; 27 import android.graphics.Point; 28 import android.graphics.Rect; 29 import android.graphics.drawable.Drawable; 30 import android.view.MotionEvent; 31 import android.view.View; 32 import android.view.WindowInsets; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 37 public class WindowInsetsPresenterDrawable extends Drawable implements View.OnTouchListener { 38 private static final int GAP = 15; 39 private final Path mPath; 40 private final Paint mMandatorySystemGesturePaint; 41 private final Paint mSystemGesturePaint; 42 private final Paint mSystemWindowPaint; 43 private final Paint mTappableElementPaint; 44 private final Paint mTouchPaint; 45 private final Paint mTouchTrackPaint; 46 private final List<Point> mAllActionPoints; 47 private final List<Point> mActionCancelPoints; 48 private final List<Point> mActionDownPoints; 49 private final List<Point> mActionUpPoints; 50 private WindowInsets mWindowInsets; 51 private float mLastX; 52 private float mLastY; 53 54 /** 55 * Initial 4 paints and 1 path for drawing. 56 * initial mPointList for recording the touch points. 57 */ WindowInsetsPresenterDrawable()58 public WindowInsetsPresenterDrawable() { 59 mMandatorySystemGesturePaint = new Paint(); 60 mMandatorySystemGesturePaint.setStrokeWidth(2); 61 mMandatorySystemGesturePaint.setStyle(Paint.Style.STROKE); 62 mMandatorySystemGesturePaint.setColor(Color.RED); 63 mMandatorySystemGesturePaint.setPathEffect(new DashPathEffect(new float[]{GAP, GAP * 3}, 64 0)); 65 66 mSystemGesturePaint = new Paint(); 67 mSystemGesturePaint.setStrokeWidth(2); 68 mSystemGesturePaint.setStyle(Paint.Style.STROKE); 69 mSystemGesturePaint.setColor(Color.GREEN); 70 mSystemGesturePaint.setPathEffect(new DashPathEffect(new float[]{GAP, GAP, GAP * 2}, 71 0)); 72 73 mTappableElementPaint = new Paint(); 74 mTappableElementPaint.setStrokeWidth(2); 75 mTappableElementPaint.setStyle(Paint.Style.STROKE); 76 mTappableElementPaint.setColor(Color.BLUE); 77 mTappableElementPaint.setPathEffect(new DashPathEffect(new float[]{GAP * 2, GAP, GAP}, 0)); 78 79 mSystemWindowPaint = new Paint(); 80 mSystemWindowPaint.setStrokeWidth(2); 81 mSystemWindowPaint.setStyle(Paint.Style.STROKE); 82 mSystemWindowPaint.setColor(Color.YELLOW); 83 mSystemWindowPaint.setPathEffect(new DashPathEffect(new float[]{0, GAP * 3, GAP}, 0)); 84 85 mTouchPaint = new Paint(); 86 mTouchPaint.setColor(0x4ffff070); 87 mTouchPaint.setStrokeWidth(10); 88 mTouchPaint.setStyle(Paint.Style.FILL_AND_STROKE); 89 90 mPath = new Path(); 91 mTouchTrackPaint = new Paint(); 92 mTouchTrackPaint.setColor(Color.WHITE); 93 mTouchTrackPaint.setStrokeWidth(1); 94 mTouchTrackPaint.setStyle(Paint.Style.STROKE); 95 mTouchTrackPaint.setPathEffect(new CornerPathEffect(5)); 96 97 mAllActionPoints = new ArrayList<>(); 98 mActionCancelPoints = new ArrayList<>(); 99 mActionDownPoints = new ArrayList<>(); 100 mActionUpPoints = new ArrayList<>(); 101 } 102 103 WindowInsetsPresenterDrawable(WindowInsets windowInsets)104 public WindowInsetsPresenterDrawable(WindowInsets windowInsets) { 105 this(); 106 mWindowInsets = windowInsets; 107 } 108 109 @Override setBounds(Rect bounds)110 public void setBounds(Rect bounds) { 111 super.setBounds(bounds); 112 } 113 drawInset(Canvas canvas, Insets insets, Paint paint)114 private void drawInset(Canvas canvas, Insets insets, Paint paint) { 115 final Rect rect = getBounds(); 116 117 if (insets.left > 0) { 118 canvas.drawRect(0, 0, insets.left, rect.bottom, paint); 119 } 120 if (insets.top > 0) { 121 canvas.drawRect(0, 0, rect.width(), insets.top, paint); 122 } 123 if (insets.right > 0) { 124 canvas.drawRect(rect.width() - insets.right, 0, rect.width(), rect.bottom, 125 paint); 126 } 127 if (insets.bottom > 0) { 128 canvas.drawRect(0, rect.height() - insets.bottom, rect.width(), rect.height(), 129 paint); 130 } 131 } 132 133 @Override draw(Canvas canvas)134 public void draw(Canvas canvas) { 135 canvas.save(); 136 137 if (mWindowInsets != null) { 138 drawInset(canvas, mWindowInsets.getSystemGestureInsets(), mSystemGesturePaint); 139 drawInset(canvas, mWindowInsets.getMandatorySystemGestureInsets(), 140 mMandatorySystemGesturePaint); 141 drawInset(canvas, mWindowInsets.getTappableElementInsets(), mTappableElementPaint); 142 drawInset(canvas, mWindowInsets.getSystemWindowInsets(), mSystemWindowPaint); 143 } 144 145 if (mAllActionPoints.size() > 0) { 146 canvas.drawPath(mPath, mTouchTrackPaint); 147 148 for (Point p : mAllActionPoints) { 149 canvas.drawPoint(p.x, p.y, mTouchPaint); 150 } 151 } 152 153 canvas.restore(); 154 } 155 156 @Override setAlpha(int alpha)157 public void setAlpha(int alpha) { 158 /* do noting, only for implement abstract method */ 159 } 160 161 @Override setColorFilter(ColorFilter colorFilter)162 public void setColorFilter(ColorFilter colorFilter) { 163 /* do noting, only for implement abstract method */ 164 } 165 166 @Override getOpacity()167 public int getOpacity() { 168 return 255; /* not transparent */ 169 } 170 171 /** 172 * To set the IwndowInsets that is showed on this drawable. 173 * @param windowInsets the WindowInsets will show. 174 */ setWindowInsets(WindowInsets windowInsets)175 public void setWindowInsets(WindowInsets windowInsets) { 176 if (windowInsets != null) { 177 mWindowInsets = new WindowInsets.Builder(windowInsets).build(); 178 invalidateSelf(); 179 } 180 } 181 182 @Override onTouch(View v, MotionEvent event)183 public boolean onTouch(View v, MotionEvent event) { 184 Point p; 185 switch (event.getAction()) { 186 case MotionEvent.ACTION_DOWN: 187 mPath.moveTo(event.getX(), event.getY()); 188 p = new Point((int) event.getX(), (int) event.getY()); 189 mAllActionPoints.add(p); 190 mActionDownPoints.add(p); 191 mLastX = event.getX(); 192 mLastY = event.getY(); 193 invalidateSelf(); 194 195 break; 196 case MotionEvent.ACTION_UP: 197 mPath.lineTo(event.getX(), event.getY()); 198 p = new Point((int) event.getX(), (int) event.getY()); 199 mAllActionPoints.add(p); 200 mActionUpPoints.add(p); 201 invalidateSelf(); 202 break; 203 case MotionEvent.ACTION_MOVE: 204 mPath.quadTo(mLastX, mLastY, event.getX(), event.getY()); 205 p = new Point((int) event.getX(), (int) event.getY()); 206 mAllActionPoints.add(p); 207 mLastX = event.getX(); 208 mLastY = event.getY(); 209 invalidateSelf(); 210 break; 211 case MotionEvent.ACTION_CANCEL: 212 mPath.lineTo(event.getX(), event.getY()); 213 p = new Point((int) event.getX(), (int) event.getY()); 214 mAllActionPoints.add(p); 215 mActionCancelPoints.add(p); 216 break; 217 default: 218 break; 219 } 220 return false; 221 } 222 getActionCancelPoints()223 public List<Point> getActionCancelPoints() { 224 return mActionCancelPoints; 225 } 226 getActionDownPoints()227 public List<Point> getActionDownPoints() { 228 return mActionDownPoints; 229 } 230 getActionUpPoints()231 public List<Point> getActionUpPoints() { 232 return mActionUpPoints; 233 } 234 } 235