uk.org.rivernile.edinburghbustracker.android.fragments.dialogs.ServicesChooserDialogFragment.java Source code

Java tutorial

Introduction

Here is the source code for uk.org.rivernile.edinburghbustracker.android.fragments.dialogs.ServicesChooserDialogFragment.java

Source

/*
 * Copyright (C) 2012 - 2013 Niall 'Rivernile' Scott
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors or contributors be held liable for
 * any damages arising from the use of this software.
 *
 * The aforementioned copyright holder(s) hereby grant you a
 * non-transferrable right to use this software for any purpose (including
 * commercial applications), and to modify it and redistribute it, subject to
 * the following conditions:
 *
 *  1. This notice may not be removed or altered from any file it appears in.
 *
 *  2. Any modifications made to this software, except those defined in
 *     clause 3 of this agreement, must be released under this license, and
 *     the source code of any modifications must be made available on a
 *     publically accessible (and locateable) website, or sent to the
 *     original author of this software.
 *
 *  3. Software modifications that do not alter the functionality of the
 *     software but are simply adaptations to a specific environment are
 *     exempt from clause 2.
 */

package uk.org.rivernile.edinburghbustracker.android.fragments.dialogs;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import uk.org.rivernile.edinburghbustracker.android.R;

/**
 * This DialogFragment allows the user to select bus services from a list and
 * store the user's selection. This may be used to ask the user to filter bus
 * services or to say which services they are interested in.
 * 
 * @author Niall Scott
 */
public class ServicesChooserDialogFragment extends DialogFragment {

    /** The argument name for services. */
    private static final String ARG_SERVICES = "services";
    /** The argument name for the default selected services. */
    private static final String ARG_SELECTED_SERVICES = "selectedServices";
    /** The argument name for the dialog title. */
    private static final String ARG_TITLE = "dialogTitle";
    /** The argument name for check boxes, stored in the instance state. */
    private static final String ARG_CHECK_BOXES = "checkBoxes";

    private Callbacks callbacks;
    private String[] services;
    private boolean[] checkBoxes;

    /**
     * Create a new instance of this Fragment, providing a list of services to
     * select from, a list of services to select by default and a title for the
     * Dialog.
     * 
     * @param services The list of services to show to the user.
     * @param selectedServices The services to select by default, null if none.
     * @param dialogTitle The title to use for the Dialog.
     * @return A new instance of this Fragment.
     */
    public static ServicesChooserDialogFragment newInstance(final String[] services,
            final String[] selectedServices, final String dialogTitle) {
        final ServicesChooserDialogFragment f = new ServicesChooserDialogFragment();
        final Bundle b = new Bundle();
        b.putStringArray(ARG_SERVICES, services);
        b.putStringArray(ARG_SELECTED_SERVICES, selectedServices);
        b.putString(ARG_TITLE, dialogTitle);
        f.setArguments(b);

        return f;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onAttach(final Activity activity) {
        super.onAttach(activity);

        try {
            callbacks = (Callbacks) activity;
        } catch (ClassCastException e) {
            throw new IllegalStateException(
                    activity.getClass().getName() + " does not implement " + Callbacks.class.getName());
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Bundle args = getArguments();
        services = args.getStringArray(ARG_SERVICES);

        // Do sanity checks.
        if (services == null || services.length == 0) {
            throw new IllegalArgumentException("A list of services must " + "be supplied.");
        }

        if (savedInstanceState != null) {
            // If there is a previous instance, get the args from the saved
            // instance state.
            checkBoxes = savedInstanceState.getBooleanArray(ARG_CHECK_BOXES);
        } else {
            final String[] selectedServices = args.getStringArray(ARG_SELECTED_SERVICES);

            checkBoxes = new boolean[services.length];

            if (selectedServices != null && selectedServices.length > 0) {
                int i;
                final int len = services.length;
                for (i = 0; i < len; i++) {
                    for (String s : selectedServices) {
                        if (services[i].equals(s)) {
                            checkBoxes[i] = true;
                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);

        // Save the state.
        outState.putBooleanArray(ARG_CHECK_BOXES, checkBoxes);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Dialog onCreateDialog(final Bundle savedInstanceState) {
        // Build the Dialog.
        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(getArguments().getString(ARG_TITLE));
        builder.setMultiChoiceItems(services, checkBoxes, new DialogInterface.OnMultiChoiceClickListener() {
            @Override
            public void onClick(final DialogInterface dialog, final int which, boolean isChecked) {
                // Change the flag for that service.
                checkBoxes[which] = isChecked;
            }
        });

        builder.setPositiveButton(R.string.close, null);

        return builder.create();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onDismiss(final DialogInterface dialog) {
        super.onDismiss(dialog);

        // Tell the listener that there may be changes.
        callbacks.onServicesChosen(getChosenServices());
    }

    /**
     * Get the list of services that was supplied to the constructor.
     * 
     * @return A list of bus services to choose from.
     */
    public String[] getServices() {
        return services;
    }

    /**
     * Get a String array of the chosen services.
     * 
     * @return A String array of the chosen services.
     */
    public String[] getChosenServices() {
        int counter = 0;

        // Firstly, count the number of chosen services so we know how big to
        // make the String array.
        for (boolean b : checkBoxes) {
            if (b)
                counter++;
        }

        // If there's no chosen services, return an empty array.
        if (counter == 0)
            return new String[] {};

        // Create the array of the determined size.
        final String[] items = new String[counter];
        int i = 0;
        final int len = checkBoxes.length;

        // Loop through the check boxes, if it is selected, add it to the output
        // String array.
        for (int j = 0; j < len; j++) {
            if (checkBoxes[j]) {
                items[i] = services[j];
                i++;
            }
        }

        return items;
    }

    /**
     * Get a String representation of the chosen services.
     * 
     * @return A String representation of the chosen services.
     */
    public String getChosenServicesAsString() {
        return getChosenServicesAsString(getChosenServices());
    }

    /**
     * Get a String representation of the chosen services.
     * 
     * @param chosenServices A String array of chosen services.
     * @return A String representation of the chosen services.
     */
    public static String getChosenServicesAsString(final String[] chosenServices) {
        // If there are no chosen services, return an empty String.
        if (chosenServices == null || chosenServices.length == 0) {
            return "";
        }

        final StringBuilder sb = new StringBuilder();
        boolean isFirst = true;

        for (String s : chosenServices) {
            if (isFirst) {
                // Used to format the String correctly.
                sb.append(s);
                isFirst = false;
            } else {
                sb.append(',').append(' ').append(s);
            }
        }

        return sb.toString();
    }

    /**
     * Any Activities which host this Fragment must implement this interface to
     * handle navigation events.
     */
    public static interface Callbacks {

        /**
         * This is called when the user dismisses the service chooser dialog.
         * This will get called even when no services are chosen, and may not
         * necessarily mean that the user has made a new selection.
         * 
         * @param chosenServices A String array of chosen services.
         */
        public void onServicesChosen(String[] chosenServices);
    }
}