/* * Geopaparazzi - Digital field mapping on Android based devices * Copyright (C) 2016 HydroloGIS (www.hydrologis.com) * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package eu.geopaparazzi.library.util; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.support.design.widget.Snackbar; import android.support.design.widget.TextInputLayout; import android.text.Editable; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.util.Log; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import eu.geopaparazzi.library.database.GPLog; /** * Created by hydrologis on 15/01/16. */ public class GPDialogs { public static void infoDialog(final Context context, final String msg, final Runnable okRunnable) { messageDialog(context, msg, android.R.drawable.ic_dialog_info, okRunnable); } /** * Execute a message dialog in an {@link AsyncTask}. * * @param context the {@link Context} to use. * @param msg the message to show. * @param iconResource the icon resource to use or -1 fro default. * @param okRunnable optional {@link Runnable} to trigger after ok was pressed. */ public static void messageDialog(final Context context, final String msg, final int iconResource, final Runnable okRunnable) { new AsyncTask<String, Void, String>() { protected String doInBackground(String... params) { return ""; //$NON-NLS-1$ } protected void onPostExecute(String response) { try { int icon = iconResource; if (icon == -1) { icon = android.R.drawable.ic_dialog_info; } AlertDialog.Builder builder = new AlertDialog.Builder(context); builder // .setMessage(msg) .setIcon(icon).setCancelable(true) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (okRunnable != null) { new Thread(okRunnable).start(); } } }); AlertDialog alertDialog = builder.create(); alertDialog.show(); } catch (Exception e) { GPLog.error("UTILITIES", "Error in messageDialog#inPostExecute -- " + msg, e); //$NON-NLS-1$ //$NON-NLS-2$ } } }.execute((String) null); } /** * Execute a message dialog with clickable links in an {@link AsyncTask}. * * @param context the {@link Context} to use. * @param msg the message to show. * @param iconResource the icon resource to use or -1 fro default. * @param okRunnable optional {@link Runnable} to trigger after ok was pressed. */ public static void messageDialogWithLink(final Context context, final String msg, final int iconResource, final Runnable okRunnable) { final SpannableString s = new SpannableString(msg); Linkify.addLinks(s, Linkify.ALL); new AsyncTask<String, Void, String>() { protected String doInBackground(String... params) { return ""; //$NON-NLS-1$ } protected void onPostExecute(String response) { try { int icon = iconResource; if (icon == -1) { icon = android.R.drawable.ic_dialog_info; } AlertDialog.Builder builder = new AlertDialog.Builder(context); builder // .setMessage(s) .setIcon(icon).setCancelable(true) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (okRunnable != null) { new Thread(okRunnable).start(); } } }); AlertDialog alertDialog = builder.create(); alertDialog.show(); ((TextView) alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); } catch (Exception e) { GPLog.error("UTILITIES", "Error in messageDialog#inPostExecute -- " + msg, e); //$NON-NLS-1$ //$NON-NLS-2$ } } }.execute((String) null); } /** * Execute a generic error dialog in an {@link AsyncTask}. * * @param context the {@link Context} to use. * @param t the exception. * @param okRunnable optional {@link Runnable} to trigger after ok was pressed. */ public static void errorDialog(final Context context, final Throwable t, final Runnable okRunnable) { new AsyncTask<String, Void, String>() { protected String doInBackground(String... params) { return ""; //$NON-NLS-1$ } protected void onPostExecute(String response) { try { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder // .setTitle(t.getLocalizedMessage()).setMessage(Log.getStackTraceString(t)) .setIcon(android.R.drawable.ic_dialog_alert).setCancelable(false) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (okRunnable != null) { new Thread(okRunnable).start(); } } }); AlertDialog alertDialog = builder.create(); alertDialog.show(); } catch (Exception e) { GPLog.error("UTILITIES", "Error in errorDialog#inPostExecute", e); //$NON-NLS-1$ //$NON-NLS-2$ } } }.execute((String) null); } /** * Execute a message dialog in an {@link AsyncTask}. * * @param context the {@link Context} to use. * @param msg the message to show. * @param yesRunnable optional {@link Runnable} to trigger after yes was pressed. * @param noRunnable optional {@link Runnable} to trigger after no was pressed. */ public static void yesNoMessageDialog(final Context context, final String msg, final Runnable yesRunnable, final Runnable noRunnable) { new AsyncTask<String, Void, String>() { protected String doInBackground(String... params) { return ""; //$NON-NLS-1$ } protected void onPostExecute(String response) { try { AlertDialog.Builder builder = new AlertDialog.Builder(context); try { builder.setMessage(msg); builder.setPositiveButton(context.getString(android.R.string.yes), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { try { if (yesRunnable != null) { new Thread(yesRunnable).start(); } } catch (Exception e) { GPLog.error(this, e.getLocalizedMessage(), e); Toast.makeText(context, e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } } } ); builder.setNegativeButton(context.getString(android.R.string.no), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { try { if (noRunnable != null) { new Thread(noRunnable).start(); } } catch (Exception e) { GPLog.error(this, e.getLocalizedMessage(), e); Toast.makeText(context, e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } } } ); } catch (Exception e) { e.printStackTrace(); } AlertDialog alertDialog = builder.create(); alertDialog.show(); } catch (Exception e) { GPLog.error("UTILITIES", "Error in yesNoMessageDialog#inPostExecute", e); //$NON-NLS-1$ //$NON-NLS-2$ } } }.execute((String) null); } /** * A warning dialog. * <p> * <b>NOT IMPLEMENTED YET, FOR NOW JUST CALLS {@link #messageDialog}</b> * * @param context the context to use. * @param msg the message. * @param okRunnable optional {@link Runnable} to trigger after ok was pressed. */ public static void warningDialog(final Context context, final String msg, final Runnable okRunnable) { messageDialog(context, msg, android.R.drawable.ic_dialog_alert, okRunnable); } /** * A warning dialog with link. * <p> * <b>NOT IMPLEMENTED YET, FOR NOW JUST CALLS {@link #messageDialog}</b> * * @param context the context to use. * @param msg the message. * @param okRunnable optional {@link Runnable} to trigger after ok was pressed. */ public static void warningDialogWithLink(final Context context, final String msg, final Runnable okRunnable) { messageDialogWithLink(context, msg, android.R.drawable.ic_dialog_alert, okRunnable); } /** * Execute a toast in an {@link AsyncTask}. * * @param context the {@link Context} to use. * @param msg the message to show. * @param length toast length. */ public static void toast(final Context context, final String msg, final int length) { new AsyncTask<String, Void, String>() { protected String doInBackground(String... params) { return ""; //$NON-NLS-1$ } protected void onPostExecute(String response) { Toast.makeText(context, msg, length).show(); } }.execute((String) null); } /** * Execute a toast in an {@link AsyncTask}. * * @param context the {@link Context} to use. * @param msgId the id of the message to show. * @param length toast length. */ public static void toast(final Context context, final int msgId, final int length) { String msg = context.getString(msgId); toast(context, msg, length); } /** * Show a quick info in the current view. * * @param view the view to attach to. * @param msg the message to show. */ public static void quickInfo(final View view, final String msg) { Snackbar.make(view, msg, Snackbar.LENGTH_SHORT).show(); } /** * Execute a message dialog in an {@link AsyncTask}. * * @param activity the {@link Activity} to use. * @param message a message to show. * @param defaultText a default text to fill in. * @param textRunnable optional {@link TextRunnable} to trigger after ok was pressed. */ public static void inputMessageDialog(final Activity activity, final String message, final String defaultText, final TextRunnable textRunnable) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); View view = activity.getLayoutInflater().inflate( eu.geopaparazzi.library.R.layout.inputdialog, null); builder.setView(view); final TextInputLayout textInputLayout = (TextInputLayout) view.findViewById(eu.geopaparazzi.library.R.id.dialogTextLayout); textInputLayout.setHint(message); final EditText editText = (EditText) view.findViewById(eu.geopaparazzi.library.R.id.dialogEdittext); if (defaultText != null) editText.setText(defaultText); final CheckBox checkBox = (CheckBox) view.findViewById(eu.geopaparazzi.library.R.id.dialogcheckBox); checkBox.setVisibility(View.GONE); try { builder.setPositiveButton(activity.getString(android.R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Editable value = editText.getText(); String newText = value.toString(); if (newText.length() < 1) { newText = defaultText; } dialog.dismiss(); if (textRunnable != null) { textRunnable.setText(newText); new Thread(textRunnable).start(); } } } ); builder.setNegativeButton(activity.getString(android.R.string.cancel), null); } catch (Exception e) { e.printStackTrace(); } AlertDialog alertDialog = builder.create(); alertDialog.show(); } /** * Execute a message dialog with checkbox in an {@link AsyncTask}. * * @param activity the {@link Context} to use. * @param message a message to show. * @param defaultText a default text to fill in. * @param checkBoxText the text of the checkbox. * @param defaultCheckboxSelection default selection for checkbox. * @param textRunnable optional {@link TextRunnable} to trigger after ok was pressed. */ public static void inputMessageAndCheckboxDialog(final Activity activity, final String message, final String defaultText, final String checkBoxText, final boolean defaultCheckboxSelection, final TextAndBooleanRunnable textRunnable) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); View view = activity.getLayoutInflater().inflate( eu.geopaparazzi.library.R.layout.inputdialog, null); builder.setView(view); // add GUI to dialog final TextInputLayout textInputLayout = (TextInputLayout) view.findViewById(eu.geopaparazzi.library.R.id.dialogTextLayout); textInputLayout.setHint(message); final EditText editText = (EditText) view.findViewById(eu.geopaparazzi.library.R.id.dialogEdittext); if (defaultText != null) editText.setText(defaultText); final CheckBox checkBox = (CheckBox) view.findViewById(eu.geopaparazzi.library.R.id.dialogcheckBox); checkBox.setText(checkBoxText); checkBox.setChecked(defaultCheckboxSelection); try { builder.setPositiveButton(activity.getString(android.R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Editable value = editText.getText(); String newText = value.toString(); if (newText.length() < 1) { newText = defaultText; } dialog.dismiss(); if (textRunnable != null) { textRunnable.setText(newText); textRunnable.setTheBoolean(checkBox.isChecked()); new Thread(textRunnable).start(); } } } ); builder.setNegativeButton(activity.getString(android.R.string.cancel), null); } catch (Exception e) { e.printStackTrace(); } AlertDialog alertDialog = builder.create(); alertDialog.show(); } /** * Dismiss {@link ProgressDialog} with check in one line. * * @param progressDialog the dialog to dismiss. */ public static void dismissProgressDialog(ProgressDialog progressDialog) { if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } } }