com.ultramegasoft.flavordex2.EntryListActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.ultramegasoft.flavordex2.EntryListActivity.java

Source

/*
 * The MIT License (MIT)
 * Copyright  2016 Steve Guidetti
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the Software?), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED AS IS?, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.ultramegasoft.flavordex2;

import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;

import com.ultramegasoft.flavordex2.dialog.AboutDialog;
import com.ultramegasoft.flavordex2.dialog.AppChooserDialog;
import com.ultramegasoft.flavordex2.dialog.FileImportDialog;
import com.ultramegasoft.flavordex2.dialog.FileSelectorDialog;
import com.ultramegasoft.flavordex2.fragment.CatListFragment;
import com.ultramegasoft.flavordex2.fragment.EntryListFragment;
import com.ultramegasoft.flavordex2.fragment.EntrySearchFragment;
import com.ultramegasoft.flavordex2.fragment.ViewEntryFragment;
import com.ultramegasoft.flavordex2.fragment.WelcomeFragment;
import com.ultramegasoft.flavordex2.provider.Tables;
import com.ultramegasoft.flavordex2.util.AppImportUtils;
import com.ultramegasoft.flavordex2.util.FileUtils;
import com.ultramegasoft.flavordex2.util.PermissionUtils;

/**
 * The main application Activity. This shows a list of the categories or all the journal entries in
 * a category. On narrow screens, selecting an entry launches a new Activity to show details. On
 * wide screens, selecting an entry shows details in a Fragment in this Activity.
 *
 * @author Steve Guidetti
 */
public class EntryListActivity extends AppCompatActivity implements FileSelectorDialog.OnFileSelectedCallbacks {
    /**
     * Request codes for external Activities
     */
    private static final int REQUEST_SEARCH = 300;

    /**
     * Keys for the saved state
     */
    private static final String STATE_SELECTED_CAT = "selected_cat";
    private static final String STATE_SELECTED_ENTRY = "selected_entry";
    private static final String STATE_FILTERS = "filters";

    /**
     * Whether the Activity is in two-pane mode
     */
    private boolean mTwoPane;

    /**
     * Fragment to show in two-pane mode when no item is selected
     */
    @Nullable
    private Fragment mWelcomeFragment;

    /**
     * The category list Fragment
     */
    private final Fragment mCatListFragment = new CatListFragment();

    /**
     * The currently selected category
     */
    private long mSelectedCat = -1;

    /**
     * The currently selected journal entry
     */
    private long mSelectedItem = -1;

    /**
     * Map of filters to populate the filter fragment
     */
    @Nullable
    private ContentValues mFilters;

