Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 package android.support.wearable.view;
     17 
     18 import android.app.AlertDialog;
     19 import android.content.Context;
     20 import android.content.DialogInterface;
     21 import android.content.res.Resources;
     22 import android.graphics.drawable.Drawable;
     23 import android.support.annotation.DrawableRes;
     24 import android.support.annotation.NonNull;
     25 import android.support.annotation.Nullable;
     26 import android.support.annotation.VisibleForTesting;
     27 import android.util.Log;
     28 import android.widget.Button;
     29 
     30 /**
     31  * Helper to add icons to AlertDialog buttons.AlertDialog buttons.
     32  */
     33 public class WearableDialogHelper {
     34     private static final String TAG = "WearableDialogHelper";
     35 
     36     private int mPositiveIconId;
     37     private Drawable mPositiveIcon;
     38 
     39     private int mNeutralIconId;
     40     private Drawable mNeutralIcon;
     41 
     42     private int mNegativeIconId;
     43     private Drawable mNegativeIcon;
     44 
     45     @VisibleForTesting /* package */ Resources mResources;
     46     @VisibleForTesting /* package */ Resources.Theme mTheme;
     47 
     48     /**
     49      * Convenience constructor, equivalent to {@code new WearableDialogHelper(context.getResources(),
     50      * context.getTheme())}.
     51      */
     52     public WearableDialogHelper(@NonNull Context context) {
     53         this(context.getResources(), context.getTheme());
     54     }
     55 
     56     /**
     57      * @param resources the Resources used to obtain Drawables from resource IDs.
     58      * @param theme the Theme used to properly obtain Drawables from resource IDs.
     59      */
     60     public WearableDialogHelper(@NonNull Resources resources, @NonNull Resources.Theme theme) {
     61         mResources = resources;
     62         mTheme = theme;
     63     }
     64 
     65     @Nullable
     66     public Drawable getPositiveIcon() {
     67         return resolveDrawable(mPositiveIcon, mPositiveIconId);
     68     }
     69 
     70     @Nullable
     71     public Drawable getNegativeIcon() {
     72         return resolveDrawable(mNegativeIcon, mNegativeIconId);
     73     }
     74 
     75     @Nullable
     76     public Drawable getNeutralIcon() {
     77         return resolveDrawable(mNeutralIcon, mNeutralIconId);
     78     }
     79 
     80     @NonNull
     81     public WearableDialogHelper setPositiveIcon(@DrawableRes int resId) {
     82         mPositiveIconId = resId;
     83         mPositiveIcon = null;
     84         return this;
     85     }
     86 
     87     @NonNull
     88     public WearableDialogHelper setPositiveIcon(@Nullable Drawable icon) {
     89         mPositiveIcon = icon;
     90         mPositiveIconId = 0;
     91         return this;
     92     }
     93 
     94     @NonNull
     95     public WearableDialogHelper setNegativeIcon(@DrawableRes int resId) {
     96         mNegativeIconId = resId;
     97         mNegativeIcon = null;
     98         return this;
     99     }
    100 
    101     @NonNull
    102     public WearableDialogHelper setNegativeIcon(@Nullable Drawable icon) {
    103         mNegativeIcon = icon;
    104         mNegativeIconId = 0;
    105         return this;
    106     }
    107 
    108     @NonNull
    109     public WearableDialogHelper setNeutralIcon(@DrawableRes int resId) {
    110         mNeutralIconId = resId;
    111         mNeutralIcon = null;
    112         return this;
    113     }
    114 
    115     @NonNull
    116     public WearableDialogHelper setNeutralIcon(@Nullable Drawable icon) {
    117         mNeutralIcon = icon;
    118         mNeutralIconId = 0;
    119         return this;
    120     }
    121 
    122     /**
    123      * Applies the button icons setup in the helper to the buttons in the dialog.
    124      *
    125      * <p>Note that this should be called after {@code AlertDialog.create()}, NOT {@code
    126      * AlertDialog.Builder.create()}. Calling {@code AlertDialog.Builder.show()} would also accomplish
    127      * the same thing.
    128      *
    129      * @param dialog the AlertDialog to style with the helper.
    130      */
    131     public void apply(@NonNull AlertDialog dialog) {
    132         applyButton(dialog.getButton(DialogInterface.BUTTON_POSITIVE), getPositiveIcon());
    133         applyButton(dialog.getButton(DialogInterface.BUTTON_NEGATIVE), getNegativeIcon());
    134         applyButton(dialog.getButton(DialogInterface.BUTTON_NEUTRAL), getNeutralIcon());
    135     }
    136 
    137     /** Applies the specified drawable to the button. */
    138     @VisibleForTesting
    139     /* package */ void applyButton(@Nullable Button button, @Nullable Drawable drawable) {
    140         if (button != null) {
    141             button.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null);
    142             button.setAllCaps(false);
    143         } else if (drawable != null) {
    144             Log.w(TAG, "non-null drawable used with missing button, did you call AlertDialog.create()?");
    145         }
    146     }
    147 
    148     /** Obtain a drawable between a drawable and a resource ID. */
    149     @VisibleForTesting
    150     /* package */ Drawable resolveDrawable(@Nullable Drawable drawable, @DrawableRes int resId) {
    151         return drawable == null && resId != 0 ? mResources.getDrawable(resId, mTheme) : drawable;
    152     }
    153 
    154     /** Convenience builder to generate an AlertDialog with icons in buttons. */
    155     public static class DialogBuilder extends AlertDialog.Builder {
    156         private final WearableDialogHelper mHelper;
    157 
    158         public DialogBuilder(Context context) {
    159             super(context);
    160             mHelper = new WearableDialogHelper(context.getResources(), context.getTheme());
    161         }
    162 
    163         public DialogBuilder(Context context, int themeResId) {
    164             super(context, themeResId);
    165             mHelper = new WearableDialogHelper(context.getResources(), context.getTheme());
    166         }
    167 
    168         public WearableDialogHelper getHelper() {
    169             return mHelper;
    170         }
    171 
    172         public DialogBuilder setPositiveIcon(@DrawableRes int iconId) {
    173             mHelper.setPositiveIcon(iconId);
    174             return this;
    175         }
    176 
    177         public DialogBuilder setPositiveIcon(@Nullable Drawable icon) {
    178             mHelper.setPositiveIcon(icon);
    179             return this;
    180         }
    181 
    182         public DialogBuilder setNegativeIcon(@DrawableRes int iconId) {
    183             mHelper.setNegativeIcon(iconId);
    184             return this;
    185         }
    186 
    187         public DialogBuilder setNegativeIcon(@Nullable Drawable icon) {
    188             mHelper.setNegativeIcon(icon);
    189             return this;
    190         }
    191 
    192         public DialogBuilder setNeutralIcon(@DrawableRes int iconId) {
    193             mHelper.setNeutralIcon(iconId);
    194             return this;
    195         }
    196 
    197         public DialogBuilder setNeutralIcon(@Nullable Drawable icon) {
    198             mHelper.setNeutralIcon(icon);
    199             return this;
    200         }
    201 
    202         @Override
    203         public AlertDialog create() {
    204             final AlertDialog dialog = super.create();
    205             dialog.create();
    206             mHelper.apply(dialog);
    207             return dialog;
    208         }
    209 
    210         @Override
    211         public AlertDialog show() {
    212             final AlertDialog dialog = this.create();
    213             dialog.show();
    214             return dialog;
    215         }
    216     }
    217 }
    218