org.taulabs.androidgcs.ObjectManagerActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.taulabs.androidgcs.ObjectManagerActivity.java

Source

/**
 ******************************************************************************
 * @file       ObjectManagerActivity.java
 * @author     Tau Labs, http://taulabs.org, Copyright (C) 2012-2013
 * @brief      Base object for all activies that use the UAVObjectManager.
 *             This class takes care of binding to the service and getting the
 *             object manager as well as setting up callbacks to the objects of
 *             interest that run on the UI thread.
 *             Implements a new Android lifecycle: onConnected() / onDisconnected()
 *             which indicates when a valid telemetry is established as well as a
 *             valid object manager handle.
 * @see        The GNU Public License (GPL) Version 3
 *****************************************************************************/
/*
 * 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, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.taulabs.androidgcs;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import org.taulabs.androidgcs.drawer.NavDrawerActivityConfiguration;
import org.taulabs.androidgcs.drawer.NavDrawerAdapter;
import org.taulabs.androidgcs.drawer.NavDrawerItem;
import org.taulabs.androidgcs.drawer.NavMenuActivity;
import org.taulabs.androidgcs.drawer.NavMenuItem;
import org.taulabs.androidgcs.drawer.NavMenuSection;
import org.taulabs.androidgcs.fragments.ObjectManagerFragment;
import org.taulabs.androidgcs.fragments.PFD;
import org.taulabs.androidgcs.fragments.Map;
import org.taulabs.androidgcs.fragments.SystemAlarmsFragment;
import org.taulabs.androidgcs.telemetry.TelemetryService;
import org.taulabs.androidgcs.telemetry.TelemetryService.ConnectionState;
import org.taulabs.androidgcs.telemetry.TelemetryService.LocalBinder;
import org.taulabs.androidgcs.telemetry.TelemetryService.TelemTask;
import org.taulabs.androidgcs.views.AlarmsSummary;
import org.taulabs.androidgcs.views.AlarmsSummary.AlarmsStatus;
import org.taulabs.androidgcs.views.TelemetryStats;
import org.taulabs.uavtalk.UAVObject;
import org.taulabs.uavtalk.UAVObjectField;
import org.taulabs.uavtalk.UAVObjectManager;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

public abstract class ObjectManagerActivity extends Activity {

    private final String TAG = "ObjectManagerActivity";
    private static int LOGLEVEL = 0;
    //   private static boolean WARN = LOGLEVEL > 1;
    private static boolean DEBUG = LOGLEVEL > 0;

    //! Object manager, populated by parent for the children to use
    UAVObjectManager objMngr;
    //! Indicates if telemetry is connected
    boolean connectedCalled = false;
    //! The binder to access the telemetry task, and thus the object manager
    LocalBinder binder;
    //! Store the broadcast receiver to unregister it
    BroadcastReceiver connectedReceiver;
    //! Indicate if this activity has already connected it's telemetry callbacks
    private boolean telemetryStatsConnected = false;
    //! Maintain a list of all the UAVObject listeners for this activity
    private HashMap<Observer, UAVObject> listeners;

    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private ListView mDrawerList;
    private CharSequence mDrawerTitle;
    private CharSequence mTitle;

    /** Called when the activity is first created. */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        navConf = getNavDrawerConfiguration();
        setContentView(navConf.getMainLayout());

        mTitle = mDrawerTitle = getTitle();

        mDrawerLayout = (DrawerLayout) findViewById(navConf.getDrawerLayoutId());
        mDrawerList = (ListView) findViewById(navConf.getLeftDrawerId());

        mDrawerList = (ListView) findViewById(navConf.getLeftDrawerId());
        mDrawerList.setAdapter(navConf.getBaseAdapter());
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        this.initDrawerShadow();

        // enable ActionBar app icon to behave as action to toggle nav drawer
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, getDrawerIcon(), navConf.getDrawerOpenDesc(),
                navConf.getDrawerCloseDesc()) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu();
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        if (savedInstanceState == null) {
            selectItem(0);
        }

    }

    /**
     * Called whenever any objects subscribed to via registerObjects
     * whenever this Activity is not paused
     */
    protected void objectUpdated(UAVObject obj) {

    }

    /**
     * Called when either the telemetry establishes a connection or
     * if it already has on creation of this activity
     *
     * This should be called by all inherited classes if they want the telemetry bar etc
     */
    void onConnected() {

        // Cannot be called repeatedly
        if (connectedCalled)
            return;
        connectedCalled = true;

        // Create a map for all the object updates register for this activity.  If anyone
        // tries to register an object update before this a null exception will occur
        listeners = new HashMap<Observer, UAVObject>();

        // We are not using the objectUpdated mechanism in place so that all the children
        // don't have to sort through the messages.

        if (!telemetryStatsConnected) {
            UAVObject stats = objMngr.getObject("GCSTelemetryStats");
            if (stats == null)
                return;

            stats.addUpdatedObserver(telemetryObserver);
            telemetryStatsConnected = true;
        }
        updateTelemetryStats();

        UAVObject alarms = objMngr.getObject("SystemAlarms");
        if (alarms != null)
            alarms.addUpdatedObserver(alarmsObserver);
        updateAlarmSummary();

        if (DEBUG)
            Log.d(TAG, "Notifying listeners about connection.  There are " + connectionListeners.countObservers());
        connectionListeners.connected();
    }

    /**
     * Called when telemetry drops the connection
     *
     * This should be called by all inherited classes if they want the telemetry bar etc
     */
    void onDisconnected() {
        if (!connectedCalled)
            return;
        connectedCalled = false;

        // Providing a null update triggers a disconnect on fragments
        connectionListeners.disconnected();

        if (objMngr == null) {
            Log.d(TAG, "onOPDisconnected(): Object manager already went away");
            return;
        }

        if (telemetryStatsConnected) {
            UAVObject stats = objMngr.getObject("GCSTelemetryStats");
            if (stats != null) {
                stats.removeUpdatedObserver(telemetryObserver);
            }
            telemetryStatsConnected = false;
            updateTelemetryStats();

            UAVObject alarms = objMngr.getObject("SystemAlarms");
            if (alarms != null) {
                alarms.removeUpdatedObserver(alarmsObserver);
            }
        }

        // Disconnect from any UAVO updates
        if (DEBUG)
            Log.d(TAG, "onOpDisconnected(): Pausing the listeners and deleting the list");
        pauseObjectUpdates();
        listeners = null;
    }

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

        if (getConnectionState() == ConnectionState.CONNECTED && objMngr != null && !telemetryStatsConnected) {

            UAVObject stats = objMngr.getObject("GCSTelemetryStats");
            if (stats == null)
                return;

            stats.addUpdatedObserver(telemetryObserver);
            telemetryStatsConnected = true;

            UAVObject alarms = objMngr.getObject("SystemAlarms");
            if (alarms != null)
                alarms.addUpdatedObserver(alarmsObserver);
            updateAlarmSummary();

        }

        resumeObjectUpdates();
        invalidateOptionsMenu();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (telemetryStatsConnected) {
            UAVObject stats = objMngr.getObject("GCSTelemetryStats");

            stats.removeUpdatedObserver(telemetryObserver);
            telemetryStatsConnected = false;

            UAVObject alarms = objMngr.getObject("SystemAlarms");
            if (alarms != null) {
                alarms.removeUpdatedObserver(alarmsObserver);
            }
        }

        pauseObjectUpdates();
    }

    @Override
    public void onStart() {
        super.onStart();
        if (DEBUG)
            Log.d(TAG, "onStart()");

        // Register a receiver to get connected/disconnected signals from the telemetry
        // service
        connectedReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (DEBUG)
                    Log.d(TAG, "Received intent");
                TelemTask task;
                if (intent.getAction().compareTo(TelemetryService.INTENT_CHANNEL_OPENED) == 0) {
                    invalidateOptionsMenu();
                } else if (intent.getAction().compareTo(TelemetryService.INTENT_ACTION_CONNECTED) == 0) {
                    if (binder == null)
                        return;
                    if ((task = binder.getTelemTask(0)) == null)
                        return;
                    objMngr = task.getObjectManager();
                    onConnected();
                    Log.d(TAG, "Connected()");
                    invalidateOptionsMenu();
                } else if (intent.getAction().compareTo(TelemetryService.INTENT_ACTION_DISCONNECTED) == 0) {
                    onDisconnected();
                    objMngr = null;
                    Log.d(TAG, "Disonnected()");
                    invalidateOptionsMenu();
                }
            }
        };

        // Set up the filters
        IntentFilter filter = new IntentFilter();
        filter.addCategory(TelemetryService.INTENT_CATEGORY_GCS);
        filter.addAction(TelemetryService.INTENT_CHANNEL_OPENED);
        filter.addAction(TelemetryService.INTENT_ACTION_CONNECTED);
        filter.addAction(TelemetryService.INTENT_ACTION_DISCONNECTED);
        registerReceiver(connectedReceiver, filter);

        // Bind to the telemetry service (which will start it)
        Intent intent = new Intent(getApplicationContext(),
                org.taulabs.androidgcs.telemetry.TelemetryService.class);
        startService(intent);
        if (DEBUG)
            Log.d(TAG, "Attempting to bind: " + intent);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

    }

    /**
     * When stopping disconnect form the service and the broadcast receiver
     */
    @Override
    public void onStop() {
        super.onStop();
        if (DEBUG)
            Log.d(TAG, "onStop()");
        unbindService(mConnection);
        unregisterReceiver(connectedReceiver);
        connectedReceiver = null;

        // Disconnect from any UAVO updates
        if (DEBUG)
            Log.d(TAG, "onStop(): Pausing the listeners and deleting the list");
        pauseObjectUpdates();
        listeners = null;
    }

    /*********** This provides the object update messaging service ************/

    /**
     * A message handler and a custom Observer to use it which calls
     * objectUpdated with the right object type
     */
    final Handler uavobjHandler = new Handler();

    private class ActivityUpdatedObserver implements Observer {
        UAVObject obj;

        ActivityUpdatedObserver(UAVObject obj) {
            this.obj = obj;
        };

        @Override
        public void update(Observable observable, Object data) {
            uavobjHandler.post(new Runnable() {
                @Override
                public void run() {
                    objectUpdated(obj);
                }
            });
        }
    };

    /**
     * Unregister all the objects connected to this activity
     */
    private boolean paused = false;

    /**
     * When an activity is paused, disconnect from all
     * updates to ensure we don't draw to an invalid view
     */
    protected void pauseObjectUpdates() {
        // When listeners is null then a pause occurred after
        // disconnecting from the service
        if (listeners == null)
            return;

        Set<Observer> s = listeners.keySet();
        Iterator<Observer> i = s.iterator();
        while (i.hasNext()) {
            Observer o = i.next();
            UAVObject obj = listeners.get(o);
            obj.removeUpdatedObserver(o);
        }
        paused = true;
    }

    /**
     * When an activity is resumed, reconnect all now the view
     * is valid again
     */
    protected void resumeObjectUpdates() {
        // When listeners is null this is the resume at the beginning
        // before connecting to the telemetry service
        if (listeners == null)
            return;

        Set<Observer> s = listeners.keySet();
        Iterator<Observer> i = s.iterator();
        while (i.hasNext()) {
            Observer o = i.next();
            UAVObject obj = listeners.get(o);
            obj.addUpdatedObserver(o);
        }
        paused = false;
    }

    /**
     * Register an activity to receive updates from this object
     * @param object The object the activity should listen to updates from
     * the objectUpdated() method will be called in the original UI thread
     */
    protected void registerObjectUpdates(UAVObject object) {
        Observer o = new ActivityUpdatedObserver(object);
        listeners.put(o, object);
        if (!paused)
            object.addUpdatedObserver(o);
    }

    /**
     * Helper method to register array of objects
     */
    protected void registerObjectUpdates(List<List<UAVObject>> objects) {
        for (int i = 0; i < objects.size(); i++) {
            List<UAVObject> inner = objects.get(i);
            for (int j = 0; j < inner.size(); j++)
                registerObjectUpdates(inner.get(j));
        }
    }

    /*********** Deals with the default visualization of all activities *******/

    //! Store reference to alarm widget from menu inflation
    private AlarmsSummary summary;

    /**
     * @brief Look for the worst alarm level and update the
     * widget view accordingly
     */
    private void updateAlarmSummary() {
        if (summary == null)
            return;

        if (objMngr == null)
            return;

        UAVObject alarms = objMngr.getObject("SystemAlarms");
        if (alarms == null)
            return;
        UAVObjectField alarmField = alarms.getField("Alarm");
        if (alarmField == null)
            return;

        int worst = 0;
        for (int i = 0; i < alarmField.getNumElements(); i++) {
            if (alarmField.getDouble(i) > worst)
                worst = (int) alarmField.getDouble(i);
        }

        String worstAlarm = alarmField.getOptions().get(worst);

        // Map from string to the enum value
        if (worstAlarm.equals("OK"))
            summary.setAlarmsStatus(AlarmsStatus.GOOD);
        else if (worstAlarm.equals("Warning"))
            summary.setAlarmsStatus(AlarmsStatus.WARNING);
        else if (worstAlarm.equals("Error"))
            summary.setAlarmsStatus(AlarmsStatus.ERROR);
        else if (worstAlarm.equals("Critical"))
            summary.setAlarmsStatus(AlarmsStatus.CRITICAL);
        else
            // Should not happen (e.g. Uninitialized)
            summary.setAlarmsStatus(AlarmsStatus.CRITICAL);
    }

    //! Updated whenever the alarms are
    private final Observer alarmsObserver = new Observer() {
        @Override
        public void update(Observable observable, Object data) {
            uavobjHandler.post(new Runnable() {
                @Override
                public void run() {
                    updateAlarmSummary();
                }
            });
        }
    };

    //! Store local reference from inflation
    private TelemetryStats telemetryStats;

    //!Show the telemetry rate in the task bar
    private void updateTelemetryStats() {
        if (telemetryStats == null)
            return;

        telemetryStats.setConnected(getConnectionState() == ConnectionState.CONNECTED);

        if (getConnectionState() != ConnectionState.CONNECTED) {
            telemetryStats.setTxRate(0);
            telemetryStats.setRxRate(0);
            return;
        }

        if (objMngr == null)
            return;

        UAVObject stats = objMngr.getObject("GCSTelemetryStats");
        if (stats == null)
            return;

        telemetryStats.setTxRate((int) stats.getField("TxDataRate").getDouble());
        telemetryStats.setRxRate((int) stats.getField("RxDataRate").getDouble());
    }

    //! Called whenever telemetry stats are updated
    final Observer telemetryObserver = new Observer() {
        @Override
        public void update(Observable observable, Object data) {
            uavobjHandler.post(new Runnable() {
                @Override
                public void run() {
                    updateTelemetryStats();
                }
            });
        }
    };

    /*********** Deals with fragments listening for connections ***************/

    /**
     * Callbacks so ObjectManagerFragments get the onConnected and onDisconnected signals
     */
    class ConnectionObserver extends Observable {
        public void disconnected() {
            synchronized (this) {
                setChanged();
                notifyObservers();
            }
        }

        public void connected() {
            synchronized (this) {
                setChanged();
                notifyObservers(objMngr);
            }
        }
    };

    private final ConnectionObserver connectionListeners = new ConnectionObserver();

    public class OnConnectionListener implements Observer {

        // Local reference of the fragment to notify, store in constructor
        ObjectManagerFragment fragment;

        OnConnectionListener(ObjectManagerFragment fragment) {
            this.fragment = fragment;
        };

        // Whenever the observer is updated either connected or disconnected based on the data
        @Override
        public void update(Observable observable, Object data) {
            Log.d(TAG, "onConnectionListener called");
            if (data == null)
                fragment.onDisconnected();
            else
                fragment.onConnected(objMngr);
        }

    };

    public void addOnConnectionListenerFragment(ObjectManagerFragment frag) {
        connectionListeners.addObserver(new OnConnectionListener(frag));
        if (DEBUG)
            Log.d(TAG, "Connecting " + frag + " there are now " + connectionListeners.countObservers());

        // We have to check the connected called flag to make sure that the activity
        // has acknowledged the connection already.
        if (getConnectionState() == ConnectionState.CONNECTED && connectedCalled)
            frag.onConnected(objMngr);
    }

    /*********** Deals with (dis)connection to telemetry service ***************/

    /** Defines callbacks for service binding, passed to bindService() */
    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName arg0, IBinder service) {
            // We've bound to LocalService, cast the IBinder and attempt to open a connection
            if (DEBUG)
                Log.d(TAG, "Service bound");
            binder = (LocalBinder) service;

            if (binder.isConnected()) {
                TelemTask task;
                if ((task = binder.getTelemTask(0)) != null) {
                    objMngr = task.getObjectManager();
                    onConnected();
                    invalidateOptionsMenu();
                }

            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            onDisconnected();
            binder = null;
            objMngr = null;
            invalidateOptionsMenu();
        }
    };

    /************* Deals with menus *****************/
    @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;
        }

        if (binder == null) {
            Log.e(TAG, "Unable to connect to service");
            return super.onOptionsItemSelected(item);
        }
        switch (item.getItemId()) {
        case R.id.menu_connect:
            binder.openConnection();
            return true;
        case R.id.menu_disconnect:
            binder.stopConnection();
            return true;
        case R.id.menu_settings:
            startActivity(new Intent(this, Preferences.class));
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }

    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {

        // Query the telemetry service for the current state
        boolean channelOpen = getConnectionState() != ConnectionState.DISCONNECTED;

        // Show the connect button based on the status reported by the telemetry
        // service
        MenuItem connectionButton = menu.findItem(R.id.menu_connect);
        if (connectionButton != null) {
            connectionButton.setEnabled(!channelOpen).setVisible(!channelOpen);
        }

        MenuItem disconnectionButton = menu.findItem(R.id.menu_disconnect);
        if (disconnectionButton != null) {
            disconnectionButton.setEnabled(channelOpen).setVisible(channelOpen);
        }

        return super.onPrepareOptionsMenu(menu);
    }

    //! Get the current connection state
    private ConnectionState getConnectionState() {
        if (binder == null)
            return ConnectionState.DISCONNECTED;
        return binder.getConnectionState();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.status_menu, menu);
        inflater.inflate(R.menu.options_menu, menu);

        telemetryStats = (TelemetryStats) (menu.findItem(R.id.telemetry_status).getActionView());
        updateTelemetryStats();

        summary = (AlarmsSummary) menu.findItem(R.id.alarms_status).getActionView();
        updateAlarmSummary();

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        updateTelemetryStats();
        return true;
    }

    /************ Deals with drawer navigation ************/
    private NavDrawerActivityConfiguration navConf;

    protected abstract NavDrawerActivityConfiguration getNavDrawerConfiguration();

    protected NavDrawerActivityConfiguration getDefaultNavDrawerConfiguration() {

        NavDrawerActivityConfiguration navDrawerActivityConfiguration = new NavDrawerActivityConfiguration();
        navDrawerActivityConfiguration.setDrawerLayoutId(R.id.drawer_layout);
        navDrawerActivityConfiguration.setLeftDrawerId(R.id.left_drawer);
        navDrawerActivityConfiguration.setDrawerShadow(R.drawable.drawer_shadow);
        navDrawerActivityConfiguration.setDrawerOpenDesc(R.string.drawer_open);
        navDrawerActivityConfiguration.setDrawerCloseDesc(R.string.drawer_close);

        // The main two things that can be overridden are the layout (must be) and the menu options

        //navDrawerActivityConfiguration.setMainLayout(R.layout.main);

        // Set up the menu
        NavDrawerItem[] menu = new NavDrawerItem[] { NavMenuSection.create(100, "Main Screens"),
                NavMenuItem.create(101, "PFD", "ic_pfd", true, this),
                NavMenuItem.create(102, "Map", "ic_map", true, this),
                NavMenuItem.create(103, "Alarms", "ic_alarms", true, this),
                NavMenuActivity.create(104, "Tuning", "ic_tuning", TuningActivity.class, true, this),
                NavMenuActivity.create(105, "Home Adjustment", "ic_map", HomeAdjustment.class, true, this),
                NavMenuActivity.create(106, "Browser", "ic_browser", ObjectBrowser.class, true, this),
                NavMenuActivity.create(107, "Logging", "ic_logging", Logging.class, true, this),
                //NavMenuActivity.create(108, "Control", "ic_controller", Controller.class, true, this),
                NavMenuActivity.create(109, "Tablet Control", "ic_tabletcontrol", TabletControl.class, true, this),
                NavMenuActivity.create(1010, "OSG", "ic_osg", OsgViewer.class, true, this), };

        navDrawerActivityConfiguration.setNavItems(menu);
        navDrawerActivityConfiguration.setBaseAdapter(new NavDrawerAdapter(this, R.layout.navdrawer_item, menu));

        return navDrawerActivityConfiguration;
    }

    protected void initDrawerShadow() {
        mDrawerLayout.setDrawerShadow(navConf.getDrawerShadow(), GravityCompat.START);
    }

    protected int getDrawerIcon() {
        return R.drawable.ic_drawer;
    }

    /* The click listener 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);
        }
    }

    /**
     * Map the IDs to the fragments for the default layout. These should
     * match the values used when creating the NavDrawerItems.
     * @param id of the fragment to fetch
     * @return the new fragment
     */
    protected Fragment getFragmentById(int id) {
        switch (id) {
        case 101:
            return new PFD();
        case 102:
            return new Map();
        case 103:
            return new SystemAlarmsFragment();
        }
        return null;
    }

    //! Set the selected drawer item and title by ID
    public void setSelectionById(int id) {
        NavDrawerItem selectedItem[] = navConf.getNavItems();
        for (int i = 0; i < selectedItem.length; i++) {
            if (selectedItem[i].getId() == id) {
                mDrawerList.setItemChecked(i, true);
                if (selectedItem[i].updateActionBarTitle()) {
                    setTitle(selectedItem[i].getLabel());
                }
            }
        }
    }

    private void selectItem(int position) {

        NavDrawerItem selectedItem = navConf.getNavItems()[position];

        // Selected item indicates an activity to launch
        if (selectedItem.getType() == NavMenuActivity.ACTIVITY_TYPE) {
            NavMenuActivity launcherItem = (NavMenuActivity) selectedItem;
            if (launcherItem.getLaunchClass() != null) {
                Log.d(TAG,
                        "ID: " + selectedItem.getId() + " " + selectedItem.getLabel() + " position: " + position);

                mDrawerList.setItemChecked(position, true);

                if (selectedItem.updateActionBarTitle()) {
                    setTitle(selectedItem.getLabel());
                }

                if (this.mDrawerLayout.isDrawerOpen(this.mDrawerList)) {
                    mDrawerLayout.closeDrawer(mDrawerList);
                }

                startActivity(new Intent(this, launcherItem.getLaunchClass()));
            }

            return;
        }

        // Selected item indicates the contents to put in the main frame
        if (selectedItem.getType() == NavMenuItem.ITEM_TYPE) {

            if (findViewById(navConf.getMainLayout()) == null) {
                // If not the new main activity should be activated.

                // Close drawer first
                mDrawerList.setItemChecked(position, true);
                if (this.mDrawerLayout.isDrawerOpen(this.mDrawerList)) {
                    mDrawerLayout.closeDrawer(mDrawerList);
                }

                // Activate main activity, indicating the fragment it should show 
                Intent mainScreen = new Intent(this, MainActivity.class);
                mainScreen.putExtra("ContentFrag", selectedItem.getId());
                startActivity(mainScreen);

                return;
            } else {

                int id = (int) selectedItem.getId();
                FragmentTransaction trans = getFragmentManager().beginTransaction();
                trans.replace(navConf.getMainLayout(), getFragmentById(id));
                trans.commit();

                mDrawerList.setItemChecked(position, true);

                if (selectedItem.updateActionBarTitle()) {
                    Log.d(TAG, "Selected item title: " + selectedItem.getLabel());
                    setTitle(selectedItem.getLabel());
                }

                if (this.mDrawerLayout.isDrawerOpen(this.mDrawerList)) {
                    mDrawerLayout.closeDrawer(mDrawerList);
                }
            }
        }

    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getActionBar().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 toggls
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

}