package com.kuxhausen.huemore;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Configuration;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.support.v4.util.ArrayMap;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.kuxhausen.huemore.alarm.AlarmsListFragment;
import com.kuxhausen.huemore.editmood.EditMoodFragment;
import com.kuxhausen.huemore.net.Connection;
import com.kuxhausen.huemore.net.ConnectionListFragment;
import com.kuxhausen.huemore.net.NetworkBulb;
import com.kuxhausen.huemore.net.NetworkBulb.ConnectivityState;
import com.kuxhausen.huemore.nfc.NfcWriterFragment;
import com.kuxhausen.huemore.persistence.Definitions.InternalArguments;
import com.kuxhausen.huemore.persistence.Definitions.PreferenceKeys;
import com.kuxhausen.huemore.persistence.PreferenceInitializer;
import com.kuxhausen.huemore.state.Group;
import java.util.ArrayList;
public class NavigationDrawerActivity extends NetworkManagedActivity implements
OnBackStackChangedListener {
private Toolbar mToolbar;
private DrawerLayout mDrawerLayout;
private View mDrawerView;
private ListView mDrawerList, mNotificationList;
private ActionBarDrawerToggle mDrawerToggle;
private NotificationRowAdapter mNotificationAdapter;
private CharSequence mTitle;
private ArrayList<String> mDrawerTitles;
private ArrayMap<String, Integer> mDrawerTitlePositions;
public int mSelectedItemPosition;
public Tag myTag;
/**
* For tracking drill-down navigation. Number of up-navigation-actions away from the top. At the
* top level, value is 0 and hamburger/nav drawer shown instead of up arrow.
*/
private int mLayersDeep = 0;
private SharedPreferences mSettings;
private Bundle mResumeBundle;
private String TITLE_BULB_FRAG, TITLE_GROUP_FRAG, TITLE_CONNECTIONS_FRAG, TITLE_ALARM_FRAG,
TITLE_NFC_FRAG, TITLE_SETTINGS_FRAG, TITLE_HELP_FRAG;
private ArrayList<SelectableList> mSelectableLists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Helpers.applyLocalizationPreference(this);
setContentView(R.layout.activity_navigation_drawer);
generateDrawerTitles();
mSelectableLists = new ArrayList<>();
mToolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(mToolbar);
mTitle = getTitle();
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.drawer_list);
// set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.day_primary_dark));
// set up the drawer's list view with items and click listener
mDrawerList
.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mDrawerTitles));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
mDrawerView = findViewById(R.id.left_drawer);
Helpers.fixBackgroundRepeat(findViewById(R.id.lampshade_banner));
mNotificationList = (ListView) findViewById(R.id.notification_list);
// enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
mToolbar,
R.string.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
) {
public void onDrawerClosed(View view) {
supportInvalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
supportInvalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mLayersDeep != 0) {
onBackPressed();
} else if (mDrawerLayout.isDrawerOpen(mDrawerView)) {
mDrawerLayout.closeDrawer(mDrawerView);
} else {
mDrawerLayout.openDrawer(mDrawerView);
}
}
});
mDrawerToggle.syncState();
Bundle b = getIntent().getExtras();
mSettings = PreferenceManager.getDefaultSharedPreferences(this);
getSupportFragmentManager().addOnBackStackChangedListener(this);
PreferenceInitializer.initializedPreferencesAndShowDialogs(this);
}
private void generateDrawerTitles() {
TITLE_BULB_FRAG = getString(R.string.nav_drawer_bulbs);
TITLE_GROUP_FRAG = getString(R.string.nav_drawer_groups);
TITLE_CONNECTIONS_FRAG = getString(R.string.nav_drawer_connections);
TITLE_ALARM_FRAG = getString(R.string.nav_drawer_alarms);
TITLE_NFC_FRAG = getString(R.string.nav_drawer_nfc);
TITLE_SETTINGS_FRAG = getString(R.string.nav_drawer_settings);
TITLE_HELP_FRAG = getString(R.string.nav_drawer_help);
/** Generate the drawer items list for this device **/
mDrawerTitles = new ArrayList<>();
mDrawerTitles.add(TITLE_BULB_FRAG);
mDrawerTitles.add(TITLE_GROUP_FRAG);
mDrawerTitles.add(TITLE_CONNECTIONS_FRAG);
mDrawerTitles.add(TITLE_ALARM_FRAG);
//Only show NFC option on supported devices
//if (NfcAdapter.getDefaultAdapter(this) == null) {
mDrawerTitles.add(TITLE_NFC_FRAG);
//}
mDrawerTitles.add(TITLE_SETTINGS_FRAG);
mDrawerTitles.add(TITLE_HELP_FRAG);
mDrawerTitlePositions = new ArrayMap<String, Integer>();
for (int i = 0; i < mDrawerTitles.size(); i++) {
mDrawerTitlePositions.put(mDrawerTitles.get(i), i);
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
if (mLayersDeep > 0) {
mLayersDeep--;
}
}
public void onResume() {
super.onResume();
mResumeBundle = getIntent().getExtras();
Uri data = getIntent().getData();
if (data != null && data.getHost().equals("lampshade.io")) {
SharedMoodDialog dialog = new SharedMoodDialog();
Bundle extras = new Bundle();
extras.putString(InternalArguments.ENCODED_MOOD, data.getQuery());
dialog.setArguments(extras);
dialog.show(getSupportFragmentManager(), InternalArguments.FRAG_MANAGER_DIALOG_TAG);
}
}
/**
* onCreate & onResumeFragments are the only lifecycle methods where fragment transactions can
* commit without risking state loss http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
*/
public void onResumeFragments() {
super.onResumeFragments();
Bundle b = mResumeBundle;
if (b != null && b.containsKey(InternalArguments.NAV_DRAWER_TITLE)) {
String desiredTitle = b.getString(InternalArguments.NAV_DRAWER_TITLE);
if (mDrawerTitlePositions.containsKey(desiredTitle)) {
selectItem(mDrawerTitlePositions.get(desiredTitle), b);
}
b.remove(InternalArguments.NAV_DRAWER_TITLE);
} else {
if (mSettings.getBoolean(PreferenceKeys.DEFAULT_TO_GROUPS, false)) {
selectItem(mDrawerTitlePositions.get(TITLE_GROUP_FRAG), b);
} else {
selectItem(mDrawerTitlePositions.get(TITLE_BULB_FRAG), b);
}
}
if (b != null && b.getBoolean(InternalArguments.FLAG_SHOW_NAV_DRAWER)) {
mDrawerLayout.openDrawer(Gravity.LEFT);
b.remove(InternalArguments.FLAG_SHOW_NAV_DRAWER);
}
mResumeBundle = null;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.navigation_drawer, menu);
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerView);
boolean hasPendingOrSuccessfulConnections = false;
if (this.boundToService()) {
ArrayList<Connection> cons = getService().getDeviceManager().getConnections();
for (Connection c : cons) {
for (NetworkBulb b : c.getBulbs()) {
if (b.getConnectivityState() == ConnectivityState.Connected
|| b.getConnectivityState() == ConnectivityState.Unknown) {
hasPendingOrSuccessfulConnections = true;
}
}
}
}
//hide connectivity error icon on connections page or no error
if (mSelectedItemPosition == mDrawerTitlePositions.get(TITLE_CONNECTIONS_FRAG)
|| hasPendingOrSuccessfulConnections) {
MenuItem unlocksItem = menu.findItem(R.id.action_connectivity_error);
unlocksItem.setEnabled(false);
unlocksItem.setVisible(false);
} else {
MenuItem unlocksItem = menu.findItem(R.id.action_connectivity_error);
unlocksItem.setEnabled(true);
unlocksItem.setVisible(true);
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
// ActionBarDrawerToggle will take care of this.
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch (item.getItemId()) {
case R.id.action_connectivity_error:
showConnectivity();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/* The click listner for ListView in the navigation drawer */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position, null);
}
}
private void selectItem(int position, Bundle b) {
if (b == null) {
b = new Bundle();
}
// record the groupbulb tab state and pass in bundle to main
if (position == mDrawerTitlePositions.get(TITLE_GROUP_FRAG)) {
b.putInt(InternalArguments.GROUPBULB_TAB, GroupBulbPagerAdapter.GROUP_LOCATION);
saveTab(GroupBulbPagerAdapter.GROUP_LOCATION);
} else if (position == mDrawerTitlePositions.get(TITLE_BULB_FRAG)) {
b.putInt(InternalArguments.GROUPBULB_TAB, GroupBulbPagerAdapter.BULB_LOCATION);
saveTab(GroupBulbPagerAdapter.BULB_LOCATION);
}
// this allows Bulb & Group to show up twice in NavBar but share fragment
int actualPosition = position;
if (actualPosition == mDrawerTitlePositions.get(TITLE_GROUP_FRAG)) {
actualPosition = mDrawerTitlePositions.get(TITLE_BULB_FRAG);
}
mSelectedItemPosition = position;
cleanUpActionBar();
Fragment
selectedFrag =
getSupportFragmentManager().findFragmentByTag(mDrawerTitles.get(actualPosition));
if (selectedFrag == null) {
if (mDrawerTitles.get(actualPosition).equals(TITLE_BULB_FRAG)) {
selectedFrag = new MainFragment();
} else if (mDrawerTitles.get(actualPosition).equals(TITLE_CONNECTIONS_FRAG)) {
selectedFrag = new ConnectionListFragment();
} else if (mDrawerTitles.get(actualPosition).equals(TITLE_SETTINGS_FRAG)) {
selectedFrag = new SettingsFragment();
} else if (mDrawerTitles.get(actualPosition).equals(TITLE_HELP_FRAG)) {
selectedFrag = new HelpFragment();
} else if (mDrawerTitles.get(actualPosition).equals(TITLE_ALARM_FRAG)) {
selectedFrag = new AlarmsListFragment();
} else if (mDrawerTitles.get(actualPosition).equals(TITLE_NFC_FRAG)) {
selectedFrag = new NfcWriterFragment();
}
selectedFrag.setArguments(b);
} else {
// if can't pass groupbulb tab data in bundle because frag already exists, pass directly
if (actualPosition == mDrawerTitlePositions.get(TITLE_BULB_FRAG)) {
((MainFragment) selectedFrag).setTab(b.getInt(InternalArguments.GROUPBULB_TAB));
}
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction()
.replace(R.id.content_frame, selectedFrag, mDrawerTitles.get(actualPosition)).commit();
mLayersDeep = 0;
this.supportInvalidateOptionsMenu();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mDrawerTitles.get(position));
mDrawerLayout.closeDrawer(mDrawerView);
}
@Override
public void onServiceConnected() {
mNotificationAdapter = new NotificationRowAdapter(this, getService().getMoodPlayer());
mNotificationList.setAdapter(mNotificationAdapter);
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
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.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggals
mDrawerToggle.onConfigurationChanged(newConfig);
}
private void cleanUpActionBar() {
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
}
@Override
public void onBackStackChanged() {
cleanUpActionBar();
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
mDrawerToggle.setDrawerIndicatorEnabled(false);
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
} else {
mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
}
}
private void onDrillDownNavigation() {
mLayersDeep++;
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
public void showHelp(String pageName) {
Bundle b = new Bundle();
b.putString(InternalArguments.HELP_PAGE, pageName);
selectItem(mDrawerTitlePositions.get(TITLE_HELP_FRAG), b);
// TODO find a way of showing help page without clearning back stack yet still enabling nav
// drawer
/*
* HelpActivity frag = new HelpActivity(); if(pageName!=null){ Bundle b = new Bundle();
* b.putString(InternalArguments.HELP_PAGE, pageName); frag.setArguments(b); } FragmentManager
* fragmentManager = getSupportFragmentManager();
* fragmentManager.beginTransaction().addToBackStack(null).replace(R.id.content_frame,
* frag).commit();
*/
}
public void showConnectivity() {
selectItem(mDrawerTitlePositions.get(TITLE_CONNECTIONS_FRAG), null);
// TODO find a way of showing connectivity page without clearning back stack yet still enabling
// nav drawer
}
public void showEditMood(String moodName) {
EditMoodFragment frag = new EditMoodFragment();
if (moodName != null) {
Bundle b = new Bundle();
b.putString(InternalArguments.MOOD_NAME, moodName);
frag.setArguments(b);
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().addToBackStack("mood").replace(R.id.content_frame, frag)
.commit();
onDrillDownNavigation();
}
public void setGroup(Group g, SelectableList from) {
super.setGroup(g);
for (SelectableList selectable : mSelectableLists) {
if (selectable != from) {
selectable.invalidateSelection();
}
}
if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK)
< Configuration.SCREENLAYOUT_SIZE_LARGE & boundToService()) {
SecondaryFragment drillDownFrag = new SecondaryFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().addToBackStack("group")
.replace(R.id.content_frame, drillDownFrag).commit();
onDrillDownNavigation();
}
}
@Override
public void setGroup(Group g) {
setGroup(g, null);
}
public void trackSelectableList(SelectableList list) {
mSelectableLists.add(list);
}
public void forgetSelectableList(SelectableList list) {
mSelectableLists.remove(list);
}
@Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Toast.makeText(this, this.getString(R.string.nfc_tag_detected), Toast.LENGTH_SHORT).show();
}
}
public void markSelected(int pagerPosition) {
int drawerPosition;
if (pagerPosition == GroupBulbPagerAdapter.BULB_LOCATION) {
drawerPosition = mDrawerTitlePositions.get(TITLE_BULB_FRAG);
} else {
drawerPosition = mDrawerTitlePositions.get(TITLE_GROUP_FRAG);
}
mDrawerList.setItemChecked(drawerPosition, true);
setTitle(mDrawerTitles.get(drawerPosition));
saveTab(pagerPosition);
}
public void saveTab(int position) {
Editor edit = mSettings.edit();
switch (position) {
case GroupBulbPagerAdapter.BULB_LOCATION:
edit.putBoolean(PreferenceKeys.DEFAULT_TO_GROUPS, false);
break;
case GroupBulbPagerAdapter.GROUP_LOCATION:
edit.putBoolean(PreferenceKeys.DEFAULT_TO_GROUPS, true);
break;
}
edit.commit();
}
@Override
public void onConnectionStatusChanged() {
this.supportInvalidateOptionsMenu();
}
@Override
protected void onDestroy() {
mNotificationAdapter.onDestroy();
super.onDestroy();
}
}