/* * Created by Angel Leon (@gubatron), Alden Torres (aldenml) * Copyright (c) 2011-2013, FrostWire(R). All rights reserved. * * 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 com.bt.download.android.gui.util; import java.io.File; import java.text.NumberFormat; import java.util.List; import java.util.Locale; import org.apache.commons.io.FilenameUtils; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; import android.text.InputType; import android.text.method.KeyListener; import android.text.method.NumberKeyListener; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.andrew.apollo.utils.MusicUtils; import com.bt.download.android.R; import com.bt.download.android.core.ConfigurationManager; import com.bt.download.android.core.Constants; import com.bt.download.android.core.FileDescriptor; import com.bt.download.android.gui.Librarian; import com.bt.download.android.gui.activities.MainActivity; import com.bt.download.android.gui.services.Engine; import com.frostwire.util.MimeDetector; import com.frostwire.uxstats.UXAction; import com.frostwire.uxstats.UXStats; /** * @author gubatron * @author aldenml * */ public final class UIUtils { private static final String TAG = "FW.UIUtils"; /** * Localizable Number Format constant for the current default locale. */ private static NumberFormat NUMBER_FORMAT0; // localized "#,##0" private static NumberFormat NUMBER_FORMAT1; // localized "#,##0.0" private static String[] BYTE_UNITS = new String[] { "b", "KB", "Mb", "Gb", "Tb" }; public static String GENERAL_UNIT_KBPSEC = "KB/s"; static { NUMBER_FORMAT0 = NumberFormat.getNumberInstance(Locale.getDefault()); NUMBER_FORMAT0.setMaximumFractionDigits(0); NUMBER_FORMAT0.setMinimumFractionDigits(0); NUMBER_FORMAT0.setGroupingUsed(true); NUMBER_FORMAT1 = NumberFormat.getNumberInstance(Locale.getDefault()); NUMBER_FORMAT1.setMaximumFractionDigits(1); NUMBER_FORMAT1.setMinimumFractionDigits(1); NUMBER_FORMAT1.setGroupingUsed(true); } public static void showToastMessage(Context context, String message, int duration, int gravity, int xOffset, int yOffset) { if (context != null && message != null) { Toast toast = Toast.makeText(context, message, duration); if (gravity != (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)) { toast.setGravity(gravity, xOffset, yOffset); } toast.show(); } } public static void showToastMessage(Context context, String message, int duration) { showToastMessage(context, message, duration, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0); } public static void showShortMessage(Context context, String message) { showToastMessage(context, message, Toast.LENGTH_SHORT); } public static void showLongMessage(Context context, String message) { showToastMessage(context, message, Toast.LENGTH_LONG); } public static void showShortMessage(Context context, int resId) { showShortMessage(context, context.getString(resId)); } public static void showLongMessage(Context context, int resId) { showLongMessage(context, context.getString(resId)); } public static void showShortMessage(Context context, int resId, Object... formatArgs) { showShortMessage(context, context.getString(resId, formatArgs)); } /** * * @param context * @param messageId * @param titleId * @param positiveListener */ public static Dialog showYesNoDialog(Context context, int messageId, int titleId, OnClickListener positiveListener) { return showYesNoDialog(context, messageId, titleId, positiveListener, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); } public static void showYesNoDialog(Context context, int iconId, String message, int titleId, OnClickListener positiveListener) { showYesNoDialog(context, iconId, message, titleId, positiveListener, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); } /** * * @param context * @param messageId * @param titleId * @param positiveListener * @param negativeListener */ public static Dialog showYesNoDialog(Context context, int messageId, int titleId, OnClickListener positiveListener, OnClickListener negativeListener) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(messageId).setTitle(titleId).setCancelable(false).setPositiveButton(android.R.string.yes, positiveListener).setNegativeButton(android.R.string.no, negativeListener); Dialog dialog = builder.create(); dialog.show(); return dialog; } public static void showYesNoDialog(Context context, int iconId, int messageId, int titleId, OnClickListener positiveListener, OnClickListener negativeListener) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setIcon(iconId).setMessage(messageId).setTitle(titleId).setCancelable(false).setPositiveButton(android.R.string.yes, positiveListener).setNegativeButton(android.R.string.no, negativeListener); builder.create().show(); } public static void showYesNoDialog(Context context, String message, int titleId, OnClickListener positiveListener, OnClickListener negativeListener) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(message).setTitle(titleId).setCancelable(false).setPositiveButton(android.R.string.yes, positiveListener).setNegativeButton(android.R.string.no, negativeListener); builder.create().show(); } public static void showYesNoDialog(Context context, int iconId, String message, int titleId, OnClickListener positiveListener, OnClickListener negativeListener) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setIcon(iconId).setMessage(message).setTitle(titleId).setCancelable(false).setPositiveButton(android.R.string.yes, positiveListener).setNegativeButton(android.R.string.no, negativeListener); builder.create().show(); } public static void showOkCancelDialog(Context context, View view, int titleId, OnClickListener okListener, OnClickListener cancelListener) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setView(view).setTitle(titleId).setPositiveButton(android.R.string.ok, okListener).setNegativeButton(android.R.string.cancel, cancelListener); builder.create().show(); } public static void showOkCancelDialog(Context context, View view, int titleId, OnClickListener okListener) { showOkCancelDialog(context, view, titleId, okListener, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); } public static EditText buildEditTextWithType(Context context, KeyListener keyListener, String text) { EditText editText = new EditText(context); editText.setKeyListener(keyListener); editText.setText(text); return editText; } public static EditText buildNumericEditText(Context context, String text) { return buildEditTextWithType(context, new NumberKeyListener() { @Override public int getInputType() { return InputType.TYPE_CLASS_NUMBER; } @Override protected char[] getAcceptedChars() { return new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; } }, text); } public static String getBytesInHuman(float size) { int i = 0; for (i = 0; size > 1024; i++) { size /= 1024f; } return String.format(Locale.US, "%.2f %s", size, BYTE_UNITS[i]); } /** * Converts an rate into a human readable and localized KB/s speed. */ public static String rate2speed(double rate) { return NUMBER_FORMAT0.format(rate) + " " + GENERAL_UNIT_KBPSEC; } public static String getFileTypeAsString(Resources resources, byte fileType) { switch (fileType) { case Constants.FILE_TYPE_APPLICATIONS: return resources.getString(R.string.applications); case Constants.FILE_TYPE_AUDIO: return resources.getString(R.string.audio); case Constants.FILE_TYPE_DOCUMENTS: return resources.getString(R.string.documents); case Constants.FILE_TYPE_PICTURES: return resources.getString(R.string.pictures); case Constants.FILE_TYPE_RINGTONES: return resources.getString(R.string.ringtones); case Constants.FILE_TYPE_VIDEOS: return resources.getString(R.string.video); case Constants.FILE_TYPE_TORRENTS: return resources.getString(R.string.media_type_torrents); default: return resources.getString(R.string.unknown); } } public static int getFileTypeIconId(byte fileType) { switch (fileType) { case Constants.FILE_TYPE_APPLICATIONS: return R.drawable.browse_peer_application_icon_selector_off; case Constants.FILE_TYPE_AUDIO: return R.drawable.browse_peer_audio_icon_selector_off; case Constants.FILE_TYPE_DOCUMENTS: return R.drawable.browse_peer_document_icon_selector_off; case Constants.FILE_TYPE_PICTURES: return R.drawable.browse_peer_picture_icon_selector_off; case Constants.FILE_TYPE_RINGTONES: return R.drawable.browse_peer_ringtone_icon_selector_off; case Constants.FILE_TYPE_VIDEOS: return R.drawable.browse_peer_video_icon_selector_off; default: return R.drawable.question_mark; } } /** * Opens the given file with the default Android activity for that File and * mime type. * * @param filePath * @param mime */ public static void openFile(Context context, String filePath, String mime) { try { if (!openAudioInternal(filePath)) { Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.fromFile(new File(filePath)), mime); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); if (mime != null && mime.contains("video")) { if (MusicUtils.isPlaying()) { MusicUtils.playOrPause(); } UXStats.instance().log(UXAction.LIBRARY_VIDEO_PLAY); } } } catch (Throwable e) { UIUtils.showShortMessage(context, R.string.cant_open_file); Log.e(TAG, "Failed to open file: " + filePath, e); } } public static void openFile(Context context, File file) { openFile(context, file.getAbsolutePath(), getMimeType(file.getAbsolutePath())); } public static void openURL(Context context, String url) { Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); context.startActivity(i); } public static String getMimeType(String filePath) { try { return MimeDetector.getMimeType(FilenameUtils.getExtension(filePath)); } catch (Throwable e) { Log.e(TAG, "Failed to read mime type for: " + filePath); return MimeDetector.UNKNOWN; } } /** * Create an ephemeral playlist with the files of the same type that live on the folder of the given file descriptor and play it. * @param fd */ public static void playEphemeralPlaylist(FileDescriptor fd) { Engine.instance().getMediaPlayer().play(Librarian.instance().createEphemeralPlaylist(fd)); } private static boolean openAudioInternal(String filePath) { try { UXStats.instance().log(UXAction.LIBRARY_PLAY_AUDIO_FROM_FILE); List<FileDescriptor> fds = Librarian.instance().getFiles(filePath, true); if (fds.size() == 1 && fds.get(0).fileType == Constants.FILE_TYPE_AUDIO) { playEphemeralPlaylist(fds.get(0)); return true; } else { return false; } } catch (Throwable e) { return false; } } /** * This method sets up the visibility of the support frostwire control (@see {@link DonationsView}) * depending on remote configuration parameters and local configuration preferences. * @param supportFrostWireView */ public static void supportFrostWire(View supportFrostWireView) { //remote kill switch if (!ConfigurationManager.instance().getBoolean(Constants.PREF_KEY_GUI_SUPPORT_FROSTWIRE_THRESHOLD)) { supportFrostWireView.setVisibility(View.GONE); Log.v(TAG, "Hiding support, above threshold."); } else if (ConfigurationManager.instance().getBoolean(Constants.PREF_KEY_GUI_SUPPORT_FROSTWIRE)) { supportFrostWireView.setVisibility(View.VISIBLE); if (supportFrostWireView.getLayoutParams() != null) { supportFrostWireView.getLayoutParams().width = LayoutParams.MATCH_PARENT; } } } /** * Android devices with SDK below target=11 do not support textView.setAlpha(). * This is a work around. * @param v - the text view * @param alpha - a value from 0 to 255. (0=transparent, 255=fully visible) */ public static void setTextViewAlpha(TextView v, int alpha) { v.setTextColor(v.getTextColors().withAlpha(alpha)); v.setHintTextColor(v.getHintTextColors().withAlpha(alpha)); v.setLinkTextColor(v.getLinkTextColors().withAlpha(alpha)); Drawable[] compoundDrawables = v.getCompoundDrawables(); for (int i = 0; i < compoundDrawables.length; i++) { Drawable d = compoundDrawables[i]; if (d != null) { d.setAlpha(alpha); } } } /** * Checks setting to show or not the transfers window right after a download has started. * This should probably be moved elsewhere (similar to GUIMediator on the desktop) * @param activity */ public static void showTransfersOnDownloadStart(Context context) { if (ConfigurationManager.instance().showTransfersOnDownloadStart() && context != null) { Intent i = new Intent(context, MainActivity.class); i.setAction(Constants.ACTION_SHOW_TRANSFERS); i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); context.startActivity(i); } } public static void showKeyboard(Context context, View view) { view.requestFocus(); InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); } public static void hideKeyboardFromActivity(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); View view = activity.getCurrentFocus(); if (view == null) { view = new View(activity); } inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); } }