package org.droidplanner.android.activities; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.graphics.Typeface; import android.os.Bundle; import android.support.design.widget.NavigationView; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.Toolbar; import android.util.TypedValue; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import com.o3dr.android.client.Drone; import com.o3dr.android.client.apis.CapabilityApi; import com.o3dr.services.android.lib.drone.attribute.AttributeEvent; import org.droidplanner.android.R; import org.droidplanner.android.activities.helpers.SuperUI; import org.droidplanner.android.fragments.SettingsFragment; import org.droidplanner.android.fragments.control.BaseFlightControlFragment; import org.droidplanner.android.tlog.TLogActivity; import org.droidplanner.android.utils.prefs.DroidPlannerPrefs; import org.droidplanner.android.view.SlidingDrawer; /** * This abstract activity provides its children access to a navigation drawer * interface. */ public abstract class DrawerNavigationUI extends SuperUI implements SlidingDrawer.OnDrawerOpenListener, SlidingDrawer.OnDrawerCloseListener, NavigationView.OnNavigationItemSelectedListener { private static final IntentFilter filter = new IntentFilter(); static { filter.addAction(AttributeEvent.TYPE_UPDATED); } private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch(intent.getAction()){ case AttributeEvent.TYPE_UPDATED: updateCompassCalibrationAvailability(); break; } } }; /** * Activates the navigation drawer when the home button is clicked. */ private ActionBarDrawerToggle mDrawerToggle; /** * Navigation drawer used to access the different sections of the app. */ private DrawerLayout mDrawerLayout; private SlidingDrawer actionDrawer; /** * Container for the activity content. */ private FrameLayout contentLayout; /** * Clicking on an entry in the open navigation drawer updates this intent. * When the navigation drawer closes, the intent is used to navigate to the desired location. */ private Intent mNavigationIntent; /** * Navigation drawer view */ private NavigationView navigationView; /** * Compass calibration menu item. This is used to enable/disable access to compass calibration * based on the vehicle type. */ private MenuItem compassCalibration; /** * Navigation view settings menu */ private NavigationView settingsMenu; private TextView accountLabel; private final CapabilityApi.FeatureSupportListener featureSupportListener = new CapabilityApi.FeatureSupportListener() { @Override public void onFeatureSupportResult(String featureId, int result, Bundle resultInfo) { switch(featureId) { case CapabilityApi.FeatureIds.COMPASS_CALIBRATION: boolean isSupported = result == CapabilityApi.FEATURE_SUPPORTED; compassCalibration.setVisible(isSupported); compassCalibration.setEnabled(isSupported); break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Retrieve the drawer layout container. mDrawerLayout = (DrawerLayout) getLayoutInflater().inflate(R.layout.activity_drawer_navigation_ui, null); contentLayout = (FrameLayout) mDrawerLayout.findViewById(R.id.content_layout); mDrawerToggle = new ActionBarDrawerToggle( this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) { @Override public void onDrawerClosed(View drawerView) { switch (drawerView.getId()) { case R.id.navigation_drawer: if (mNavigationIntent != null) { startActivity(mNavigationIntent); mNavigationIntent = null; } break; } } }; mDrawerLayout.setDrawerListener(mDrawerToggle); actionDrawer = (SlidingDrawer) mDrawerLayout.findViewById(R.id.action_drawer_container); actionDrawer.setOnDrawerCloseListener(this); actionDrawer.setOnDrawerOpenListener(this); } protected View getActionDrawer() { return actionDrawer; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case BaseFlightControlFragment.FOLLOW_SETTINGS_UPDATE: LocalBroadcastManager.getInstance(getApplicationContext()) .sendBroadcast(new Intent(SettingsFragment.ACTION_LOCATION_SETTINGS_UPDATED) .putExtra(SettingsFragment.EXTRA_RESULT_CODE, resultCode)); break; default: super.onActivityResult(requestCode, resultCode, data); break; } } /** * Intercepts the call to 'setContentView', and wrap the passed layout * within a DrawerLayout object. This way, the children of this class don't * have to do anything to benefit from the navigation drawer. * * @param layoutResID layout resource for the activity view */ @Override public void setContentView(int layoutResID) { final View contentView = getLayoutInflater().inflate(layoutResID, mDrawerLayout, false); contentLayout.addView(contentView); setContentView(mDrawerLayout); navigationView = (NavigationView) findViewById(R.id.navigation_drawer_view); if (navigationView != null) { navigationView.inflateHeaderView(DroidPlannerPrefs.ENABLE_DRONESHARE_ACCOUNT ? R.layout.nav_header_droneshare : R.layout.nav_header_main); navigationView.setNavigationItemSelectedListener(this); Menu navigationMenu = navigationView.getMenu(); compassCalibration = navigationMenu.findItem(R.id.navigation_compass_calibration); View navigationHeaderView = navigationView.getHeaderView(0); accountLabel = (TextView) navigationHeaderView.findViewById(R.id.account_screen_label); LinearLayout llAccount = (LinearLayout) navigationHeaderView.findViewById(R.id.navigation_account); if (llAccount != null) { llAccount.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(getApplicationContext(), AccountActivity.class)); mDrawerLayout.closeDrawer(GravityCompat.START); } }); } } settingsMenu = (NavigationView) findViewById(R.id.navigation_drawer_settings); if (settingsMenu != null) { settingsMenu.setNavigationItemSelectedListener(this); } } @Override protected void onDroneConnected(){ super.onDroneConnected(); updateCompassCalibrationAvailability(); getBroadcastManager().registerReceiver(receiver, filter); } @Override protected void onDroneDisconnected(){ super.onDroneDisconnected(); getBroadcastManager().unregisterReceiver(receiver); updateCompassCalibrationAvailability(); } private void updateCompassCalibrationAvailability() { Drone drone = dpApp.getDrone(); if(drone != null){ CapabilityApi.getApi(drone).checkFeatureSupport(CapabilityApi.FeatureIds.COMPASS_CALIBRATION, featureSupportListener); } else{ compassCalibration.setVisible(false); compassCalibration.setEnabled(false); } } @Override protected void initToolbar(Toolbar toolbar) { super.initToolbar(toolbar); toolbar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { final float topMargin = getActionDrawerTopMargin(); final int fullTopMargin = (int) (topMargin + (bottom - top)); ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) actionDrawer.getLayoutParams(); if (lp.topMargin != fullTopMargin) { lp.topMargin = fullTopMargin; actionDrawer.requestLayout(); } onToolbarLayoutChange(left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom); } }); } /** * Manage Navigation drawer menu items */ @Override public boolean onNavigationItemSelected(MenuItem menuItem) { int id = menuItem.getItemId(); switch (id) { case R.id.navigation_flight_data: mNavigationIntent = new Intent(this, FlightActivity.class); break; case R.id.navigation_editor: mNavigationIntent = new Intent(this, EditorActivity.class); break; case R.id.navigation_locator: mNavigationIntent = new Intent(this, TLogActivity.class); break; case R.id.navigation_params: mNavigationIntent = new Intent(this, ConfigurationActivity.class) .putExtra(ConfigurationActivity.EXTRA_CONFIG_SCREEN_ID, id); break; case R.id.navigation_checklist: mNavigationIntent = new Intent(this, ConfigurationActivity.class) .putExtra(ConfigurationActivity.EXTRA_CONFIG_SCREEN_ID, id); break; case R.id.navigation_imu_calibration: mNavigationIntent = new Intent(this, ConfigurationActivity.class) .putExtra(ConfigurationActivity.EXTRA_CONFIG_SCREEN_ID, id); break; case R.id.navigation_compass_calibration: mNavigationIntent = new Intent(this, ConfigurationActivity.class) .putExtra(ConfigurationActivity.EXTRA_CONFIG_SCREEN_ID, id); break; case R.id.navigation_settings: mNavigationIntent = new Intent(this, SettingsActivity.class); break; } mDrawerLayout.closeDrawer(GravityCompat.START); return true; } protected void onToolbarLayoutChange(int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { } protected float getActionDrawerTopMargin() { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics()); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (mDrawerToggle != null) mDrawerToggle.onConfigurationChanged(newConfig); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Pass the event to ActionBarDrawerToggle, if it returns // true, then it has handled the app icon touch event if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } @Override public void onResume(){ super.onResume(); updateNavigationDrawer(); } private void updateNavigationDrawer() { final int navDrawerEntryId = getNavigationDrawerMenuItemId(); switch (navDrawerEntryId) { case R.id.navigation_account: if (accountLabel != null) { accountLabel.setTypeface(null, Typeface.BOLD); } break; default: navigationView.setCheckedItem(navDrawerEntryId); break; } MenuItem settings = settingsMenu.getMenu().findItem(R.id.navigation_settings); if(settings != null){ settings.setChecked(false); } } @Override public void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); if (mDrawerToggle != null) { // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerToggle.syncState(); } } public boolean isActionDrawerOpened() { return actionDrawer.isOpened(); } protected int getActionDrawerId() { return R.id.action_drawer_content; } /** * Called when the action drawer is opened. * Should be override by children as needed. */ @Override public void onDrawerOpened() { } /** * Called when the action drawer is closed. * Should be override by children as needed. */ @Override public void onDrawerClosed() { } public void openActionDrawer() { actionDrawer.animateOpen(); actionDrawer.lock(); } public void closeActionDrawer() { actionDrawer.animateClose(); actionDrawer.lock(); } protected abstract int getNavigationDrawerMenuItemId(); }