blob: 42118149cbffac6d65fd3630bad3b7ae10307450 [file] [log] [blame]
Amith Yamasanid7993472010-08-18 13:59:28 -07001/*
2 * Copyright (C) 2010 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
17package com.android.settings;
18
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070019import android.app.Activity;
Amith Yamasanid7993472010-08-18 13:59:28 -070020import android.app.Dialog;
21import android.app.DialogFragment;
Daisuke Miyakawab5647c52010-09-10 18:04:02 -070022import android.app.Fragment;
Amith Yamasanid7993472010-08-18 13:59:28 -070023import android.content.ContentResolver;
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070024import android.content.Intent;
Amith Yamasanid7993472010-08-18 13:59:28 -070025import android.content.pm.PackageManager;
26import android.content.res.Resources;
27import android.os.Bundle;
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070028import android.preference.PreferenceActivity;
Amith Yamasanid7993472010-08-18 13:59:28 -070029import android.preference.PreferenceFragment;
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070030import android.text.TextUtils;
Amith Yamasanid7993472010-08-18 13:59:28 -070031import android.util.Log;
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070032import android.view.View;
33import android.view.View.OnClickListener;
34import android.widget.Button;
Amith Yamasanid7993472010-08-18 13:59:28 -070035
Daisuke Miyakawaf58090d2010-09-12 17:27:33 -070036/**
37 * Letting the class, assumed to be Fragment, create a Dialog on it. Should be useful
38 * you want to utilize some capability in {@link SettingsPreferenceFragment} but don't want
39 * the class inherit the class itself (See {@link ProxySelector} for example).
40 */
Daisuke Miyakawa21c1abc2010-09-12 15:42:56 -070041interface DialogCreatable {
42 public Dialog onCreateDialog(int dialogId);
43}
44
Amith Yamasanid7993472010-08-18 13:59:28 -070045/**
46 * Base class for Settings fragments, with some helper functions and dialog management.
47 */
Daisuke Miyakawa21c1abc2010-09-12 15:42:56 -070048public class SettingsPreferenceFragment extends PreferenceFragment
49 implements DialogCreatable {
Amith Yamasanid7993472010-08-18 13:59:28 -070050
51 private static final String TAG = "SettingsPreferenceFragment";
52
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070053 // Originally from PreferenceActivity.
54 private static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
55 private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
56 private static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
57 private static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
58
Amith Yamasanid7993472010-08-18 13:59:28 -070059 private SettingsDialogFragment mDialogFragment;
60
Daisuke Miyakawab5647c52010-09-10 18:04:02 -070061 private int mResultCode = Activity.RESULT_CANCELED;
62 private Intent mResultData;
Amith Yamasanid7993472010-08-18 13:59:28 -070063
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070064 private Button mNextButton;
65
Daisuke Miyakawab5647c52010-09-10 18:04:02 -070066 @Override
67 public void onResume() {
68 super.onResume();
69
70 final Fragment f = getTargetFragment();
71 final int requestCode = getTargetRequestCode();
72
73 // TargetFragment becomes invalid when this object is resumed. Notify it to
74 // FragmentManager. Without this code, FragmentManager wrongly take the TargetFragment
75 // as live, and throws IllegalStateException.
76 setTargetFragment(null, -1);
77
78 if (f != null && (f instanceof SettingsPreferenceFragment)) {
79 final SettingsPreferenceFragment spf = (SettingsPreferenceFragment)f;
80 final int resultCode = spf.getResultCode();
81 final Intent resultData = spf.getResultData();
82 onActivityResult(requestCode, resultCode, resultData);
83 }
84 }
85
Amith Yamasanid7993472010-08-18 13:59:28 -070086 @Override
87 public void onActivityCreated(Bundle savedInstanceState) {
88 super.onActivityCreated(savedInstanceState);
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070089 setupButtonBar();
Amith Yamasanid7993472010-08-18 13:59:28 -070090 }
91
Daisuke Miyakawab5647c52010-09-10 18:04:02 -070092 public final void setResult(int resultCode) {
93 mResultCode = resultCode;
94 mResultData = null;
95 }
96
97 public final void setResult(int resultCode, Intent data) {
98 mResultCode = resultCode;
99 mResultData = data;
100 }
101
102 public final int getResultCode() {
103 return mResultCode;
104 }
105
106 public final Intent getResultData() {
107 return mResultData;
108 }
109
110 /*
111 * The name is intentionally made different from Activity#finish(), so that
112 * users won't misunderstand its meaning.
113 */
114 public final void finishFragment() {
115 getActivity().onBackPressed();
116 }
117
Amith Yamasanid7993472010-08-18 13:59:28 -0700118 // Some helpers for functions used by the settings fragments when they were activities
119
120 /**
121 * Returns the ContentResolver from the owning Activity.
122 */
123 protected ContentResolver getContentResolver() {
124 return getActivity().getContentResolver();
125 }
126
127 /**
128 * Returns the specified system service from the owning Activity.
129 */
130 protected Object getSystemService(final String name) {
131 return getActivity().getSystemService(name);
132 }
133
134 /**
135 * Returns the Resources from the owning Activity.
136 */
137 protected Resources getResources() {
138 return getActivity().getResources();
139 }
140
141 /**
142 * Returns the PackageManager from the owning Activity.
143 */
144 protected PackageManager getPackageManager() {
145 return getActivity().getPackageManager();
146 }
147
148 // Dialog management
149
150 protected void showDialog(int dialogId) {
151 if (mDialogFragment != null) {
152 Log.e(TAG, "Old dialog fragment not null!");
153 }
154 mDialogFragment = new SettingsDialogFragment(this, dialogId);
Daisuke Miyakawa21c1abc2010-09-12 15:42:56 -0700155 mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
Amith Yamasanid7993472010-08-18 13:59:28 -0700156 }
157
Daisuke Miyakawa21c1abc2010-09-12 15:42:56 -0700158 @Override
Amith Yamasanid7993472010-08-18 13:59:28 -0700159 public Dialog onCreateDialog(int dialogId) {
160 return null;
161 }
162
163 protected void removeDialog(int dialogId) {
164 if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId
165 && mDialogFragment.isVisible()) {
166 mDialogFragment.dismiss();
167 }
168 mDialogFragment = null;
169 }
170
171 static class SettingsDialogFragment extends DialogFragment {
172 private int mDialogId;
173
Daisuke Miyakawa21c1abc2010-09-12 15:42:56 -0700174 private DialogCreatable mFragment;
Amith Yamasanid7993472010-08-18 13:59:28 -0700175
Daisuke Miyakawa21c1abc2010-09-12 15:42:56 -0700176 SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
Amith Yamasanid7993472010-08-18 13:59:28 -0700177 mDialogId = dialogId;
178 mFragment = fragment;
179 }
180
181 @Override
182 public Dialog onCreateDialog(Bundle savedInstanceState) {
183 return mFragment.onCreateDialog(mDialogId);
184 }
185
186 public int getDialogId() {
187 return mDialogId;
188 }
189 }
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -0700190
191 protected boolean hasNextButton() {
192 return mNextButton != null;
193 }
194
195 protected Button getNextButton() {
196 return mNextButton;
197 }
198
Daisuke Miyakawa6ebf8612010-09-10 09:48:51 -0700199 public void finish() {
200 getActivity().onBackPressed();
201 }
202
Daisuke Miyakawab5647c52010-09-10 18:04:02 -0700203 public boolean startFragment(
204 Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
Daisuke Miyakawa25af1502010-09-24 11:29:31 -0700205 if (getActivity() instanceof PreferenceActivity) {
206 PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
207 Fragment f = Fragment.instantiate(getActivity(), fragmentClass, extras);
208 caller.setTargetFragment(f, requestCode);
209 preferenceActivity.switchToHeader(fragmentClass, extras);
210 return true;
Daisuke Miyakawab5647c52010-09-10 18:04:02 -0700211 } else {
Daisuke Miyakawa25af1502010-09-24 11:29:31 -0700212 Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
213 + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
214 + ")");
Daisuke Miyakawab5647c52010-09-10 18:04:02 -0700215 return false;
216 }
217 }
218
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -0700219 /**
220 * Sets up Button Bar possibly required in the Fragment. Probably available only in
221 * phones.
222 *
223 * Previously {@link PreferenceActivity} had the capability as hidden functionality.
224 */
225 private void setupButtonBar() {
226 // Originally from PreferenceActivity, which has had button bar inside its layout.
227 final Activity activity = getActivity();
228 final Intent intent = activity.getIntent();
229 final View buttonBar = activity.findViewById(com.android.internal.R.id.button_bar);
230 if (!intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false) || buttonBar == null) {
231 return;
232 }
233
234 buttonBar.setVisibility(View.VISIBLE);
235 View tmpView = activity.findViewById(com.android.internal.R.id.back_button);
236 if (tmpView != null) {
237 // TODO: Assume this is pressed only in single pane, finishing current Activity.
238 try {
239 final Button backButton = (Button)tmpView;
240 backButton.setOnClickListener(new OnClickListener() {
241 public void onClick(View v) {
242 activity.setResult(Activity.RESULT_CANCELED);
243 activity.finish();
244 }
245 });
246 if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
247 String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
248 if (TextUtils.isEmpty(buttonText)) {
249 backButton.setVisibility(View.GONE);
250 }
251 else {
252 backButton.setText(buttonText);
253 }
254 }
255 } catch (ClassCastException e) {
256 Log.w(TAG, "The view originally for back_button is used not as Button. " +
257 "Ignored.");
258 }
259 }
260
261 tmpView = activity.findViewById(com.android.internal.R.id.skip_button);
262 if (tmpView != null) {
263 try {
264 final Button skipButton = (Button)tmpView;
265 skipButton.setOnClickListener(new OnClickListener() {
266 public void onClick(View v) {
267 activity.setResult(Activity.RESULT_OK);
268 activity.finish();
269 }
270 });
271 if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
272 skipButton.setVisibility(View.VISIBLE);
273 }
274 } catch (ClassCastException e) {
275 Log.w(TAG, "The view originally for skip_button is used not as Button. " +
276 "Ignored.");
277 }
278 }
279
280 tmpView = activity.findViewById(com.android.internal.R.id.next_button);
281 if (tmpView != null) {
282 try {
283 mNextButton = (Button)tmpView;
284 mNextButton.setOnClickListener(new OnClickListener() {
285 public void onClick(View v) {
286 activity.setResult(Activity.RESULT_OK);
287 activity.finish();
288 }
289 });
290 // set our various button parameters
291 if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
292 String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
293 if (TextUtils.isEmpty(buttonText)) {
294 mNextButton.setVisibility(View.GONE);
295 }
296 else {
297 mNextButton.setText(buttonText);
298 }
299 }
300 } catch (ClassCastException e) {
301 Log.w(TAG, "The view originally for next_button is used not as Button. " +
302 "Ignored.");
303 mNextButton = null;
304 }
305 }
306 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700307}