1a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes/*
2a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * Copyright (C) 2014 The Android Open Source Project
3a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes *
4a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * you may not use this file except in compliance with the License.
6a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * You may obtain a copy of the License at
7a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes *
8a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
9a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes *
10a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * Unless required by applicable law or agreed to in writing, software
11a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * See the License for the specific language governing permissions and
14a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes * limitations under the License.
15a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes */
16a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
172cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banespackage android.support.v7.widget;
18a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
19a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banesimport android.content.Context;
20a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banesimport android.content.res.ColorStateList;
21a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banesimport android.graphics.PorterDuff;
22684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banesimport android.graphics.drawable.Drawable;
23091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.support.annotation.DrawableRes;
24a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banesimport android.support.annotation.Nullable;
25a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banesimport android.support.v4.view.TintableBackgroundView;
262cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banesimport android.support.v7.appcompat.R;
272cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banesimport android.support.v7.internal.text.AllCapsTransformationMethod;
282cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banesimport android.support.v7.internal.widget.TintManager;
29a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banesimport android.util.AttributeSet;
302cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banesimport android.view.accessibility.AccessibilityEvent;
312cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banesimport android.view.accessibility.AccessibilityNodeInfo;
32a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banesimport android.widget.Button;
33a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
34a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes/**
35091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * A {@link Button} which supports compatible features on older version of the platform,
36091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * including:
37091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * <ul>
38091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *     <li>Supports {@link R.attr#textAllCaps} style attribute which works back to
39091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *     {@link android.os.Build.VERSION_CODES#ECLAIR_MR1 Eclair MR1}.</li>
40091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *     <li>Allows dynamic tint of it background via the background tint methods in
41091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *     {@link android.support.v4.view.ViewCompat}.</li>
42091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *     <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
43091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *     {@link R.attr#backgroundTintMode}.</li>
44091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * </ul>
45091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes *
46091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * <p>This will automatically be used when you use {@link android.widget.Button} in your
47091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * layouts. You should only need to manually use this class when writing custom views.</p>
48a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes */
492cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banespublic class AppCompatButton extends Button implements TintableBackgroundView {
50a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
51091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    private final TintManager mTintManager;
52091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    private final AppCompatBackgroundHelper mBackgroundTintHelper;
53091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    private final AppCompatTextHelper mTextHelper;
54a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
552cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    public AppCompatButton(Context context) {
56a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes        this(context, null);
57a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes    }
58a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
592cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    public AppCompatButton(Context context, AttributeSet attrs) {
602cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes        this(context, attrs, R.attr.buttonStyle);
61a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes    }
62a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
632cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    public AppCompatButton(Context context, AttributeSet attrs, int defStyleAttr) {
64a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes        super(context, attrs, defStyleAttr);
65a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
66091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        mTintManager = TintManager.get(getContext());
67091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        mBackgroundTintHelper = new AppCompatBackgroundHelper(this, mTintManager);
68091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
69a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes
70091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        mTextHelper = new AppCompatTextHelper(this);
71091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        mTextHelper.loadFromAttributes(attrs, defStyleAttr);
72a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    }
73a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
74684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes    @Override
75091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public void setBackgroundResource(@DrawableRes int resId) {
76684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes        super.setBackgroundResource(resId);
77091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        if (mBackgroundTintHelper != null) {
78091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            mBackgroundTintHelper.onSetBackgroundResource(resId);
79091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
80684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes    }
81684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes
82684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes    @Override
83684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes    public void setBackgroundDrawable(Drawable background) {
84684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes        super.setBackgroundDrawable(background);
85091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        if (mBackgroundTintHelper != null) {
86091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            mBackgroundTintHelper.onSetBackgroundDrawable(background);
87091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        }
88684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes    }
89684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes
90a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    /**
91a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * This should be accessed via
92091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
93a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     *
94a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * @hide
95a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     */
96a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    @Override
97a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
98091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        if (mBackgroundTintHelper != null) {
99091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            mBackgroundTintHelper.setSupportBackgroundTintList(tint);
100fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes        }
101a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    }
102a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes
103a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    /**
104a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * This should be accessed via
105a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * {@link android.support.v4.view.ViewCompat#getBackgroundTintList(android.view.View)}
106a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     *
107a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * @hide
108a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     */
109a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    @Override
110a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    @Nullable
111a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    public ColorStateList getSupportBackgroundTintList() {
112091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        return mBackgroundTintHelper != null
113091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes                ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
114a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes    }
115a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes
116a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    /**
117a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * This should be accessed via
118091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
119a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     *
120a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * @hide
121a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     */
122a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes    @Override
123a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
124091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        if (mBackgroundTintHelper != null) {
125091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
126a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes        }
127a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    }
128a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes
129a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    /**
130a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * This should be accessed via
131a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * {@link android.support.v4.view.ViewCompat#getBackgroundTintMode(android.view.View)}
132a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     *
133a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     * @hide
134a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes     */
135a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    @Override
136a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    @Nullable
137a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    public PorterDuff.Mode getSupportBackgroundTintMode() {
138091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        return mBackgroundTintHelper != null
139091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes                ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
140a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    }
141a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes
142a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    @Override
143a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes    protected void drawableStateChanged() {
144a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes        super.drawableStateChanged();
145091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        if (mBackgroundTintHelper != null) {
146091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            mBackgroundTintHelper.applySupportBackgroundTint();
147684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes        }
148684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes    }
149684dbfaf7105761b5a19a82e8273ed79d3b0641eChris Banes
150091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    @Override
151091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public void setTextAppearance(Context context, int resId) {
152091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        super.setTextAppearance(context, resId);
153091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        if (mTextHelper != null) {
154091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            mTextHelper.onSetTextAppearance(context, resId);
155fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes        }
156a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes    }
157a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes
1582cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    @Override
1592cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
1602cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes        super.onInitializeAccessibilityEvent(event);
1612cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes        event.setClassName(Button.class.getName());
1622cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    }
1632cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes
1642cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    @Override
1652cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
1662cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes        super.onInitializeAccessibilityNodeInfo(info);
1672cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes        info.setClassName(Button.class.getName());
1682cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    }
1692cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes
170091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    /**
171091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * Sets the properties of this field to transform input to ALL CAPS
172091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * display. This may use a "small caps" formatting if available.
173091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * This setting will be ignored if this field is editable or selectable.
174091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     *
175091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * This call replaces the current transformation method. Disabling this
176091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * will not necessarily restore the previous behavior from before this
177091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     * was enabled.
178091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes     */
179091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes    public void setSupportAllCaps(boolean allCaps) {
180091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes        if (mTextHelper != null) {
181091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes            mTextHelper.setAllCaps(allCaps);
1822cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes        }
1832cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes    }
184a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes}
185