com.eleybourn.bookcatalogue.dialogs.StandardDialogs.java Source code

Java tutorial

Introduction

Here is the source code for com.eleybourn.bookcatalogue.dialogs.StandardDialogs.java

Source

/*
 * @copyright 2013 Philip Warner
 * @license GNU General Public License
 * 
 * This file is part of Book Catalogue.
 *
 * Book Catalogue 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.
 *
 * Book Catalogue 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 Book Catalogue.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.eleybourn.bookcatalogue.dialogs;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.TextView;

import com.eleybourn.bookcatalogue.AdministrationLibraryThing;
import com.eleybourn.bookcatalogue.Author;
import com.eleybourn.bookcatalogue.CatalogueDBAdapter;
import com.eleybourn.bookcatalogue.LibraryThingManager;
import com.eleybourn.bookcatalogue.R;
import com.eleybourn.bookcatalogue.Series;
import com.eleybourn.bookcatalogue.goodreads.GoodreadsRegister;
import com.eleybourn.bookcatalogue.utils.Logger;
import com.eleybourn.bookcatalogue.utils.Utils;
import com.eleybourn.bookcatalogue.utils.ViewTagger;

public class StandardDialogs {

    /**
     * Show a dialog asking if unsaved edits should be ignored. Finish if so.
     */
    public static void showConfirmUnsavedEditsDialog(final Activity a, final Runnable r) {
        AlertDialog.Builder dialog = new Builder(a);

        dialog.setTitle(R.string.details_have_changed);
        dialog.setMessage(R.string.you_have_unsaved_changes);

        dialog.setPositiveButton(R.string.exit, new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                if (r != null) {
                    r.run();
                } else {
                    a.finish();
                }
            }
        });

        dialog.setNegativeButton(R.string.continue_editing, new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dialog.setCancelable(false);
        dialog.create().show();
    }

    public static void needLibraryThingAlert(final Context context, final boolean ltRequired,
            final String prefSuffix) {
        boolean showAlert;
        int msgId;
        final String prefName = LibraryThingManager.LT_HIDE_ALERT_PREF_NAME + "_" + prefSuffix;
        if (!ltRequired) {
            msgId = R.string.uses_library_thing_info;
            SharedPreferences prefs = context.getSharedPreferences("bookCatalogue",
                    android.content.Context.MODE_PRIVATE);
            showAlert = !prefs.getBoolean(prefName, false);
        } else {
            msgId = R.string.require_library_thing_info;
            showAlert = true;
        }

        if (!showAlert)
            return;

        final AlertDialog dlg = new AlertDialog.Builder(context).setMessage(msgId).create();

        dlg.setTitle(R.string.reg_library_thing_title);
        dlg.setIcon(android.R.drawable.ic_menu_info_details);

        dlg.setButton(DialogInterface.BUTTON_POSITIVE, context.getResources().getString(R.string.more_info),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent i = new Intent(context, AdministrationLibraryThing.class);
                        context.startActivity(i);
                        dlg.dismiss();
                    }
                });

        if (!ltRequired) {
            dlg.setButton(DialogInterface.BUTTON_NEUTRAL,
                    context.getResources().getString(R.string.disable_dialogue),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            SharedPreferences prefs = context.getSharedPreferences("bookCatalogue",
                                    android.content.Context.MODE_PRIVATE);
                            SharedPreferences.Editor ed = prefs.edit();
                            ed.putBoolean(prefName, true);
                            ed.commit();
                            dlg.dismiss();
                        }
                    });
        }

        dlg.setButton(DialogInterface.BUTTON_NEGATIVE, context.getResources().getString(R.string.cancel),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dlg.dismiss();
                    }
                });

        dlg.show();
    }

    public static void deleteSeriesAlert(Context context, final CatalogueDBAdapter dbHelper, final Series series,
            final Runnable onDeleted) {

        // When we get here, we know the names are genuinely different and the old series is used in more than one place.
        String message = "Delete series";
        try {
            message = String.format(context.getResources().getString(R.string.really_delete_series), series.name);
        } catch (NullPointerException e) {
            Logger.logError(e);
        }
        final AlertDialog alertDialog = new AlertDialog.Builder(context).setMessage(message).create();

        alertDialog.setTitle(R.string.delete_series);
        alertDialog.setIcon(android.R.drawable.ic_menu_info_details);
        //alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, context.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
        alertDialog.setButton2(context.getResources().getString(R.string.ok),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dbHelper.deleteSeries(series);
                        alertDialog.dismiss();
                        onDeleted.run();
                    }
                });

        //alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
        alertDialog.setButton(context.getResources().getString(R.string.cancel),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        alertDialog.dismiss();
                    }
                });

        alertDialog.show();
    }

    public static int deleteBookAlert(Context context, final CatalogueDBAdapter dbHelper, final long id,
            final Runnable onDeleted) {

        ArrayList<Author> authorList = dbHelper.getBookAuthorList(id);

        String title;
        Cursor cur = dbHelper.fetchBookById(id);
        try {
            if (cur == null || !cur.moveToFirst())
                return R.string.unable_to_find_book;

            title = cur.getString(cur.getColumnIndex(CatalogueDBAdapter.KEY_TITLE));
            if (title == null || title.length() == 0)
                title = "<Unknown>";

        } finally {
            if (cur != null)
                cur.close();
        }

        // Format the list of authors nicely
        String authors;
        if (authorList.size() == 0)
            authors = "<Unknown>";
        else {
            authors = authorList.get(0).getDisplayName();
            for (int i = 1; i < authorList.size() - 1; i++) {
                authors += ", " + authorList.get(i).getDisplayName();
            }
            if (authorList.size() > 1)
                authors += " " + context.getResources().getString(R.string.list_and) + " "
                        + authorList.get(authorList.size() - 1).getDisplayName();
        }

        // Get the title      
        String format = context.getResources().getString(R.string.really_delete_book);

        String message = String.format(format, title, authors);
        final AlertDialog alertDialog = new AlertDialog.Builder(context).setMessage(message).create();

        alertDialog.setTitle(R.string.menu_delete);
        alertDialog.setIcon(android.R.drawable.ic_menu_info_details);
        //alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, context.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
        alertDialog.setButton2(context.getResources().getString(R.string.ok),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dbHelper.deleteBook(id);
                        alertDialog.dismiss();
                        onDeleted.run();
                    }
                });

        //alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
        alertDialog.setButton(context.getResources().getString(R.string.cancel),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        alertDialog.dismiss();
                    }
                });

        alertDialog.show();
        return 0;

    }

    /**
     * Display a dialog warning the user that goodreads authentication is required; gives them
     * the options: 'request now', 'more info' or 'cancel'.
     */
    public static int goodreadsAuthAlert(final FragmentActivity context) {
        // Get the title      
        final AlertDialog alertDialog = new AlertDialog.Builder(context).setTitle(R.string.authorize_access)
                .setMessage(R.string.goodreads_action_cannot_blah_blah).create();

        alertDialog.setIcon(android.R.drawable.ic_menu_info_details);
        alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, context.getResources().getString(R.string.ok),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        alertDialog.dismiss();
                        GoodreadsRegister.requestAuthorizationInBackground(context);
                    }
                });

        alertDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
                context.getResources().getString(R.string.tell_me_more), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        alertDialog.dismiss();
                        Intent i = new Intent(context, GoodreadsRegister.class);
                        context.startActivity(i);
                    }
                });

        alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getResources().getString(R.string.cancel),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        alertDialog.dismiss();
                    }
                });

        alertDialog.show();
        return 0;

    }

    /**
     * Interface for item that displays in a custom dialog list
     */
    public static interface SimpleDialogItem {
        View getView(LayoutInflater inflater);

        RadioButton getSelector(View v);
    }

    /**
     * Interface to listen for item selection in a custom dialog list
     */
    public static interface SimpleDialogOnClickListener {
        void onClick(SimpleDialogItem item);
    }

    /**
     * Select a custom item from a list, and call halder when/if item is selected.
     */
    public static void selectItemDialog(LayoutInflater inflater, String message, ArrayList<SimpleDialogItem> items,
            SimpleDialogItem selectedItem, final SimpleDialogOnClickListener handler) {
        // Get the view and the radio group
        final View root = inflater.inflate(R.layout.select_list_dialog, null);
        TextView msg = (TextView) root.findViewById(R.id.message);

        // Build the base dialog
        final AlertDialog.Builder builder = new AlertDialog.Builder(inflater.getContext()).setView(root);
        if (message != null && !message.equals("")) {
            msg.setText(message);
        } else {
            msg.setVisibility(View.GONE);
        }

        final AlertDialog dialog = builder.create();

        // Create the listener for each item
        OnClickListener listener = new OnClickListener() {
            @Override
            public void onClick(View v) {
                SimpleDialogItem item = (SimpleDialogItem) ViewTagger.getTag(v, R.id.TAG_DIALOG_ITEM);
                // For a consistent UI, make sure the selector is checked as well. NOT mandatory from
                // a functional point of view, just consistent
                if (!(v instanceof RadioButton)) {
                    RadioButton btn = item.getSelector(v);
                    if (btn != null) {
                        btn.setChecked(true);
                        btn.invalidate();
                    }
                }
                //
                // It would be nice to have the other radio buttons reflect the new state before it
                // disappears, but not really worth the effort. Esp. since the code below does not work...
                // and the dialog disappears too fast to make this worthwhile.
                //
                //LinearLayout list = (LinearLayout)root.findViewById(R.id.list);
                //for(int i = 0; i < list.getChildCount(); i++) {
                //   View child = list.getChildAt(i);
                //   SimpleDialogItem other = (SimpleDialogItem)ViewTagger.getTag(child, R.id.TAG_DIALOG_ITEM);
                //   RadioButton btn = other.getSelector(child);
                //   btn.setSelected(other == item);
                //   btn.invalidate();
                //}
                dialog.dismiss();
                handler.onClick(item);
            }
        };

        // Add the items to the dialog
        LinearLayout list = (LinearLayout) root.findViewById(R.id.list);
        for (SimpleDialogItem item : items) {
            View v = item.getView(inflater);
            v.setBackgroundResource(android.R.drawable.list_selector_background);
            ViewTagger.setTag(v, R.id.TAG_DIALOG_ITEM, item);
            list.addView(v);
            v.setOnClickListener(listener);
            RadioButton btn = item.getSelector(v);
            if (btn != null) {
                ViewTagger.setTag(btn, R.id.TAG_DIALOG_ITEM, item);
                btn.setChecked(item == selectedItem);
                btn.setOnClickListener(listener);
            }
        }
        dialog.show();
    }

    /**
     * Wrapper class to present a list of files for selection
     */
    public static void selectFileDialog(LayoutInflater inflater, String title, ArrayList<File> files,
            final SimpleDialogOnClickListener handler) {
        ArrayList<SimpleDialogItem> items = new ArrayList<SimpleDialogItem>();
        for (File file : files) {
            items.add(new SimpleDialogFileItem(file));
        }
        selectItemDialog(inflater, title, items, null, handler);
    }

    /**
     * Wrapper class to present a list of arbitrary objects for selection; it uses
     * the toString() method to display a simple list.
     */
    public static <T extends Object> void selectStringDialog(LayoutInflater inflater, String title,
            ArrayList<T> objects, String current, final SimpleDialogOnClickListener handler) {
        ArrayList<SimpleDialogItem> items = new ArrayList<SimpleDialogItem>();
        SimpleDialogItem selectedItem = null;
        for (T o : objects) {
            SimpleDialogObjectItem item = new SimpleDialogObjectItem(o);
            if (current != null && o.toString().equalsIgnoreCase(current))
                selectedItem = item;
            items.add(item);
        }
        selectItemDialog(inflater, title, items, selectedItem, handler);
    }

    /**
     * Simple item to manage a File object in a list of items.
     */
    public static class SimpleDialogFileItem implements SimpleDialogItem {
        private final File mFile;

        public SimpleDialogFileItem(File file) {
            mFile = file;
        }

        public File getFile() {
            return mFile;
        }

        public RadioButton getSelector(View v) {
            return null;
        }

        /**
         * Get a View to display the file
         */
        public View getView(LayoutInflater inflater) {
            // Create the view
            View v = inflater.inflate(R.layout.file_list_item, null);
            // Set the file name
            TextView name = (TextView) v.findViewById(R.id.name);
            name.setText(mFile.getName());
            // Set the path
            TextView location = (TextView) v.findViewById(R.id.path);
            location.setText(mFile.getParent());
            // Set the size
            TextView size = (TextView) v.findViewById(R.id.size);
            size.setText(Utils.formatFileSize(mFile.length()));
            // Set the last modified date
            TextView update = (TextView) v.findViewById(R.id.updated);
            update.setText(Utils.toPrettyDateTime(new Date(mFile.lastModified())));
            // Return it
            return v;
        }
    }

    /**
     * Item to manage an Object in a list of items.
     */
    public static class SimpleDialogObjectItem implements SimpleDialogItem {
        private final Object mObject;

        public SimpleDialogObjectItem(Object object) {
            mObject = object;
        }

        public Object getObject() {
            return mObject;
        }

        /**
         * Get a View to display the object
         */
        public View getView(LayoutInflater inflater) {
            // Create the view
            View v = inflater.inflate(R.layout.string_list_item, null);
            // Set the name
            TextView name = (TextView) v.findViewById(R.id.name);
            name.setText(mObject.toString());
            // Return it
            return v;
        }

        public RadioButton getSelector(View v) {
            return (RadioButton) v.findViewById(R.id.selector);
        }

        /**
         * Get the underlying object as a string
         */
        @Override
        public String toString() {
            return mObject.toString();
        }
    }

    public static class SimpleDialogMenuItem extends SimpleDialogObjectItem {
        final int mItemId;
        final int mDrawableId;

        public SimpleDialogMenuItem(Object object, int itemId, int icon) {
            super(object);
            mItemId = itemId;
            mDrawableId = icon;
        }

        public int getItemId() {
            return mItemId;
        }

        @Override
        public View getView(LayoutInflater inflater) {
            View v = super.getView(inflater);
            TextView name = (TextView) v.findViewById(R.id.name);
            name.setCompoundDrawablesWithIntrinsicBounds(mDrawableId, 0, 0, 0);
            getSelector(v).setVisibility(View.GONE);
            return v;
        }
    }

}