19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viveretteimport android.annotation.NonNull;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport com.android.internal.widget.ScrollBarUtils;
2799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
29029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette * This is only used by View for displaying its scroll bars. It should probably
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be moved in to the view package since it is used in that lower-level layer.
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For now, we'll hide it so it can be cleaned up later.
32029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette *
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
35029d039ea5df180218288f955f96f66d57b74bc3Alan Viverettepublic class ScrollBarDrawable extends Drawable implements Drawable.Callback {
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mVerticalTrack;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mHorizontalTrack;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mVerticalThumb;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mHorizontalThumb;
40029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mRange;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mOffset;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mExtent;
44029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mVertical;
46029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private boolean mBoundsChanged;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mRangeChanged;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAlwaysDrawHorizontalTrack;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAlwaysDrawVerticalTrack;
50f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette    private boolean mMutated;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
52029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private int mAlpha = 255;
53029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private boolean mHasSetAlpha;
54029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
55029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private ColorFilter mColorFilter;
56029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private boolean mHasSetColorFilter;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
59029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * Indicate whether the horizontal scrollbar track should always be drawn
60029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * regardless of the extent. Defaults to false.
61029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     *
62029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @param alwaysDrawTrack Whether the track should always be drawn
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
64029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @see #getAlwaysDrawHorizontalTrack()
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlwaysDrawHorizontalTrack(boolean alwaysDrawTrack) {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAlwaysDrawHorizontalTrack = alwaysDrawTrack;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
71029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * Indicate whether the vertical scrollbar track should always be drawn
72029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * regardless of the extent. Defaults to false.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
74029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @param alwaysDrawTrack Whether the track should always be drawn
75029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     *
76029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @see #getAlwaysDrawVerticalTrack()
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAlwaysDrawVerticalTrack = alwaysDrawTrack;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
83029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @return whether the vertical scrollbar track should always be drawn
84029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     *         regardless of the extent.
85029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     *
86029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @see #setAlwaysDrawVerticalTrack(boolean)
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getAlwaysDrawVerticalTrack() {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAlwaysDrawVerticalTrack;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
93029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @return whether the horizontal scrollbar track should always be drawn
94029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     *         regardless of the extent.
95029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     *
96029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette     * @see #setAlwaysDrawHorizontalTrack(boolean)
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getAlwaysDrawHorizontalTrack() {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAlwaysDrawHorizontalTrack;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setParameters(int range, int offset, int extent, boolean vertical) {
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mVertical != vertical) {
104029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mVertical = vertical;
105029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
106029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mBoundsChanged = true;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRange != range || mOffset != offset || mExtent != extent) {
110029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mRange = range;
111029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mOffset = offset;
112029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mExtent = extent;
113029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRangeChanged = true;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas) {
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean vertical = mVertical;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int extent = mExtent;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int range = mRange;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean drawTrack = true;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean drawThumb = true;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extent <= 0 || range <= extent) {
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            drawTrack = vertical ? mAlwaysDrawVerticalTrack : mAlwaysDrawHorizontalTrack;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            drawThumb = false;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
131029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        final Rect r = getBounds();
1328fb954263dd2f918ad339045cc6d82e346515599Romain Guy        if (canvas.quickReject(r.left, r.top, r.right, r.bottom, Canvas.EdgeType.AA)) {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
135029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (drawTrack) {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            drawTrack(canvas, r, vertical);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (drawThumb) {
141d85bc5074dc1211fdb1c6799d9321af54ac5a32fKeisuke Kuroyanagi            final int scrollBarLength = vertical ? r.height() : r.width();
142029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            final int thickness = vertical ? r.width() : r.height();
143d85bc5074dc1211fdb1c6799d9321af54ac5a32fKeisuke Kuroyanagi            final int thumbLength =
144d85bc5074dc1211fdb1c6799d9321af54ac5a32fKeisuke Kuroyanagi                    ScrollBarUtils.getThumbLength(scrollBarLength, thickness, extent, range);
145d85bc5074dc1211fdb1c6799d9321af54ac5a32fKeisuke Kuroyanagi            final int thumbOffset =
146d85bc5074dc1211fdb1c6799d9321af54ac5a32fKeisuke Kuroyanagi                    ScrollBarUtils.getThumbOffset(scrollBarLength, thumbLength, extent, range,
147d85bc5074dc1211fdb1c6799d9321af54ac5a32fKeisuke Kuroyanagi                            mOffset);
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
149d85bc5074dc1211fdb1c6799d9321af54ac5a32fKeisuke Kuroyanagi            drawThumb(canvas, r, thumbOffset, thumbLength, vertical);
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect bounds) {
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onBoundsChange(bounds);
156029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        mBoundsChanged = true;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
159029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    @Override
160029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    public boolean isStateful() {
161029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        return (mVerticalTrack != null && mVerticalTrack.isStateful())
162029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                || (mVerticalThumb != null && mVerticalThumb.isStateful())
163029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                || (mHorizontalTrack != null && mHorizontalTrack.isStateful())
164029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                || (mHorizontalThumb != null && mHorizontalThumb.isStateful())
165029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                || super.isStateful();
166029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    }
167029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
168029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    @Override
169029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    protected boolean onStateChange(int[] state) {
170029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        boolean changed = super.onStateChange(state);
171029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mVerticalTrack != null) {
172029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            changed |= mVerticalTrack.setState(state);
173029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        }
174029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mVerticalThumb != null) {
175029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            changed |= mVerticalThumb.setState(state);
176029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        }
177029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mHorizontalTrack != null) {
178029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            changed |= mHorizontalTrack.setState(state);
179029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        }
180029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mHorizontalThumb != null) {
181029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            changed |= mHorizontalThumb.setState(state);
182029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        }
183029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        return changed;
184029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    }
185029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
186029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private void drawTrack(Canvas canvas, Rect bounds, boolean vertical) {
187029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        final Drawable track;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (vertical) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            track = mVerticalTrack;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            track = mHorizontalTrack;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
193029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (track != null) {
195029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            if (mBoundsChanged) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                track.setBounds(bounds);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            track.draw(canvas);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
202029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) {
203029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        final boolean changed = mRangeChanged || mBoundsChanged;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (vertical) {
2056c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            if (mVerticalThumb != null) {
2066c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase                final Drawable thumb = mVerticalThumb;
207029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                if (changed) {
208029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                    thumb.setBounds(bounds.left, bounds.top + offset,
209029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                            bounds.right, bounds.top + offset + length);
210029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                }
211029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
2126c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase                thumb.draw(canvas);
2136c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2156c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            if (mHorizontalThumb != null) {
2166c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase                final Drawable thumb = mHorizontalThumb;
217029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                if (changed) {
218029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                    thumb.setBounds(bounds.left + offset, bounds.top,
219029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                            bounds.left + offset + length, bounds.bottom);
220029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                }
221029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
2226c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase                thumb.draw(canvas);
2236c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setVerticalThumbDrawable(Drawable thumb) {
228029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mVerticalThumb != null) {
229029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mVerticalThumb.setCallback(null);
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
231029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
232029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        propagateCurrentState(thumb);
233029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        mVerticalThumb = thumb;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setVerticalTrackDrawable(Drawable track) {
237029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mVerticalTrack != null) {
238029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mVerticalTrack.setCallback(null);
23903748a5707fe3d1f071226ea3caf571abdc0d25dAlan Viverette        }
240029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
241029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        propagateCurrentState(track);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVerticalTrack = track;
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setHorizontalThumbDrawable(Drawable thumb) {
246029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mHorizontalThumb != null) {
247029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mHorizontalThumb.setCallback(null);
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
249029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
250029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        propagateCurrentState(thumb);
251029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        mHorizontalThumb = thumb;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setHorizontalTrackDrawable(Drawable track) {
255029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (mHorizontalTrack != null) {
256029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            mHorizontalTrack.setCallback(null);
25703748a5707fe3d1f071226ea3caf571abdc0d25dAlan Viverette        }
258029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
259029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        propagateCurrentState(track);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHorizontalTrack = track;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
263029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    private void propagateCurrentState(Drawable d) {
264029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        if (d != null) {
265f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            if (mMutated) {
266b989c5561ea10e623d73e7bb89b37ac38ccdd908Alan Viverette                d.mutate();
267b989c5561ea10e623d73e7bb89b37ac38ccdd908Alan Viverette            }
268b989c5561ea10e623d73e7bb89b37ac38ccdd908Alan Viverette
269029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            d.setState(getState());
270029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            d.setCallback(this);
271029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
272029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            if (mHasSetAlpha) {
273029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                d.setAlpha(mAlpha);
274029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            }
275029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
276029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            if (mHasSetColorFilter) {
277029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette                d.setColorFilter(mColorFilter);
278029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette            }
279029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        }
280029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    }
281029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSize(boolean vertical) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (vertical) {
2846c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            return mVerticalTrack != null ? mVerticalTrack.getIntrinsicWidth() :
2856c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase                    mVerticalThumb != null ? mVerticalThumb.getIntrinsicWidth() : 0;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2876c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            return mHorizontalTrack != null ? mHorizontalTrack.getIntrinsicHeight() :
2886c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase                    mHorizontalThumb != null ? mHorizontalThumb.getIntrinsicHeight() : 0;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
293f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette    public ScrollBarDrawable mutate() {
294f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette        if (!mMutated && super.mutate() == this) {
295f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            if (mVerticalTrack != null) {
296f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette                mVerticalTrack.mutate();
297f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            }
298f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            if (mVerticalThumb != null) {
299f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette                mVerticalThumb.mutate();
300f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            }
301f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            if (mHorizontalTrack != null) {
302f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette                mHorizontalTrack.mutate();
303f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            }
304f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            if (mHorizontalThumb != null) {
305f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette                mHorizontalThumb.mutate();
306f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            }
307f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette            mMutated = true;
308f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette        }
309f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette        return this;
310f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette    }
311f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette
312f8512ce08174426dfbba96e8108e5a64332f1e71Alan Viverette    @Override
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
314029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        mAlpha = alpha;
315029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        mHasSetAlpha = true;
316029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mVerticalTrack != null) {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVerticalTrack.setAlpha(alpha);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3206c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        if (mVerticalThumb != null) {
3216c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            mVerticalThumb.setAlpha(alpha);
3226c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        }
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mHorizontalTrack != null) {
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHorizontalTrack.setAlpha(alpha);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3266c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        if (mHorizontalThumb != null) {
3276c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase            mHorizontalThumb.setAlpha(alpha);
3286c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
332b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
333029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        return mAlpha;
334b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
335b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
336b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
337bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik    public void setColorFilter(ColorFilter colorFilter) {
338bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik        mColorFilter = colorFilter;
339029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        mHasSetColorFilter = true;
340029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mVerticalTrack != null) {
342bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mVerticalTrack.setColorFilter(colorFilter);
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3446c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        if (mVerticalThumb != null) {
345bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mVerticalThumb.setColorFilter(colorFilter);
3466c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mHorizontalTrack != null) {
348bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mHorizontalTrack.setColorFilter(colorFilter);
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3506c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        if (mHorizontalThumb != null) {
351bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mHorizontalThumb.setColorFilter(colorFilter);
3526c8fef7fb866d244486a962dd82f4a6f26505f16Chet Haase        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
356029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    public ColorFilter getColorFilter() {
357029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        return mColorFilter;
358029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    }
359029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
360029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    @Override
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return PixelFormat.TRANSLUCENT;
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
366f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void invalidateDrawable(@NonNull Drawable who) {
367029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        invalidateSelf();
368029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    }
369029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
370029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    @Override
371f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
372029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        scheduleSelf(what, when);
373029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    }
374029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
375029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    @Override
376f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
377029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette        unscheduleSelf(what);
378029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    }
379029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette
380029d039ea5df180218288f955f96f66d57b74bc3Alan Viverette    @Override
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset +
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               " extent=" + mExtent + (mVertical ? " V" : " H");
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
388