net.reichholf.dreamdroid.fragment.NavigationFragment.java Source code

Java tutorial

Introduction

Here is the source code for net.reichholf.dreamdroid.fragment.NavigationFragment.java

Source

/*  2010 Stephan Reichholf <stephan at reichholf dot net>
 * 
 * Licensed under the Create-Commons Attribution-Noncommercial-Share Alike 3.0 Unported
 * http://creativecommons.org/licenses/by-nc-sa/3.0/
 */

package net.reichholf.dreamdroid.fragment;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import net.reichholf.dreamdroid.DreamDroid;
import net.reichholf.dreamdroid.R;
import net.reichholf.dreamdroid.activities.MainActivity;
import net.reichholf.dreamdroid.activities.MyPreferenceActivity;
import net.reichholf.dreamdroid.activities.SimpleNoTitleFragmentActivity;
import net.reichholf.dreamdroid.adapter.NavigationListAdapter;
import net.reichholf.dreamdroid.fragment.abs.AbstractHttpListFragment;
import net.reichholf.dreamdroid.fragment.dialogs.AboutDialog;
import net.reichholf.dreamdroid.fragment.dialogs.ActionDialog;
import net.reichholf.dreamdroid.fragment.dialogs.SendMessageDialog;
import net.reichholf.dreamdroid.fragment.dialogs.SimpleChoiceDialog;
import net.reichholf.dreamdroid.fragment.dialogs.SimpleProgressDialog;
import net.reichholf.dreamdroid.fragment.dialogs.SleepTimerDialog;
import net.reichholf.dreamdroid.helpers.DateTime;
import net.reichholf.dreamdroid.helpers.ExtendedHashMap;
import net.reichholf.dreamdroid.helpers.Python;
import net.reichholf.dreamdroid.helpers.Statics;
import net.reichholf.dreamdroid.helpers.enigma2.Event;
import net.reichholf.dreamdroid.helpers.enigma2.Message;
import net.reichholf.dreamdroid.helpers.enigma2.PowerState;
import net.reichholf.dreamdroid.helpers.enigma2.SleepTimer;
import net.reichholf.dreamdroid.helpers.enigma2.requesthandler.MessageRequestHandler;
import net.reichholf.dreamdroid.helpers.enigma2.requesthandler.PowerStateRequestHandler;
import net.reichholf.dreamdroid.helpers.enigma2.requesthandler.SleepTimerRequestHandler;
import net.reichholf.dreamdroid.loader.LoaderResult;
import net.reichholf.dreamdroid.widget.CheckableImageButton;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import java.util.ArrayList;
import java.util.Calendar;

/**
 * This is where all begins. It's the "main menu activity" which acts as central
 * navigation instance
 *
 * @author sreichholf
 */
