1 /*
2  * Copyright (C) 2017 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.tv.settings.system;
18 
19 import android.app.timedetector.ManualTimeSuggestion;
20 import android.app.timedetector.TimeDetector;
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.text.TextUtils;
24 import android.util.TypedValue;
25 import android.view.ContextThemeWrapper;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.TextView;
30 
31 import androidx.leanback.preference.LeanbackPreferenceDialogFragment;
32 import androidx.leanback.widget.picker.DatePicker;
33 import androidx.leanback.widget.picker.TimePicker;
34 import androidx.preference.DialogPreference;
35 
36 import com.android.tv.settings.R;
37 
38 import java.util.Calendar;
39 
40 /**
41  * A DialogFragment started for either setting date or setting time purposes. The type of
42  * fragment launched is controlled by the type of {@link LeanbackPickerDialogPreference}
43  * that's clicked. Launching of these two fragments is done inside
44  * {@link com.android.tv.settings.BaseSettingsFragment#onPreferenceDisplayDialog}.
45  */
46 public class LeanbackPickerDialogFragment extends LeanbackPreferenceDialogFragment {
47 
48     private static final String EXTRA_PICKER_TYPE = "LeanbackPickerDialogFragment.PickerType";
49     private static final String TYPE_DATE = "date";
50     private static final String TYPE_TIME = "time";
51     private static final String SAVE_STATE_TITLE = "LeanbackPickerDialogFragment.title";
52 
53     private CharSequence mDialogTitle;
54     private Calendar mCalendar;
55 
56     /**
57      * Generated a new DialogFragment displaying a Leanback DatePicker widget.
58      * @param key The preference key starting this DialogFragment.
59      * @return The fragment to be started displaying a DatePicker widget for setting date.
60      */
newDatePickerInstance(String key)61     public static LeanbackPickerDialogFragment newDatePickerInstance(String key) {
62         final Bundle args = new Bundle(1);
63         args.putString(ARG_KEY, key);
64         args.putString(EXTRA_PICKER_TYPE, TYPE_DATE);
65 
66         final LeanbackPickerDialogFragment fragment = new LeanbackPickerDialogFragment();
67         fragment.setArguments(args);
68         return fragment;
69     }
70 
71     /**
72      * Generated a new DialogFragment displaying a Leanback TimePicker widget.
73      * @param key The preference key starting this DialogFragment.
74      * @return The fragment to be started displaying a TimePicker widget for setting time.
75      */
newTimePickerInstance(String key)76     public static LeanbackPickerDialogFragment newTimePickerInstance(String key) {
77         final Bundle args = new Bundle(1);
78         args.putString(ARG_KEY, key);
79         args.putString(EXTRA_PICKER_TYPE, TYPE_TIME);
80 
81         final LeanbackPickerDialogFragment fragment = new LeanbackPickerDialogFragment();
82         fragment.setArguments(args);
83         return fragment;
84     }
85 
86     @Override
onCreate(Bundle savedInstanceState)87     public void onCreate(Bundle savedInstanceState) {
88         super.onCreate(savedInstanceState);
89 
90         if (savedInstanceState == null) {
91             final DialogPreference preference = getPreference();
92             mDialogTitle = preference.getDialogTitle();
93         } else {
94             mDialogTitle = savedInstanceState.getCharSequence(SAVE_STATE_TITLE);
95         }
96         mCalendar = Calendar.getInstance();
97     }
98 
99     @Override
onSaveInstanceState(Bundle outState)100     public void onSaveInstanceState(Bundle outState) {
101         super.onSaveInstanceState(outState);
102         outState.putCharSequence(SAVE_STATE_TITLE, mDialogTitle);
103     }
104 
105     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)106     public View onCreateView(LayoutInflater inflater, ViewGroup container,
107                              Bundle savedInstanceState) {
108         final String pickerType = getArguments().getString(EXTRA_PICKER_TYPE);
109 
110         final TypedValue tv = new TypedValue();
111         getActivity().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
112         int theme = tv.resourceId;
113         if (theme == 0) {
114             // Fallback to default theme.
115             theme = R.style.PreferenceThemeOverlayLeanback;
116         }
117         Context styledContext = new ContextThemeWrapper(getActivity(), theme);
118         LayoutInflater styledInflater = inflater.cloneInContext(styledContext);
119         final View view = styledInflater.inflate(R.layout.picker_dialog_fragment, container, false);
120         ViewGroup pickerContainer = view.findViewById(R.id.picker_container);
121         if (pickerType.equals(TYPE_DATE)) {
122             styledInflater.inflate(R.layout.date_picker_widget, pickerContainer, true);
123             DatePicker datePicker = pickerContainer.findViewById(R.id.date_picker);
124             datePicker.setActivated(true);
125             datePicker.setOnClickListener(v -> {
126                 // Setting the new system date
127                 long whenMillis = datePicker.getDate();
128                 TimeDetector timeDetector = getContext().getSystemService(TimeDetector.class);
129                 ManualTimeSuggestion manualTimeSuggestion = TimeDetector.createManualTimeSuggestion(
130                         whenMillis, "Settings: Set date");
131                 timeDetector.suggestManualTime(manualTimeSuggestion);
132                 // Finish the fragment/activity when clicked.
133                 if (!getFragmentManager().popBackStackImmediate()) {
134                     getActivity().finish();
135                 }
136             });
137 
138         } else {
139             styledInflater.inflate(R.layout.time_picker_widget, pickerContainer, true);
140             TimePicker timePicker = pickerContainer.findViewById(R.id.time_picker);
141             timePicker.setActivated(true);
142             timePicker.setOnClickListener(v -> {
143                 // Setting the new system time
144                 mCalendar.set(Calendar.HOUR_OF_DAY, timePicker.getHour());
145                 mCalendar.set(Calendar.MINUTE, timePicker.getMinute());
146                 mCalendar.set(Calendar.SECOND, 0);
147                 mCalendar.set(Calendar.MILLISECOND, 0);
148                 long whenMillis = mCalendar.getTimeInMillis();
149 
150                 TimeDetector timeDetector = getContext().getSystemService(TimeDetector.class);
151                 ManualTimeSuggestion manualTimeSuggestion = TimeDetector.createManualTimeSuggestion(
152                         whenMillis, "Settings: Set time");
153                 timeDetector.suggestManualTime(manualTimeSuggestion);
154 
155                 // Finish the fragment/activity when clicked.
156                 if (!getFragmentManager().popBackStackImmediate()) {
157                     getActivity().finish();
158                 }
159             });
160         }
161 
162         final CharSequence title = mDialogTitle;
163         if (!TextUtils.isEmpty(title)) {
164             final TextView titleView = view.findViewById(R.id.decor_title);
165             titleView.setText(title);
166         }
167         return view;
168     }
169 }
170