CompositeDrawable.java revision ac5fe7c617c66850fff75a9fce9979c6e5674b0f
1df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata/*
2df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * Copyright (C) 2015 The Android Open Source Project
3df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *
4df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * Licensed under the Apache License, Version 2.0 (the "License");
5df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * you may not use this file except in compliance with the License.
6df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * You may obtain a copy of the License at
7df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *
8df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *      http://www.apache.org/licenses/LICENSE-2.0
9df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *
10df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * Unless required by applicable law or agreed to in writing, software
11df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * distributed under the License is distributed on an "AS IS" BASIS,
12df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * See the License for the specific language governing permissions and
14df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * limitations under the License.
15df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata */
16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.graphics;
17df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
1800f780c9e3cca0b2e364c61e936147e09877c43fDake Guimport android.content.res.Resources;
19df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.Canvas;
20df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.ColorFilter;
21df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.PixelFormat;
22df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.Rect;
23df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.drawable.Drawable;
24ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull;
25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.leanback.graphics.BoundsRule.ValueRule;
26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.graphics.drawable.DrawableCompat;
273d9017263a760990ba79d5ebf3d1b6587e0bd311susnataimport android.util.Property;
28df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
29df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport java.util.ArrayList;
30df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
31df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata/**
323d9017263a760990ba79d5ebf3d1b6587e0bd311susnata * Generic drawable class that can be composed of multiple children. Whenever the bounds changes
3344ece5ceaaee232f9139ccbde40ac4a5e642bdeeChristophe Beyls * for this class, it updates those of its children.
34df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata */
353d9017263a760990ba79d5ebf3d1b6587e0bd311susnatapublic class CompositeDrawable extends Drawable implements Drawable.Callback {
3600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
3700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    static class CompositeState extends Drawable.ConstantState {
3800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
3900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> mChildren;
4000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
4100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        CompositeState() {
4200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mChildren = new ArrayList<ChildDrawable>();
4300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
4400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
4500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        CompositeState(CompositeState other, CompositeDrawable parent, Resources res) {
4600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final int n = other.mChildren.size();
4700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mChildren = new ArrayList<ChildDrawable>(n);
4800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            for (int k = 0; k < n; k++) {
4900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                mChildren.add(new ChildDrawable(other.mChildren.get(k), parent, res));
5000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
5100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
5200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
5300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @NonNull
5400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @Override
5500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        public Drawable newDrawable() {
5600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return new CompositeDrawable(this);
5700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
5800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
5900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @Override
6000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        public int getChangingConfigurations() {
6100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return 0;
6200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
6300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
6500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    CompositeState mState;
6700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    boolean mMutated = false;
6800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public CompositeDrawable() {
7000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState = new CompositeState();
7100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
7200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
7300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    CompositeDrawable(CompositeState state) {
7400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState = state;
7500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
7600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
7700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    @Override
7800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public ConstantState getConstantState() {
7900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState;
8000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
8100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
8200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    @Override
8300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public Drawable mutate() {
8400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        if (!mMutated && super.mutate() == this) {
8500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mState = new CompositeState(mState, this, null);
8600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final ArrayList<ChildDrawable> children = mState.mChildren;
8700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            for (int i = 0, n = children.size(); i < n; i++) {
8800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                final Drawable dr = children.get(i).mDrawable;
8900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                if (dr != null) {
9000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                    dr.mutate();
9100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                }
9200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
9300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mMutated = true;
9400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
9500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return this;
9600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
97df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
98df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
99df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Adds the supplied region.
100df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1013d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void addChildDrawable(Drawable drawable) {
10200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState.mChildren.add(new ChildDrawable(drawable, this));
103df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
104df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
105df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
106e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Sets the supplied region at given index.
107e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
108e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public void setChildDrawableAt(int index, Drawable drawable) {
109e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mState.mChildren.set(index, new ChildDrawable(drawable, this));
110e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
111e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
112e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
1133d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Returns the {@link Drawable} for the given index.
114df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public Drawable getDrawable(int index) {
11600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState.mChildren.get(index).mDrawable;
117df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
118df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
119df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
1203d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Returns the {@link ChildDrawable} at the given index.
121df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public ChildDrawable getChildAt(int index) {
12300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState.mChildren.get(index);
1243d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
1253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
1263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    /**
1273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Removes the child corresponding to the given index.
1283d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     */
1293d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void removeChild(int index) {
13000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState.mChildren.remove(index);
131df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
132df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
133df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
134df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Removes the given region.
135df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1363d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void removeDrawable(Drawable drawable) {
13700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1383d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1393d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            if (drawable == children.get(i).mDrawable) {
1403d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                children.get(i).mDrawable.setCallback(null);
1413d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                children.remove(i);
1423d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                return;
1433d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
1443d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
145df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
146df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
147df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
1483d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Returns the total number of children.
149df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1503d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public int getChildCount() {
15100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState.mChildren.size();
152df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
153df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
154df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
155df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void draw(Canvas canvas) {
15600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1573d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1583d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            children.get(i).mDrawable.draw(canvas);
159df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
160df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
161df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
162df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
163df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    protected void onBoundsChange(Rect bounds) {
164df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        super.onBoundsChange(bounds);
1653d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        updateBounds(bounds);
166df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
167df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
168df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
169df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setColorFilter(ColorFilter colorFilter) {
17000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1713d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1723d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            children.get(i).mDrawable.setColorFilter(colorFilter);
173df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
174df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
175df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
176df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
177df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public int getOpacity() {
178df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        return PixelFormat.UNKNOWN;
179df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
180df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
181df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
182df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setAlpha(int alpha) {
18300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1843d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1853d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            children.get(i).mDrawable.setAlpha(alpha);
1863d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
1873d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
1883d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
18900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    /**
19000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu     * @return Alpha value between 0(inclusive) and 255(inclusive)
19100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu     */
192e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas    @Override
19300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public int getAlpha() {
19400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final Drawable dr = getFirstNonNullDrawable();
19500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        if (dr != null) {
19600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return DrawableCompat.getAlpha(dr);
19700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        } else {
19800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return 0xFF;
19900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
20000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
20100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
20200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    final Drawable getFirstNonNullDrawable() {
20300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
20400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        for (int i = 0, n = children.size(); i < n; i++) {
20500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final Drawable dr = children.get(i).mDrawable;
20600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            if (dr != null) {
20700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                return dr;
20800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
20900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
21000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return null;
21100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
21200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
2133d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    @Override
2143d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void invalidateDrawable(Drawable who) {
2153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        invalidateSelf();
2163d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2173d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2183d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    @Override
2193d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void scheduleDrawable(Drawable who, Runnable what, long when) {
2203d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        scheduleSelf(what, when);
2213d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    @Override
2243d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void unscheduleDrawable(Drawable who, Runnable what) {
2253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        unscheduleSelf(what);
2263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2283d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    /**
2293d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Updates the bounds based on the {@link BoundsRule}.
2303d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     */
2313d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    void updateBounds(Rect bounds) {
23200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
2333d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
2343d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            ChildDrawable childDrawable = children.get(i);
2353d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            childDrawable.updateBounds(bounds);
2363d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2373d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2383d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2393d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    /**
2403d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Wrapper class holding a drawable object and {@link BoundsRule} to update drawable bounds
2413d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * when parent bound changes.
2423d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     */
2433d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public static final class ChildDrawable {
244450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata        private final BoundsRule mBoundsRule;
2453d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        private final Drawable mDrawable;
2463d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        private final Rect adjustedBounds = new Rect();
247738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu        final CompositeDrawable mParent;
2483d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2493d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        public ChildDrawable(Drawable drawable, CompositeDrawable parent) {
2503d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            this.mDrawable = drawable;
2513d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            this.mParent = parent;
252450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            this.mBoundsRule = new BoundsRule();
25300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            drawable.setCallback(parent);
25400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
25500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
25600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        ChildDrawable(ChildDrawable orig, CompositeDrawable parent, Resources res) {
25700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final Drawable dr = orig.mDrawable;
25800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final Drawable clone;
25900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            if (dr != null) {
26000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                final ConstantState cs = dr.getConstantState();
26100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                if (res != null) {
26200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                    clone = cs.newDrawable(res);
26300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                } else {
26400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                    clone = cs.newDrawable();
26500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                }
26600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone.setCallback(parent);
26700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                DrawableCompat.setLayoutDirection(clone, DrawableCompat.getLayoutDirection(dr));
26800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone.setBounds(dr.getBounds());
26900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone.setLevel(dr.getLevel());
27000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            } else {
27100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone = null;
27200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
273450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            if (orig.mBoundsRule != null) {
274450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata                this.mBoundsRule = new BoundsRule(orig.mBoundsRule);
275450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            } else {
276450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata                this.mBoundsRule = new BoundsRule();
277450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            }
27800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mDrawable = clone;
27900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mParent = parent;
2803d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2813d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2823d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
2833d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Returns the instance of {@link BoundsRule}.
2843d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
2853d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        public BoundsRule getBoundsRule() {
286450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            return this.mBoundsRule;
2873d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2883d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2893d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
2903d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Returns the {@link Drawable}.
2913d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
2923d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        public Drawable getDrawable() {
2933d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            return mDrawable;
2943d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2953d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2963d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
2973d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Updates the bounds based on the {@link BoundsRule}.
2983d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
2993d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        void updateBounds(Rect bounds) {
300450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            mBoundsRule.calculateBounds(bounds, adjustedBounds);
3013d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            mDrawable.setBounds(adjustedBounds);
3023d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
3033d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
304e464e5647326c000d2bd48e7d4369a279894f360susnata        /**
305e464e5647326c000d2bd48e7d4369a279894f360susnata         * After changing the {@link BoundsRule}, user should call this function
306e464e5647326c000d2bd48e7d4369a279894f360susnata         * for the drawable to recalculate its bounds.
307e464e5647326c000d2bd48e7d4369a279894f360susnata         */
308e464e5647326c000d2bd48e7d4369a279894f360susnata        public void recomputeBounds() {
3093d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            updateBounds(mParent.getBounds());
310df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
3113d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3123d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3133d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideTop attribute.
3143d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3153103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> TOP_ABSOLUTE =
3163103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3173103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteTop") {
3183d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3193d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
320e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
321bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().top = ValueRule.absoluteValue(value);
3223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
323e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().top.setAbsoluteValue(value);
3243d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
3253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
3273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3283d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3293d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3303d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
331e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
332738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().top;
333738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
334e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().top.getAbsoluteValue();
3353d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3363d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
3373d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3383d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3393d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideBottom attribute.
3403d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3413103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> BOTTOM_ABSOLUTE =
3423103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3433103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteBottom") {
3443d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3453d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
346e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
347bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().bottom = ValueRule.absoluteValue(value);
3483d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
349e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().bottom.setAbsoluteValue(value);
3503d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
3513d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3523d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
3533d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3543d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3553d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3563d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
357e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
358738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().bottom;
359738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
360e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().bottom.getAbsoluteValue();
3613d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3623d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
3633d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3643d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3653d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3663d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideLeft attribute.
3673d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3683103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> LEFT_ABSOLUTE =
3693103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3703103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteLeft") {
3713d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3723d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
373e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
374bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().left = ValueRule.absoluteValue(value);
3753d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
376e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().left.setAbsoluteValue(value);
3773d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
3783d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3793d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
3803d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3813d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3823d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3833d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
384e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
385738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().left;
386738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
387e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().left.getAbsoluteValue();
3883d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3893d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
3903d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3913d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3923d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideRight attribute.
3933d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3943103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> RIGHT_ABSOLUTE =
3953103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3963103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteRight") {
3973d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3983d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
399e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
400bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().right = ValueRule.absoluteValue(value);
4013d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
402e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().right.setAbsoluteValue(value);
4033d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4043d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4053d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4063d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4073d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4083d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4093d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
410e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
411738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().right;
412738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
413e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().right.getAbsoluteValue();
4143d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
4163d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4173d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
4183d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
4193d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
4203d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
4213d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_TOP_ABSOLUTE} when the exact start/end position of scroll movement
4223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
4233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
4243103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> TOP_FRACTION =
4253103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Float>(Float.class, "fractionTop") {
4263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
428e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
429bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().top = ValueRule.inheritFromParent(value);
4303d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
431e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().top.setFraction(value);
4323d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4333d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4343d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4353d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4363d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4373d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4383d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
439e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
440738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 0f;
441738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
442e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().top.getFraction();
4433d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4443d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
4453d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4463d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
4473d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
4483d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
4493d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
4503d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_BOTTOM_ABSOLUTE} when the exact start/end position of scroll movement
4513d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
4523d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
4533103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> BOTTOM_FRACTION =
4543103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Float>(
4553103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Float.class, "fractionBottom") {
4563d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4573d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
458e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
459bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().bottom = ValueRule.inheritFromParent(value);
4603d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
461e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().bottom.setFraction(value);
4623d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4633d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4643d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4653d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4663d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4673d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4683d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
469e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
470738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 1f;
471738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
472e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().bottom.getFraction();
4733d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4743d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
4753d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4763d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
4773d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
4783d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
4793d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
4803d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_LEFT_ABSOLUTE} when the exact start/end position of scroll movement
4813d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
4823d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
4833103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> LEFT_FRACTION =
4843103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Float>(Float.class, "fractionLeft") {
4853d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4863d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
487e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
488bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().left = ValueRule.inheritFromParent(value);
4893d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
490e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().left.setFraction(value);
4913d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4923d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4933d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4943d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4953d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4963d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4973d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
498e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
499738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 0f;
500738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
501e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().left.getFraction();
5023d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
5033d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
5043d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
5053d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
5063d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
5073d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
5083d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
5093d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_RIGHT_ABSOLUTE} when the exact start/end position of scroll movement
5103d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
5113d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
5123103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> RIGHT_FRACTION =
513bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                new Property<CompositeDrawable.ChildDrawable, Float>(Float.class, "fractionRight") {
5143d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
5153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
516e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
517bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().right = ValueRule.inheritFromParent(value);
5183d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
519e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().right.setFraction(value);
5203d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
5213d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
5223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
5233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
5243d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
5253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
5263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
527e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
528738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 1f;
529738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
530e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().right.getFraction();
5313d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
5323d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
533df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
534df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata}
535