<commit_before>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
package ti.modules.titanium.ui.widget;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollProxy;
import org.appcelerator.kroll.common.AsyncResult;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.kroll.common.TiConfig;
import org.appcelerator.kroll.common.TiMessenger;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.TiBlob;
import org.appcelerator.titanium.TiC;
import org.appcelerator.titanium.TiDimension;
import org.appcelerator.titanium.TiLifecycle.OnLifecycleEvent;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.util.TiBackgroundImageLoadTask;
import org.appcelerator.titanium.util.TiConvert;
import org.appcelerator.titanium.util.TiDownloadListener;
import org.appcelerator.titanium.util.TiResponseCache;
import org.appcelerator.titanium.util.TiUIHelper;
import org.appcelerator.titanium.view.TiDrawableReference;
import org.appcelerator.titanium.view.TiUIView;

import ti.modules.titanium.filesystem.FileProxy;
import ti.modules.titanium.ui.ImageViewProxy;
import ti.modules.titanium.ui.widget.TiImageView.OnSizeChangeListener;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.ViewParent;
import android.webkit.URLUtil;

public class TiUIImageView extends TiUIView implements OnLifecycleEvent, Handler.Callback
{
	private static final String LCAT = "TiUIImageView";
	private static final boolean DBG = TiConfig.LOGD;
	private static final AtomicInteger imageTokenGenerator = new AtomicInteger(0);
	private static final int FRAME_QUEUE_SIZE = 5;
	public static final int INFINITE = 0;

	// TIMOB-3599: A bug in Gingerbread forces us to retry decoding bitmaps when they initially fail
	private static final String PROPERTY_DECODE_RETRIES = "decodeRetries";
	private static final int DEFAULT_DECODE_RETRIES = 5;

	private Timer timer;
	private Animator animator;
	private Object[] images;
	private Loader loader;
	private Thread loaderThread;
	private AtomicBoolean animating = new AtomicBoolean(false);
	private boolean reverse = false;
	private boolean paused = false;
	private int token;
	private boolean firedLoad;
	private ImageViewProxy imageViewProxy;

	private TiDimension requestedWidth;
	private TiDimension requestedHeight;

	private ArrayList<TiDrawableReference> imageSources;
	private TiDrawableReference defaultImageSource;
	private TiDownloadListener downloadListener;
	private int decodeRetries = 0;

	private class BgImageLoader extends TiBackgroundImageLoadTask
	{
		private int token;

		public BgImageLoader(TiDimension imageWidth, TiDimension imageHeight, int token)
		{
			super(getParentView(), imageWidth, imageHeight);
			this.token = token;
		}

		@Override
		protected void onPostExecute(Drawable d)
		{
			super.onPostExecute(d);

			if (d != null) {
				setImageDrawable(d, token);
			} else {
				if (DBG) {
					String traceMsg = "Background image load returned null";
					if (proxy.hasProperty(TiC.PROPERTY_IMAGE)) {
						Object image = proxy.getProperty(TiC.PROPERTY_IMAGE);
						if (image instanceof String) {
							traceMsg += " (" + TiConvert.toString(image) + ")";
						}
					}
					Log.d(LCAT, traceMsg);
				}
			}
		}
	}

