/* * @copyright 2012 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.utils; import java.util.Enumeration; import java.util.Hashtable; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.content.SharedPreferences.Editor; import android.text.Html; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.text.method.LinkMovementMethod; import android.text.style.URLSpan; import android.text.util.Linkify; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; import com.eleybourn.bookcatalogue.BookCatalogueApp; import com.eleybourn.bookcatalogue.BookCataloguePreferences; import com.eleybourn.bookcatalogue.R; /** * Class to manage the display of 'hints' withing the application. Each hint dialog has * a 'Do not show again' option, that results in an update to the preferences which * are checked by this code. * * To add a new hint, create a string resource and add it to mHints. Then, to display the * hint, simply call HintManager.displayHint(a, stringId). * * @author Philip Warner */ public class HintManager { /** Preferences prefix */ private final static String TAG = "HintManager"; /** Preferences prefix for hints */ private final static String PREF_HINT = TAG + ".Hint."; /** All hints managed by this class */ private static final Hints mHints = new Hints() .add("BOOKLIST_STYLES_EDITOR", R.string.hint_booklist_styles_editor) .add("BOOKLIST_STYLE_GROUPS", R.string.hint_booklist_style_groups) .add("BOOKLIST_STYLE_PROPERTIES", R.string.hint_booklist_style_properties) .add("BOOKLIST_GLOBAL_PROPERTIES", R.string.hint_booklist_global_properties) .add("BOOKLIST_MULTI_AUTHORS", R.string.hint_authors_book_may_appear_more_than_once) .add("BOOKLIST_MULTI_SERIES", R.string.hint_series_book_may_appear_more_than_once) .add("BACKGROUND_TASKS", R.string.hint_background_tasks) .add("BACKGROUND_TASK_EVENTS", R.string.hint_background_task_events) .add("STARTUP_SCREEN", R.string.hint_startup_screen) .add("explain_goodreads_no_isbn", R.string.explain_goodreads_no_isbn) .add("explain_goodreads_no_match", R.string.explain_goodreads_no_match) .add("hint_booklist_style_menu", R.string.hint_booklist_style_menu) .add("hint_autorotate_camera_images", R.string.hint_autorotate_camera_images) .add("hint_view_only_book_details", R.string.hint_view_only_book_details) .add("hint_view_only_help", R.string.hint_view_only_help) .add("hint_evan_book", R.string.hint_evan_book) .add("hint_book_list", R.string.hint_book_list) .add("hint_amazon_links_blurb", R.string.hint_amazon_links_blurb) ; public static interface HintOwner { public int getHint(); } /** Reset all hints to that they will be displayed again */ public static void resetHints() { Enumeration<Hint> hints = mHints.getHints(); while(hints.hasMoreElements()) { Hint h = hints.nextElement(); h.setVisibility(true); h.setHasBeenDisplayed(false); } } public static boolean shouldBeShown(int hintStringId) { final Hint h = mHints.getHint(hintStringId); return h.shouldBeShown(); } /** Display the passed hint, if the user has not disabled it */ public static boolean displayHint(Context context, int stringId, final Runnable postRun, Object... args) { // Get the hint and return if it has been disabled. final Hint h = mHints.getHint(stringId); if (!h.shouldBeShown()) { if (postRun != null) postRun.run(); return false; } // Build the hint dialog final Dialog dialog = new Dialog(context); dialog.setContentView(R.layout.hint_dialogue); // Get the various Views final TextView msg = (TextView)dialog.findViewById(R.id.hint); final CheckBox cb = (CheckBox)dialog.findViewById(R.id.hide_hint_checkbox); // new CheckBox(context); final Button ok = (Button)dialog.findViewById(R.id.confirm); // Setup the views String hintText = BookCatalogueApp.context.getResources().getString(stringId, args); msg.setText(Utils.linkifyHtml(hintText, Linkify.ALL)); // Automatically start a browser (or whatever) msg.setMovementMethod(LinkMovementMethod.getInstance()); //msg.setText(Html.fromHtml(hintText)); //stringId); //Linkify.addLinks(msg, Linkify.ALL); dialog.setTitle(R.string.hint); // Handle the 'OK' click ok.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); // Disable hint if checkbox checked if (cb.isChecked()) { h.setVisibility(false); } } }); dialog.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { if (postRun != null) postRun.run(); } }); dialog.show(); h.setHasBeenDisplayed(true); return true; } /** * Class to represent a collection of all defined hints * * @author Philip Warner */ private static class Hints { /** USed to lookup hint based on string ID */ private Hashtable<Integer, Hint> mHintsById = new Hashtable<Integer, Hint>(); /** Used to prevent two hints having the same preference name */ private Hashtable<String, Hint> mHintsByKey = new Hashtable<String, Hint>(); /** * Add a hint to the collection * * @param key Unique preference suffix for this hint * @param stringId String ID to display * * @return Hints, for chaining */ public Hints add(String key, int stringId) { Hint h = new Hint(key, stringId); mHintsById.put(stringId, h); mHintsByKey.put(key.trim().toLowerCase(), h); return this; } /** * Return the hint based on string ID * @param stringId * @return */ public Hint getHint(int stringId) { Hint h = mHintsById.get(stringId); if (h == null) throw new RuntimeException("Hint not found for ID " + stringId); return h; } /** * Get an enumeration of all hints. * * @return */ public Enumeration<Hint> getHints() { return mHintsById.elements(); } } /** * Class to represent a single Hint. * * @author Philip Warner */ private static class Hint { /** Preferences key suffix specific to this hint */ public final String key; /** String to display for this hint */ //public final int stringId; /** Indicates that this hint was displayed already in this instance of the app */ public boolean mHasBeenDisplayed = false; /** * Constructor * * @param key Preferences key suffix specific to this hint * @param stringId String to display for this hint */ private Hint(String key, int stringId) { this.key = key; //this.stringId = stringId; } /** * Get the preference name for this hint * * @return Fully qualified preference name */ public String getFullPrefName() { return PREF_HINT + key; } /** * Set the preference to indicate if this hint should be shown again * * @param visible Flag indicating future visibility */ public void setVisibility(boolean visible) { BookCataloguePreferences prefs = BookCatalogueApp.getAppPreferences(); Editor ed = prefs.edit(); String name = getFullPrefName(); ed.putBoolean(name, visible); ed.commit(); } /** * Check if this hint should be shown * * @return */ public boolean shouldBeShown() { if (hasBeenDisplayed()) return false; BookCataloguePreferences prefs = BookCatalogueApp.getAppPreferences(); return prefs.getBoolean(getFullPrefName(), true); } public boolean hasBeenDisplayed() { return mHasBeenDisplayed; } public void setHasBeenDisplayed(boolean hasBeenDisplayed) { mHasBeenDisplayed = hasBeenDisplayed; } } }