package mobi.monaca.framework.nativeui;
import java.util.Iterator;
import java.util.regex.Pattern;
import mobi.monaca.framework.util.MyLog;
import mobi.monaca.utils.TimeStamp;
import mobi.monaca.utils.log.LogItem;
import mobi.monaca.utils.log.LogItem.LogLevel;
import mobi.monaca.utils.log.LogItem.Source;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.util.SparseIntArray;
import android.util.TypedValue;
/** This class has utility methods for native component framework. */
public class UIUtil {
static protected Pattern colorPattern = Pattern
.compile("^#[0-9a-fA-F]{6}$");
public static final String TAG = "PhoneGapLog";
static protected SparseIntArray computedFontSizeCache = new SparseIntArray();
/** Build color integer from color string and opacity value. */
public static int buildColor(String colorString, double opacity) throws IllegalArgumentException{
int baseColor = 0;
if (opacity > 1.0) {
opacity = 1.0;
}
if (colorPattern.matcher(colorString).matches()) {
baseColor = Integer.parseInt(colorString.substring(1, 7), 16);
} else {
throw new IllegalArgumentException("Cannot convert " + colorString + " to Color");
}
long opacityLong = (Math.round((opacity / 1.0) * 0xff) & 0xff) << 24;
return (int) (baseColor + opacityLong);
}
public static int buildColor(String color) throws IllegalArgumentException{
return UIUtil.buildColor(color, 1.0);
}
public static void updateJSONObject(JSONObject target, JSONObject source) {
Iterator<String> iterator = source.keys();
while (iterator.hasNext()) {
String key = iterator.next();
try {
target.put(key, source.get(key));
} catch (JSONException e) {
}
}
}
public static int buildOpacity(double opacity) {
opacity = opacity < 1.0 ? opacity : 1.0;
return Math.round((int) (255 * (opacity / 1.0)));
}
public static int dip2px(Context context, int dip) {
return Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources()
.getDisplayMetrics()));
}
public static void reportJSONParseError(Context context, String msg) {
LogItem logItem = new LogItem(TimeStamp.getCurrentTimeStamp(), Source.SYSTEM, LogLevel.ERROR, "NativeComponent:JSONParseError:" + msg, "", 0);
MyLog.sendBroadcastDebugLog(context, logItem);
}
public static void reportInvalidJSONStructure(Context context, String msg) {
LogItem logItem = new LogItem(TimeStamp.getCurrentTimeStamp(), Source.SYSTEM, LogLevel.ERROR, "NativeComponent:InvalidJSONStructure:" + msg, "", 0);
MyLog.sendBroadcastDebugLog(context, logItem);
}
public static void reportInvalidComponent(Context context, String msg) {
LogItem logItem = new LogItem(TimeStamp.getCurrentTimeStamp(), Source.SYSTEM, LogLevel.ERROR, "NativeComponent:InvalidComponent:" + msg, "", 0);
MyLog.sendBroadcastDebugLog(context, logItem);
}
public static void reportInvalidContainer(Context context, String msg) {
LogItem logItem = new LogItem(TimeStamp.getCurrentTimeStamp(), Source.SYSTEM, LogLevel.ERROR, "NativeComponent:InvalidContainer:" + msg, "", 0);
MyLog.sendBroadcastDebugLog(context, logItem);
}
public static void reportUndefinedProperty(Context context, String msg) {
LogItem logItem = new LogItem(TimeStamp.getCurrentTimeStamp(), Source.SYSTEM, LogLevel.ERROR, "NativeComponent:UndefinedProperty:" + msg, "", 0);
MyLog.sendBroadcastDebugLog(context, logItem);
}
public static void reportInvalidStyleProperty(Context context, String msg) {
MyLog.e(TAG, "InvalidStyleProperty: " + msg);
LogItem logItem = new LogItem(TimeStamp.getCurrentTimeStamp(), Source.SYSTEM, LogLevel.ERROR, "NativeComponent:InvalidStyleProperty:" + msg, "", 0);
MyLog.sendBroadcastDebugLog(context, logItem);
}
public static void reportIgnoredStyleProperty(Context context, String msg) {
MyLog.e(TAG, "IgnoredStyleProperty: " + msg);
LogItem logItem = new LogItem(TimeStamp.getCurrentTimeStamp(), Source.SYSTEM, LogLevel.ERROR, "NativeComponent:IgnoredStyleProperty:" + msg, "", 0);
MyLog.sendBroadcastDebugLog(context, logItem);
}
public static int multiplyColor(int base, int filter) {
int left, right, result;
left = 255 & base;
right = 255 & filter;
result = (255 & Math.round(left * right / 255));
left = 255 & (base >> 8);
right = 255 & (filter >> 8);
result += (255 & Math.round(left * right / 255)) << 8;
left = 255 & (base >> 16);
right = 255 & (filter >> 16);
result += (255 & Math.round(left * right / 255)) << 16;
return result + 0xff000000;
}
/** Create Bitmap instance from Drawable. */
public static Bitmap createBitmapFromDrawable(Drawable drawable) {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
drawable.setBounds(0, 0, width, height);
drawable.draw(new Canvas(bitmap));
return bitmap;
}
/** Create drawable instance from drawable and setted color filter. */
public static Bitmap createBitmapWithColorFilter(Drawable drawable,
ColorFilter colorFilter) {
Bitmap bitmap = createBitmapFromDrawable(drawable);
return createBitmapWithColorFilter(bitmap, colorFilter);
}
/** Create drawable instance from drawable and setted color filter. */
public static Bitmap createBitmapWithColorFilter(Bitmap bitmap,
ColorFilter colorFilter) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
// paint filtered bitmap
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, width, height).copy(
Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT));
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
paint.setColorFilter(colorFilter);
canvas.drawPaint(paint);
return result;
}
public static Bitmap resizeBitmap(Bitmap bitmap, int resizeWidth,
int resizeHeight) {
float resizeScaleWidth;
float resizeScaleHeight;
Matrix matrix = new Matrix();
resizeScaleWidth = (float) resizeWidth / (float) bitmap.getWidth();
resizeScaleHeight = (float) resizeHeight / (float) bitmap.getHeight();
matrix.postScale(resizeScaleWidth, resizeScaleHeight);
Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizeBitmap;
}
public static Bitmap resizeBitmap(Bitmap bitmap, int resizeHeight) {
float resizeScaleHeight;
Matrix matrix = new Matrix();
resizeScaleHeight = (float) resizeHeight / (float) bitmap.getHeight();
matrix.postScale(resizeScaleHeight, resizeScaleHeight);
Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizeBitmap;
}
public static Bitmap resizeButtonImageBitmap(DisplayMetrics metrics,
Bitmap bitmap) {
// xhdpi
// do nothing
if (metrics.densityDpi == DisplayMetrics.DENSITY_HIGH) {
// hdpi
bitmap = resizeBitmap(bitmap,
(int) Math.round(bitmap.getWidth() * 0.75),
(int) Math.round(bitmap.getHeight() * 0.75));
} else if (metrics.densityDpi == DisplayMetrics.DENSITY_MEDIUM) {
// mdpi
bitmap = resizeBitmap(bitmap,
(int) Math.round(bitmap.getWidth() * 0.5),
(int) Math.round(bitmap.getHeight() * 0.5));
} else if (metrics.densityDpi == DisplayMetrics.DENSITY_LOW) {
// ldpi
bitmap = resizeBitmap(bitmap,
(int) Math.round(bitmap.getWidth() * 0.375),
(int) Math.round(bitmap.getHeight() * 0.375));
}
return bitmap;
}
public static int getFontSizeFromDip(Context context, int dip) {
if (computedFontSizeCache.get(dip, -1) != -1) {
return computedFontSizeCache.get(dip);
}
Integer result = computeFontSizeFromFontHeightDip(context, dip);
return result;
}
protected static int computeFontSizeFromFontHeightDip(Context context,
int dip) {
int targetHeight = UIUtil.dip2px(context, dip);
float resultTextSize = 0;
float oldHeight = 0;
for (int i = 0; i < 100; i++) {
Paint paint = new Paint();
paint.setTextSize(i);
FontMetrics metrics = paint.getFontMetrics();
float height = metrics.descent - metrics.ascent;
if (Math.abs(targetHeight - oldHeight) > Math.abs(targetHeight
- height)) {
resultTextSize = i;
}
oldHeight = height;
}
return (int) resultTextSize;
}
}