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;
248619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport android.util.Property;
258619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas
26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull;
27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.graphics.drawable.DrawableCompat;
288619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.graphics.BoundsRule.ValueRule;
29df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
30df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport java.util.ArrayList;
31df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
32df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata/**
333d9017263a760990ba79d5ebf3d1b6587e0bd311susnata * Generic drawable class that can be composed of multiple children. Whenever the bounds changes
3444ece5ceaaee232f9139ccbde40ac4a5e642bdeeChristophe Beyls * for this class, it updates those of its children.
35df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata */
363d9017263a760990ba79d5ebf3d1b6587e0bd311susnatapublic class CompositeDrawable extends Drawable implements Drawable.Callback {
3700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
3800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    static class CompositeState extends Drawable.ConstantState {
3900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
4000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> mChildren;
4100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
4200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        CompositeState() {
4300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mChildren = new ArrayList<ChildDrawable>();
4400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
4500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
4600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        CompositeState(CompositeState other, CompositeDrawable parent, Resources res) {
4700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final int n = other.mChildren.size();
4800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mChildren = new ArrayList<ChildDrawable>(n);
4900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            for (int k = 0; k < n; k++) {
5000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                mChildren.add(new ChildDrawable(other.mChildren.get(k), parent, res));
5100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
5200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
5300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
5400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @NonNull
5500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @Override
5600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        public Drawable newDrawable() {
5700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return new CompositeDrawable(this);
5800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
5900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @Override
6100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        public int getChangingConfigurations() {
6200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return 0;
6300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
6400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
6600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    CompositeState mState;
6800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    boolean mMutated = false;
6900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
7000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public CompositeDrawable() {
7100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState = new CompositeState();
7200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
7300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
7400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    CompositeDrawable(CompositeState state) {
7500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState = state;
7600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
7700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
7800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    @Override
7900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public ConstantState getConstantState() {
8000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState;
8100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
8200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
8300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    @Override
8400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public Drawable mutate() {
8500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        if (!mMutated && super.mutate() == this) {
8600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mState = new CompositeState(mState, this, null);
8700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final ArrayList<ChildDrawable> children = mState.mChildren;
8800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            for (int i = 0, n = children.size(); i < n; i++) {
8900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                final Drawable dr = children.get(i).mDrawable;
9000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                if (dr != null) {
9100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                    dr.mutate();
9200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                }
9300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
9400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mMutated = true;
9500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
9600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return this;
9700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
98df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
99df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
100df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Adds the supplied region.
101df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1023d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void addChildDrawable(Drawable drawable) {
10300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState.mChildren.add(new ChildDrawable(drawable, this));
104df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
105df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
106df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
107e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Sets the supplied region at given index.
108e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
109e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public void setChildDrawableAt(int index, Drawable drawable) {
110e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mState.mChildren.set(index, new ChildDrawable(drawable, this));
111e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
112e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
113e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
1143d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Returns the {@link Drawable} for the given index.
115df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1163d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public Drawable getDrawable(int index) {
11700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState.mChildren.get(index).mDrawable;
118df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
119df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
120df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
1213d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Returns the {@link ChildDrawable} at the given index.
122df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public ChildDrawable getChildAt(int index) {
12400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState.mChildren.get(index);
1253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
1263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
1273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    /**
1283d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Removes the child corresponding to the given index.
1293d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     */
1303d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void removeChild(int index) {
13100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mState.mChildren.remove(index);
132df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
133df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
134df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
135df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Removes the given region.
136df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1373d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void removeDrawable(Drawable drawable) {
13800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1393d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1403d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            if (drawable == children.get(i).mDrawable) {
1413d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                children.get(i).mDrawable.setCallback(null);
1423d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                children.remove(i);
1433d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                return;
1443d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
1453d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
146df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
147df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
148df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
1493d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Returns the total number of children.
150df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
1513d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public int getChildCount() {
15200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mState.mChildren.size();
153df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
154df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
155df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
156df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void draw(Canvas canvas) {
15700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1583d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1593d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            children.get(i).mDrawable.draw(canvas);
160df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
161df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
162df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
163df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
164df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    protected void onBoundsChange(Rect bounds) {
165df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        super.onBoundsChange(bounds);
1663d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        updateBounds(bounds);
167df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
168df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
169df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
170df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setColorFilter(ColorFilter colorFilter) {
17100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1723d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1733d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            children.get(i).mDrawable.setColorFilter(colorFilter);
174df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
175df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
176df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
177df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
178df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public int getOpacity() {
179df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        return PixelFormat.UNKNOWN;
180df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
181df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
182df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
183df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setAlpha(int alpha) {
18400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
1853d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
1863d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            children.get(i).mDrawable.setAlpha(alpha);
1873d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
1883d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
1893d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
19000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    /**
19100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu     * @return Alpha value between 0(inclusive) and 255(inclusive)
19200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu     */
193e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas    @Override
19400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public int getAlpha() {
19500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final Drawable dr = getFirstNonNullDrawable();
19600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        if (dr != null) {
19700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return DrawableCompat.getAlpha(dr);
19800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        } else {
19900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return 0xFF;
20000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
20100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
20200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
20300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    final Drawable getFirstNonNullDrawable() {
20400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
20500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        for (int i = 0, n = children.size(); i < n; i++) {
20600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final Drawable dr = children.get(i).mDrawable;
20700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            if (dr != null) {
20800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                return dr;
20900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
21000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
21100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return null;
21200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
21300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
2143d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    @Override
2153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void invalidateDrawable(Drawable who) {
2163d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        invalidateSelf();
2173d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2183d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2193d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    @Override
2203d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void scheduleDrawable(Drawable who, Runnable what, long when) {
2213d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        scheduleSelf(what, when);
2223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2243d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    @Override
2253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public void unscheduleDrawable(Drawable who, Runnable what) {
2263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        unscheduleSelf(what);
2273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2283d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2293d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    /**
2303d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Updates the bounds based on the {@link BoundsRule}.
2313d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     */
2323d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    void updateBounds(Rect bounds) {
23300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final ArrayList<ChildDrawable> children = mState.mChildren;
2343d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        for (int i = 0; i < children.size(); i++) {
2353d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            ChildDrawable childDrawable = children.get(i);
2363d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            childDrawable.updateBounds(bounds);
2373d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2383d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
2393d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2403d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    /**
2413d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Wrapper class holding a drawable object and {@link BoundsRule} to update drawable bounds
2423d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * when parent bound changes.
2433d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     */
2443d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public static final class ChildDrawable {
245450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata        private final BoundsRule mBoundsRule;
2463d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        private final Drawable mDrawable;
2473d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        private final Rect adjustedBounds = new Rect();
248738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu        final CompositeDrawable mParent;
2493d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2503d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        public ChildDrawable(Drawable drawable, CompositeDrawable parent) {
2513d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            this.mDrawable = drawable;
2523d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            this.mParent = parent;
253450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            this.mBoundsRule = new BoundsRule();
25400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            drawable.setCallback(parent);
25500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
25600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
25700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        ChildDrawable(ChildDrawable orig, CompositeDrawable parent, Resources res) {
25800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final Drawable dr = orig.mDrawable;
25900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            final Drawable clone;
26000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            if (dr != null) {
26100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                final ConstantState cs = dr.getConstantState();
26200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                if (res != null) {
26300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                    clone = cs.newDrawable(res);
26400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                } else {
26500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                    clone = cs.newDrawable();
26600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                }
26700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone.setCallback(parent);
26800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                DrawableCompat.setLayoutDirection(clone, DrawableCompat.getLayoutDirection(dr));
26900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone.setBounds(dr.getBounds());
27000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone.setLevel(dr.getLevel());
27100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            } else {
27200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                clone = null;
27300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            }
274450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            if (orig.mBoundsRule != null) {
275450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata                this.mBoundsRule = new BoundsRule(orig.mBoundsRule);
276450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            } else {
277450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata                this.mBoundsRule = new BoundsRule();
278450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            }
27900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mDrawable = clone;
28000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mParent = parent;
2813d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2823d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2833d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
2843d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Returns the instance of {@link BoundsRule}.
2853d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
2863d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        public BoundsRule getBoundsRule() {
287450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            return this.mBoundsRule;
2883d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2893d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2903d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
2913d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Returns the {@link Drawable}.
2923d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
2933d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        public Drawable getDrawable() {
2943d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            return mDrawable;
2953d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
2963d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
2973d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
2983d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Updates the bounds based on the {@link BoundsRule}.
2993d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3003d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        void updateBounds(Rect bounds) {
301450fe7ab2d8a911ecdc335d55c60dfbae70f2407susnata            mBoundsRule.calculateBounds(bounds, adjustedBounds);
3023d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            mDrawable.setBounds(adjustedBounds);
3033d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        }
3043d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
305e464e5647326c000d2bd48e7d4369a279894f360susnata        /**
306e464e5647326c000d2bd48e7d4369a279894f360susnata         * After changing the {@link BoundsRule}, user should call this function
307e464e5647326c000d2bd48e7d4369a279894f360susnata         * for the drawable to recalculate its bounds.
308e464e5647326c000d2bd48e7d4369a279894f360susnata         */
309e464e5647326c000d2bd48e7d4369a279894f360susnata        public void recomputeBounds() {
3103d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            updateBounds(mParent.getBounds());
311df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
3123d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3133d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3143d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideTop attribute.
3153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3163103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> TOP_ABSOLUTE =
3173103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3183103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteTop") {
3193d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3203d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
321e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
322bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().top = ValueRule.absoluteValue(value);
3233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
324e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().top.setAbsoluteValue(value);
3253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
3263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
3283d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3293d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3303d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3313d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
332e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
333738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().top;
334738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
335e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().top.getAbsoluteValue();
3363d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3373d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
3383d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3393d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3403d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideBottom attribute.
3413d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3423103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> BOTTOM_ABSOLUTE =
3433103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3443103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteBottom") {
3453d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3463d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
347e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
348bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().bottom = ValueRule.absoluteValue(value);
3493d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
350e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().bottom.setAbsoluteValue(value);
3513d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
3523d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3533d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
3543d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3553d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3563d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3573d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
358e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
359738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().bottom;
360738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
361e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().bottom.getAbsoluteValue();
3623d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3633d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
3643d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3653d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3663d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3673d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideLeft attribute.
3683d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3693103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> LEFT_ABSOLUTE =
3703103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3713103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteLeft") {
3723d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3733d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
374e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
375bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().left = ValueRule.absoluteValue(value);
3763d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
377e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().left.setAbsoluteValue(value);
3783d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
3793d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3803d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
3813d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3823d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3833d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3843d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
385e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
386738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().left;
387738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
388e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().left.getAbsoluteValue();
3893d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
3903d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
3913d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
3923d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
3933d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overrideRight attribute.
3943d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
3953103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Integer> RIGHT_ABSOLUTE =
3963103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Integer>(
3973103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Integer.class, "absoluteRight") {
3983d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
3993d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Integer value) {
400e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
401bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().right = ValueRule.absoluteValue(value);
4023d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
403e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().right.setAbsoluteValue(value);
4043d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4053d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4063d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4073d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4083d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4093d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4103d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Integer get(CompositeDrawable.ChildDrawable obj) {
411e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
412738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return obj.mParent.getBounds().right;
413738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
414e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().right.getAbsoluteValue();
4153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4163d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
4173d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4183d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
4193d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
4203d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
4213d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
4223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_TOP_ABSOLUTE} when the exact start/end position of scroll movement
4233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
4243d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
4253103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> TOP_FRACTION =
4263103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Float>(Float.class, "fractionTop") {
4273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4283d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
429e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
430bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().top = ValueRule.inheritFromParent(value);
4313d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
432e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().top.setFraction(value);
4333d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4343d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4353d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4363d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4373d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4383d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4393d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
440e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().top == null) {
441738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 0f;
442738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
443e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().top.getFraction();
4443d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4453d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
4463d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4473d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
4483d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
4493d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
4503d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
4513d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_BOTTOM_ABSOLUTE} when the exact start/end position of scroll movement
4523d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
4533d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
4543103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> BOTTOM_FRACTION =
4553103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Float>(
4563103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                        Float.class, "fractionBottom") {
4573d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4583d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
459e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
460bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().bottom = ValueRule.inheritFromParent(value);
4613d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
462e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().bottom.setFraction(value);
4633d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4643d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4653d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4663d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4673d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4683d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4693d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
470e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().bottom == null) {
471738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 1f;
472738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
473e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().bottom.getFraction();
4743d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4753d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
4763d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4773d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
4783d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
4793d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
4803d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
4813d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_LEFT_ABSOLUTE} when the exact start/end position of scroll movement
4823d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
4833d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
4843103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> LEFT_FRACTION =
4853103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                new Property<CompositeDrawable.ChildDrawable, Float>(Float.class, "fractionLeft") {
4863d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4873d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
488e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
489bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().left = ValueRule.inheritFromParent(value);
4903d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
491e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().left.setFraction(value);
4923d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
4933d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4943d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
4953d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
4963d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
4973d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
4983d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
499e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().left == null) {
500738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 0f;
501738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
502e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().left.getFraction();
5033d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
5043d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
5053d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
5063d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        /**
5073d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * Implementation of {@link Property} for overwriting the bottom attribute of
5083d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@link BoundsRule} associated with this {@link ChildDrawable}. This allows users to
5093d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * change the bounds rules as a percentage of parent size. This is preferable over
5103d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * {@see PROPERTY_RIGHT_ABSOLUTE} when the exact start/end position of scroll movement
5113d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         * isn't available at compile time.
5123d9017263a760990ba79d5ebf3d1b6587e0bd311susnata         */
5133103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        public static final Property<CompositeDrawable.ChildDrawable, Float> RIGHT_FRACTION =
514bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                new Property<CompositeDrawable.ChildDrawable, Float>(Float.class, "fractionRight") {
5153d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
5163d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public void set(CompositeDrawable.ChildDrawable obj, Float value) {
517e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
518bf4318c67254bc11307796601b9fb4a8bbfe67b2Dake Gu                    obj.getBoundsRule().right = ValueRule.inheritFromParent(value);
5193d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                } else {
520e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    obj.getBoundsRule().right.setFraction(value);
5213d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                }
5223d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
5233d9017263a760990ba79d5ebf3d1b6587e0bd311susnata                obj.recomputeBounds();
5243d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
5253d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
5263d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            @Override
5273d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            public Float get(CompositeDrawable.ChildDrawable obj) {
528e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                if (obj.getBoundsRule().right == null) {
529738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                    return 1f;
530738deb3f9c75ea32dff1bf335753703e40e87f39Dake Gu                }
531e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return obj.getBoundsRule().right.getFraction();
5323d9017263a760990ba79d5ebf3d1b6587e0bd311susnata            }
5333d9017263a760990ba79d5ebf3d1b6587e0bd311susnata        };
534df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
535df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata}
536