Home | History | Annotate | Download | only in settings
      1 /*
      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 
     17 package com.android.settings;
     18 
     19 import android.app.Dialog;
     20 import android.app.DialogFragment;
     21 import android.app.Fragment;
     22 import android.content.ContentResolver;
     23 import android.content.DialogInterface;
     24 import android.content.Intent;
     25 import android.content.pm.PackageManager;
     26 import android.net.Uri;
     27 import android.os.Bundle;
     28 import android.preference.PreferenceActivity;
     29 import android.preference.PreferenceFragment;
     30 import android.text.TextUtils;
     31 import android.util.Log;
     32 import android.view.Menu;
     33 import android.view.MenuInflater;
     34 import android.view.MenuItem;
     35 import android.widget.Button;
     36 
     37 /**
     38  * Base class for Settings fragments, with some helper functions and dialog management.
     39  */
     40 public class SettingsPreferenceFragment extends PreferenceFragment implements DialogCreatable {
     41 
     42     private static final String TAG = "SettingsPreferenceFragment";
     43 
     44     private static final int MENU_HELP = Menu.FIRST + 100;
     45 
     46     private SettingsDialogFragment mDialogFragment;
     47 
     48     private String mHelpUrl;
     49 
     50     @Override
     51     public void onCreate(Bundle icicle) {
     52         super.onCreate(icicle);
     53 
     54         // Prepare help url and enable menu if necessary
     55         int helpResource = getHelpResource();
     56         if (helpResource != 0) {
     57             mHelpUrl = getResources().getString(helpResource);
     58         }
     59     }
     60 
     61     @Override
     62     public void onActivityCreated(Bundle savedInstanceState) {
     63         super.onActivityCreated(savedInstanceState);
     64         if (!TextUtils.isEmpty(mHelpUrl)) {
     65             setHasOptionsMenu(true);
     66         }
     67     }
     68 
     69     /**
     70      * Override this if you want to show a help item in the menu, by returning the resource id.
     71      * @return the resource id for the help url
     72      */
     73     protected int getHelpResource() {
     74         return 0;
     75     }
     76 
     77     @Override
     78     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
     79         if (mHelpUrl != null) {
     80             Intent helpIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mHelpUrl));
     81             helpIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
     82                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
     83             MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_label);
     84             helpItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
     85             helpItem.setIntent(helpIntent);
     86         }
     87     }
     88 
     89     /*
     90      * The name is intentionally made different from Activity#finish(), so that
     91      * users won't misunderstand its meaning.
     92      */
     93     public final void finishFragment() {
     94         getActivity().onBackPressed();
     95     }
     96 
     97     // Some helpers for functions used by the settings fragments when they were activities
     98 
     99     /**
    100      * Returns the ContentResolver from the owning Activity.
    101      */
    102     protected ContentResolver getContentResolver() {
    103         return getActivity().getContentResolver();
    104     }
    105 
    106     /**
    107      * Returns the specified system service from the owning Activity.
    108      */
    109     protected Object getSystemService(final String name) {
    110         return getActivity().getSystemService(name);
    111     }
    112 
    113     /**
    114      * Returns the PackageManager from the owning Activity.
    115      */
    116     protected PackageManager getPackageManager() {
    117         return getActivity().getPackageManager();
    118     }
    119 
    120     @Override
    121     public void onDetach() {
    122         if (isRemoving()) {
    123             if (mDialogFragment != null) {
    124                 mDialogFragment.dismiss();
    125                 mDialogFragment = null;
    126             }
    127         }
    128         super.onDetach();
    129     }
    130 
    131     // Dialog management
    132 
    133     protected void showDialog(int dialogId) {
    134         if (mDialogFragment != null) {
    135             Log.e(TAG, "Old dialog fragment not null!");
    136         }
    137         mDialogFragment = new SettingsDialogFragment(this, dialogId);
    138         mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
    139     }
    140 
    141     public Dialog onCreateDialog(int dialogId) {
    142         return null;
    143     }
    144 
    145     protected void removeDialog(int dialogId) {
    146         // mDialogFragment may not be visible yet in parent fragment's onResume().
    147         // To be able to dismiss dialog at that time, don't check
    148         // mDialogFragment.isVisible().
    149         if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) {
    150             mDialogFragment.dismiss();
    151         }
    152         mDialogFragment = null;
    153     }
    154 
    155     /**
    156      * Sets the OnCancelListener of the dialog shown. This method can only be
    157      * called after showDialog(int) and before removeDialog(int). The method
    158      * does nothing otherwise.
    159      */
    160     protected void setOnCancelListener(DialogInterface.OnCancelListener listener) {
    161         if (mDialogFragment != null) {
    162             mDialogFragment.mOnCancelListener = listener;
    163         }
    164     }
    165 
    166     /**
    167      * Sets the OnDismissListener of the dialog shown. This method can only be
    168      * called after showDialog(int) and before removeDialog(int). The method
    169      * does nothing otherwise.
    170      */
    171     protected void setOnDismissListener(DialogInterface.OnDismissListener listener) {
    172         if (mDialogFragment != null) {
    173             mDialogFragment.mOnDismissListener = listener;
    174         }
    175     }
    176 
    177     public static class SettingsDialogFragment extends DialogFragment {
    178         private static final String KEY_DIALOG_ID = "key_dialog_id";
    179         private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id";
    180 
    181         private int mDialogId;
    182 
    183         private Fragment mParentFragment;
    184 
    185         private DialogInterface.OnCancelListener mOnCancelListener;
    186         private DialogInterface.OnDismissListener mOnDismissListener;
    187 
    188         public SettingsDialogFragment() {
    189             /* do nothing */
    190         }
    191 
    192         public SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
    193             mDialogId = dialogId;
    194             if (!(fragment instanceof Fragment)) {
    195                 throw new IllegalArgumentException("fragment argument must be an instance of "
    196                         + Fragment.class.getName());
    197             }
    198             mParentFragment = (Fragment) fragment;
    199         }
    200 
    201         @Override
    202         public void onSaveInstanceState(Bundle outState) {
    203             super.onSaveInstanceState(outState);
    204             if (mParentFragment != null) {
    205                 outState.putInt(KEY_DIALOG_ID, mDialogId);
    206                 outState.putInt(KEY_PARENT_FRAGMENT_ID, mParentFragment.getId());
    207             }
    208         }
    209 
    210         @Override
    211         public Dialog onCreateDialog(Bundle savedInstanceState) {
    212             if (savedInstanceState != null) {
    213                 mDialogId = savedInstanceState.getInt(KEY_DIALOG_ID, 0);
    214                 int mParentFragmentId = savedInstanceState.getInt(KEY_PARENT_FRAGMENT_ID, -1);
    215                 if (mParentFragmentId > -1) {
    216                     mParentFragment = getFragmentManager().findFragmentById(mParentFragmentId);
    217                     if (!(mParentFragment instanceof DialogCreatable)) {
    218                         throw new IllegalArgumentException(
    219                                 KEY_PARENT_FRAGMENT_ID + " must implement "
    220                                         + DialogCreatable.class.getName());
    221                     }
    222                 }
    223                 // This dialog fragment could be created from non-SettingsPreferenceFragment
    224                 if (mParentFragment instanceof SettingsPreferenceFragment) {
    225                     // restore mDialogFragment in mParentFragment
    226                     ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = this;
    227                 }
    228             }
    229             return ((DialogCreatable) mParentFragment).onCreateDialog(mDialogId);
    230         }
    231 
    232         @Override
    233         public void onCancel(DialogInterface dialog) {
    234             super.onCancel(dialog);
    235             if (mOnCancelListener != null) {
    236                 mOnCancelListener.onCancel(dialog);
    237             }
    238         }
    239 
    240         @Override
    241         public void onDismiss(DialogInterface dialog) {
    242             super.onDismiss(dialog);
    243             if (mOnDismissListener != null) {
    244                 mOnDismissListener.onDismiss(dialog);
    245             }
    246         }
    247 
    248         public int getDialogId() {
    249             return mDialogId;
    250         }
    251 
    252         @Override
    253         public void onDetach() {
    254             super.onDetach();
    255 
    256             // This dialog fragment could be created from non-SettingsPreferenceFragment
    257             if (mParentFragment instanceof SettingsPreferenceFragment) {
    258                 // in case the dialog is not explicitly removed by removeDialog()
    259                 if (((SettingsPreferenceFragment) mParentFragment).mDialogFragment == this) {
    260                     ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = null;
    261                 }
    262             }
    263         }
    264     }
    265 
    266     protected boolean hasNextButton() {
    267         return ((ButtonBarHandler)getActivity()).hasNextButton();
    268     }
    269 
    270     protected Button getNextButton() {
    271         return ((ButtonBarHandler)getActivity()).getNextButton();
    272     }
    273 
    274     public void finish() {
    275         getActivity().onBackPressed();
    276     }
    277 
    278     public boolean startFragment(
    279             Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
    280         if (getActivity() instanceof PreferenceActivity) {
    281             PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
    282             preferenceActivity.startPreferencePanel(fragmentClass, extras,
    283                     R.string.lock_settings_picker_title, null, caller, requestCode);
    284             return true;
    285         } else {
    286             Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
    287                     + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
    288                     + ")");
    289             return false;
    290         }
    291     }
    292 
    293 }
    294