1091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes/*
2091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * Copyright (C) 2015 The Android Open Source Project
3091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *
4091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * you may not use this file except in compliance with the License.
6091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * You may obtain a copy of the License at
7091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *
8091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *      http://www.apache.org/licenses/LICENSE-2.0
9091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *
10091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * Unless required by applicable law or agreed to in writing, software
11091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * See the License for the specific language governing permissions and
14091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * limitations under the License.
15091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes */
16091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
17091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banespackage android.support.v4.widget;
18091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
19091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.content.Context;
20091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.content.res.ColorStateList;
21091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.graphics.Canvas;
22091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.graphics.PorterDuff;
23091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.graphics.drawable.Drawable;
24091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.os.Build;
25091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.support.annotation.NonNull;
26091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.support.annotation.Nullable;
27091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.support.v4.graphics.drawable.DrawableCompat;
28091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.widget.CompoundButton;
29091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
30091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes/**
31091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * Helper for accessing {@link android.widget.CompoundButton} methods introduced after
32091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * API level 4 in a backwards compatible fashion.
33091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes */
34091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banespublic final class CompoundButtonCompat {
35091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
36091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    private static final CompoundButtonCompatImpl IMPL;
37091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
38091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    static {
39091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        final int sdk = Build.VERSION.SDK_INT;
40080abff1400d6461206a6dc367411115590abda9Adam Powell        if (sdk >= 23) {
41091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            IMPL = new Api23CompoundButtonImpl();
42091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        } else if (sdk >= 21) {
43091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            IMPL = new LollipopCompoundButtonImpl();
44091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        } else {
45091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            IMPL = new BaseCompoundButtonCompat();
46091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
47091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
48091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
49091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    interface CompoundButtonCompatImpl {
50091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        void setButtonTintList(CompoundButton button, ColorStateList tint);
51091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        ColorStateList getButtonTintList(CompoundButton button);
52091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode);
53091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        PorterDuff.Mode getButtonTintMode(CompoundButton button);
54091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        Drawable getButtonDrawable(CompoundButton button);
55091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
56091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
57091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    static class BaseCompoundButtonCompat implements CompoundButtonCompatImpl {
58091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
59091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public void setButtonTintList(CompoundButton button, ColorStateList tint) {
60091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            CompoundButtonCompatDonut.setButtonTintList(button, tint);
61091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
62091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
63091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
64091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public ColorStateList getButtonTintList(CompoundButton button) {
65091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            return CompoundButtonCompatDonut.getButtonTintList(button);
66091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
67091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
68091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
69091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode) {
70091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            CompoundButtonCompatDonut.setButtonTintMode(button, tintMode);
71091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
72091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
73091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
74091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public PorterDuff.Mode getButtonTintMode(CompoundButton button) {
75091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            return CompoundButtonCompatDonut.getButtonTintMode(button);
76091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
77091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
78091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
79091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public Drawable getButtonDrawable(CompoundButton button) {
80091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            return CompoundButtonCompatDonut.getButtonDrawable(button);
81091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
82091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
83091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
84091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    static class LollipopCompoundButtonImpl extends BaseCompoundButtonCompat {
85091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
86091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public void setButtonTintList(CompoundButton button, ColorStateList tint) {
87091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            CompoundButtonCompatLollipop.setButtonTintList(button, tint);
88091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
89091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
90091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
91091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public ColorStateList getButtonTintList(CompoundButton button) {
92091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            return CompoundButtonCompatLollipop.getButtonTintList(button);
93091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
94091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
95091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
96091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode) {
97091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            CompoundButtonCompatLollipop.setButtonTintMode(button, tintMode);
98091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
99091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
100091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
101091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public PorterDuff.Mode getButtonTintMode(CompoundButton button) {
102091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            return CompoundButtonCompatLollipop.getButtonTintMode(button);
103091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
104091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
105091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
106091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    static class Api23CompoundButtonImpl extends LollipopCompoundButtonImpl {
107091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        @Override
108091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        public Drawable getButtonDrawable(CompoundButton button) {
109091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            return CompoundButtonCompatApi23.getButtonDrawable(button);
110091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
111091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
112091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
113091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    private CompoundButtonCompat() {}
114091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
115091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    /**
116091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * Applies a tint to the button drawable. Does not modify the current tint
117091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
118091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * <p>
119091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * Subsequent calls to {@link CompoundButton#setButtonDrawable(Drawable)} should
120091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * automatically mutate the drawable and apply the specified tint and tint
121091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * mode using {@link DrawableCompat#setTintList(Drawable, ColorStateList)}.
122091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *
123091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @param tint the tint to apply, may be {@code null} to clear tint
124091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *
125091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @see #setButtonTintList(CompoundButton, ColorStateList)
126091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     */
127091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public static void setButtonTintList(@NonNull CompoundButton button, @Nullable ColorStateList tint) {
128091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        IMPL.setButtonTintList(button, tint);
129091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
130091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
131091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    /**
132091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * Returns the tint applied to the button drawable
133091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *
134091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @see #setButtonTintList(CompoundButton, ColorStateList)
135091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     */
136091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    @Nullable
137091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public static ColorStateList getButtonTintList(@NonNull CompoundButton button) {
138091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        return IMPL.getButtonTintList(button);
139091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
140091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
141091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    /**
142091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * Specifies the blending mode used to apply the tint specified by
143091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * {@link #setButtonTintList(CompoundButton, ColorStateList)}} to the button drawable. The
144091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * default mode is {@link PorterDuff.Mode#SRC_IN}.
145091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *
146091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @param tintMode the blending mode used to apply the tint, may be
147091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *                 {@code null} to clear tint
148091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *
149091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @see #getButtonTintMode(CompoundButton)
150091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @see DrawableCompat#setTintMode(Drawable, PorterDuff.Mode)
151091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     */
152091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public static void setButtonTintMode(@NonNull CompoundButton button,
153091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            @Nullable PorterDuff.Mode tintMode) {
154091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        IMPL.setButtonTintMode(button, tintMode);
155091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
156091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
157091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    /**
158091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @return the blending mode used to apply the tint to the button drawable
159091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @attr ref android.R.styleable#CompoundButton_buttonTintMode
160091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @see #setButtonTintMode(PorterDuff.Mode)
161091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     */
162091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    @Nullable
163091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public static PorterDuff.Mode getButtonTintMode(@NonNull CompoundButton button) {
164091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        return IMPL.getButtonTintMode(button);
165091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
166091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes
167091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    /**
168091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * Returns the drawable used as the compound button image
169091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *
170091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * @see CompoundButton#setButtonDrawable(Drawable)
171091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     */
172091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    @Nullable
173091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public static Drawable getButtonDrawable(@NonNull CompoundButton button) {
174091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        return IMPL.getButtonDrawable(button);
175091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    }
176091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes}
177