Java tutorial
/* * ================================================================================= * Copyright (C) 2013 Martin Albedinsky [Wolf-ITechnologies] * ================================================================================= * Licensed under the Apache License, Version 2.0 or later (further "License" only); * --------------------------------------------------------------------------------- * You may use this file only in compliance with the License. More details and copy * of this License you may obtain at * * http://www.apache.org/licenses/LICENSE-2.0 * * You can redistribute, modify or publish any part of the code written in this * file but as it is described in the License, the software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF * ANY KIND. * * See the License for the specific language governing permissions and limitations * under the License. * ================================================================================= */ package com.wit.and.dialog.manage; import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.support.v4.app.DialogFragment; import com.wit.and.dialog.Dialog; import com.wit.and.dialog.Dialog.Buttons; import com.wit.and.dialog.EditDialog; import com.wit.and.dialog.IDialog; import com.wit.and.dialog.ListDialog; import com.wit.and.dialog.LoginDialog; import com.wit.and.dialog.ProgressDialog; import com.wit.and.dialog.WebDialog; import java.util.ArrayList; import java.util.List; /** * <h4>Class Overview</h4> * <p> * Dialogs factory to handle creating instances of {@link com.wit.and.dialog.Dialog}. * Factory provides these instances for the {@link DialogManager} which provides * basic operations with dialog fragments (showing and dismissing). * </p> * <p> * <b>TAG</b><br/> * If you want to show more dialog fragments at the same time on the screen, you * must provide for these dialog instances different tags, because if you want * to show some dialog fragment but there is some right now showing and the new * one have the same tag, than the new one don't be showed. See * {@link #getDialogTag(int)}. * </p> * <p> * Factory also provides support methods to obtain all types of the useful * dialogs like {@link com.wit.and.dialog.WebDialog}, {@link com.wit.and.dialog.ProgressDialog} * and so on. The buttons type for these dialogs will be auto-resolved from the given * {@link com.wit.and.dialog.manage.DialogOptions}. * </p> * * @author Martin Albedinsky * @see DialogManager */ public abstract class DialogFactory implements DialogManager.IDialogFactory { /** * Constants ============================= */ /** * Log TAG. */ // private static final String TAG = DialogFactory.class.getSimpleName(); /** * Indicates if debug private output trough log-cat is enabled. */ // private static final boolean DEBUG = true; /** * Indicates if logging for user output trough log-cat is enabled. */ // private static final boolean USER_LOG = true; /** * Enums ================================= */ /** * Possible included dialog fragment implementation to create. */ private enum DialogType { /** * */ COMMON(0, Buttons.NONE), /** * */ INFO(DialogOptions.DIALOG_ICON_INFO, Buttons.SINGLE), /** * */ ALERT(DialogOptions.DIALOG_ICON_ALERT, Buttons.PAIR), /** * */ ERROR(DialogOptions.DIALOG_ICON_ERROR, Buttons.SINGLE), /** * */ PROGRESS(DialogOptions.DIALOG_ICON_PROGRESS, Buttons.NONE), /** * */ WEB(DialogOptions.DIALOG_ICON_WEB, Buttons.SINGLE), /** * */ LIST(DialogOptions.DIALOG_ICON_LIST, Buttons.SINGLE), /** * */ SELECTION(0, Buttons.SINGLE), /** * */ LOGIN(DialogOptions.DIALOG_ICON_LOGIN, Buttons.PAIR), /** * */ EDIT(DialogOptions.DIALOG_ICON_EDIT, Buttons.PAIR); private final int defIcon; private final Buttons defButtons; private DialogType(int icon, Buttons buttons) { this.defIcon = icon; this.defButtons = buttons; } } /** * Static members ======================== */ /** * Members =============================== */ /** * Application mResources to handle obtaining of strings and so on. */ private Resources mResources; /** * Context in which is this factory placed. */ private Context mContext; /** * Listeners ----------------------------- */ /** * Arrays -------------------------------- */ /** * Array with joined dialog factories. Instances and tags are first obtained * from these factories. */ private List<DialogManager.IDialogFactory> aJoinedFactories = new ArrayList<DialogManager.IDialogFactory>(); /** * Booleans ------------------------------ */ /** * Constructors ========================== */ /** * <p> * Creates factory with the given context and accessible * application mResources. * </p> * * @param context {@link Activity} or {@link Context} are allowed. */ public DialogFactory(Context context) { this.mContext = context; if (context != null) { this.mResources = context.getResources(); } } /** * Methods =============================== */ /** * Public -------------------------------- */ /** * <p> * Creates dialog tag in required format depends on the passed * <var>factory</var> package name and <var>dialogName</var>. * </p> * <p> * Example format: <u>com.android.app.dialog.factories.ScreenLoginFactory.ConfirmDialog.TAG</u><br/><br/> * - where <b>com.android.app.dialog.factories</b> is name of package where <var>factory</var> is placed, * <b>ScreenLoginFactory</b> is factory class name, <b>ConfirmDialog</b> is <var>dialogName</var> and * <b>TAG</b> is tag identifier. * </p> * * @param factoryClass Class of factory for which is creation of dialog tag requested. * @param dialogName Dialog name (can be dialog class name) for which tag should be created. * @return Dialog tag in required format, or <code>null</code> if <var>dialogName</var> is <code>null</code> or empty. */ public static String createDialogTag(Class<? extends DialogManager.IDialogFactory> factoryClass, String dialogName) { // Only valid dialog name is allowed. if (dialogName == null || dialogName.length() == 0) { return null; } return factoryClass.getPackage().getName() + "." + factoryClass.getSimpleName() + "." + dialogName + ".TAG"; } /** * <p> * Same as {@link #dialog(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty * listeners. * </p> * * @param options Dialog options with dialog data. * @return New instance of {@link Dialog}. */ public static Dialog dialog(DialogOptions options) { return dialog(options, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link Dialog}. * Dialog options will be created from the given fast options. * </p> * * @param options Dialog options with dialog data. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link Dialog}. */ public static Dialog dialog(DialogOptions options, DialogManager.ListenerOptions listeners) { return createDialog(DialogType.COMMON, options, listeners); } /** * <p> * Same as {@link #info(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty * listeners. * </p> * * @param options Dialog options with dialog data. * @return New instance of {@link Dialog}. */ public static Dialog info(DialogOptions options) { return info(options, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link Dialog} with info icon and neutral button. * Dialog options will be created from the given fast options. * </p> * * @param options Dialog options with dialog data. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link Dialog}. */ public static Dialog info(DialogOptions options, DialogManager.ListenerOptions listeners) { return createDialog(DialogType.INFO, options, listeners); } /** * <p> * Same as {@link #alert(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty * listeners. * </p> * * @param options Dialog options with dialog data. * @return New instance of {@link Dialog}. */ public static Dialog alert(DialogOptions options) { return alert(options, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link Dialog} wit alert icon and negative * + positive button. Dialog options will be created from the given fast options. * </p> * * @param options Dialog options with dialog data. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link Dialog}. */ public static Dialog alert(DialogOptions options, DialogManager.ListenerOptions listeners) { return createDialog(DialogType.ALERT, options, listeners); } /** * <p> * Same as {@link #error(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty * listeners. * </p> * * @param options Dialog options with dialog data. * @return New instance of {@link Dialog}. */ public static Dialog error(DialogOptions options) { return createDialog(DialogType.ERROR, options, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link Dialog} with error icon and neutral button. * Dialog options will be created from the given fast options. * </p> * * @param options Dialog options with dialog data. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link Dialog}. */ public static Dialog error(DialogOptions options, DialogManager.ListenerOptions listeners) { return createDialog(DialogType.ERROR, options, listeners); } /** * <p> * Same as {@link #progress(ProgressDialog.ProgressOptions)}, where default * {@link com.wit.and.dialog.ProgressDialog.ProgressOptions} will be used and message will be included * into that options. * </p> * <p> * This actually shows the dialog with circle progress bar without title (booth icon and title text are * hided). * </p> * * @param message Message to show at the right of circle progress bar. * @return New instance of {@link com.wit.and.dialog.ProgressDialog} with circle progress bar. */ public static ProgressDialog loading(String message) { return progress(new ProgressDialog.ProgressOptions().message(message).icon(0)); } /** * <p> * Same as {@link #progress(ProgressDialog.ProgressOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with * empty listeners. * </p> * * @param progressOptions Progress options specific for progress dialog. * @return New instance of {@link ProgressDialog}. */ public static ProgressDialog progress(ProgressDialog.ProgressOptions progressOptions) { return progress(progressOptions, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link ProgressDialog}. Dialog options will * be created from the given fast options. * </p> * * @param progressOptions Progress options specific for progress dialog. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link ProgressDialog}. */ public static ProgressDialog progress(ProgressDialog.ProgressOptions progressOptions, DialogManager.ListenerOptions listeners) { // Prepare options for dialog and create and set-up new instance of dialog. final ProgressDialog dialog = ProgressDialog .newInstance(prepareOptions(DialogType.PROGRESS, progressOptions)); // Resolve listeners and return. return DialogManager.resolveListeners(dialog, listeners); } /** * <p> * Same as {@link #list(ListDialog.ListOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty * listeners. * </p> * * @param listOptions List options specific for list dialog. * @return New instance of {@link ListDialog}. */ public static ListDialog list(ListDialog.ListOptions listOptions) { return list(listOptions, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link ListDialog} with list icon and no button. * Dialog options will be created from the given fast options. * </p> * * @param listOptions List options specific for list dialog. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link ListDialog}. */ public static ListDialog list(ListDialog.ListOptions listOptions, DialogManager.ListenerOptions listeners) { // Prepare options for dialog and create and set-up new instance of dialog. final ListDialog dialog = ListDialog.newInstance(prepareOptions(DialogType.LIST, listOptions)); // Resolve listeners and return. return DialogManager.resolveListeners(dialog, listeners); } /** * <p> * Same as {@link #web(WebDialog.WebOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, * but with empty listeners. * </p> * * @param webOptions Web options specific for web dialog. * @return New instance of {@link WebDialog}. */ public static WebDialog web(WebDialog.WebOptions webOptions) { return web(webOptions, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link WebDialog} with web icon * and neutral button. Dialog options will be created from the given fast options. * </p> * * @param webOptions Web options specific for web dialog. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link WebDialog}. */ public static WebDialog web(WebDialog.WebOptions webOptions, DialogManager.ListenerOptions listeners) { // Prepare options for dialog and create and set-up new instance of dialog. final WebDialog dialog = WebDialog.newInstance(prepareOptions(DialogType.WEB, webOptions)); // Resolve listeners and return. return DialogManager.resolveListeners(dialog, listeners); } /** * <p> * Same as {@link #login(com.wit.and.dialog.LoginDialog.LoginOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, * but with empty listeners. * </p> * * @param loginOptions Login options specific for login dialog. * @return New instance of {@link com.wit.and.dialog.LoginDialog}. */ public static Dialog login(LoginDialog.LoginOptions loginOptions) { return login(loginOptions, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link LoginDialog} with login * icon and negative + positive button. * </p> * * @param loginOptions Login options specific for login dialog. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link LoginDialog}. */ public static LoginDialog login(LoginDialog.LoginOptions loginOptions, DialogManager.ListenerOptions listeners) { // Prepare options for dialog and create and set-up new instance of dialog. final LoginDialog dialog = LoginDialog.newInstance(prepareOptions(DialogType.LOGIN, loginOptions)); // Resolve listeners and return. return DialogManager.resolveListeners(dialog, listeners); } /** * <p> * Same as {@link #edit(com.wit.and.dialog.EditDialog.EditOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, * but with empty listeners. * </p> * * @param editOptions Edit options specific for login dialog. * @return New instance of {@link com.wit.and.dialog.EditDialog}. */ public static EditDialog edit(EditDialog.EditOptions editOptions) { return edit(editOptions, new DialogManager.ListenerOptions()); } /** * <p> * Returns new instance of the {@link EditDialog} with edit * icon and negative + positive button. * </p> * * @param editOptions Edit options specific for edit dialog. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link EditDialog}. */ public static EditDialog edit(EditDialog.EditOptions editOptions, DialogManager.ListenerOptions listeners) { // Prepare options for dialog and create and set-up new instance of dialog. final EditDialog dialog = EditDialog.newInstance(prepareOptions(DialogType.EDIT, editOptions)); // Resolve listeners and return. return DialogManager.resolveListeners(dialog, listeners); } /** */ @Override public DialogFragment createDialogInstance(int dialogID, DialogOptions options) { DialogFragment dialog = null; // Try to obtain dialog fragment from the joined factories. for (DialogManager.IDialogFactory factory : aJoinedFactories) { dialog = factory.createDialogInstance(dialogID, options); if (dialog != null) break; } if (dialog == null) { // Get dialog from this factory. dialog = onCreateDialogInstance(dialogID, options); } // Set up dialog id. if (dialog != null && dialog instanceof IDialog) { // Set dialog id. This id is fired with the dialog callback. ((IDialog) dialog).setDialogID(dialogID); } return dialog; } /** */ @Override public String getDialogTag(int dialogID) { String tag = null; // Try to obtain tag from the joined factories. for (DialogManager.IDialogFactory factory : aJoinedFactories) { tag = factory.getDialogTag(dialogID); if (tag != null) break; } return (tag != null && tag.length() > 0) ? tag : onGetDialogTag(dialogID); } /** * Getters + Setters --------------------- */ /** * Protected ----------------------------- */ /** * <p> * Joins the given dialog factory with this current one. <b>Note</b>, that * dialog fragment instances (and their tags) are obtained from these joined * libraries in order as they was joined. * </p> * * @param factory Dialog factory to join with. */ protected final void joinFactory(DialogManager.IDialogFactory factory) { if (!aJoinedFactories.contains(factory)) { aJoinedFactories.add(factory); } } /** * <p> * Returns array with currently joined dialog factories to this one. * </p> * * @return Set of factories. */ protected final List<DialogManager.IDialogFactory> getJoinedFactories() { return aJoinedFactories; } /** * <p> * Returns actual application mResources. * </p> * * @return Resources. */ protected final Resources getResources() { return mResources; } /** * <p> * Returns string from the application mResources. * </p> * * @param stringResID Resource of string to obtain. * @return Obtained string from application mResources. */ protected final String getString(int stringResID) { return this.mResources.getString(stringResID); } /** * <p> * Returns context with which was this factory created. * </p> * * @return Can be {@link Activity} or {@link Context}. */ protected final Context getContext() { return mContext; } /** * Resolves the buttons type. * * @param options Dialog options. * @return Given dialog options with resolved buttons type. */ static <O extends DialogOptions> O resolveButtons(O options) { String negative, neutral, positive; negative = options.getNegative(); neutral = options.getNeutral(); positive = options.getPositive(); int typeOrdinal = Buttons.DEFAULT.ordinal(); if (negative == null && neutral == null && positive == null) { // There will be no button showed in the dialog. typeOrdinal = Buttons.NONE.ordinal(); } else { // Check for text values and resolve type of buttons. typeOrdinal = (negative == null || negative.length() == 0) ? typeOrdinal : ++typeOrdinal; typeOrdinal = (neutral == null || neutral.length() == 0) ? typeOrdinal : ++typeOrdinal; typeOrdinal = (positive == null || positive.length() == 0) ? typeOrdinal : ++typeOrdinal; } // Set up type. options.buttonsType(Buttons.values()[typeOrdinal]); return options; } /** * Private ------------------------------- */ /** * Creates new instance of the dialog depends on the given type. * Created instance of dialog will be fully set-upped and ready to show. * * @param type Dialog type. * @param options Fast dialog options. * @param listeners Set of listeners for requested dialog. * @return New instance of {@link Dialog}. */ private static Dialog createDialog(DialogType type, DialogOptions options, DialogManager.ListenerOptions listeners) { // Prepare options for dialog and create and set-up new instance of dialog. final Dialog dialog = Dialog.newInstance(prepareOptions(type, options)); // Resolve listeners and return. return DialogManager.resolveListeners(dialog, listeners); } /** * Resolves buttons type and also resolves default set-up depends on the given dialog type. * * @param type Dialog type. * @return New instance of dialog options. */ private static <O extends DialogOptions> O prepareOptions(DialogType type, O options) { // Resolve buttons depends on the button text values. options = resolveButtons(options); // Resolve default set-ups and return. return resolveDefault(type, options); } /** * Resolves default icon and buttons type depends on the given dialog type. * * @param type Dialog type. * @param options Dialog options. * @return Given dialog options with resolved default data for requested type. */ private static <O extends DialogOptions> O resolveDefault(DialogType type, O options) { // There can be already set some custom buttons type or custom icon, // so we will override only that which are still at default value. // Resolve buttons. if (options.getButtonsType() == Buttons.DEFAULT) { options.buttonsType(type.defButtons); } // Resolve icon. if (options.getIcon() == -1) { options.icon(type.defIcon); } return options; } /** * Abstract methods ---------------------- */ /** * <p> * Invoked after call of <code>showDialog(int, ...)</code> from the * {@link DialogManager} and after iterations trough joined factories. * Implemented factory should here return instance of {@link DialogFragment} * assigned to requested <var>dialogID</var>. Here passed <var>options</var> can be * <code>null</code>, then default should be created and filled in the factory context. * </p> * * @param dialogID Id of dialog which was requested to show from dialog manger. * @param options Dialog options from application context, or <code>null</code> if only * dialog with id was requested to show. * @return New instance of dialog fragment. */ protected abstract DialogFragment onCreateDialogInstance(int dialogID, DialogOptions options); /** * <p> * Invoked to obtain tag for dialog fragment instance associated with the * given <var>dialogID</var>. If here provided tag is <code>null</code>, * default tag from {@link DialogManager} will be used to show actual dialog * </p> * * @param dialogID Id of dialog which was requested to show from dialog manger. * @return Tag for dialog. */ protected abstract String onGetDialogTag(int dialogID); /** * Inner classes ========================= */ /** * Interface ============================= */ }