/****************************************************************************************
* Copyright (c) 2014 Timothy Rae <perceptualchaos2@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 3 of the License, or (at your option) any later *
* version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
package com.ichi2.anki;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.SwitchCompat;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton;
import com.ichi2.anim.ActivityTransitionAnimation;
import com.ichi2.compat.CompatHelper;
import com.ichi2.themes.Themes;
import timber.log.Timber;
public class NavigationDrawerActivity extends AnkiActivity implements NavigationView.OnNavigationItemSelectedListener {
/** Navigation Drawer */
protected CharSequence mTitle;
protected Boolean mFragmented = false;
private boolean mNavButtonGoesBack = false;
// Other members
private String mOldColPath;
private int mOldTheme;
// Navigation drawer list item entries
private DrawerLayout mDrawerLayout;
private NavigationView mNavigationView;
private ActionBarDrawerToggle mDrawerToggle;
private SwitchCompat mNightModeSwitch;
// Intent request codes
public static final int REQUEST_PREFERENCES_UPDATE = 100;
public static final int REQUEST_BROWSE_CARDS = 101;
public static final int REQUEST_STATISTICS = 102;
/**
* runnable that will be executed after the drawer has been closed.
*/
private Runnable pendingRunnable;
// Navigation drawer initialisation
protected void initNavigationDrawer(View mainView){
// Create inherited navigation drawer layout here so that it can be used by parent class
mDrawerLayout = (DrawerLayout) mainView.findViewById(R.id.drawer_layout);
// set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mNavigationView = (NavigationView) mDrawerLayout.findViewById(R.id.navdrawer_items_container);
mNavigationView.setNavigationItemSelectedListener(this);
Toolbar toolbar = (Toolbar) mainView.findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
// enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
// Decide which action to take when the navigation button is tapped.
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mNavButtonGoesBack) {
finishWithAnimation(ActivityTransitionAnimation.RIGHT);
} else {
mDrawerLayout.openDrawer(Gravity.LEFT);
}
}
});
}
// Configure night-mode switch
final SharedPreferences preferences = AnkiDroidApp.getSharedPrefs(NavigationDrawerActivity.this);
View actionLayout = MenuItemCompat.getActionView(mNavigationView.getMenu().findItem(R.id.nav_night_mode));
mNightModeSwitch = (SwitchCompat) actionLayout.findViewById(R.id.switch_compat);
mNightModeSwitch.setChecked(preferences.getBoolean("invertedColors", false));
mNightModeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Timber.i("StudyOptionsFragment:: Night mode was enabled");
preferences.edit().putBoolean("invertedColors", true).commit();
} else {
Timber.i("StudyOptionsFragment:: Night mode was disabled");
preferences.edit().putBoolean("invertedColors", false).commit();
}
CompatHelper.getCompat().restartActivityInvalidateBackstack(NavigationDrawerActivity.this);
}
});
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 0, 0) {
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
supportInvalidateOptionsMenu();
if(pendingRunnable != null) {
new Handler().post(pendingRunnable);
pendingRunnable = null;
}
}
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
supportInvalidateOptionsMenu();
}
};
mDrawerLayout.addDrawerListener(mDrawerToggle);
}
/** Sets selected navigation drawer item */
protected void selectNavigationItem(int itemId) {
if (mNavigationView == null) {
Timber.e("Could not select item in navigation drawer as NavigationView null");
return;
}
Menu menu = mNavigationView.getMenu();
if (itemId == -1) {
for (int i = 0; i < menu.size(); i++) {
menu.getItem(i).setChecked(false);
}
} else {
MenuItem item = menu.findItem(itemId);
if (item != null) {
item.setChecked(true);
} else {
Timber.e("Could not find item %d", itemId);
}
}
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(mTitle);
}
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
if (mDrawerToggle != null) {
mDrawerToggle.syncState();
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
if (mDrawerToggle != null) {
mDrawerToggle.onConfigurationChanged(newConfig);
}
}
public ActionBarDrawerToggle getDrawerToggle() {
return mDrawerToggle;
}
/**
* This function locks the navigation drawer closed in regards to swipes,
* but continues to allowed it to be opened via it's indicator button. This
* function in a noop if the drawer hasn't been initialized.
*/
protected void disableDrawerSwipe() {
if (mDrawerLayout != null) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}
}
/**
* This function allows swipes to open the navigation drawer. This
* function in a noop if the drawer hasn't been initialized.
*/
protected void enableDrawerSwipe() {
if (mDrawerLayout != null) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
SharedPreferences preferences = AnkiDroidApp.getSharedPrefs(this);
// Update language
AnkiDroidApp.setLanguage(preferences.getString(Preferences.LANGUAGE, ""));
// Restart the activity on preference change
if (requestCode == REQUEST_PREFERENCES_UPDATE) {
if (mOldColPath!=null && CollectionHelper.getCurrentAnkiDroidDirectory(this).equals(mOldColPath)) {
// collection path hasn't been changed so just restart the current activity
if ((this instanceof Reviewer) && preferences.getBoolean("tts", false)) {
// Workaround to kick user back to StudyOptions after opening settings from Reviewer
// because onDestroy() of old Activity interferes with TTS in new Activity
finishWithoutAnimation();
} else if (mOldTheme != Themes.getCurrentTheme(getApplicationContext())) {
// The current theme was changed, so need to reload the stack with the new theme
CompatHelper.getCompat().restartActivityInvalidateBackstack(NavigationDrawerActivity.this);
} else {
restartActivity();
}
} else {
// collection path has changed so kick the user back to the DeckPicker
CollectionHelper.getInstance().closeCollection(true);
CompatHelper.getCompat().restartActivityInvalidateBackstack(this);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onBackPressed() {
if (isDrawerOpen()) {
Timber.i("Back key pressed");
mDrawerLayout.closeDrawers();
} else {
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(final MenuItem item) {
// Don't do anything if user selects already selected position
if (item.isChecked()) {
return true;
}
/*
* This runnable will be executed in onDrawerClosed(...)
* to make the animation more fluid on older devices.
*/
pendingRunnable = new Runnable() {
@Override
public void run() {
// Take action if a different item selected
switch (item.getItemId()) {
case R.id.nav_decks:
Intent deckPicker = new Intent(NavigationDrawerActivity.this, DeckPicker.class);
deckPicker.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); // opening DeckPicker should clear back history
startActivityWithAnimation(deckPicker, ActivityTransitionAnimation.RIGHT);
break;
case R.id.nav_browser:
openCardBrowser();
break;
case R.id.nav_stats:
Intent intent = new Intent(NavigationDrawerActivity.this, Statistics.class);
intent.putExtra("selectedDeck", getCol().getDecks().selected());
startActivityForResultWithAnimation(intent, REQUEST_STATISTICS, ActivityTransitionAnimation.LEFT);
break;
case R.id.nav_night_mode:
mNightModeSwitch.performClick();
break;
case R.id.nav_settings:
mOldColPath = CollectionHelper.getCurrentAnkiDroidDirectory(NavigationDrawerActivity.this);
// Remember the theme we started with so we can restart the Activity if it changes
mOldTheme = Themes.getCurrentTheme(getApplicationContext());
startActivityForResultWithAnimation(new Intent(NavigationDrawerActivity.this, Preferences.class), REQUEST_PREFERENCES_UPDATE, ActivityTransitionAnimation.FADE);
break;
case R.id.nav_help:
openUrl(Uri.parse(AnkiDroidApp.getManualUrl()));
break;
case R.id.nav_feedback:
openUrl(Uri.parse(AnkiDroidApp.getFeedbackUrl()));
break;
default:
break;
}
}
};
mDrawerLayout.closeDrawers();
return true;
}
/**
* Open the card browser. Override this method to pass it custom arguments
*/
protected void openCardBrowser() {
Intent cardBrowser = new Intent(this, CardBrowser.class);
cardBrowser.putExtra("selectedDeck", getCol().getDecks().selected());
startActivityForResultWithAnimation(cardBrowser, REQUEST_BROWSE_CARDS, ActivityTransitionAnimation.LEFT);
}
protected void showBackIcon() {
if (mDrawerToggle != null) {
mDrawerToggle.setDrawerIndicatorEnabled(false);
}
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
mNavButtonGoesBack = true;
}
public boolean isDrawerOpen() {
return mDrawerLayout.isDrawerOpen(GravityCompat.START);
}
}