org.gnucash.android.ui.common.BaseDrawerActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.gnucash.android.ui.common.BaseDrawerActivity.java

Source

/*
 * Copyright (c) 2015 Ngewi Fet <ngewif@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.gnucash.android.ui.common;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.LayoutRes;
import android.support.annotation.StringRes;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.uservoice.uservoicesdk.UserVoice;

import org.gnucash.android.R;
import org.gnucash.android.app.GnuCashApplication;
import org.gnucash.android.db.DatabaseSchema;
import org.gnucash.android.db.adapter.BooksDbAdapter;
import org.gnucash.android.ui.account.AccountsActivity;
import org.gnucash.android.ui.passcode.PasscodeLockActivity;
import org.gnucash.android.ui.report.ReportsActivity;
import org.gnucash.android.ui.settings.PreferenceActivity;
import org.gnucash.android.ui.transaction.ScheduledActionsActivity;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Base activity implementing the navigation drawer, to be extended by all activities requiring one.
 * <p>
 *     Each activity inheriting from this class has an indeterminate progress bar at the top,
 *     (above the action bar) which can be used to display busy operations. See {@link #getProgressBar()}
 * </p>
 *
 * <p>Sub-classes should simply provide their layout using {@link #getContentView()} and then annotate
 * any variables they wish to use with {@link ButterKnife#bind(Activity)} annotations. The view
 * binding will be done in this base abstract class.<br>
 * The activity layout of the subclass is expected to contain {@code DrawerLayout} and
 * a {@code NavigationView}.<br>
 * Sub-class should also consider using the {@code toolbar.xml} or {@code toolbar_with_spinner.xml}
 * for the action bar in their XML layout. Otherwise provide another which contains widgets for the
 * toolbar and progress indicator with the IDs {@code R.id.toolbar} and {@code R.id.progress_indicator} respectively.
 * </p>
 * @author Ngewi Fet <ngewif@gmail.com>
 */
public abstract class BaseDrawerActivity extends PasscodeLockActivity implements PopupMenu.OnMenuItemClickListener {

    public static final int ID_MANAGE_BOOKS = 0xB00C;
    @BindView(R.id.drawer_layout)
    DrawerLayout mDrawerLayout;
    @BindView(R.id.nav_view)
    NavigationView mNavigationView;
    @BindView(R.id.toolbar)
    Toolbar mToolbar;
    @BindView(R.id.toolbar_progress)
    ProgressBar mToolbarProgress;
    protected TextView mBookNameTextView;

    protected ActionBarDrawerToggle mDrawerToggle;

    public static final int REQUEST_OPEN_DOCUMENT = 0x20;

