Home | History | Annotate | Download | only in notification
      1 /*
      2  * Copyright (C) 2015 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 
     17 package com.android.settings.notification;
     18 
     19 import static com.android.settings.notification.ZenModeScheduleDaysSelection.DAYS;
     20 
     21 import android.app.AlertDialog;
     22 import android.app.Dialog;
     23 import android.app.DialogFragment;
     24 import android.app.FragmentManager;
     25 import android.app.TimePickerDialog;
     26 import android.content.Context;
     27 import android.content.DialogInterface;
     28 import android.content.DialogInterface.OnDismissListener;
     29 import android.os.Bundle;
     30 import android.preference.Preference;
     31 import android.preference.Preference.OnPreferenceClickListener;
     32 import android.preference.PreferenceScreen;
     33 import android.provider.Settings;
     34 import android.service.notification.ZenModeConfig;
     35 import android.service.notification.ZenModeConfig.ScheduleInfo;
     36 import android.service.notification.ZenModeConfig.ZenRule;
     37 import android.text.format.DateFormat;
     38 import android.util.Log;
     39 import android.widget.TimePicker;
     40 
     41 import com.android.internal.logging.MetricsLogger;
     42 import com.android.settings.R;
     43 
     44 import java.text.SimpleDateFormat;
     45 import java.util.Arrays;
     46 import java.util.Calendar;
     47 
     48 public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
     49     private static final String KEY_DAYS = "days";
     50     private static final String KEY_START_TIME = "start_time";
     51     private static final String KEY_END_TIME = "end_time";
     52 
     53     public static final String ACTION = Settings.ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS;
     54 
     55     // per-instance to ensure we're always using the current locale
     56     private final SimpleDateFormat mDayFormat = new SimpleDateFormat("EEE");
     57 
     58     private Preference mDays;
     59     private TimePickerPreference mStart;
     60     private TimePickerPreference mEnd;
     61 
     62     private ScheduleInfo mSchedule;
     63 
     64     @Override
     65     protected boolean setRule(ZenRule rule) {
     66         mSchedule = rule != null ? ZenModeConfig.tryParseScheduleConditionId(rule.conditionId)
     67                 : null;
     68         return mSchedule != null;
     69     }
     70 
     71     @Override
     72     protected String getZenModeDependency() {
     73         return mDays.getKey();
     74     }
     75 
     76     @Override
     77     protected int getEnabledToastText() {
     78         return R.string.zen_schedule_rule_enabled_toast;
     79     }
     80 
     81     @Override
     82     protected void onCreateInternal() {
     83         addPreferencesFromResource(R.xml.zen_mode_schedule_rule_settings);
     84         final PreferenceScreen root = getPreferenceScreen();
     85 
     86         mDays = root.findPreference(KEY_DAYS);
     87         mDays.setOnPreferenceClickListener(new OnPreferenceClickListener() {
     88             @Override
     89             public boolean onPreferenceClick(Preference preference) {
     90                 showDaysDialog();
     91                 return true;
     92             }
     93         });
     94 
     95         final FragmentManager mgr = getFragmentManager();
     96 
     97         mStart = new TimePickerPreference(mContext, mgr);
     98         mStart.setKey(KEY_START_TIME);
     99         mStart.setTitle(R.string.zen_mode_start_time);
    100         mStart.setCallback(new TimePickerPreference.Callback() {
    101             @Override
    102             public boolean onSetTime(final int hour, final int minute) {
    103                 if (mDisableListeners) return true;
    104                 if (!ZenModeConfig.isValidHour(hour)) return false;
    105                 if (!ZenModeConfig.isValidMinute(minute)) return false;
    106                 if (hour == mSchedule.startHour && minute == mSchedule.startMinute) {
    107                     return true;
    108                 }
    109                 if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute);
    110                 mSchedule.startHour = hour;
    111                 mSchedule.startMinute = minute;
    112                 updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
    113                 return true;
    114             }
    115         });
    116         root.addPreference(mStart);
    117         mStart.setDependency(mDays.getKey());
    118 
    119         mEnd = new TimePickerPreference(mContext, mgr);
    120         mEnd.setKey(KEY_END_TIME);
    121         mEnd.setTitle(R.string.zen_mode_end_time);
    122         mEnd.setCallback(new TimePickerPreference.Callback() {
    123             @Override
    124             public boolean onSetTime(final int hour, final int minute) {
    125                 if (mDisableListeners) return true;
    126                 if (!ZenModeConfig.isValidHour(hour)) return false;
    127                 if (!ZenModeConfig.isValidMinute(minute)) return false;
    128                 if (hour == mSchedule.endHour && minute == mSchedule.endMinute) {
    129                     return true;
    130                 }
    131                 if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute);
    132                 mSchedule.endHour = hour;
    133                 mSchedule.endMinute = minute;
    134                 updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
    135                 return true;
    136             }
    137         });
    138         root.addPreference(mEnd);
    139         mEnd.setDependency(mDays.getKey());
    140     }
    141 
    142     private void updateDays() {
    143         // Compute an ordered, delimited list of day names based on the persisted user config.
    144         final int[] days = mSchedule.days;
    145         if (days != null && days.length > 0) {
    146             final StringBuilder sb = new StringBuilder();
    147             final Calendar c = Calendar.getInstance();
    148             for (int i = 0; i < DAYS.length; i++) {
    149                 final int day = DAYS[i];
    150                 for (int j = 0; j < days.length; j++) {
    151                     if (day == days[j]) {
    152                         c.set(Calendar.DAY_OF_WEEK, day);
    153                         if (sb.length() > 0) {
    154                             sb.append(mContext.getString(R.string.summary_divider_text));
    155                         }
    156                         sb.append(mDayFormat.format(c.getTime()));
    157                         break;
    158                     }
    159                 }
    160             }
    161             if (sb.length() > 0) {
    162                 mDays.setSummary(sb);
    163                 mDays.notifyDependencyChange(false);
    164                 return;
    165             }
    166         }
    167         mDays.setSummary(R.string.zen_mode_schedule_rule_days_none);
    168         mDays.notifyDependencyChange(true);
    169     }
    170 
    171     private void updateEndSummary() {
    172         final int startMin = 60 * mSchedule.startHour + mSchedule.startMinute;
    173         final int endMin = 60 * mSchedule.endHour + mSchedule.endMinute;
    174         final boolean nextDay = startMin >= endMin;
    175         final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0;
    176         mEnd.setSummaryFormat(summaryFormat);
    177     }
    178 
    179     @Override
    180     protected void updateControlsInternal() {
    181         updateDays();
    182         mStart.setTime(mSchedule.startHour, mSchedule.startMinute);
    183         mEnd.setTime(mSchedule.endHour, mSchedule.endMinute);
    184         updateEndSummary();
    185     }
    186 
    187     @Override
    188     protected int getMetricsCategory() {
    189         return MetricsLogger.NOTIFICATION_ZEN_MODE_SCHEDULE_RULE;
    190     }
    191 
    192     private void showDaysDialog() {
    193         new AlertDialog.Builder(mContext)
    194                 .setTitle(R.string.zen_mode_schedule_rule_days)
    195                 .setView(new ZenModeScheduleDaysSelection(mContext, mSchedule.days) {
    196                       @Override
    197                       protected void onChanged(final int[] days) {
    198                           if (mDisableListeners) return;
    199                           if (Arrays.equals(days, mSchedule.days)) return;
    200                           if (DEBUG) Log.d(TAG, "days.onChanged days=" + Arrays.asList(days));
    201                           mSchedule.days = days;
    202                           updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
    203                       }
    204                 })
    205                 .setOnDismissListener(new OnDismissListener() {
    206                     @Override
    207                     public void onDismiss(DialogInterface dialog) {
    208                         updateDays();
    209                     }
    210                 })
    211                 .setPositiveButton(R.string.done_button, null)
    212                 .show();
    213     }
    214 
    215     private static class TimePickerPreference extends Preference {
    216         private final Context mContext;
    217 
    218         private int mSummaryFormat;
    219         private int mHourOfDay;
    220         private int mMinute;
    221         private Callback mCallback;
    222 
    223         public TimePickerPreference(Context context, final FragmentManager mgr) {
    224             super(context);
    225             mContext = context;
    226             setPersistent(false);
    227             setOnPreferenceClickListener(new OnPreferenceClickListener(){
    228                 @Override
    229                 public boolean onPreferenceClick(Preference preference) {
    230                     final TimePickerFragment frag = new TimePickerFragment();
    231                     frag.pref = TimePickerPreference.this;
    232                     frag.show(mgr, TimePickerPreference.class.getName());
    233                     return true;
    234                 }
    235             });
    236         }
    237 
    238         public void setCallback(Callback callback) {
    239             mCallback = callback;
    240         }
    241 
    242         public void setSummaryFormat(int resId) {
    243             mSummaryFormat = resId;
    244             updateSummary();
    245         }
    246 
    247         public void setTime(int hourOfDay, int minute) {
    248             if (mCallback != null && !mCallback.onSetTime(hourOfDay, minute)) return;
    249             mHourOfDay = hourOfDay;
    250             mMinute = minute;
    251             updateSummary();
    252         }
    253 
    254         private void updateSummary() {
    255             final Calendar c = Calendar.getInstance();
    256             c.set(Calendar.HOUR_OF_DAY, mHourOfDay);
    257             c.set(Calendar.MINUTE, mMinute);
    258             String time = DateFormat.getTimeFormat(mContext).format(c.getTime());
    259             if (mSummaryFormat != 0) {
    260                 time = mContext.getResources().getString(mSummaryFormat, time);
    261             }
    262             setSummary(time);
    263         }
    264 
    265         public static class TimePickerFragment extends DialogFragment implements
    266                 TimePickerDialog.OnTimeSetListener {
    267             public TimePickerPreference pref;
    268 
    269             @Override
    270             public Dialog onCreateDialog(Bundle savedInstanceState) {
    271                 final boolean usePref = pref != null && pref.mHourOfDay >= 0 && pref.mMinute >= 0;
    272                 final Calendar c = Calendar.getInstance();
    273                 final int hour = usePref ? pref.mHourOfDay : c.get(Calendar.HOUR_OF_DAY);
    274                 final int minute = usePref ? pref.mMinute : c.get(Calendar.MINUTE);
    275                 return new TimePickerDialog(getActivity(), this, hour, minute,
    276                         DateFormat.is24HourFormat(getActivity()));
    277             }
    278 
    279             public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
    280                 if (pref != null) {
    281                     pref.setTime(hourOfDay, minute);
    282                 }
    283             }
    284         }
    285 
    286         public interface Callback {
    287             boolean onSetTime(int hour, int minute);
    288         }
    289     }
    290 
    291 }
    292