com.microsoft.onenote.pickerlib.OneNotePickerActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.onenote.pickerlib.OneNotePickerActivity.java

Source

//----------------------------------------------------------------------------
//  Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
//  Licensed under the Apache License, Version 2.0.
//  See License.txt in the project root for license information.
//----------------------------------------------------------------------------
package com.microsoft.onenote.pickerlib;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.ProgressBar;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONObject;

public class OneNotePickerActivity extends ActionBarActivity {

    private int mNavTextColor = -1;
    private String mAccessToken;

    private ControllerFragment mControllerFragment;
    private PickerListFragment mNotebooksFragment;
    private OneNotePickerThemeColor mThemeColor;

    private void setUpActionBar() {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayShowHomeEnabled(false); //remove actionbar icon

        if (mNavTextColor != -1) {
            actionBar.setHomeAsUpIndicator(
                    UiUtility.colorizedDrawable(this, mNavTextColor, R.drawable.ic_back_arrow));
        }

        //default settings
        updateActionBar(getString(R.string.text_notebooks), getString(R.string.text_onenote), false);
    }

    private void readExtras() {
        Intent intent = getIntent();
        mNavTextColor = intent.getIntExtra("NAV_TEXT_COLOR", -1);
        mAccessToken = intent.getStringExtra("ACCESS_TOKEN");
        mThemeColor = (OneNotePickerThemeColor) intent.getSerializableExtra("THEME_COLOR");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Handle uncaught and system exceptions
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable throwable) {
                handleError(throwable);
            }
        });

        // Use the slide in animation
        overridePendingTransition(R.anim.slide_in, R.anim.hold);

        readExtras();

        // Determine the theme to use
        if (mThemeColor == null || mThemeColor == OneNotePickerThemeColor.LIGHT) {
            setTheme(R.style.OneNotePicker_Light);
        } else if (mThemeColor == OneNotePickerThemeColor.DARK) {
            setTheme(R.style.OneNotePicker_Dark);
        }

        setUpActionBar();

        setContentView(R.layout.activity_onenote_picker);

        // Retrieve the controller fragment
        FragmentManager fm = getSupportFragmentManager();
        mControllerFragment = (ControllerFragment) fm.findFragmentByTag("controller");

        if (savedInstanceState == null) {
            mNotebooksFragment = new PickerListFragment(new UiActionBarSettings(getString(R.string.text_notebooks),
                    getString(R.string.text_onenote), false));

            mNotebooksFragment.mLoading = true;

            // Create the controller fragment the first time
            if (mControllerFragment == null) {
                mControllerFragment = new ControllerFragment(mAccessToken, mNotebooksFragment);
                fm.beginTransaction().add(mControllerFragment, "controller").commit();
            }

            // Show the first fragment
            addFragment(mNotebooksFragment);
        }

    }

    @Override
    public void onBackPressed() {
        if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
            cancelPickerActivity();
        }
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        // Use the slide out animation
        overridePendingTransition(R.anim.hold, R.anim.slide_out);
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        if (isFinishing()) {
            mControllerFragment.cleanup();
            mControllerFragment = null;
            mNotebooksFragment = null;
        }
        super.onDestroy();
    }

    protected void updateActionBar(UiActionBarSettings settings) {
        this.updateActionBar(settings.getTitle(), settings.getSubtitle(), settings.getShowArrow());
    }

    protected void updateActionBarTitle(String title) {
        updateActionBar(title, null, null);
    }

    protected void updateActionBarSubTitle(String subtitle) {
        updateActionBar(null, subtitle, null);
    }

    private void updateActionBar(String title, String subtitle, Boolean displayHomeAsUpEnabled) {
        ActionBar actionBar = getSupportActionBar();

        if (mNavTextColor == -1) {
            if (title != null) {
                actionBar.setSubtitle(title); // Action Bar's Subtitle as our "Main Title"
            }
            if (subtitle != null) {
                actionBar.setTitle(subtitle); // Action Bar's Title as our "Sub Title"
            }
        } else {
            // Display titles with custom text color
            if (title != null) {
                actionBar.setSubtitle(UiUtility.colorizedText(mNavTextColor, title));
            }
            if (subtitle != null) {
                actionBar.setTitle(UiUtility.colorizedText(UiUtility.adjustAlpha(mNavTextColor, 153), subtitle));
            }
        }

        if (displayHomeAsUpEnabled != null) {
            // Display the back arrow or not
            actionBar.setDisplayHomeAsUpEnabled(displayHomeAsUpEnabled);
            actionBar.setHomeButtonEnabled(displayHomeAsUpEnabled);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_onenote_picker, menu);

        if (mNavTextColor != -1) {
            menu.findItem(R.id.action_close)
                    .setIcon(UiUtility.colorizedDrawable(this, mNavTextColor, R.drawable.ic_action_close_dark));
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_close) {
            // Cancel & close activity
            cancelPickerActivity();
        } else if (id == android.R.id.home) {
            this.onBackPressed();
        }
        return super.onOptionsItemSelected(item);
    }

    // Drill down on a fragment
    protected void showFragment(Fragment fragment) {
        if (fragment != null) {
            getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack("ONP")
                    .commit();
        }
    }

    // Show the very first fragment
    protected void addFragment(Fragment fragment) {
        if (fragment != null) {
            getSupportFragmentManager().beginTransaction().add(R.id.container, fragment).commit();
        }
    }

    // Clicking on an item can either return (if it is a section) or drill down (if it is a notebook or section group)
    protected void handlePickerItemClick(PickerListFragment parent, UiPickerItemModel model) {
        if (model.getType() == UiPickerItemType.SECTION) {
            Intent resultIntent = new Intent();
            ApiSectionResponse response = (ApiSectionResponse) model.getResultData();
            resultIntent.putExtra("SECTION_ID", response.getId());
            resultIntent.putExtra("SECTION_NAME", response.getName());
            resultIntent.putExtra("PAGES_URL", response.getPagesUrl());
            resultIntent.putExtra("CREATED_TIME", response.getCreatedTime());
            resultIntent.putExtra("MODIFIED_TIME", response.getModifiedTime());
            resultIntent.putExtra("LAST_MODIFIED_BY", response.getLastModifiedBy());
            closePickerActivity(RESULT_OK, resultIntent);
        } else {
            showFragment(mControllerFragment.getPickerFragment(parent, model));
        }
    }

    // Handle any type of exception that was thrown
    protected void handleError(Throwable exception) {
        boolean apiError;
        Intent resultIntent = new Intent();
        resultIntent.putExtra("USER_CANCELLED", false);
        if (exception instanceof ApiException) {
            apiError = true;
            ApiException apiException = (ApiException) exception;
            resultIntent.putExtra("API_ERROR_CODE", apiException.getErrorCode());
            resultIntent.putExtra("API_ERROR_STRING", apiException.getErrorMessage());
            resultIntent.putExtra("API_ERROR_URL", apiException.getErrorUrl());
        } else {
            apiError = false;
            resultIntent.putExtra("SYSTEM_EXCEPTION", exception);
        }
        resultIntent.putExtra("API_ERROR", apiError);

        closePickerActivity(RESULT_CANCELED, resultIntent);
    }

    private void closePickerActivity(int resultCode, Intent resultIntent) {
        setResult(resultCode, resultIntent);
        if (!isFinishing()) {
            finish();
        }
    }

    private void cancelPickerActivity() {
        Intent resultIntent = new Intent();
        resultIntent.putExtra("USER_CANCELLED", true);
        closePickerActivity(RESULT_CANCELED, resultIntent);
    }

    @SuppressLint("ValidFragment")
    private class ControllerFragment extends RetainedFragment {

        private ApiController mApiController;

        private HashMap<ApiResponse, PickerListFragment> mPickerListFragments = new HashMap<ApiResponse, PickerListFragment>();

        private String mAccessToken;

        private PickerListFragment mStartFragment;

        public ControllerFragment(String mAccessToken, PickerListFragment startFragment) {
            this.mAccessToken = mAccessToken;
            this.mStartFragment = startFragment;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            mApiController = new ApiController(mAccessToken) {
                // On an API response, check for failures, then populate fragments recursively
                @Override
                public void onApiResponse(ApiNotebookResponse[] responses, Exception error) {

                    if (error != null) {
                        ((OneNotePickerActivity) getActivity()).handleError(error);
                        return;
                    }

                    for (int i = 0; i < responses.length; i++) {
                        ApiNotebookResponse notebookResponse = responses[i];

                        // Add to start fragment models
                        mStartFragment.mLoadedModels.add(new UiPickerItemModel(UiPickerItemType.NOTEBOOK,
                                notebookResponse.getName(), notebookResponse));

                        // Cycle through the returned notebooks and populate mPickerListFragments
                        PickerListFragment notebookFragment = new PickerListFragment(
                                new UiActionBarSettings(notebookResponse.getName(), null, null));

                        // Also populate their children sections/sectionGroups
                        addSectionsToFragment(notebookResponse.sections, notebookFragment);
                        addSectionGroupsToFragment(notebookResponse.sectionGroups, notebookFragment);

                        notebookFragment.updateListAdapterWithModels();
                        // Add the notebook to mPickerListFragments
                        mPickerListFragments.put(notebookResponse, notebookFragment);
                    }

                    mStartFragment.updateListAdapterWithModels();
                }

                // Add sections to fragment
                private void addSectionsToFragment(List<ApiSectionResponse> sections, PickerListFragment fragment) {
                    for (int k = 0; k < sections.size(); k++) {
                        ApiSectionResponse sectionResponse = sections.get(k);
                        fragment.mLoadedModels.add(new UiPickerItemModel(UiPickerItemType.SECTION,
                                sectionResponse.getName(), sectionResponse));
                    }
                }

                // Add sectionGroups to a fragment, and to mPickerListFragments
                private void addSectionGroupsToFragment(List<ApiSectionGroupResponse> sectionGroups,
                        PickerListFragment fragment) {
                    for (int k = 0; k < sectionGroups.size(); k++) {
                        ApiSectionGroupResponse sectionGroupResponse = sectionGroups.get(k);
                        fragment.mLoadedModels.add(new UiPickerItemModel(UiPickerItemType.SECTION_GROUP,
                                sectionGroupResponse.getName(), sectionGroupResponse));

                        // This section group should also be its own fragment - Add it to mPickerListFragments
                        PickerListFragment sectionGroupFragment = new PickerListFragment(
                                new UiActionBarSettings(sectionGroupResponse.getName(), null, null));
                        // Also populate their children sections/sectionGroups
                        addSectionsToFragment(sectionGroupResponse.sections, sectionGroupFragment);
                        addSectionGroupsToFragment(sectionGroupResponse.sectionGroups, sectionGroupFragment);

                        sectionGroupFragment.updateListAdapterWithModels();

                        mPickerListFragments.put(sectionGroupResponse, sectionGroupFragment);
                    }
                }
            };
            mApiController.begin();
        }

        public PickerListFragment getPickerFragment(PickerListFragment parent, UiPickerItemModel model) {
            PickerListFragment fragment = mPickerListFragments.get(model.getResultData());
            if (fragment != null) {
                fragment.getActionBarSettings().setShowArrow(true);
                fragment.getActionBarSettings().setSubtitle(parent.getActionBarSettings().getTitle());
                fragment.updateListAdapterWithModels();
            }
            return fragment;
        }

        public void cleanup() {
            mPickerListFragments.clear();
            mStartFragment = null;
        }
    }

    /**
     * A fragment that acts as an API response controller and a picker list view
     */
    @SuppressLint("ValidFragment")
    private class PickerListFragment extends RetainedFragment implements AdapterView.OnItemClickListener {

        private UiPickerListAdapter mListAdapter = null;
        private List<UiPickerItemModel> mLoadedModels = new ArrayList<UiPickerItemModel>();
        private UiActionBarSettings mActionBarSettings;
        private OneNotePickerActivity mPickerActivity;

        // Used exclusively for the progressbar showing/hiding on the first API call
        public boolean mLoading = false;

        public PickerListFragment(UiActionBarSettings actionBarSettings) {
            mActionBarSettings = actionBarSettings;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_picker_list, container, false);

            mPickerActivity = ((OneNotePickerActivity) getActivity());

            // set up parent activity's action bar
            mPickerActivity.updateActionBar(mActionBarSettings);

            // set up list view & adapter
            ListView listView = (ListView) rootView.findViewById(R.id.listView);
            if (mListAdapter == null) {
                mListAdapter = new UiPickerListAdapter(mPickerActivity, new ArrayList<UiPickerItemModel>());
                mListAdapter.setNotifyOnChange(false);
            }
            listView.setAdapter(mListAdapter);

            listView.setOnItemClickListener(this);

            // loading spinner
            final ProgressBar loadingSpinner = (ProgressBar) rootView.findViewById(R.id.progressBar);

            // handle if data has not been loaded
            if (mLoading) {

                loadingSpinner.setVisibility(View.VISIBLE);

                // update the action bar to its original title after data has loaded
                mListAdapter.registerDataSetObserver(new DataSetObserver() {
                    @Override
                    public void onChanged() {
                        super.onChanged();
                        if (PickerListFragment.this.isVisible()) {
                            loadingSpinner.setVisibility(View.GONE);
                        }
                    }
                });
            } else {
                updateListAdapterWithModels();
            }
            return rootView;
        }

        public void updateListAdapterWithModels() {
            if (mLoadedModels != null && mListAdapter != null) {
                mLoading = false;
                mListAdapter.clear();
                for (UiPickerItemModel model : mLoadedModels) {
                    mListAdapter.add(model);
                }
                mListAdapter.notifyDataSetChanged();
            }
        }

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            mPickerActivity.handlePickerItemClick(this, mListAdapter.getItem(i));
        }

        public UiActionBarSettings getActionBarSettings() {
            return mActionBarSettings;
        }
    }

    @SuppressLint("ValidFragment")
    private class RetainedFragment extends Fragment {

        @Override
        public void onDetach() {
            super.onDetach();
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // retain this fragment
            setRetainInstance(true);
        }
    }
}