package org.mtransit.android.ui;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import org.mtransit.android.R;
import org.mtransit.android.commons.BundleUtils;
import org.mtransit.android.commons.CollectionUtils;
import org.mtransit.android.commons.MTLog;
import org.mtransit.android.commons.PreferenceUtils;
import org.mtransit.android.commons.TaskUtils;
import org.mtransit.android.commons.task.MTAsyncTask;
import org.mtransit.android.data.DataSourceProvider;
import org.mtransit.android.data.DataSourceType;
import org.mtransit.android.task.ServiceUpdateLoader;
import org.mtransit.android.task.StatusLoader;
import org.mtransit.android.ui.fragment.ABFragment;
import org.mtransit.android.ui.fragment.AgencyTypeFragment;
import org.mtransit.android.ui.fragment.FavoritesFragment;
import org.mtransit.android.ui.fragment.HomeFragment;
import org.mtransit.android.ui.fragment.MapFragment;
import org.mtransit.android.ui.fragment.NearbyFragment;
import org.mtransit.android.ui.fragment.NewsFragment;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class NavigationDrawerController implements MTLog.Loggable, NavigationView.OnNavigationItemSelectedListener, DataSourceProvider.ModulesUpdateListener {
private static final String TAG = "Stack-" + NavigationDrawerController.class.getSimpleName();
@Override
public String getLogTag() {
return TAG;
}
private static final String ITEM_ID_AGENCYTYPE_START_WITH = "agencytype-";
private static final String ITEM_ID_STATIC_START_WITH = "static-";
private static final int ITEM_INDEX_HOME = 0;
private static final int ITEM_INDEX_FAVORITE = 1;
private static final int ITEM_INDEX_NEARBY = 2;
private static final int ITEM_INDEX_MAP = 3;
private static final int ITEM_INDEX_NEWS = 4;
private static final int ITEM_ID_SELECTED_SCREEN_NAV_ITEM_DEFAULT = R.id.nav_home;
public static final String ITEM_ID_SELECTED_SCREEN_DEFAULT = ITEM_ID_STATIC_START_WITH + ITEM_INDEX_HOME;
private WeakReference<MainActivity> mainActivityWR;
private DrawerLayout drawerLayout;
private ABDrawerToggle drawerToggle;
private NavigationView navigationView;
private Integer currentSelectedScreenItemNavId = null;
private String currentSelectedScreenItemId = null;
public NavigationDrawerController(MainActivity mainActivity) {
this.mainActivityWR = new WeakReference<MainActivity>(mainActivity);
DataSourceProvider.addModulesUpdateListener(this);
}
public void setup(Bundle savedInstanceState) {
MainActivity mainActivity = this.mainActivityWR == null ? null : this.mainActivityWR.get();
if (mainActivity != null) {
this.navigationView = (NavigationView) mainActivity.findViewById(R.id.nav_view);
this.navigationView.setNavigationItemSelectedListener(this);
this.drawerLayout = (DrawerLayout) mainActivity.findViewById(R.id.drawer_layout);
this.drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
this.drawerToggle = new ABDrawerToggle(mainActivity, this.drawerLayout);
this.drawerLayout.addDrawerListener(this.drawerToggle);
finishSetupAsync(savedInstanceState);
}
}
private void finishSetupAsync(Bundle savedInstanceState) {
new MTAsyncTask<Bundle, String, String>() {
private final String TAG = NavigationDrawerController.TAG + ">finishSetupAsync()";
@Override
public String getLogTag() {
return TAG;
}
@Override
protected String doInBackgroundMT(Bundle... params) {
Context context = NavigationDrawerController.this.mainActivityWR == null ? null : NavigationDrawerController.this.mainActivityWR.get();
String itemId = null;
if (context != null && !isCurrentSelectedSet()) {
itemId = PreferenceUtils.getPrefLcl(context, PreferenceUtils.PREFS_LCL_ROOT_SCREEN_ITEM_ID, ITEM_ID_SELECTED_SCREEN_DEFAULT);
publishProgress(itemId);
}
return itemId;
}
@Override
protected void onPostExecute(String itemId) {
setVisibleMenuItems();
selectItemId(itemId);
if (!hasUserLearnedDrawer()) {
openDrawer();
setUserLearnedDrawer();
}
}
public void selectItemId(String itemId) {
if (!TextUtils.isEmpty(itemId)) {
Integer navItemId = getScreenNavItemId(itemId);
selectItem(navItemId, false);
}
}
@Override
protected void onProgressUpdate(String... itemIds) {
super.onProgressUpdate(itemIds);
selectItemId(itemIds == null || itemIds.length == 0 ? null : itemIds[0]);
}
}.executeOnExecutor(TaskUtils.THREAD_POOL_EXECUTOR, savedInstanceState);
}
private Boolean userLearnedDrawer = null;
private boolean hasUserLearnedDrawer() {
if (this.userLearnedDrawer == null) {
MainActivity mainActivity = this.mainActivityWR == null ? null : this.mainActivityWR.get();
if (mainActivity != null) {
this.userLearnedDrawer = PreferenceUtils.getPrefDefault(mainActivity, PreferenceUtils.PREF_USER_LEARNED_DRAWER,
PreferenceUtils.PREF_USER_LEARNED_DRAWER_DEFAULT);
}
}
return this.userLearnedDrawer == null ? false : this.userLearnedDrawer;
}
protected void setUserLearnedDrawer() {
this.userLearnedDrawer = true;
MainActivity mainActivity = this.mainActivityWR == null ? null : this.mainActivityWR.get();
if (mainActivity != null) {
PreferenceUtils.savePrefDefault(mainActivity, PreferenceUtils.PREF_USER_LEARNED_DRAWER, this.userLearnedDrawer, false); // asynchronous
}
}
private ArrayList<DataSourceType> allAgencyTypes = null;
private ArrayList<DataSourceType> getAllAgencyTypes() {
if (this.allAgencyTypes == null) {
initAllAgencyTypes();
}
return this.allAgencyTypes;
}
private void initAllAgencyTypes() {
Context context = this.mainActivityWR == null ? null : this.mainActivityWR.get();
if (context != null) {
this.allAgencyTypes = filterAgencyTypes(DataSourceProvider.get(context).getAvailableAgencyTypes());
}
}
private ArrayList<DataSourceType> filterAgencyTypes(ArrayList<DataSourceType> availableAgencyTypes) {
if (availableAgencyTypes != null) {
Iterator<DataSourceType> it = availableAgencyTypes.iterator();
while (it.hasNext()) {
if (!it.next().isMenuList()) {
it.remove();
}
}
}
return availableAgencyTypes;
}
private void setVisibleMenuItems() {
if (this.navigationView == null) {
MTLog.w(this, "setVisibleMenuItems() > skip (no navigation view)");
return;
}
ArrayList<DataSourceType> allAgencyTypes = getAllAgencyTypes();
for (DataSourceType dst : DataSourceType.values()) {
if (allAgencyTypes != null && allAgencyTypes.contains(dst)) {
continue;
}
if (!dst.isMenuList()) {
continue;
}
if (this.navigationView.getMenu().findItem(dst.getNavResId()) == null) {
continue;
}
this.navigationView.getMenu().findItem(dst.getNavResId()).setVisible(false);
}
if (allAgencyTypes != null) {
for (DataSourceType dst : allAgencyTypes) {
if (this.navigationView.getMenu().findItem(dst.getNavResId()) == null) {
MenuItem newMenuItem = this.navigationView.getMenu().add(R.id.drawer_modules, dst.getNavResId(), Menu.NONE, dst.getAllStringResId());
newMenuItem.setIcon(dst.getBlackIconResId());
}
this.navigationView.getMenu().findItem(dst.getNavResId()).setVisible(true);
}
}
}
private boolean menuUpdated = false;
private void onMenuUpdated() {
this.menuUpdated = true;
if (this.navigationView == null) {
return;
}
MainActivity mainActivity = this.mainActivityWR == null ? null : this.mainActivityWR.get();
if (mainActivity == null) {
return;
}
if (!mainActivity.isMTResumed()) {
return;
}
String itemId = PreferenceUtils.getPrefLcl(mainActivity, PreferenceUtils.PREFS_LCL_ROOT_SCREEN_ITEM_ID, ITEM_ID_SELECTED_SCREEN_DEFAULT);
Integer newSelectedNavItemId = getScreenNavItemId(itemId);
if (this.currentSelectedScreenItemNavId != null && this.currentSelectedScreenItemNavId.equals(newSelectedNavItemId)
&& this.currentSelectedScreenItemId != null && this.currentSelectedScreenItemId.equals(itemId)) {
this.currentSelectedScreenItemNavId = newSelectedNavItemId;
setCurrentSelectedItemChecked(mainActivity.getBackStackEntryCount() == 0);
return;
}
selectItem(newSelectedNavItemId, false);
this.menuUpdated = false; // processed
}
public String getScreenItemId(Integer navItemId) {
if (navItemId == null) {
return null;
}
switch (navItemId) {
case R.id.nav_home:
return ITEM_ID_STATIC_START_WITH + ITEM_INDEX_HOME;
case R.id.nav_favorites:
return ITEM_ID_STATIC_START_WITH + ITEM_INDEX_FAVORITE;
case R.id.nav_nearby:
return ITEM_ID_STATIC_START_WITH + ITEM_INDEX_NEARBY;
case R.id.nav_map:
return ITEM_ID_STATIC_START_WITH + ITEM_INDEX_MAP;
case R.id.nav_news:
return ITEM_ID_STATIC_START_WITH + ITEM_INDEX_NEWS;
case R.id.nav_light_rail:
return ITEM_ID_AGENCYTYPE_START_WITH + DataSourceType.TYPE_LIGHT_RAIL.getId();
case R.id.nav_subway:
return ITEM_ID_AGENCYTYPE_START_WITH + DataSourceType.TYPE_SUBWAY.getId();
case R.id.nav_rail:
return ITEM_ID_AGENCYTYPE_START_WITH + DataSourceType.TYPE_RAIL.getId();
case R.id.nav_bus:
return ITEM_ID_AGENCYTYPE_START_WITH + DataSourceType.TYPE_BUS.getId();
case R.id.nav_ferry:
return ITEM_ID_AGENCYTYPE_START_WITH + DataSourceType.TYPE_FERRY.getId();
case R.id.nav_bike:
return ITEM_ID_AGENCYTYPE_START_WITH + DataSourceType.TYPE_BIKE.getId();
case R.id.nav_module:
return ITEM_ID_AGENCYTYPE_START_WITH + DataSourceType.TYPE_MODULE.getId();
case R.id.nav_settings:
return null;
default:
MTLog.w(this, "Unexpected screen nav item ID '%s'!", navItemId);
return null;
}
}
private Integer getScreenNavItemId(String itemId) {
if (TextUtils.isEmpty(itemId)) {
return ITEM_ID_SELECTED_SCREEN_NAV_ITEM_DEFAULT;
}
if (itemId.startsWith(ITEM_ID_STATIC_START_WITH)) {
try {
switch (Integer.parseInt(itemId.substring(ITEM_ID_STATIC_START_WITH.length()))) {
case ITEM_INDEX_HOME:
return R.id.nav_home;
case ITEM_INDEX_FAVORITE:
return R.id.nav_favorites;
case ITEM_INDEX_NEARBY:
return R.id.nav_nearby;
case ITEM_INDEX_MAP:
return R.id.nav_map;
case ITEM_INDEX_NEWS:
return R.id.nav_news;
default:
MTLog.w(this, "Unexpected static screen item ID '%s'!", itemId);
return ITEM_ID_SELECTED_SCREEN_NAV_ITEM_DEFAULT;
}
} catch (Exception e) {
MTLog.w(this, e, "Error while finding static screen item ID '%s'!", itemId);
return ITEM_ID_SELECTED_SCREEN_NAV_ITEM_DEFAULT;
}
} else if (itemId.startsWith(ITEM_ID_AGENCYTYPE_START_WITH)) {
try {
DataSourceType dst = DataSourceType.parseId(Integer.parseInt(itemId.substring(ITEM_ID_AGENCYTYPE_START_WITH.length())));
if (dst != null) {
ArrayList<DataSourceType> allAgencyTypes = getAllAgencyTypes();
if (allAgencyTypes != null && allAgencyTypes.contains(dst)) {
return dst.getNavResId();
}
}
} catch (Exception e) {
MTLog.w(this, e, "Error while finding agency type screen item ID '%s'!", itemId);
return ITEM_ID_SELECTED_SCREEN_NAV_ITEM_DEFAULT;
}
}
MTLog.w(this, "Unknown item ID'%s'!", itemId);
return ITEM_ID_SELECTED_SCREEN_NAV_ITEM_DEFAULT;
}
public void forceReset() {
if (this.currentSelectedScreenItemNavId == null) {
return;
}
Integer saveCurrentSelectedScreenItemNavId = this.currentSelectedScreenItemNavId;
this.currentSelectedScreenItemNavId = null;
this.currentSelectedScreenItemId = null;
selectItem(saveCurrentSelectedScreenItemNavId, true);
}
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
closeDrawer();
selectItem(menuItem.getItemId(), true);
return true; // processed
}
private void selectItem(Integer navItemId, boolean clearStack) {
if (navItemId == null) {
return;
}
MainActivity mainActivity = this.mainActivityWR == null ? null : this.mainActivityWR.get();
if (mainActivity == null) {
return;
}
if (navItemId.equals(this.currentSelectedScreenItemNavId)) {
if (clearStack) {
mainActivity.clearFragmentBackStackImmediate();
}
if (mainActivity.getBackStackEntryCount() == 0) {
setCurrentSelectedItemChecked(true);
}
mainActivity.showContentFrameAsLoaded();
return;
}
if (!isRootScreen(navItemId)) {
startNewScreen(mainActivity, navItemId);
setCurrentSelectedItemChecked(true); // keep current position
return;
}
ABFragment newFragment = getNewStaticFragmentAt(navItemId);
if (newFragment == null) {
return;
}
this.currentSelectedScreenItemNavId = navItemId;
this.currentSelectedScreenItemId = getScreenItemId(navItemId);
mainActivity.clearFragmentBackStackImmediate(); // root screen
StatusLoader.get().clearAllTasks();
ServiceUpdateLoader.get().clearAllTasks();
mainActivity.showNewFragment(newFragment, false);
if (isRootScreen(navItemId)) {
PreferenceUtils.savePrefLcl(mainActivity, PreferenceUtils.PREFS_LCL_ROOT_SCREEN_ITEM_ID, this.currentSelectedScreenItemId, false);
}
}
private ABFragment getNewStaticFragmentAt(Integer navItemId) {
if (navItemId == null) {
MTLog.w(this, "getNewStaticFragmentAt() > skip (nav item ID null)");
return null;
}
switch (navItemId) {
case R.id.nav_home:
return HomeFragment.newInstance(null);
case R.id.nav_favorites:
return FavoritesFragment.newInstance();
case R.id.nav_nearby:
return NearbyFragment.newNearbyInstance(null, null);
case R.id.nav_map:
return MapFragment.newInstance(null, null, null);
case R.id.nav_news:
return NewsFragment.newInstance(null, null, null, null, null);
}
DataSourceType dst = DataSourceType.parseNavResId(navItemId);
if (dst != null) {
return AgencyTypeFragment.newInstance(dst.getId(), dst);
}
MTLog.w(this, "getNewStaticFragmentAt() > Unexpected screen nav item ID: %s", navItemId);
return null;
}
private void startNewScreen(Activity activity, Integer navItemId) {
if (navItemId == null) {
MTLog.w(this, "startNewScreen() > skip (nav item ID null)");
return;
}
if (activity == null) {
MTLog.w(this, "startNewScreen() > skip (activity null)");
return;
}
switch (navItemId) {
case R.id.nav_settings:
activity.startActivity(PreferencesActivity.newInstance(activity));
break;
default:
MTLog.w(this, "startNewScreen() > Unexptected screen nav item ID: %s", navItemId);
}
}
private boolean isRootScreen(Integer navItemId) {
if (navItemId == null) {
MTLog.w(this, "isRootScreen() > null (return false)");
return false;
}
switch (navItemId) {
case R.id.nav_settings:
return false;
default:
return true;
}
}
public void openDrawer() {
if (this.drawerLayout != null && this.navigationView != null) {
this.drawerLayout.openDrawer(this.navigationView);
}
}
public void closeDrawer() {
if (this.drawerLayout != null && this.navigationView != null) {
this.drawerLayout.closeDrawer(this.navigationView);
}
}
public boolean isDrawerOpen() {
return this.drawerLayout != null && this.navigationView != null && this.drawerLayout.isDrawerOpen(this.navigationView);
}
public boolean onBackPressed() {
if (isDrawerOpen()) {
closeDrawer();
return true; // processed
}
return false; // not processed
}
public void setDrawerToggleIndicatorEnabled(boolean enabled) {
if (this.drawerToggle != null) {
this.drawerToggle.setDrawerIndicatorEnabled(enabled);
}
}
public void syncDrawerToggleState() {
if (this.drawerToggle != null) {
this.drawerToggle.syncState();
}
}
public void onActivityPostCreate() {
syncDrawerToggleState();
}
public void onDrawerToggleConfigurationChanged(Configuration newConfig) {
if (this.drawerToggle != null) {
this.drawerToggle.onConfigurationChanged(newConfig);
}
}
public void onConfigurationChanged(Configuration newConfig) {
onDrawerToggleConfigurationChanged(newConfig);
}
public boolean onOptionsItemSelected(MenuItem item) {
if (this.drawerToggle != null && this.drawerToggle.onOptionsItemSelected(item)) {
return true; // processed
}
return false; // not processed
}
private boolean isCurrentSelectedSet() {
return this.currentSelectedScreenItemNavId != null && !TextUtils.isEmpty(this.currentSelectedScreenItemId);
}
public void setCurrentSelectedItemChecked(boolean checked) {
if (this.navigationView != null && this.currentSelectedScreenItemNavId != null) {
if (checked) { // unchecked all others (not automatic because multiple groups not handled by navigation view)
this.navigationView.getMenu().findItem(this.currentSelectedScreenItemNavId).setCheckable(true);
this.navigationView.getMenu().findItem(this.currentSelectedScreenItemNavId).setChecked(true);
uncheckOtherMenuItems();
} else {
this.navigationView.getMenu().findItem(this.currentSelectedScreenItemNavId).setCheckable(false);
}
}
}
private void uncheckOtherMenuItems() {
this.navigationView.getMenu().findItem(R.id.nav_home).setCheckable(this.currentSelectedScreenItemNavId == R.id.nav_home);
this.navigationView.getMenu().findItem(R.id.nav_favorites).setCheckable(this.currentSelectedScreenItemNavId == R.id.nav_favorites);
this.navigationView.getMenu().findItem(R.id.nav_nearby).setCheckable(this.currentSelectedScreenItemNavId == R.id.nav_nearby);
this.navigationView.getMenu().findItem(R.id.nav_map).setCheckable(this.currentSelectedScreenItemNavId == R.id.nav_map);
this.navigationView.getMenu().findItem(R.id.nav_news).setCheckable(this.currentSelectedScreenItemNavId == R.id.nav_news);
for (DataSourceType dst : DataSourceType.values()) {
if (dst.getNavResId() == this.currentSelectedScreenItemNavId) {
continue;
}
if (!dst.isMenuList()) {
continue;
}
this.navigationView.getMenu().findItem(dst.getNavResId()).setCheckable(false);
}
this.navigationView.getMenu().findItem(R.id.nav_settings).setCheckable(this.currentSelectedScreenItemNavId == R.id.nav_settings);
}
public void onBackStackChanged(int backStackEntryCount) {
setCurrentSelectedItemChecked(backStackEntryCount == 0);
}
private boolean modulesUpdated = false;
@Override
public void onModulesUpdated() {
this.modulesUpdated = true;
if (!this.resumed) {
return;
}
MainActivity mainActivity = this.mainActivityWR == null ? null : this.mainActivityWR.get();
ArrayList<DataSourceType> newAllAgencyTypes = filterAgencyTypes(DataSourceProvider.get(mainActivity).getAvailableAgencyTypes());
if (CollectionUtils.getSize(this.allAgencyTypes) != CollectionUtils.getSize(newAllAgencyTypes)) {
this.allAgencyTypes = newAllAgencyTypes; // force reset
setVisibleMenuItems();
onMenuUpdated();
this.modulesUpdated = false; // processed
} else {
this.modulesUpdated = false; // nothing to do
}
}
private boolean resumed = false;
public void onResume() {
this.resumed = true;
if (this.menuUpdated) {
onMenuUpdated();
}
if (this.modulesUpdated) {
new Handler().post(new Runnable() {
@Override
public void run() {
if (NavigationDrawerController.this.modulesUpdated) {
onModulesUpdated();
}
}
});
}
}
public void onPause() {
this.resumed = false;
}
private static final String EXTRA_SELECTED_ROOT_SCREEN_ID = "extra_selected_root_screen_id";
private static final String EXTRA_SELECTED_ROOT_SCREEN_NAV_ITEM_ID = "extra_selected_root_screen_nav_item_id";
public void onSaveState(Bundle outState) {
if (this.currentSelectedScreenItemNavId != null) {
outState.putInt(EXTRA_SELECTED_ROOT_SCREEN_NAV_ITEM_ID, this.currentSelectedScreenItemNavId);
}
if (!TextUtils.isEmpty(this.currentSelectedScreenItemId)) {
outState.putString(EXTRA_SELECTED_ROOT_SCREEN_ID, this.currentSelectedScreenItemId);
}
}
public void onRestoreState(Bundle savedInstanceState) {
Integer newSavedRootScreenNavItem = BundleUtils.getInt(EXTRA_SELECTED_ROOT_SCREEN_NAV_ITEM_ID, savedInstanceState);
if (newSavedRootScreenNavItem != null && !newSavedRootScreenNavItem.equals(this.currentSelectedScreenItemNavId)) {
this.currentSelectedScreenItemNavId = newSavedRootScreenNavItem;
}
String newRootScreenId = BundleUtils.getString(EXTRA_SELECTED_ROOT_SCREEN_ID, savedInstanceState);
if (!TextUtils.isEmpty(newRootScreenId) && !newRootScreenId.equals(this.currentSelectedScreenItemId)) {
this.currentSelectedScreenItemId = newRootScreenId;
}
}
public void destroy() {
DataSourceProvider.removeModulesUpdateListener(this);
if (this.mainActivityWR != null) {
this.mainActivityWR.clear();
this.mainActivityWR = null;
}
this.currentSelectedScreenItemNavId = null;
this.currentSelectedScreenItemId = null;
this.navigationView = null;
if (this.drawerLayout != null) {
if (this.drawerToggle != null) {
this.drawerLayout.removeDrawerListener(this.drawerToggle);
}
this.drawerLayout = null;
}
this.drawerToggle = null;
}
private static class ABDrawerToggle extends ActionBarDrawerToggle implements MTLog.Loggable {
private static final String TAG = MainActivity.class.getSimpleName() + ">" + ABDrawerToggle.class.getSimpleName();
@Override
public String getLogTag() {
return TAG;
}
private WeakReference<MainActivity> mainActivityWR;
public ABDrawerToggle(MainActivity mainActivity, DrawerLayout drawerLayout) {
super(mainActivity, drawerLayout, R.string.drawer_open, R.string.drawer_close);
this.mainActivityWR = new WeakReference<MainActivity>(mainActivity);
}
@Override
public void onDrawerClosed(View view) {
MainActivity mainActivity = this.mainActivityWR == null ? null : this.mainActivityWR.get();
if (mainActivity != null) {
ActionBarController abController = mainActivity.getAbController();
if (abController != null) {
abController.updateABDrawerClosed();
}
}
}
}
}