	public TiUIImageView(TiViewProxy proxy)
	{
		super(proxy);
		imageViewProxy = (ImageViewProxy) proxy;

		if (DBG) {
			Log.d(LCAT, "Creating an ImageView");
		}

		TiImageView view = new TiImageView(proxy.getActivity());
		view.setOnSizeChangeListener(new OnSizeChangeListener()
		{

			@Override
			public void sizeChanged(int w, int h, int oldWidth, int oldHeight)
			{
				// By the time this hits, we've already set the drawable in the view.
				// And this runs even the first time the view is drawn (in which
				// case oldWidth and oldHeight are 0.) This was leading to
				// setImage running twice unnecessarily, so the if block here
				// will avoid a second, unnecessary call to setImage.
				if (oldWidth == 0 && oldHeight == 0) {
					TiImageView view = getView();
					if (view != null) {
						Drawable drawable = view.getImageDrawable();
						if (drawable != null && drawable.getIntrinsicHeight() == h && drawable.getIntrinsicWidth() == w) {
							return;
						}
					}
				}
				setImage(true);
			}
		});

		downloadListener = new TiDownloadListener()
		{
			@Override
			public void downloadFinished(URI uri)
			{
				if (!TiResponseCache.peek(uri)) {
					// The requested image did not make it into our TiResponseCache,
					// possibly because it had a header forbidding that. Now get it
					// via the "old way" (not relying on cache).
					synchronized (imageTokenGenerator) {
						token = imageTokenGenerator.incrementAndGet();
						imageSources.get(0).getBitmapAsync(new BgImageLoader(requestedWidth, requestedHeight, token));
					}
				} else {
					firedLoad = false;<commit_msg>TIMOB-6295 Do null check on imageSources in async callback, since by that point -- being that it's async -- the view could have gone away already.<commit_after>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2011 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
package ti.modules.titanium.ui.widget;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollProxy;
import org.appcelerator.kroll.common.AsyncResult;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.kroll.common.TiConfig;
import org.appcelerator.kroll.common.TiMessenger;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.TiBlob;
import org.appcelerator.titanium.TiC;
import org.appcelerator.titanium.TiDimension;
import org.appcelerator.titanium.TiLifecycle.OnLifecycleEvent;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.util.TiBackgroundImageLoadTask;
import org.appcelerator.titanium.util.TiConvert;
import org.appcelerator.titanium.util.TiDownloadListener;
import org.appcelerator.titanium.util.TiResponseCache;
import org.appcelerator.titanium.util.TiUIHelper;
import org.appcelerator.titanium.view.TiDrawableReference;
import org.appcelerator.titanium.view.TiUIView;

import ti.modules.titanium.filesystem.FileProxy;
import ti.modules.titanium.ui.ImageViewProxy;
import ti.modules.titanium.ui.widget.TiImageView.OnSizeChangeListener;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.ViewParent;
import android.webkit.URLUtil;

public class TiUIImageView extends TiUIView implements OnLifecycleEvent, Handler.Callback
{
	private static final String LCAT = "TiUIImageView";
	private static final boolean DBG = TiConfig.LOGD;
	private static final AtomicInteger imageTokenGenerator = new AtomicInteger(0);
	private static final int FRAME_QUEUE_SIZE = 5;
	public static final int INFINITE = 0;

	// TIMOB-3599: A bug in Gingerbread forces us to retry decoding bitmaps when they initially fail
	private static final String PROPERTY_DECODE_RETRIES = "decodeRetries";
	private static final int DEFAULT_DECODE_RETRIES = 5;

	private Timer timer;
	private Animator animator;
	private Object[] images;
	private Loader loader;
	private Thread loaderThread;
	private AtomicBoolean animating = new AtomicBoolean(false);
	private boolean reverse = false;
	private boolean paused = false;
	private int token;
	private boolean firedLoad;
	private ImageViewProxy imageViewProxy;

	private TiDimension requestedWidth;
	private TiDimension requestedHeight;

	private ArrayList<TiDrawableReference> imageSources;
	private TiDrawableReference defaultImageSource;
	private TiDownloadListener downloadListener;
	private int decodeRetries = 0;

	private class BgImageLoader extends TiBackgroundImageLoadTask
	{
		private int token;

		public BgImageLoader(TiDimension imageWidth, TiDimension imageHeight, int token)
		{
			super(getParentView(), imageWidth, imageHeight);
			this.token = token;
		}

		@Override
		protected void onPostExecute(Drawable d)
		{
			super.onPostExecute(d);

			if (d != null) {
				setImageDrawable(d, token);
			} else {
				if (DBG) {
					String traceMsg = "Background image load returned null";
					if (proxy.hasProperty(TiC.PROPERTY_IMAGE)) {
						Object image = proxy.getProperty(TiC.PROPERTY_IMAGE);
						if (image instanceof String) {
							traceMsg += " (" + TiConvert.toString(image) + ")";
						}
					}
					Log.d(LCAT, traceMsg);
				}
			}
		}
	}

	public TiUIImageView(TiViewProxy proxy)
	{
		super(proxy);
		imageViewProxy = (ImageViewProxy) proxy;

		if (DBG) {
			Log.d(LCAT, "Creating an ImageView");
		}

		TiImageView view = new TiImageView(proxy.getActivity());
		view.setOnSizeChangeListener(new OnSizeChangeListener()
		{

			@Override
			public void sizeChanged(int w, int h, int oldWidth, int oldHeight)
			{
				// By the time this hits, we've already set the drawable in the view.
				// And this runs even the first time the view is drawn (in which
				// case oldWidth and oldHeight are 0.) This was leading to
				// setImage running twice unnecessarily, so the if block here
				// will avoid a second, unnecessary call to setImage.
				if (oldWidth == 0 && oldHeight == 0) {
					TiImageView view = getView();
					if (view != null) {
						Drawable drawable = view.getImageDrawable();
						if (drawable != null && drawable.getIntrinsicHeight() == h && drawable.getIntrinsicWidth() == w) {
							return;
						}
					}
				}
				setImage(true);
			}
		});

		downloadListener = new TiDownloadListener()
		{
			@Override
			public void downloadFinished(URI uri)
			{
				if (!TiResponseCache.peek(uri)) {
					// The requested image did not make it into our TiResponseCache,
					// possibly because it had a header forbidding that. Now get it
					// via the "old way" (not relying on cache).
					synchronized (imageTokenGenerator) {
						token = imageTokenGenerator.incrementAndGet();
						if (imageSources != null && imageSources.size() > 0) {
							imageSources.get(0).getBitmapAsync(new BgImageLoader(requestedWidth, requestedHeight, token));
						}
					}
				} else {
					firedLoad = false;
{'fraction_non_alphanumeric': 0.08907165981275703, 'fraction_numerical': 0.004112345787032986, 'mean_word_length': 4.411931818181818, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2772145', 'n_tokens_mistral': 3944, 'n_tokens_neox': 3414, 'n_words': 923}