blob: 50aa1df12b2b64a4adf156336efa0397822b1a8f [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/*
2 * Copyright (C) 2008 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
Amith Yamasanid7993472010-08-18 13:59:28 -070019import android.app.Activity;
20import android.app.Fragment;
Amith Yamasanib61cf512010-09-12 08:17:50 -070021import android.content.Context;
Amith Yamasanid7993472010-08-18 13:59:28 -070022import android.content.Intent;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080023import android.os.Bundle;
Amith Yamasani0e2ab4f2010-01-14 16:12:21 -080024import android.preference.Preference;
Amith Yamasanid7993472010-08-18 13:59:28 -070025import android.preference.PreferenceFragment;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080026import android.preference.PreferenceGroup;
Amith Yamasanid7993472010-08-18 13:59:28 -070027import android.preference.PreferenceScreen;
28import android.text.TextUtils;
Amith Yamasanib61cf512010-09-12 08:17:50 -070029import android.util.AttributeSet;
Amith Yamasanid7993472010-08-18 13:59:28 -070030import android.util.Log;
Amith Yamasanib61cf512010-09-12 08:17:50 -070031import android.view.LayoutInflater;
Amith Yamasanid7993472010-08-18 13:59:28 -070032import android.view.View;
Amith Yamasanib61cf512010-09-12 08:17:50 -070033import android.view.View.OnClickListener;
34import android.widget.LinearLayout;
35import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080036
Amith Yamasanid7993472010-08-18 13:59:28 -070037import java.util.ArrayList;
38
39/**
40 * Top-level settings activity to handle single pane and double pane UI layout.
41 */
42public class Settings extends Activity
43 implements PreferenceFragment.OnPreferenceStartFragmentCallback,
44 SettingsPreferenceFragment.OnStateListener {
45
Amith Yamasanib61cf512010-09-12 08:17:50 -070046 private static final boolean DBG = false;
47
Amith Yamasanid7993472010-08-18 13:59:28 -070048 private static final String TAG = "Settings";
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080049
50 private static final String KEY_PARENT = "parent";
51 private static final String KEY_CALL_SETTINGS = "call_settings";
52 private static final String KEY_SYNC_SETTINGS = "sync_settings";
Bjorn Bringerta9d5be12009-04-27 15:16:25 +010053 private static final String KEY_SEARCH_SETTINGS = "search_settings";
Amith Yamasani0e2ab4f2010-01-14 16:12:21 -080054 private static final String KEY_DOCK_SETTINGS = "dock_settings";
Amith Yamasanid7993472010-08-18 13:59:28 -070055
Anders Hammar1b2dd9032010-04-08 10:03:50 +020056 private static final String KEY_OPERATOR_SETTINGS = "operator_settings";
57 private static final String KEY_MANUFACTURER_SETTINGS = "manufacturer_settings";
58
Amith Yamasanid7993472010-08-18 13:59:28 -070059 public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
Chouting Zhang5ee06352009-07-22 22:51:40 -050060
Amith Yamasanid7993472010-08-18 13:59:28 -070061 public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
Amith Yamasani0e2ab4f2010-01-14 16:12:21 -080062
Amith Yamasanid7993472010-08-18 13:59:28 -070063 private static final String BACK_STACK_PREFS = ":settings:prefs";
Anders Hammar1b2dd9032010-04-08 10:03:50 +020064
Amith Yamasanid7993472010-08-18 13:59:28 -070065 private View mPrefsPane;
66 private View mMainPane;
67 private boolean mSinglePane;
68
Amith Yamasanib61cf512010-09-12 08:17:50 -070069 private BreadCrumbs mBreadCrumbs;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080070
Amith Yamasanid7993472010-08-18 13:59:28 -070071 @Override
72 protected void onCreate(Bundle savedInstanceState) {
73 super.onCreate(savedInstanceState);
74 setContentView(R.layout.settings_top_level);
75 mPrefsPane = findViewById(R.id.prefs);
76 mMainPane = findViewById(R.id.top_level);
77 mSinglePane = mMainPane == null;
78 if (mSinglePane) mMainPane = mPrefsPane;
79
80 final Intent intent = getIntent();
81 String initialFragment = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
82 Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
83
Amith Yamasanib61cf512010-09-12 08:17:50 -070084 createActionBar();
85
Amith Yamasanid7993472010-08-18 13:59:28 -070086 if (mSinglePane) {
87 if (initialFragment != null) {
88 showFragment(initialFragment, initialArguments);
89 } else {
Daisuke Miyakawa0cc35e42010-08-24 15:50:43 -070090 // Intent#getCompontent() lets us get Fragment name, even when the Intent is
91 // given via <activity-alias>.
92 //
93 // e.g. When we reach here via "ChildSetting" activity-alias,
94 // we should get the name here instead of targetActivity ("Settings").
Amith Yamasanid7993472010-08-18 13:59:28 -070095 if (intent.getComponent().getClassName().equals(this.getClass().getName())) {
96 showFragment(TopLevelSettings.class.getName(), null);
97 } else {
98 showFragment(intent.getComponent().getClassName(), intent.getExtras());
99 }
100 }
101 } else {
102 if (!intent.getComponent().getClassName().equals(this.getClass().getName())) {
103 if (showFragment(intent.getComponent().getClassName(), intent.getExtras())) {
104 mMainPane.setVisibility(View.GONE);
105 }
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -0700106 } else {
107 Fragment topLevel = getFragmentManager().findFragmentById(R.id.top_level);
108 if (topLevel != null) {
109 ((TopLevelSettings) topLevel).selectFirst();
110 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700111 }
112 }
113 }
114
Amith Yamasanib61cf512010-09-12 08:17:50 -0700115 private void createActionBar() {
116 LayoutInflater inflater = (LayoutInflater)
117 getSystemService(Context.LAYOUT_INFLATER_SERVICE);
118 View customNavBar = inflater.inflate(R.layout.settings_actionbar, null, false);
119 getActionBar().setCustomNavigationMode(customNavBar);
120 mBreadCrumbs = (BreadCrumbs) customNavBar.findViewById(R.id.bread_crumbs);
121 mBreadCrumbs.setActivity(this);
122 }
123
Amith Yamasanid7993472010-08-18 13:59:28 -0700124 boolean showFragment(Preference preference) {
125 if (mSinglePane) {
126 startWithFragment(preference.getFragment(), preference.getExtras());
127 return false;
128 } else {
Amith Yamasanib61cf512010-09-12 08:17:50 -0700129 mBreadCrumbs.clear();
Amith Yamasanid7993472010-08-18 13:59:28 -0700130 return showFragment(preference.getFragment(), preference.getExtras());
131 }
132 }
133
134 private void startWithFragment(String fragmentName, Bundle args) {
135 Intent intent = new Intent(Intent.ACTION_MAIN);
136 intent.setClass(this, getClass());
137 intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
138 intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
139 startActivity(intent);
140 }
141
142 private boolean showFragment(String fragmentClass, Bundle extras) {
Amith Yamasanib61cf512010-09-12 08:17:50 -0700143 if (DBG) Log.d(TAG, "showFragment");
144 Fragment f = Fragment.instantiate(this, fragmentClass, extras);
Amith Yamasani60133dd2010-09-11 14:17:31 -0700145 if (f instanceof SettingsPreferenceFragment) {
146 ((SettingsPreferenceFragment) f).setOnStateListener(this);
Amith Yamasanid7993472010-08-18 13:59:28 -0700147 }
Amith Yamasanib61cf512010-09-12 08:17:50 -0700148 mBreadCrumbs.clear();
149 getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
Amith Yamasani60133dd2010-09-11 14:17:31 -0700150 getFragmentManager().openTransaction().replace(R.id.prefs, f).commit();
151 return true;
Amith Yamasanid7993472010-08-18 13:59:28 -0700152 }
153
154 private void addToBreadCrumbs(Fragment fragment) {
155 final CharSequence title = ((PreferenceFragment) fragment)
156 .getPreferenceScreen().getTitle();
Amith Yamasanib61cf512010-09-12 08:17:50 -0700157 if (mSinglePane) {
158 mBreadCrumbs.clear();
Amith Yamasanid7993472010-08-18 13:59:28 -0700159 }
Amith Yamasanib61cf512010-09-12 08:17:50 -0700160 mBreadCrumbs.push(title);
Amith Yamasanid7993472010-08-18 13:59:28 -0700161 }
162
163 private void removeFromBreadCrumbs(Fragment fragment) {
Amith Yamasanib61cf512010-09-12 08:17:50 -0700164 mBreadCrumbs.pop(((PreferenceFragment) fragment).getPreferenceScreen().getTitle());
165 mBreadCrumbs.update();
Amith Yamasanid7993472010-08-18 13:59:28 -0700166 }
167
168 public void onCreated(SettingsPreferenceFragment fragment) {
Amith Yamasanib61cf512010-09-12 08:17:50 -0700169 if (DBG) Log.d(TAG, "Fragment created " + fragment);
Amith Yamasanid7993472010-08-18 13:59:28 -0700170 addToBreadCrumbs(fragment);
171 }
172
173 public void onDestroyed(SettingsPreferenceFragment fragment) {
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -0700174 Log.d(TAG, "Fragment destroyed " + fragment + " (name: " + fragment.getClass() + ")");
Amith Yamasanid7993472010-08-18 13:59:28 -0700175 }
176
177 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
Amith Yamasanib61cf512010-09-12 08:17:50 -0700178 if (DBG) Log.d(TAG, "onPreferenceStartFragment");
Amith Yamasanid7993472010-08-18 13:59:28 -0700179 Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras());
180 if (f instanceof SettingsPreferenceFragment) {
181 ((SettingsPreferenceFragment) f).setOnStateListener(this);
182 }
183 getFragmentManager().openTransaction().replace(R.id.prefs, f)
184 .addToBackStack(BACK_STACK_PREFS).commit();
185 return true;
186 }
187
Amith Yamasanib61cf512010-09-12 08:17:50 -0700188 @Override
189 public void onBackPressed() {
190 mBreadCrumbs.pop();
191 mBreadCrumbs.update();
192 super.onBackPressed();
193 }
194
Amith Yamasanid7993472010-08-18 13:59:28 -0700195 public static class TopLevelSettings extends PreferenceFragment {
196
197 private IconPreferenceScreen mHighlightedPreference;
198
199 @Override
200 public void onCreate(Bundle savedInstanceState) {
201 super.onCreate(savedInstanceState);
202
203 // Load the preferences from an XML resource
204 addPreferencesFromResource(R.xml.settings);
205
206 updatePreferenceList();
207 }
208
Amith Yamasanib61cf512010-09-12 08:17:50 -0700209 @Override
210 public void onResume() {
211 super.onResume();
212
213 updateCallSettings();
214 }
215
216 private void updateCallSettings() {
217 Preference callSettings = findPreference(KEY_CALL_SETTINGS);
218 // Might have been removed in non-voice-capable devices
219 if (callSettings != null) {
220 callSettings.setEnabled(!AirplaneModeEnabler.isAirplaneModeOn(getActivity()));
221 }
222 }
223
Amith Yamasanid7993472010-08-18 13:59:28 -0700224 private void updatePreferenceList() {
225 final Activity activity = getActivity();
226 PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
227 Utils.updatePreferenceToSpecificActivityOrRemove(activity, parent,
228 KEY_SYNC_SETTINGS, 0);
Amith Yamasanid7993472010-08-18 13:59:28 -0700229 Preference dockSettings = parent.findPreference(KEY_DOCK_SETTINGS);
230 if (activity.getResources().getBoolean(R.bool.has_dock_settings) == false
231 && dockSettings != null) {
232 parent.removePreference(dockSettings);
233 }
234
235 Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
236 KEY_OPERATOR_SETTINGS);
237 Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
238 KEY_MANUFACTURER_SETTINGS);
Amith Yamasani60133dd2010-09-11 14:17:31 -0700239
240 Preference callSettings = parent.findPreference(KEY_CALL_SETTINGS);
241 if (!Utils.isVoiceCapable(activity) && callSettings != null) {
242 parent.removePreference(callSettings);
243 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700244 }
245
246 @Override
247 public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
248 // If it is a fragment preference, replace the prefs pane in the 2 pane UI.
249 final String fragmentClass = preference.getFragment();
250 if (fragmentClass != null) {
251 boolean showed = ((Settings) getActivity()).showFragment(preference);
252 if (showed) {
253 highlight(preference);
254 }
255 return showed;
256 }
257 return false;
258 }
259
260 void highlight(Preference preference) {
261 if (mHighlightedPreference != null) {
262 mHighlightedPreference.setHighlighted(false);
263 }
264 mHighlightedPreference = (IconPreferenceScreen) preference;
265 mHighlightedPreference.setHighlighted(true);
266 }
267
268 void selectFirst() {
269 Preference first = getPreferenceScreen().getPreference(0);
270 onPreferenceTreeClick(getPreferenceScreen(), first);
271 }
272 }
Amith Yamasanib61cf512010-09-12 08:17:50 -0700273
274 public static class BreadCrumbs extends LinearLayout implements OnClickListener {
275
276 private ArrayList<CharSequence> mTitles = new ArrayList<CharSequence>();
277 private TextView mLevelUpTitle;
278 private TextView mCurrentLevelTitle;
279 private View mDivider;
280 private Activity mActivity;
281
282 public BreadCrumbs(Context context) {
283 this(context, null);
284 }
285
286 public BreadCrumbs(Context context, AttributeSet attrs) {
287 super(context, attrs);
288 }
289
290 public void push(CharSequence title) {
291 if (mTitles.size() == 0
292 || !TextUtils.equals(title, mTitles.get(mTitles.size() - 1))) {
293 mTitles.add(title);
294 update();
295 }
296 }
297
298 public void pop() {
299 if (mTitles.size() > 0) {
300 mTitles.remove(mTitles.size() - 1);
301 }
302 }
303
304 public void pop(CharSequence title) {
305 if (mTitles.size() > 1) {
306 mTitles.remove(title);
307 }
308 }
309
310 public void clear() {
311 mTitles.clear();
312 }
313
314 private void initNavViews() {
315 if (mLevelUpTitle == null) {
316 mLevelUpTitle = (TextView) findViewById(R.id.level_up_title);
317 mCurrentLevelTitle = (TextView) findViewById(R.id.level_current_title);
318 mDivider = findViewById(R.id.level_divider);
319 if (mLevelUpTitle != null) {
320 mLevelUpTitle.setOnClickListener(this);
321 }
322 if (mCurrentLevelTitle != null) {
323 mCurrentLevelTitle.setOnClickListener(this);
324 }
325 }
326 }
327
328 public void update() {
329 initNavViews();
330 if (mLevelUpTitle == null) return;
331
332 final int titleCount = mTitles.size();
333 if (titleCount > 1) {
334 mLevelUpTitle.setText(mTitles.get(titleCount - 2));
335 mLevelUpTitle.setVisibility(VISIBLE);
336 mDivider.setVisibility(VISIBLE);
337 } else {
338 mLevelUpTitle.setVisibility(GONE);
339 mDivider.setVisibility(GONE);
340 }
341 if (titleCount > 0) {
342 mCurrentLevelTitle.setText(mTitles.get(titleCount - 1));
343 } else {
344 mCurrentLevelTitle.setText("");
345 }
346 }
347
348 public void setActivity(Activity activity) {
349 mActivity = activity;
350 }
351
352 public void onClick(View v) {
353 if (mActivity == null)
354 return;
355 if (v == mLevelUpTitle) {
356 mActivity.onBackPressed();
357 }
358 }
359 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800360}