    /**
     * The result returned by the search Activity
     */
    @Nullable
    private Intent mSearchResult;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_entry_list);

        if (findViewById(R.id.entry_detail_container) != null) {
            mTwoPane = true;
            mWelcomeFragment = new WelcomeFragment();
        }

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().add(R.id.entry_list, mCatListFragment).commit();
            if (mTwoPane) {
                getSupportFragmentManager().beginTransaction().add(R.id.entry_detail_container, mWelcomeFragment)
                        .commit();
            }

            loadPreferences(PreferenceManager.getDefaultSharedPreferences(this));

            PermissionUtils.checkExternalStoragePerm(this, R.string.message_request_storage);
        } else {
            mSelectedCat = savedInstanceState.getLong(STATE_SELECTED_CAT, mSelectedCat);
            mSelectedItem = savedInstanceState.getLong(STATE_SELECTED_ENTRY, mSelectedItem);
            mFilters = savedInstanceState.getParcelable(STATE_FILTERS);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(STATE_SELECTED_CAT, mSelectedCat);
        outState.putLong(STATE_SELECTED_ENTRY, mSelectedItem);
        outState.putParcelable(STATE_FILTERS, mFilters);
    }

    /**
     * Load the Shared Preferences for the Activity.
     *
     * @param prefs The default SharedPreferences
     */
    private void loadPreferences(@NonNull SharedPreferences prefs) {
        if (prefs.getBoolean(FlavordexApp.PREF_FIRST_RUN, true)) {
            if (AppImportUtils.isAnyAppInstalled(this)) {
                AppChooserDialog.showDialog(getSupportFragmentManager(), true);
            }
            prefs.edit().putBoolean(FlavordexApp.PREF_FIRST_RUN, false).apply();
        }

        final int oldVersion = prefs.getInt(FlavordexApp.PREF_VERSION, 0);
        final int newVersion = BuildConfig.VERSION_CODE;
        if (newVersion > oldVersion) {
            prefs.edit().putInt(FlavordexApp.PREF_VERSION, newVersion).apply();
        }

        final long catId = prefs.getLong(FlavordexApp.PREF_LIST_CAT_ID, -1);
        if (catId > -1) {
            onCatSelected(catId, false);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        final boolean showFileXport = Environment.getExternalStorageDirectory().canWrite()
                || PermissionUtils.shouldAskExternalStoragePerm(this);
        final boolean showAppImport = AppImportUtils.isAnyAppInstalled(this);
        menu.findItem(R.id.menu_xport).setVisible(showFileXport || showAppImport);
        menu.findItem(R.id.menu_import).setVisible(showFileXport);
        menu.findItem(R.id.menu_export).setVisible(showFileXport);
        menu.findItem(R.id.menu_import_app).setVisible(showAppImport);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_search:
            onOpenSearch();
            return true;
        case R.id.menu_import:
            if (!PermissionUtils.checkExternalStoragePerm(this, R.string.message_request_storage_xport)) {
                return true;
            }
            final String rootPath = Environment.getExternalStorageDirectory().getPath();
            FileSelectorDialog.showDialog(getSupportFragmentManager(), null, 0, rootPath, false,
                    new String[] { FileUtils.EXT_CSV, FileUtils.EXT_ZIP });
            return true;
        case R.id.menu_import_app:
            AppChooserDialog.showDialog(getSupportFragmentManager(), false);
            return true;
        case R.id.menu_export:
            if (PermissionUtils.checkExternalStoragePerm(this, R.string.message_request_storage_xport)) {
                enableExportMode();
            }
            return true;
        case R.id.menu_settings:
            startActivity(new Intent(this, SettingsActivity.class));
            return true;
        case R.id.menu_about:
            AboutDialog.showDialog(getSupportFragmentManager());
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionUtils.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_SEARCH && resultCode == RESULT_OK) {
            mSearchResult = data;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mSearchResult != null) {
            final ContentValues filters = mSearchResult.getParcelableExtra(EntrySearchFragment.EXTRA_FILTERS);
            final String where = mSearchResult.getStringExtra(EntrySearchFragment.EXTRA_WHERE);
            final String[] whereArgs = mSearchResult.getStringArrayExtra(EntrySearchFragment.EXTRA_WHERE_ARGS);
            onSearchSubmitted(filters, where, whereArgs);
            mSearchResult = null;
        }
    }

    /**
     * Called by the CatListFragment when an item is selected.
     *
     * @param id         The category ID
     * @param exportMode Whether to start the entry list Fragment in export mode
     */
    public void onCatSelected(long id, boolean exportMode) {
        mSelectedCat = id;
        final Fragment fragment;
        if (id < 0) {
            fragment = mCatListFragment;
            mFilters = null;
        } else {
            fragment = EntryListFragment.getInstance(id, mTwoPane, mSelectedItem, exportMode, null, null);
        }
        getSupportFragmentManager().beginTransaction().replace(R.id.entry_list, fragment).commit();
    }

    /**
     * Called by the EntryListFragment when an item is selected.
     *
     * @param id      The entry ID
     * @param catName The name of the entry category
     * @param catId   The ID of the entry category
     */
    public void onItemSelected(long id, @Nullable String catName, long catId) {
        if (mTwoPane) {
            mSelectedItem = id;
            final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            final Fragment fragment;
            if (id == -1) {
                fragment = mWelcomeFragment;
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
            } else {
                final Bundle args = new Bundle();
                args.putLong(ViewEntryFragment.ARG_ENTRY_ID, id);
                args.putString(ViewEntryFragment.ARG_ENTRY_CAT, catName);
                args.putLong(ViewEntryFragment.ARG_ENTRY_CAT_ID, catId);

                fragment = new ViewEntryFragment();
                fragment.setArguments(args);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            }

            ft.replace(R.id.entry_detail_container, fragment).commit();
        } else {
            final Intent intent = new Intent(this, ViewEntryActivity.class);
            intent.putExtra(ViewEntryFragment.ARG_ENTRY_ID, id);
            intent.putExtra(ViewEntryFragment.ARG_ENTRY_CAT, catName);
            intent.putExtra(ViewEntryFragment.ARG_ENTRY_CAT_ID, catId);
            startActivity(intent);
        }
    }

    /**
     * Open the search page.
     */
    private void onOpenSearch() {
        if (mTwoPane) {
            final FragmentManager fm = getSupportFragmentManager();
            if (fm.findFragmentById(R.id.entry_detail_container) instanceof EntrySearchFragment) {
                return;
            }
            final Bundle args = new Bundle();
            args.putLong(EntrySearchFragment.ARG_CAT_ID, mSelectedCat);
            args.putParcelable(EntrySearchFragment.ARG_FILTERS, mFilters);
            final Fragment fragment = new EntrySearchFragment();
            fragment.setArguments(args);
            fm.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .replace(R.id.entry_detail_container, fragment).commit();
        } else {
            final Intent intent = new Intent(this, EntrySearchActivity.class);
            intent.putExtra(EntrySearchActivity.EXTRA_FILTERS, mFilters);
            startActivityForResult(intent, REQUEST_SEARCH);
        }
    }

    /**
     * Open the entry list with search results.
     *
     * @param filters   The filter values
     * @param where     The where clause
     * @param whereArgs The values for the parameters of the where clause
     */
    public void onSearchSubmitted(@NonNull ContentValues filters, @NonNull String where,
            @NonNull String[] whereArgs) {
        mFilters = filters;
        final long catId = filters.getAsLong(Tables.Entries.CAT_ID);
        final Fragment fragment = EntryListFragment.getInstance(catId, mTwoPane, mSelectedItem, false, where,
                whereArgs);
        getSupportFragmentManager().beginTransaction().replace(R.id.entry_list, fragment).commit();
    }

    @Override
    public void onFileSelected(@NonNull String filePath) {
        FileImportDialog.showDialog(getSupportFragmentManager(), filePath);
    }

    /**
     * Enable export mode.
     */
    private void enableExportMode() {
        final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.entry_list);
        if (fragment instanceof EntryListFragment) {
            ((EntryListFragment) fragment).setExportMode(true, true);
        } else {
            onCatSelected(0, true);
        }
    }

    @Override
    public void onBackPressed() {
        if (mTwoPane) {
            final FragmentManager fm = getSupportFragmentManager();
            Fragment fragment = fm.findFragmentById(R.id.entry_detail_container);
            if (fragment instanceof ViewEntryFragment) {
                if (!((ViewEntryFragment) fragment).onBackButtonPressed()) {
                    fragment = fm.findFragmentById(R.id.entry_list);
                    if (fragment instanceof EntryListFragment) {
                        ((EntryListFragment) fragment).clearSelection();
                    } else {
                        final ActionBar actionBar = getSupportActionBar();
                        if (actionBar != null) {
                            actionBar.setSubtitle(null);
                        }
                        onItemSelected(-1, null, 0);
                    }
                }
                return;
            } else if (fragment instanceof EntrySearchFragment) {
                fm.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE)
                        .replace(R.id.entry_detail_container, mWelcomeFragment).commit();
                return;
            }
        }
        super.onBackPressed();
    }
}