Breadcrumbs in the action bar for navigating up one level and showing current title.

Change-Id: I595e06549b888bd67c6dddd599a4cc77416c3a41
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 2ce0bcc..50aa1df 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.Fragment;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.preference.Preference;
@@ -25,8 +26,13 @@
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
 import android.text.TextUtils;
+import android.util.AttributeSet;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import java.util.ArrayList;
 
@@ -37,6 +43,8 @@
         implements PreferenceFragment.OnPreferenceStartFragmentCallback,
         SettingsPreferenceFragment.OnStateListener {
 
+    private static final boolean DBG = false;
+
     private static final String TAG = "Settings";
 
     private static final String KEY_PARENT = "parent";
@@ -52,22 +60,13 @@
 
     public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
 
-    // Temporary, until all top-level settings are converted to fragments
     private static final String BACK_STACK_PREFS = ":settings:prefs";
 
     private View mPrefsPane;
     private View mMainPane;
     private boolean mSinglePane;
 
-    private ArrayList<CharSequence> mTrail = new ArrayList<CharSequence>();
-
-    /*
-    @Override
-    protected void onResume() {
-        super.onResume();
-        findPreference(KEY_CALL_SETTINGS).setEnabled(!AirplaneModeEnabler.isAirplaneModeOn(this));
-    }
-    */
+    private BreadCrumbs mBreadCrumbs;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -82,6 +81,8 @@
         String initialFragment = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
         Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
 
+        createActionBar();
+
         if (mSinglePane) {
             if (initialFragment != null) {
                 showFragment(initialFragment, initialArguments);
@@ -111,11 +112,21 @@
         }
     }
 
+    private void createActionBar() {
+        LayoutInflater inflater = (LayoutInflater)
+                getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        View customNavBar = inflater.inflate(R.layout.settings_actionbar, null, false);
+        getActionBar().setCustomNavigationMode(customNavBar);
+        mBreadCrumbs = (BreadCrumbs) customNavBar.findViewById(R.id.bread_crumbs);
+        mBreadCrumbs.setActivity(this);
+    }
+
     boolean showFragment(Preference preference) {
         if (mSinglePane) {
             startWithFragment(preference.getFragment(), preference.getExtras());
             return false;
         } else {
+            mBreadCrumbs.clear();
             return showFragment(preference.getFragment(), preference.getExtras());
         }
     }
@@ -129,10 +140,13 @@
     }
 
     private boolean showFragment(String fragmentClass, Bundle extras) {
-        Fragment f = Fragment.instantiate(this, fragmentClass, extras);
+        if (DBG) Log.d(TAG, "showFragment");
+       Fragment f = Fragment.instantiate(this, fragmentClass, extras);
         if (f instanceof SettingsPreferenceFragment) {
             ((SettingsPreferenceFragment) f).setOnStateListener(this);
         }
+        mBreadCrumbs.clear();
+        getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
         getFragmentManager().openTransaction().replace(R.id.prefs, f).commit();
         return true;
     }
@@ -140,41 +154,28 @@
     private void addToBreadCrumbs(Fragment fragment) {
         final CharSequence title = ((PreferenceFragment) fragment)
                 .getPreferenceScreen().getTitle();
-        if (mSinglePane) mTrail.clear();
-        if (mTrail.size() == 0 || !TextUtils.equals(title, mTrail.get(mTrail.size() - 1))) {
-            mTrail.add(title);
-            updateTitle();
+        if (mSinglePane) {
+            mBreadCrumbs.clear();
         }
+        mBreadCrumbs.push(title);
     }
 
     private void removeFromBreadCrumbs(Fragment fragment) {
-        if (mTrail.size() > 0) {
-            mTrail.remove(mTrail.size() - 1);
-        }
-        updateTitle();
-    }
-
-    private void updateTitle() {
-        String trail = "";
-        for (CharSequence trailPart : mTrail) {
-            if (trail.length() != 0)
-                trail += " | ";
-            trail = trail + trailPart;
-        }
-        setTitle(trail);
+        mBreadCrumbs.pop(((PreferenceFragment) fragment).getPreferenceScreen().getTitle());
+        mBreadCrumbs.update();
     }
 
     public void onCreated(SettingsPreferenceFragment fragment) {
-        Log.d(TAG, "Fragment created " + fragment + " (name: " + fragment.getClass() + ")");
+        if (DBG) Log.d(TAG, "Fragment created " + fragment);
         addToBreadCrumbs(fragment);
     }
 
     public void onDestroyed(SettingsPreferenceFragment fragment) {
-        removeFromBreadCrumbs(fragment);
         Log.d(TAG, "Fragment destroyed " + fragment + " (name: " + fragment.getClass() + ")");
     }
 
     public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
+        if (DBG) Log.d(TAG, "onPreferenceStartFragment");
         Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras());
         if (f instanceof SettingsPreferenceFragment) {
             ((SettingsPreferenceFragment) f).setOnStateListener(this);
@@ -184,6 +185,13 @@
         return true;
     }
 
