Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(532)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/appmenu/PulseDrawable.java

Issue 2779543005: Add support for highlighting menu items (Closed)
Patch Set: Debugged drawable issues Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.appmenu;
6
7 import android.content.res.Resources;
8 import android.graphics.Canvas;
9 import android.graphics.ColorFilter;
10 import android.graphics.Paint;
11 import android.graphics.PixelFormat;
12 import android.graphics.Rect;
13 import android.graphics.drawable.Animatable;
14 import android.graphics.drawable.Drawable;
15 import android.os.SystemClock;
16 import android.support.annotation.ColorInt;
17 import android.support.annotation.ColorRes;
18 import android.view.animation.Interpolator;
19
20 import org.chromium.base.ApiCompatibilityUtils;
21
22 /**
23 * A custom {@link Drawable} that will animate a pulse using the {@link PulseInt erpolator}. Meant
24 * to be created with a {@link PulseDrawable#Painter} that does the actual drawi ng work based on
25 * the pulse interpolation value.
26 */
27 public class PulseDrawable extends Drawable implements Animatable {
28 private static final long PULSE_DURATION_MS = 2500;
29 private static final long FRAME_RATE = 60;
30
31 /**
32 * An interface that does the actual drawing work for this {@link Drawable}. Not meant to be
33 * stateful, as this could be shared across multiple instances of this drawa ble if it gets
34 * copied or mutated.
35 */
36 public interface Painter {
37 /**
38 * Called when this drawable updates it's pulse interpolation. Should m utate the drawable
39 * as necessary. This is responsible for invalidating this {@link Drawa ble} if something
40 * needs to be redrawn.
41 *
42 * @param drawable The {@link PulseDrawable} that is updated.
43 * @param interpolation The current progress of whatever is being pulsed .
44 */
45 void modifyDrawable(PulseDrawable drawable, float interpolation);
46
47 /**
48 * Called when this {@link PulseDrawable} needs to draw. Should perform any draw operation
49 * for the specific type of pulse.
50 * @param drawable The calling {@link PulseDrawable}.
51 * @param paint A {@link Paint} object to use. This will automa tically have the
52 * color set.
53 * @param canvas The {@link Canvas} to draw to.
54 * @param interpolation The current progress of whatever is being pulsed .
55 */
56 void draw(PulseDrawable drawable, Paint paint, Canvas canvas, float inte rpolation);
57 }
58
59 private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
60 private final Rect mInset = new Rect();
61 private final Rect mOriginalBounds = new Rect();
62 private final Rect mInsetBounds = new Rect();
63
64 protected PulseState mState;
Ted C 2017/04/12 18:05:57 why protected?
David Trainor- moved to gerrit 2017/04/12 18:59:37 Ah I was planning on overriding this class for the
65 private boolean mMutated;
66 private boolean mRunning;
67
68 /**
69 * Creates a new {@link PulseDrawable} instance.
70 * @param res A {@link Resources} object used to load the {@link Dr awable} parameters.
71 * @param color A color resource.
72 * @param interpolator An {@link Interpolator} that defines how the pulse wi ll fade in and out.
73 * @param painter The {@link Painter} that will be responsible for draw ing the pulse.
74 */
75 public PulseDrawable(
76 Resources res, @ColorRes int color, Interpolator interpolator, Paint er painter) {
77 this(new PulseState(res, color, interpolator, painter));
78 }
79
80 private PulseDrawable(PulseState state) {
81 mState = state;
82 }
83
84 /** What color to set the pulse to. */
85 public void setColor(@ColorInt int color) {
Ted C 2017/04/12 18:05:57 I'd rather this not be configurable right now. I'
David Trainor- moved to gerrit 2017/04/12 18:59:37 I can have it set light/dark if you'd like. We on
86 int alpha = getAlpha();
87 mState.color = mState.drawColor = color;
88 setAlpha(alpha);
89 invalidateSelf();
90 }
91
92 /** How much to inset the bounds of this {@link Drawable} by. */
93 public void setInset(int left, int top, int right, int bottom) {
94 mInset.set(left, top, right, bottom);
95 setBounds(mOriginalBounds);
Ted C 2017/04/12 18:05:57 Should we only call this if !mOriginalBounds.isEmp
David Trainor- moved to gerrit 2017/04/12 18:59:37 Yes good point.
96 }
97
98 // Animatable implementation.
99 @Override
100 public void start() {
101 if (mRunning) {
102 unscheduleSelf(mNextFrame);
103 scheduleSelf(mNextFrame, SystemClock.uptimeMillis() + 1000 / FRAME_R ATE);
104 } else {
105 mRunning = true;
106 if (mState.startTime == 0) mState.startTime = SystemClock.uptimeMill is();
107 mNextFrame.run();
108 }
109 }
110
111 @Override
112 public void stop() {
113 mRunning = false;
114 mState.startTime = 0;
115 unscheduleSelf(mNextFrame);
116 }
117
118 @Override
119 public boolean isRunning() {
120 return mRunning;
121 }
122
123 // Drawable implementation.
124 // Overriding only this method because {@link Drawable#setBounds(Rect)} call s into this.
125 @Override
126 public void setBounds(int left, int top, int right, int bottom) {
127 mOriginalBounds.set(left, top, right, bottom);
128 mInsetBounds.set(
129 left + mInset.left, top + mInset.top, right - mInset.right, bott om - mInset.bottom);
130 super.setBounds(
131 mInsetBounds.left, mInsetBounds.top, mInsetBounds.right, mInsetB ounds.bottom);
132 }
133
134 @Override
135 public void draw(Canvas canvas) {
136 mPaint.setColor(mState.drawColor);
137 mState.painter.draw(this, mPaint, canvas, mState.progress);
138 }
139
140 @Override
141 public void setAlpha(int alpha) {
142 // Encode the alpha into the color.
143 alpha += alpha >> 7; // make it 0..256
144 final int baseAlpha = mState.color >>> 24;
145 final int useAlpha = baseAlpha * alpha >> 8;
146 final int useColor = (mState.color << 8 >>> 8) | (useAlpha << 24);
147 if (mState.drawColor != useColor) {
148 mState.drawColor = useColor;
149 invalidateSelf();
150 }
151 }
152
153 @Override
154 public int getAlpha() {
155 return mState.drawColor >>> 24;
156 }
157
158 @Override
159 public void setColorFilter(ColorFilter colorFilter) {
160 mPaint.setColorFilter(colorFilter);
161 }
162
163 @Override
164 public int getOpacity() {
165 return PixelFormat.TRANSLUCENT;
166 }
167
168 @Override
169 public boolean setVisible(boolean visible, boolean restart) {
170 final boolean changed = super.setVisible(visible, restart);
171 if (visible) {
172 if (changed || restart) start();
173 } else {
174 stop();
175 }
176 return changed;
177 }
178
179 @Override
180 public Drawable mutate() {
181 if (!mMutated && super.mutate() == this) {
182 mState = new PulseState(mState);
183 mMutated = true;
184 }
185 return this;
186 }
187
188 @Override
189 public ConstantState getConstantState() {
190 return mState;
191 }
192
193 private void stepPulse() {
194 long curTime = SystemClock.uptimeMillis();
195 long msIntoAnim = (curTime - mState.startTime) % PULSE_DURATION_MS;
196 float progress = ((float) msIntoAnim) / ((float) PULSE_DURATION_MS);
197 mState.progress = mState.interpolator.getInterpolation(progress);
198 mState.painter.modifyDrawable(PulseDrawable.this, mState.progress);
199 }
200
201 /**
202 * The {@link ConstantState} subclass for this {@link PulseDrawable}.
203 */
204 private static final class PulseState extends ConstantState {
205 // Current Paint State.
206 /** The current color, including alpha, to draw. */
207 public int drawColor;
208
209 /** The original color to draw (may not include any alpha updates. */
Ted C 2017/04/12 18:05:57 may not, or does not? also missing trailing ) I
David Trainor- moved to gerrit 2017/04/12 18:59:37 It depends on whether or not the color passed in h
210 public int color;
211
212 // Current Animation State
213 /** The time from {@link SystemClock#updateMillis()} that this animation started at. */
214 public long startTime;
215
216 /** The current progress from 0 to 1 of the pulse. */
217 public float progress;
218
219 /** The {@link Interpolator} that makes the pulse and generates the prog ress. */
220 public Interpolator interpolator;
221
222 /**
223 * The {@link Painter} object that is responsible for modifying and draw ing this
224 * {@link PulseDrawable}.
225 */
226 public Painter painter;
227
228 PulseState(Resources res, @ColorRes int color, Interpolator interpolator , Painter painter) {
229 this.color = this.drawColor = ApiCompatibilityUtils.getColor(res, co lor);
230
231 this.interpolator = new PulseInterpolator(interpolator);
232 this.painter = painter;
233 }
234
235 PulseState(PulseState other) {
236 drawColor = other.drawColor;
237 color = other.color;
238
239 startTime = other.startTime;
240
241 interpolator = other.interpolator;
242 painter = other.painter;
243 }
244
245 @Override
246 public Drawable newDrawable() {
247 return new PulseDrawable(this);
248 }
249
250 @Override
251 public int getChangingConfigurations() {
252 return 0;
253 }
254 }
255
256 private final Runnable mNextFrame = new Runnable() {
Ted C 2017/04/12 18:05:57 I'd put this above the constructor as it is a loca
David Trainor- moved to gerrit 2017/04/12 18:59:37 Done.
257 @Override
258 public void run() {
259 stepPulse();
260 if (mRunning) scheduleSelf(mNextFrame, SystemClock.uptimeMillis() + 1000 / FRAME_RATE);
261 }
262 };
263 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698