    private class DrawerItemClickListener implements NavigationView.OnNavigationItemSelectedListener {

        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem) {
            onDrawerMenuItemClicked(menuItem.getItemId());
            return true;
        }

    }

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

        //if a parameter was passed to open an account within a specific book, then switch
        String bookUID = getIntent().getStringExtra(UxArgument.BOOK_UID);
        if (bookUID != null && !bookUID.equals(BooksDbAdapter.getInstance().getActiveBookUID())) {
            GnuCashApplication.activateBook(bookUID);
        }

        ButterKnife.bind(this);
        setSupportActionBar(mToolbar);
        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setHomeButtonEnabled(true);
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setTitle(getTitleRes());
        }

        mToolbarProgress.getIndeterminateDrawable().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);

        View headerView = mNavigationView.getHeaderView(0);
        headerView.findViewById(R.id.drawer_title).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickAppTitle(v);
            }
        });

        mBookNameTextView = (TextView) headerView.findViewById(R.id.book_name);
        mBookNameTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickBook(v);
            }
        });
        updateActiveBookName();
        setUpNavigationDrawer();
    }

    @Override
    protected void onResume() {
        super.onResume();
        updateActiveBookName();
    }

    /**
     * Return the layout to inflate for this activity
     * @return Layout resource identifier
     */
    public abstract @LayoutRes int getContentView();

    /**
     * Return the title for this activity.
     * This will be displayed in the action bar
     * @return String resource identifier
     */
    public abstract @StringRes int getTitleRes();

    /**
     * Returns the progress bar for the activity.
     * <p>This progress bar is displayed above the toolbar and should be used to show busy status
     * for long operations.<br/>
     * The progress bar visibility is set to {@link View#GONE} by default. Make visible to use </p>
     * @return Indeterminate progress bar.
     */
    public ProgressBar getProgressBar() {
        return mToolbarProgress;
    }

    /**
     * Sets up the navigation drawer for this activity.
     */
    private void setUpNavigationDrawer() {
        mNavigationView.setNavigationItemSelectedListener(new DrawerItemClickListener());

        mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
                mDrawerLayout, /* DrawerLayout object */
                R.string.drawer_open, /* "open drawer" description */
                R.string.drawer_close /* "close drawer" description */
        ) {

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
            }
        };

        mDrawerLayout.setDrawerListener(mDrawerToggle);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            if (!mDrawerLayout.isDrawerOpen(mNavigationView))
                mDrawerLayout.openDrawer(mNavigationView);
            else
                mDrawerLayout.closeDrawer(mNavigationView);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * Update the display name of the currently active book
     */
    protected void updateActiveBookName() {
        mBookNameTextView.setText(BooksDbAdapter.getInstance().getActiveBookDisplayName());
    }

    /**
     * Handler for the navigation drawer items
     * */
    protected void onDrawerMenuItemClicked(int itemId) {
        switch (itemId) {
        case R.id.nav_item_open: { //Open... files
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                //use the storage access framework
                Intent openDocument = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                openDocument.addCategory(Intent.CATEGORY_OPENABLE);
                openDocument.setType("*/*");
                startActivityForResult(openDocument, REQUEST_OPEN_DOCUMENT);

            } else {
                AccountsActivity.startXmlFileChooser(this);
            }
        }
            break;

        case R.id.nav_item_favorites: { //favorite accounts
            Intent intent = new Intent(this, AccountsActivity.class);
            intent.putExtra(AccountsActivity.EXTRA_TAB_INDEX, AccountsActivity.INDEX_FAVORITE_ACCOUNTS_FRAGMENT);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent);
        }
            break;

        case R.id.nav_item_reports: {
            Intent intent = new Intent(this, ReportsActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent);
        }
            break;

        /*
        //todo: Re-enable this when Budget UI is complete
        case R.id.nav_item_budgets:
            startActivity(new Intent(this, BudgetsActivity.class));
            break;
        */
        case R.id.nav_item_scheduled_actions: { //show scheduled transactions
            Intent intent = new Intent(this, ScheduledActionsActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent);
        }
            break;

        case R.id.nav_item_export:
            AccountsActivity.openExportFragment(this);
            break;

        case R.id.nav_item_settings: //Settings activity
            startActivity(new Intent(this, PreferenceActivity.class));
            break;

        case R.id.nav_item_help:
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
            prefs.edit().putBoolean(UxArgument.SKIP_PASSCODE_SCREEN, true).apply();
            UserVoice.launchUserVoice(this);
            break;
        }
        mDrawerLayout.closeDrawer(mNavigationView);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_CANCELED) {
            super.onActivityResult(requestCode, resultCode, data);
            return;
        }

        switch (requestCode) {
        case AccountsActivity.REQUEST_PICK_ACCOUNTS_FILE:
            AccountsActivity.importXmlFileFromIntent(this, data, null);
            break;
        case BaseDrawerActivity.REQUEST_OPEN_DOCUMENT: //this uses the Storage Access Framework
            final int takeFlags = data.getFlags()
                    & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            AccountsActivity.importXmlFileFromIntent(this, data, null);
            getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
        }
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        long id = item.getItemId();
        if (id == ID_MANAGE_BOOKS) {
            Intent intent = new Intent(this, PreferenceActivity.class);
            intent.setAction(PreferenceActivity.ACTION_MANAGE_BOOKS);
            startActivity(intent);
            mDrawerLayout.closeDrawer(mNavigationView);
            return true;
        }
        BooksDbAdapter booksDbAdapter = BooksDbAdapter.getInstance();
        String bookUID = booksDbAdapter.getUID(id);
        if (!bookUID.equals(booksDbAdapter.getActiveBookUID())) {
            GnuCashApplication.loadBook(bookUID);
            finish();
        }
        AccountsActivity.start(GnuCashApplication.getAppContext());
        return true;
    }

    public void onClickAppTitle(View view) {
        mDrawerLayout.closeDrawer(mNavigationView);
        AccountsActivity.start(this);
    }

    public void onClickBook(View view) {
        PopupMenu popup = new PopupMenu(this, view);
        popup.setOnMenuItemClickListener(this);

        Menu menu = popup.getMenu();
        int maxRecent = 0;
        Cursor cursor = BooksDbAdapter.getInstance().fetchAllRecords(null, null,
                DatabaseSchema.BookEntry.COLUMN_MODIFIED_AT + " DESC");
        while (cursor.moveToNext() && maxRecent++ < 5) {
            long id = cursor.getLong(cursor.getColumnIndexOrThrow(DatabaseSchema.BookEntry._ID));
            String name = cursor
                    .getString(cursor.getColumnIndexOrThrow(DatabaseSchema.BookEntry.COLUMN_DISPLAY_NAME));
            menu.add(0, (int) id, maxRecent, name);
        }
        menu.add(0, ID_MANAGE_BOOKS, maxRecent, R.string.menu_manage_books);

        popup.show();
    }
}