+    @Override
+    public void onBackPressed() {
+        mBreadCrumbs.pop();
+        mBreadCrumbs.update();
+        super.onBackPressed();
+    }
+
     public static class TopLevelSettings extends PreferenceFragment {
 
         private IconPreferenceScreen mHighlightedPreference;
@@ -198,6 +206,21 @@
             updatePreferenceList();
         }
 
+        @Override
+        public void onResume() {
+            super.onResume();
+
+            updateCallSettings();
+        }
+
+        private void updateCallSettings() {
+            Preference callSettings = findPreference(KEY_CALL_SETTINGS);
+            // Might have been removed in non-voice-capable devices
+            if (callSettings != null) {
+                callSettings.setEnabled(!AirplaneModeEnabler.isAirplaneModeOn(getActivity()));
+            }
+        }
+
         private void updatePreferenceList() {
             final Activity activity = getActivity();
             PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
@@ -247,4 +270,91 @@
             onPreferenceTreeClick(getPreferenceScreen(), first);
         }
     }
+
+    public static class BreadCrumbs extends LinearLayout implements OnClickListener {
+
+        private ArrayList<CharSequence> mTitles = new ArrayList<CharSequence>();
+        private TextView mLevelUpTitle;
+        private TextView mCurrentLevelTitle;
+        private View mDivider;
+        private Activity mActivity;
+
+        public BreadCrumbs(Context context) {
+            this(context, null);
+        }
+
+        public BreadCrumbs(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public void push(CharSequence title) {
+            if (mTitles.size() == 0
+                    || !TextUtils.equals(title, mTitles.get(mTitles.size() - 1))) {
+                mTitles.add(title);
+                update();
+            }
+        }
+
+        public void pop() {
+            if (mTitles.size() > 0) {
+                mTitles.remove(mTitles.size() - 1);
+            }
+        }
+
+        public void pop(CharSequence title) {
+            if (mTitles.size() > 1) {
+                mTitles.remove(title);
+            }
+        }
+
+        public void clear() {
+            mTitles.clear();
+        }
+
+        private void initNavViews() {
+            if (mLevelUpTitle == null) {
+                mLevelUpTitle = (TextView) findViewById(R.id.level_up_title);
+                mCurrentLevelTitle = (TextView) findViewById(R.id.level_current_title);
+                mDivider = findViewById(R.id.level_divider);
+                if (mLevelUpTitle != null) {
+                    mLevelUpTitle.setOnClickListener(this);
+                }
+                if (mCurrentLevelTitle != null) {
+                    mCurrentLevelTitle.setOnClickListener(this);
+                }
+            }
+        }
+
+        public void update() {
+            initNavViews();
+            if (mLevelUpTitle == null) return;
+
+            final int titleCount = mTitles.size();
+            if (titleCount > 1) {
+                mLevelUpTitle.setText(mTitles.get(titleCount - 2));
+                mLevelUpTitle.setVisibility(VISIBLE);
+                mDivider.setVisibility(VISIBLE);
+            } else {
+                mLevelUpTitle.setVisibility(GONE);
+                mDivider.setVisibility(GONE);
+            }
+            if (titleCount > 0) {
+                mCurrentLevelTitle.setText(mTitles.get(titleCount - 1));
+            } else {
+                mCurrentLevelTitle.setText("");
+            }
+        }
+
+        public void setActivity(Activity activity) {
+            mActivity = activity;
+        }
+
+        public void onClick(View v) {
+            if (mActivity == null)
+                return;
+            if (v == mLevelUpTitle) {
+                mActivity.onBackPressed();
+            }
+        }
+    }
 }