• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.android.systemui.recents.views.grid;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Path;
22 import android.util.AttributeSet;
23 
24 import com.android.systemui.R;
25 import com.android.systemui.recents.views.TaskViewThumbnail;
26 
27 public class GridTaskViewThumbnail extends TaskViewThumbnail {
28 
29     private final Path mThumbnailOutline = new Path();
30     private final Path mRestBackgroundOutline = new Path();
31     // True if either this view's size or thumbnail scale has changed and mThumbnailOutline should
32     // be updated.
33     private boolean mUpdateThumbnailOutline = true;
34 
GridTaskViewThumbnail(Context context)35     public GridTaskViewThumbnail(Context context) {
36         this(context, null);
37     }
38 
GridTaskViewThumbnail(Context context, AttributeSet attrs)39     public GridTaskViewThumbnail(Context context, AttributeSet attrs) {
40         this(context, attrs, 0);
41     }
42 
GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr)43     public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr) {
44         this(context, attrs, defStyleAttr, 0);
45     }
46 
GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)47     public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr,
48         int defStyleRes) {
49         super(context, attrs, defStyleAttr, defStyleRes);
50         mCornerRadius = getResources().getDimensionPixelSize(
51                 R.dimen.recents_grid_task_view_rounded_corners_radius);
52     }
53 
54     /**
55      * Called when the task view frame changes, allowing us to move the contents of the header
56      * to match the frame changes.
57      */
onTaskViewSizeChanged(int width, int height)58     public void onTaskViewSizeChanged(int width, int height) {
59         mUpdateThumbnailOutline = true;
60         super.onTaskViewSizeChanged(width, height);
61     }
62 
63     /**
64      * Updates the scale of the bitmap relative to this view.
65      */
updateThumbnailMatrix()66     public void updateThumbnailMatrix() {
67         mUpdateThumbnailOutline = true;
68         super.updateThumbnailMatrix();
69     }
70 
updateThumbnailOutline()71     private void updateThumbnailOutline() {
72         final int titleHeight = getResources().getDimensionPixelSize(
73             R.dimen.recents_grid_task_view_header_height);
74         final int viewWidth = mTaskViewRect.width();
75         final int viewHeight = mTaskViewRect.height() - titleHeight;
76         final int thumbnailWidth = Math.min(viewWidth,
77             (int) (mThumbnailRect.width() * mThumbnailScale));
78         final int thumbnailHeight = Math.min(viewHeight,
79             (int) (mThumbnailRect.height() * mThumbnailScale));
80 
81         if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
82             // Draw the thumbnail, we only round the bottom corners:
83             //
84             // outerLeft                outerRight
85             //    <----------------------->            mRestBackgroundOutline
86             //    _________________________            (thumbnailWidth < viewWidth)
87             //    |_______________________| outerTop     A ____ B
88             //    |                       |    ↑           |  |
89             //    |                       |    |           |  |
90             //    |                       |    |           |  |
91             //    |                       |    |           |  | C
92             //    \_______________________/    ↓           |__/
93             //  mCornerRadius             outerBottom    E    D
94             //
95             //  mRestBackgroundOutline (thumbnailHeight < viewHeight)
96             //  A _________________________ B
97             //    |                       | C
98             //  F \_______________________/
99             //    E                       D
100             final int outerLeft = 0;
101             final int outerTop = 0;
102             final int outerRight = outerLeft + thumbnailWidth;
103             final int outerBottom = outerTop + thumbnailHeight;
104             createThumbnailPath(outerLeft, outerTop, outerRight, outerBottom, mThumbnailOutline);
105 
106             if (thumbnailWidth < viewWidth) {
107                 final int l = Math.max(0, outerRight - mCornerRadius);
108                 final int r = outerRight;
109                 final int t = outerTop;
110                 final int b = outerBottom;
111                 mRestBackgroundOutline.reset();
112                 mRestBackgroundOutline.moveTo(l, t); // A
113                 mRestBackgroundOutline.lineTo(r, t); // B
114                 mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
115                 mRestBackgroundOutline.arcTo(r -  2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
116                         0, 90, false); // D
117                 mRestBackgroundOutline.lineTo(l, b); // E
118                 mRestBackgroundOutline.lineTo(l, t); // A
119                 mRestBackgroundOutline.close();
120 
121             }
122             if (thumbnailHeight < viewHeight) {
123                 final int l = outerLeft;
124                 final int r = outerRight;
125                 final int t = Math.max(0, thumbnailHeight - mCornerRadius);
126                 final int b = outerBottom;
127                 mRestBackgroundOutline.reset();
128                 mRestBackgroundOutline.moveTo(l, t); // A
129                 mRestBackgroundOutline.lineTo(r, t); // B
130                 mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
131                 mRestBackgroundOutline.arcTo(r -  2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
132                         0, 90, false); // D
133                 mRestBackgroundOutline.lineTo(l + mCornerRadius, b); // E
134                 mRestBackgroundOutline.arcTo(l, b - 2 * mCornerRadius, l + 2 * mCornerRadius, b,
135                         90, 90, false); // F
136                 mRestBackgroundOutline.lineTo(l, t); // A
137                 mRestBackgroundOutline.close();
138             }
139         } else {
140             createThumbnailPath(0, 0, viewWidth, viewHeight, mThumbnailOutline);
141         }
142     }
143 
createThumbnailPath(int outerLeft, int outerTop, int outerRight, int outerBottom, Path outPath)144     private void createThumbnailPath(int outerLeft, int outerTop, int outerRight, int outerBottom,
145             Path outPath) {
146         outPath.reset();
147         outPath.moveTo(outerLeft, outerTop);
148         outPath.lineTo(outerRight, outerTop);
149         outPath.lineTo(outerRight, outerBottom - mCornerRadius);
150         outPath.arcTo(outerRight -  2 * mCornerRadius, outerBottom - 2 * mCornerRadius, outerRight,
151                 outerBottom, 0, 90, false);
152         outPath.lineTo(outerLeft + mCornerRadius, outerBottom);
153         outPath.arcTo(outerLeft, outerBottom - 2 * mCornerRadius, outerLeft + 2 * mCornerRadius,
154                 outerBottom, 90, 90, false);
155         outPath.lineTo(outerLeft, outerTop);
156         outPath.close();
157     }
158 
159     @Override
onDraw(Canvas canvas)160     protected void onDraw(Canvas canvas) {
161         final int titleHeight = getResources().getDimensionPixelSize(
162             R.dimen.recents_grid_task_view_header_height);
163         final int viewWidth = mTaskViewRect.width();
164         final int viewHeight = mTaskViewRect.height() - titleHeight;
165         final int thumbnailWidth = Math.min(viewWidth,
166             (int) (mThumbnailRect.width() * mThumbnailScale));
167         final int thumbnailHeight = Math.min(viewHeight,
168             (int) (mThumbnailRect.height() * mThumbnailScale));
169 
170         if (mUpdateThumbnailOutline) {
171             updateThumbnailOutline();
172             mUpdateThumbnailOutline = false;
173         }
174 
175         if (mUserLocked) {
176             canvas.drawPath(mThumbnailOutline, mLockedPaint);
177         } else if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
178             // Draw the background, there will be some small overdraw with the thumbnail
179             if (thumbnailWidth < viewWidth) {
180                 // Portrait thumbnail on a landscape task view
181                 canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
182             }
183             if (thumbnailHeight < viewHeight) {
184                 // Landscape thumbnail on a portrait task view
185                 canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
186             }
187             canvas.drawPath(mThumbnailOutline, getDrawPaint());
188         } else {
189             canvas.drawPath(mThumbnailOutline, mBgFillPaint);
190         }
191     }
192 }
193