1f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette/*
2f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Copyright (C) 2015 The Android Open Source Project
3f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette *
4f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Licensed under the Apache License, Version 2.0 (the "License");
5f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * you may not use this file except in compliance with the License.
6f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * You may obtain a copy of the License at
7f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette *
8f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette *      http://www.apache.org/licenses/LICENSE-2.0
9f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette *
10f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Unless required by applicable law or agreed to in writing, software
11f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * distributed under the License is distributed on an "AS IS" BASIS,
12f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * See the License for the specific language governing permissions and
14f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * limitations under the License.
15f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */
16f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
17f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverettepackage android.graphics.drawable;
18f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
19f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.animation.Animator;
20f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.graphics.Canvas;
21f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.graphics.Paint;
22f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.graphics.Rect;
23bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viveretteimport android.util.DisplayMetrics;
24f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craikimport android.view.DisplayListCanvas;
25f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.view.RenderNodeAnimator;
26f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
27f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport java.util.ArrayList;
28f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
29f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette/**
300c453ccb87e0b5a4f4b318df01700c9a9a0da545John Reck * Abstract class that handles size & positioning common to the ripple & focus states.
31f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */
32f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteabstract class RippleComponent {
330c453ccb87e0b5a4f4b318df01700c9a9a0da545John Reck    protected final RippleDrawable mOwner;
34f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
35f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    /** Bounds used for computing max radius. May be modified by the owner. */
36f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    protected final Rect mBounds;
37f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
38f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    /** Whether we have an explicit maximum radius. */
39f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    private boolean mHasMaxRadius;
40f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
41f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    /** How big this ripple should be when fully entered. */
42f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    protected float mTargetRadius;
43f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
44f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    /** Screen density used to adjust pixel-based constants. */
45bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viverette    protected float mDensityScale;
46f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
470c453ccb87e0b5a4f4b318df01700c9a9a0da545John Reck    public RippleComponent(RippleDrawable owner, Rect bounds) {
48f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        mOwner = owner;
49f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        mBounds = bounds;
50f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    }
51f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
525bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette    public void onBoundsChange() {
535bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette        if (!mHasMaxRadius) {
545bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette            mTargetRadius = getTargetRadius(mBounds);
555bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette            onTargetRadiusChanged(mTargetRadius);
565bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette        }
575bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette    }
585bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette
59bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viverette    public final void setup(float maxRadius, int densityDpi) {
60f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        if (maxRadius >= 0) {
61f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette            mHasMaxRadius = true;
62f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette            mTargetRadius = maxRadius;
63f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        } else {
645bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette            mTargetRadius = getTargetRadius(mBounds);
65f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        }
66f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
67bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viverette        mDensityScale = densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
68f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
69f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        onTargetRadiusChanged(mTargetRadius);
70f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    }
71f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
725bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette    private static float getTargetRadius(Rect bounds) {
735bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette        final float halfWidth = bounds.width() / 2.0f;
745bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette        final float halfHeight = bounds.height() / 2.0f;
755bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette        return (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight);
765bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette    }
775bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette
78f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    /**
79f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     * Populates {@code bounds} with the maximum drawing bounds of the ripple
80f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     * relative to its center. The resulting bounds should be translated into
81f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     * parent drawable coordinates before use.
82f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     *
83f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     * @param bounds the rect to populate with drawing bounds
84f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     */
85f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    public void getBounds(Rect bounds) {
86f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        final int r = (int) Math.ceil(mTargetRadius);
87f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        bounds.set(-r, -r, r, r);
88f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    }
89f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
90f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    protected final void invalidateSelf() {
9115ce834e52806378d6ab2b90f573bae14cb3fd4bAlan Viverette        mOwner.invalidateSelf(false);
92f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    }
93f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
94f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    protected final void onHotspotBoundsChanged() {
95f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        if (!mHasMaxRadius) {
967bb9f374c07258039232711c49a743ea8dc982ffJohn Reck            mTargetRadius = getTargetRadius(mBounds);
977bb9f374c07258039232711c49a743ea8dc982ffJohn Reck            onTargetRadiusChanged(mTargetRadius);
98f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        }
99f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    }
100f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette
101f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    /**
102f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     * Called when the target radius changes.
103f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     *
104f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     * @param targetRadius the new target radius
105f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette     */
106f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    protected void onTargetRadiusChanged(float targetRadius) {
107f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette        // Stub.
108f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette    }
109f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette}
110