Settings.java revision 9c8bde576ab18fcfe653587f3e63604430c8791c
1/*
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
19import android.app.Activity;
20import android.app.Fragment;
21import android.app.Fragment.InstantiationException;
22import android.content.Intent;
23import android.os.Bundle;
24import android.preference.Preference;
25import android.preference.PreferenceFragment;
26import android.preference.PreferenceGroup;
27import android.preference.PreferenceScreen;
28import android.text.TextUtils;
29import android.util.Log;
30import android.view.View;
31
32import java.util.ArrayList;
33
34/**
35 * Top-level settings activity to handle single pane and double pane UI layout.
36 */
37public class Settings extends Activity
38        implements PreferenceFragment.OnPreferenceStartFragmentCallback,
39        SettingsPreferenceFragment.OnStateListener {
40
41    private static final String TAG = "Settings";
42
43    private static final String KEY_PARENT = "parent";
44    private static final String KEY_CALL_SETTINGS = "call_settings";
45    private static final String KEY_SYNC_SETTINGS = "sync_settings";
46    private static final String KEY_SEARCH_SETTINGS = "search_settings";
47    private static final String KEY_DOCK_SETTINGS = "dock_settings";
48
49    private static final String KEY_OPERATOR_SETTINGS = "operator_settings";
50    private static final String KEY_MANUFACTURER_SETTINGS = "manufacturer_settings";
51
52    public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
53
54    public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
55
56    // Temporary, until all top-level settings are converted to fragments
57    private static final String BACK_STACK_PREFS = ":settings:prefs";
58
59    private View mPrefsPane;
60    private View mMainPane;
61    private boolean mSinglePane;
62
63    private ArrayList<CharSequence> mTrail = new ArrayList<CharSequence>();
64
65    /*
66    @Override
67    protected void onResume() {
68        super.onResume();
69        findPreference(KEY_CALL_SETTINGS).setEnabled(!AirplaneModeEnabler.isAirplaneModeOn(this));
70    }
71    */
72
73    @Override
74    protected void onCreate(Bundle savedInstanceState) {
75        super.onCreate(savedInstanceState);
76        setContentView(R.layout.settings_top_level);
77        mPrefsPane = findViewById(R.id.prefs);
78        mMainPane = findViewById(R.id.top_level);
79        mSinglePane = mMainPane == null;
80        if (mSinglePane) mMainPane = mPrefsPane;
81
82        final Intent intent = getIntent();
83        String initialFragment = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
84        Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
85
86        if (mSinglePane) {
87            if (initialFragment != null) {
88                showFragment(initialFragment, initialArguments);
89            } else {
90                if (intent.getComponent().getClassName().equals(this.getClass().getName())) {
91                    showFragment(TopLevelSettings.class.getName(), null);
92                } else {
93                    showFragment(intent.getComponent().getClassName(), intent.getExtras());
94                }
95            }
96        } else {
97            if (!intent.getComponent().getClassName().equals(this.getClass().getName())) {
98                if (showFragment(intent.getComponent().getClassName(), intent.getExtras())) {
99                    mMainPane.setVisibility(View.GONE);
100                }
101            } else {
102                Fragment topLevel = getFragmentManager().findFragmentById(R.id.top_level);
103                if (topLevel != null) {
104                    ((TopLevelSettings) topLevel).selectFirst();
105                }
106            }
107        }
108    }
109
110    boolean showFragment(Preference preference) {
111        if (mSinglePane) {
112            startWithFragment(preference.getFragment(), preference.getExtras());
113            return false;
114        } else {
115            return showFragment(preference.getFragment(), preference.getExtras());
116        }
117    }
118
119    private void startWithFragment(String fragmentName, Bundle args) {
120        Intent intent = new Intent(Intent.ACTION_MAIN);
121        intent.setClass(this, getClass());
122        intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
123        intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
124        startActivity(intent);
125    }
126
127    private boolean showFragment(String fragmentClass, Bundle extras) {
128        try {
129            Fragment f = Fragment.instantiate(this, fragmentClass, extras);
130            if (f instanceof SettingsPreferenceFragment) {
131                ((SettingsPreferenceFragment) f).setOnStateListener(this);
132            }
133            getFragmentManager().openTransaction().replace(R.id.prefs, f).commit();
134            return true;
135        } catch (InstantiationException exc) {
136            Log.d(TAG, "Couldn't instantiate fragment " + fragmentClass);
137            return false;
138        }
139    }
140
141    private void addToBreadCrumbs(Fragment fragment) {
142        final CharSequence title = ((PreferenceFragment) fragment)
143                .getPreferenceScreen().getTitle();
144        if (mSinglePane) mTrail.clear();
145        if (mTrail.size() == 0 || !TextUtils.equals(title, mTrail.get(mTrail.size() - 1))) {
146            mTrail.add(title);
147            updateTitle();
148        }
149    }
150
151    private void removeFromBreadCrumbs(Fragment fragment) {
152        if (mTrail.size() > 0) {
153            mTrail.remove(mTrail.size() - 1);
154        }
155        updateTitle();
156    }
157
158    private void updateTitle() {
159        String trail = "";
160        for (CharSequence trailPart : mTrail) {
161            if (trail.length() != 0)
162                trail += " | ";
163            trail = trail + trailPart;
164        }
165        setTitle(trail);
166    }
167
168    public void onCreated(SettingsPreferenceFragment fragment) {
169        Log.d(TAG, "Fragment created " + fragment + " (name: " + fragment.getClass() + ")");
170        addToBreadCrumbs(fragment);
171    }
172
173    public void onDestroyed(SettingsPreferenceFragment fragment) {
174        removeFromBreadCrumbs(fragment);
175        Log.d(TAG, "Fragment destroyed " + fragment + " (name: " + fragment.getClass() + ")");
176    }
177
178    public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
179        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
188    public static class TopLevelSettings extends PreferenceFragment {
189
190        private IconPreferenceScreen mHighlightedPreference;
191
192        @Override
193        public void onCreate(Bundle savedInstanceState) {
194            super.onCreate(savedInstanceState);
195
196            // Load the preferences from an XML resource
197            addPreferencesFromResource(R.xml.settings);
198
199            updatePreferenceList();
200        }
201
202        private void updatePreferenceList() {
203            final Activity activity = getActivity();
204            PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
205            Utils.updatePreferenceToSpecificActivityOrRemove(activity, parent,
206                    KEY_SYNC_SETTINGS, 0);
207            Utils.updatePreferenceToSpecificActivityOrRemove(activity, parent,
208                    KEY_SEARCH_SETTINGS, 0);
209
210            Preference dockSettings = parent.findPreference(KEY_DOCK_SETTINGS);
211            if (activity.getResources().getBoolean(R.bool.has_dock_settings) == false
212                    && dockSettings != null) {
213                parent.removePreference(dockSettings);
214            }
215
216            Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
217                    KEY_OPERATOR_SETTINGS);
218            Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
219                    KEY_MANUFACTURER_SETTINGS);
220        }
221
222        @Override
223        public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
224            // If it is a fragment preference, replace the prefs pane in the 2 pane UI.
225            final String fragmentClass = preference.getFragment();
226            if (fragmentClass != null) {
227                boolean showed = ((Settings) getActivity()).showFragment(preference);
228                if (showed) {
229                    highlight(preference);
230                }
231                return showed;
232            }
233            return false;
234        }
235
236        void highlight(Preference preference) {
237            if (mHighlightedPreference != null) {
238                mHighlightedPreference.setHighlighted(false);
239            }
240            mHighlightedPreference = (IconPreferenceScreen) preference;
241            mHighlightedPreference.setHighlighted(true);
242        }
243
244        void selectFirst() {
245            Preference first = getPreferenceScreen().getPreference(0);
246            onPreferenceTreeClick(getPreferenceScreen(), first);
247        }
248    }
249}
250