public class NavigationFragment extends AbstractHttpListFragment implements ActionDialog.DialogActionListener,
        SleepTimerDialog.SleepTimerDialogActionListener, SendMessageDialog.SendMessageDialogActionListener {

    @SuppressWarnings("unused")
    private static final String LOG_TAG = "NavigationFragment";

    // [ ID, string.ID, drawable.ID, Available (1=yes, 0=no), isDialog (2=yes if
    // no SlidingMenu else no, 1=yes,
    // 0=no) ]
    public static final int[][] MENU_ITEMS = {
            { Statics.ITEM_SERVICES, R.string.services, R.attr.ic_menu_services, 1, 0 },
            { Statics.ITEM_BOUQUETEPG, R.string.epg, R.attr.ic_menu_epg, 1, 0 },
            { Statics.ITEM_MOVIES, R.string.movies, R.attr.ic_menu_movie, 1, 0 },
            { Statics.ITEM_TIMER, R.string.timer, R.attr.ic_menu_timer, 1, 0 },
            { Statics.ITEM_REMOTE, R.string.virtual_remote, R.attr.ic_menu_remote, 1, 2 },
            { Statics.ITEM_CURRENT, R.string.current_service, R.attr.ic_menu_current, 1, 0 },
            { Statics.ITEM_POWERSTATE_DIALOG, R.string.powercontrol, R.attr.ic_menu_power_off, 1, 1 },
            { Statics.ITEM_MEDIA_PLAYER, R.string.mediaplayer, R.attr.ic_menu_music, 1, 0 },
            { Statics.ITEM_ZAP, R.string.zap, R.attr.ic_menu_zap, 1, 0 },
            { Statics.ITEM_SLEEPTIMER, R.string.sleeptimer, R.attr.ic_menu_sleeptimer,
                    DreamDroid.featureSleepTimer() ? 1 : 0, 1 },
            { Statics.ITEM_SCREENSHOT, R.string.screenshot, R.attr.ic_menu_picture, 1, 0 },
            { Statics.ITEM_INFO, R.string.device_info, R.attr.ic_menu_device, 1, 0 },
            { Statics.ITEM_MESSAGE, R.string.send_message, R.attr.ic_menu_mail, 1, 1 },
            { Statics.ITEM_SIGNAL, R.string.signal_meter, R.attr.ic_menu_signal, 1, 0 }, };

    private int[] mCurrent;
    private int mCurrentListItem;
    private boolean mHighlightCurrent;

    private SetPowerStateTask mSetPowerStateTask;
    private SleepTimerTask mSleepTimerTask;

    public NavigationFragment() {
        super();
        initTitle("");
        setHighlightCurrent(true);
    }

    /**
     * <code>AsyncTask</code> to set the powerstate of the target device
     *
     * @author sre
     */
    private class SetPowerStateTask extends AsyncTask<String, String, Boolean> {
        private ExtendedHashMap mResult;

        @Override
        protected Boolean doInBackground(String... params) {
            PowerStateRequestHandler handler = new PowerStateRequestHandler();
            String xml = handler.get(getHttpClient(), PowerState.getStateParams(params[0]));

            if (xml != null) {
                if (isCancelled())
                    return false;
                ExtendedHashMap result = new ExtendedHashMap();
                handler.parse(xml, result);

                mResult = result;
                return true;
            }

            return false;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if (!result || mResult == null) {
                mResult = new ExtendedHashMap();

                if (getHttpClient().hasError()) {
                    showToast(getText(R.string.get_content_error) + "\n" + getHttpClient().getErrorText());
                } else {
                    showToast(getText(R.string.get_content_error));
                }
            } else {
                onPowerStateSet((Boolean) mResult.get(PowerState.KEY_IN_STANDBY));
            }

        }
    }

    /**
     * @author sre
     */
    private class SleepTimerTask extends AsyncTask<ArrayList<NameValuePair>, Void, Boolean> {
        private ExtendedHashMap mResult;
        private SleepTimerRequestHandler mHandler;
        private boolean mDialogOnFinish;
        private SimpleProgressDialog mProgressDialogFragment;

        public SleepTimerTask(boolean dialogOnFinish) {
            mHandler = new SleepTimerRequestHandler();
            mDialogOnFinish = dialogOnFinish;
        }

        @Override
        protected Boolean doInBackground(ArrayList<NameValuePair>... params) {
            publishProgress();
            String xml = mHandler.get(getHttpClient(), params[0]);

            if (xml != null) {
                ExtendedHashMap result = new ExtendedHashMap();
                mHandler.parse(xml, result);

                String enabled = result.getString(SleepTimer.KEY_ENABLED);

                if (enabled != null) {
                    mResult = result;
                    return true;
                }
            }

            return false;
        }

        @Override
        protected void onProgressUpdate(Void... progress) {
            mProgressDialogFragment = SimpleProgressDialog.newInstance(getString(R.string.sleeptimer),
                    getString(R.string.loading));
            getMultiPaneHandler().showDialogFragment(mProgressDialogFragment, "sleeptimer_progress_dialog");
        }

        @Override
        protected void onPostExecute(Boolean result) {
            mProgressDialogFragment.dismiss();
            if (!result || mResult == null) {
                mResult = new ExtendedHashMap();
            }

            onSleepTimerResult(result, mResult, mDialogOnFinish);
        }
    }

    /**
     * @param time
     * @param action
     * @param enabled
     */
    public void onSetSleepTimer(String time, String action, boolean enabled) {
        ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("cmd", SleepTimer.CMD_SET));
        params.add(new BasicNameValuePair("time", time));
        params.add(new BasicNameValuePair("action", action));

        if (enabled) {
            params.add(new BasicNameValuePair("enabled", Python.TRUE));
        } else {
            params.add(new BasicNameValuePair("enabled", Python.FALSE));
        }

        execSleepTimerTask(params, false);
    }

    /**
     *
     */
    private void getSleepTimer(boolean showDialogOnFinish) {
        ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
        execSleepTimerTask(params, showDialogOnFinish);
    }

    /**
     * @param params
     */
    @SuppressWarnings("unchecked")
    private void execSleepTimerTask(ArrayList<NameValuePair> params, boolean showDialogOnFinish) {
        if (mSleepTimerTask != null) {
            mSleepTimerTask.cancel(true);
        }

        mSleepTimerTask = new SleepTimerTask(showDialogOnFinish);
        mSleepTimerTask.execute(params);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initTitle(getString(R.string.app_name));

        mCurrentListItem = -1;

        setAdapter();
    }

    @Override
    public void onDestroy() {
        if (mSleepTimerTask != null)
            mSleepTimerTask.cancel(true);
        if (mSetPowerStateTask != null)
            mSetPowerStateTask.cancel(true);
        super.onDestroy();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.navigation_layout, container, false);
        registerImageButtonListener(view, R.id.buttonSettings);
        registerImageButtonListener(view, R.id.buttonAbout);
        registerImageButtonListener(view, R.id.buttonProfiles);
        registerImageButtonListener(view, R.id.buttonChangeLog);

        return view;
    }

    private void registerImageButtonListener(View view, int buttonId) {
        CheckableImageButton b = (CheckableImageButton) view.findViewById(buttonId);
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CheckableImageButton cib = (CheckableImageButton) v;
                if (cib.getId() == R.id.buttonProfiles) {
                    getListView().setItemChecked(mCurrentListItem, false);
                    mCurrentListItem = -1;
                    if (cib.isChecked()) {
                        getMainActivity().showContent();
                        return;
                    }
                    cib.setChecked(true);
                } else {
                    CheckableImageButton btn = (CheckableImageButton) findViewById(R.id.buttonProfiles);
                    btn.setChecked(false);
                }
                onItemSelected(v.getId());
            }
        });
    }

    public void setHighlightCurrent(boolean highlight) {
        mHighlightCurrent = highlight;
    }

    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        getListView().setTextFilterEnabled(true);
    }

    @SuppressLint("NewApi")
    public void setSelectedItem(int position) {
        if (Build.VERSION.SDK_INT >= 8)
            getListView().smoothScrollToPosition(position);
        onListItemClick(getListView(), null, position, position);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        if (mCurrentListItem == position) {
            // Don't reload what we already see but close
            getMainActivity().showContent();
            return;
        }

        mCurrent = (int[]) l.getItemAtPosition(position);

        // only mark the entry if it isn't a "dialog-only-item"
        // TODO find a reliable way to mark the current item...
        if (mHighlightCurrent) {
            CheckableImageButton btn = (CheckableImageButton) findViewById(R.id.buttonProfiles);
            btn.setChecked(false);

            if (mCurrent[4] == 0 || (mCurrent[4] == 2 && isTablet())) {
                l.setItemChecked(position, true);
                mCurrentListItem = position;
            } else {
                l.setItemChecked(position, false);
                if (mCurrentListItem > 0) {
                    l.setItemChecked(mCurrentListItem, true);
                }
            }
        } else {
            l.setItemChecked(position, false);
        }

        onItemSelected(mCurrent[0]);
    }

    private void setAdapter() {
        mAdapter = new NavigationListAdapter(getMainActivity(), MENU_ITEMS);
        setListAdapter(mAdapter);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.preferences, menu);
    }

    /**
     * Execute the proper action for a item ID (<code>ITEM_*</code> statics)
     *
     * @param id The id used to identify the item clicked (<code>ITEM_*</code>
     *           statics)
     */
    protected boolean onItemSelected(int id) {
        boolean retVal = true;
        Intent intent;
        switch (id) {
        case Statics.ITEM_TIMER:
            clearBackStack();
            getMainActivity().showDetails(TimerListFragment.class);
            break;

        case Statics.ITEM_MOVIES:
            clearBackStack();
            getMainActivity().showDetails(MovieListFragment.class);
            break;

        case Statics.ITEM_SERVICES:
            clearBackStack();
            getMainActivity().showDetails(ServiceListFragment.class);
            break;

        case Statics.ITEM_INFO:
            clearBackStack();
            getMainActivity().showDetails(DeviceInfoFragment.class);
            break;

        case Statics.ITEM_CURRENT:
            clearBackStack();
            getMainActivity().showDetails(CurrentServiceFragment.class);
            break;

        case Statics.ITEM_REMOTE:
            if (!isTablet()) {
                intent = new Intent(getMainActivity(), SimpleNoTitleFragmentActivity.class);
                intent.putExtra("fragmentClass", VirtualRemotePagerFragment.class);
                startActivity(intent);
            } else {
                clearBackStack();
                getMainActivity().showDetails(VirtualRemotePagerFragment.class);
            }
            break;

        case Statics.ITEM_PREFERENCES:
            intent = new Intent(getMainActivity(), MyPreferenceActivity.class);
            startActivityForResult(intent, Statics.REQUEST_ANY);
            break;

        case Statics.ITEM_MESSAGE:
            getMultiPaneHandler().showDialogFragment(SendMessageDialog.newInstance(), "sendmessage_dialog");
            break;

        case Statics.ITEM_SCREENSHOT:
            clearBackStack();
            getMainActivity().showDetails(ScreenShotFragment.class);
            break;

        case Statics.ITEM_TOGGLE_STANDBY:
            setPowerState(PowerState.STATE_TOGGLE);
            break;

        case Statics.ITEM_RESTART_GUI:
            setPowerState(PowerState.STATE_GUI_RESTART);
            break;

        case Statics.ITEM_REBOOT:
            setPowerState(PowerState.STATE_SYSTEM_REBOOT);
            break;

        case Statics.ITEM_SHUTDOWN:
            setPowerState(PowerState.STATE_SHUTDOWN);
            break;

        case Statics.ITEM_POWERSTATE_DIALOG:
            CharSequence[] actions = { getText(R.string.standby), getText(R.string.restart_gui),
                    getText(R.string.reboot), getText(R.string.shutdown) };
            int[] actionIds = { Statics.ITEM_TOGGLE_STANDBY, Statics.ITEM_RESTART_GUI, Statics.ITEM_REBOOT,
                    Statics.ITEM_SHUTDOWN };
            getMultiPaneHandler().showDialogFragment(
                    SimpleChoiceDialog.newInstance(getString(R.string.powercontrol), actions, actionIds),
                    "powerstate_dialog");
            break;

        case Statics.ITEM_ABOUT:
            getMultiPaneHandler().showDialogFragment(AboutDialog.newInstance(), "about_dialog");
            break;

        case Statics.ITEM_CHECK_CONN:
            getMainActivity().onProfileChanged(DreamDroid.getCurrentProfile());
            break;

        case Statics.ITEM_CHANGELOG:
            getMainActivity().showChangeLogIfNeeded(false);
            break;

        case Statics.ITEM_SLEEPTIMER:
            getSleepTimer(true);
            break;

        case Statics.ITEM_MEDIA_PLAYER:
            clearBackStack();
            getMainActivity().showDetails(MediaPlayerFragment.class);
            break;

        case Statics.ITEM_PROFILES:
            clearBackStack();
            getMainActivity().showDetails(ProfileListFragment.class);
            break;

        case Statics.ITEM_SIGNAL:
            clearBackStack();
            getMainActivity().showDetails(SignalFragment.class);
            break;
        case Statics.ITEM_ZAP:
            clearBackStack();
            getMainActivity().showDetails(ZapFragment.class);
            break;
        case Statics.ITEM_RELOAD:
            return false;
        case Statics.ITEM_BOUQUETEPG:
            clearBackStack();
            Bundle args = new Bundle();

            String ref = DreamDroid.getCurrentProfile().getDefaultRef();
            args.putString(Event.KEY_SERVICE_REFERENCE, ref);

            String name = DreamDroid.getCurrentProfile().getDefaultRefName();
            args.putString(Event.KEY_SERVICE_NAME, name);

            EpgBouquetFragment f = new EpgBouquetFragment();
            f.setArguments(args);
            getMainActivity().showDetails(f);
            break;
        default:
            retVal = super.onItemSelected(id);
        }
        getMainActivity().showContent();
        return retVal;
    }

    private void clearBackStack() {
        // Pop the backstack completely everytime the user navigates "away"
        // Avoid's "stacking" fragments due to back-button behaviour that feels
        // really mysterious
        FragmentManager fm = getActionBarActivity().getSupportFragmentManager();
        if (fm.getBackStackEntryCount() > 0) {
            fm.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        }
    }

    /**
     * @param state The powerstate to set. For example defined in
     *              <code>helpers.enigma2.PowerState.STATE_*</code>
     */
    private void setPowerState(String state) {
        if (mSetPowerStateTask != null) {
            mSetPowerStateTask.cancel(true);
        }

        mSetPowerStateTask = new SetPowerStateTask();
        mSetPowerStateTask.execute(state);
    }

    /**
     * Shows success/error toasts after power state has been set
     *
     * @param isRunning
     */
    private void onPowerStateSet(boolean isRunning) {
        if (isRunning) {
            showToast(getString(R.string.is_running));
        } else {
            showToast(getString(R.string.in_standby));
        }
    }

    /**
     * Send a message to the target device which will be shown on TV
     *
     * @param text    The message text
     * @param type    Type of the message as defined in
     *                <code>helpers.enigma2.Message.STATE_*</code>
     * @param timeout Timeout for the message, 0 means no timeout will occur
     */
    public void onSendMessage(String text, String type, String timeout) {
        ExtendedHashMap msg = new ExtendedHashMap();
        msg.put(Message.KEY_TEXT, text);
        msg.put(Message.KEY_TYPE, type);
        msg.put(Message.KEY_TIMEOUT, timeout);

        execSimpleResultTask(new MessageRequestHandler(), Message.getParams(msg));
    }

    public void setAvailableFeatures() {
        // TODO implement feature-handling for list-navigation
    }

    /**
     * @param success
     * @param sleepTimer
     */
    private void onSleepTimerResult(boolean success, ExtendedHashMap sleepTimer, boolean openDialog) {
        if (success) {
            if (openDialog) {
                getMultiPaneHandler().showDialogFragment(SleepTimerDialog.newInstance(sleepTimer),
                        "sleeptimer_dialog");
                return;
            }
            String text = sleepTimer.getString(SleepTimer.KEY_TEXT);
            showToast(text);
        } else {
            showToast(getString(R.string.error));
        }
    }

    private boolean isTablet() {
        return getResources().getBoolean(R.bool.is_tablet);
    }

    /**
     * @param id
     * @return
     */
    public View findViewById(int id) {
        return getActionBarActivity().findViewById(id);
    }

    @Override
    public Loader<LoaderResult<ArrayList<ExtendedHashMap>>> onCreateLoader(int arg0, Bundle arg1) {
        return null;
    }

    private MainActivity getMainActivity() {
        return (MainActivity) getActivity();
    }

    /*
     * (non-Javadoc)
     * 
     * @see net.reichholf.dreamdroid.fragment.dialogs.PrimitiveDialog.
     * DialogActionListener#onDialogAction(int)
     */
    @Override
    public void onDialogAction(int action, Object details, String dialogTag) {
        onItemSelected(action);
    }
}