In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Flickr!Flickr!Flickr!

http://www.libspark.org/wiki/ThreadのFlickrSphereをシンプルにしてFlickrの写真を読み込むだけにした。
*
Get Adobe Flash player
by paq 01 Apr 2009
/**
 * 
 * http://www.libspark.org/wiki/ThreadのFlickrSphereをシンプルにしてFlickrの写真を読み込むだけにした。
 * 
 */

package
{
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import org.libspark.thread.EnterFrameThreadExecutor;
	import org.libspark.thread.Thread;
	
	[SWF(width=465, height=465, backgroundColor=0x000000, framelate=60)]
	public class FlickrTest extends Sprite
	{		
		private var _context:Context = new Context();
		
		public function FlickrTest()
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.LEFT;
			
			addEventListener(Event.ADDED_TO_STAGE, initialize);
		}
		
		private function initialize(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, initialize);
			
			_context.stage = stage;
			
			Thread.initialize(new EnterFrameThreadExecutor());
						
			var main:MainThread = new MainThread(_context);
			main.start();
		}
	}
}

/*=============================================================================================
*///===========================================================================================

import flash.display.Bitmap;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.Loader;
import flash.display.BitmapData;
import flash.events.Event;
import flash.net.URLRequest;
import flash.net.URLVariables;
import flash.system.LoaderContext;
import flash.geom.Matrix;
import org.libspark.thread.IMonitor;
import org.libspark.thread.Monitor;
import org.libspark.thread.threads.display.LoaderThread;
import org.libspark.thread.EnterFrameThreadExecutor;
import org.libspark.thread.Thread;
import org.libspark.thread.threads.net.URLLoaderThread;
import org.libspark.thread.utils.ParallelExecutor;
import org.libspark.thread.threads.tweener.TweenerThread;

/***********************************************************************************************
 * MainThread - メイン
 */

internal class MainThread  extends Thread
{
	/**
	 * @param	context	コンテキスト
	 */
	public function MainThread(context:Context)
	{
		_context = context;
	}
	
	private var _context:Context;
	private var _searchFlickr:SearchFlickrPhotoThread;
		
	//検索するキーワード
	private const KEYWORD:String = "HDR";
	
	override protected function run():void
	{
		next(seach);
	}
	
	private function seach():void
	{
		_searchFlickr = new SearchFlickrPhotoThread(KEYWORD);
		_searchFlickr.start();
		_searchFlickr.join();
		
		next(seachComplete);
	}
	
	private function seachComplete():void
	{
		var flickrphotos:Array = _searchFlickr.photos;
		
		var displayFlickr:DisplayFlickrPhotoThread = new DisplayFlickrPhotoThread(_context, flickrphotos);
		displayFlickr.start();
	}
}

/***********************************************************************************************
 * Context - Thread内で必要なものを保有するクラス
 */
internal class Context
{
	public var stage:Stage;
}
	
/***********************************************************************************************
 * DisplayFlickrPhotoThread - 写真を表示
 */
internal class DisplayFlickrPhotoThread extends Thread
{
	/**
	 * @param	context	コンテキスト
	 * @param	photos	表示する FlickrPhoto の配列
	 */
	public function DisplayFlickrPhotoThread(context:Context, photos:Array)
	{
		_context = context;
		_photos = photos;
		_tempMatrix = new Matrix();
		_imageCount = 0;
	}
	
	private var _context:Context;
	private var _photos:Array;
	
	private var _queue:PhotoImageQueue;
	private var _loaders:ParallelExecutor;
	
	private var _imageBitmaps:Array;
	private var _imageCount:uint;
	
	private var _tempMatrix:Matrix;
	
	private var _tweens:Array;
	
	override protected function run():void
	{
		_imageBitmaps = [];
		
		// ロードされた写真を受け取るためのキュー
		_queue = new PhotoImageQueue();
		
		// 写真イメージをロードするためのスレッドを 4 つ作る
		_loaders = new ParallelExecutor();
		_loaders.addThread(new LoadFlickrPhotoImagesThread(_photos, _queue));
		_loaders.addThread(new LoadFlickrPhotoImagesThread(_photos, _queue));
		_loaders.addThread(new LoadFlickrPhotoImagesThread(_photos, _queue));
		_loaders.addThread(new LoadFlickrPhotoImagesThread(_photos, _queue));
		
		// ロード開始
		_loaders.start();
		
		// 写真表示
		displayPhoto();
	}
	
	private function displayPhoto():void
	{
		// 読み込まれている写真が無ければ待つ
		if (_queue.checkPoll()) {
			next(displayPhoto);
			interrupted(displayPhotoInterrupted);
			return;
		}
		
		// 割り込まれていたら displayInterrupted へ
		if (checkInterrupted()) {
			displayPhotoInterrupted();
			return;
		}
		
		// 写真イメージを取得
		var image:Loader = _queue.poll();
		
		// BitmapData に転写
		var imageBitmap:BitmapData = getBitmapData(image, 47);		
		
		// ローダ開放
		image.unload();
		
		var bmp:Bitmap = new Bitmap(imageBitmap);
		bmp.x = _imageCount * 47 - (int(_imageCount/10) * 47)*10;
		bmp.y = int(_imageCount / 10) * 47;
		bmp.scaleX = bmp.scaleY = 1;
	
		_context.stage.addChild(bmp);
		
		_imageCount++;
		_imageBitmaps.push(imageBitmap);
		
		// 次の写真イメージへ
		next(displayPhoto);
	}
	
	private function getBitmapData(image:Loader, size:uint):BitmapData
	{
		// BitmapData
		var bitmapData:BitmapData = new BitmapData(size, size, false);
		// 指定されたサイズに縮小して描画
		_tempMatrix.identity();
		_tempMatrix.scale(size / image.contentLoaderInfo.width, size / image.contentLoaderInfo.height);
		bitmapData.draw(image.content, _tempMatrix);
		return bitmapData;
	}
	
	private function displayPhotoInterrupted():void
	{
		// 全てのロードをキャンセル
		_loaders.interrupt();
		_loaders = null;
	}
	
	override protected function finalize():void
	{
		// BitmapData 開放
		for each (var bitmap:BitmapData in _imageBitmaps) {
			bitmap.dispose();
		}
		_imageBitmaps = null;
	}
}

/***********************************************************************************************
 * LoadFlickrPhotoImagesThread - FlickPhoto のイメージを読み込んで PhotoImageQueue に追加
 */
internal class LoadFlickrPhotoImagesThread extends Thread
{
	/**
	 * @param	photos	読み込む FlickrPhoto の配列
	 * @param	queue	読み込んだイメージを格納する PhotoImageQueue
	 */
	public function LoadFlickrPhotoImagesThread(photos:Array, queue:PhotoImageQueue)
	{
		_photos = photos;
		_queue = queue;
	}
	
	private var _photos:Array;
	private var _queue:PhotoImageQueue;
	private var _loader:LoaderThread;
	
	override protected function run():void
	{
		// もう読み込む写真が無ければ終了
		if (_photos.length == 0) {
			return;
		}
		
		// 読み込む写真
		var photo:FlickrPhoto = FlickrPhoto(_photos.shift());
		
		// ロード開始
		_loader = new LoaderThread(new URLRequest(photo.smallSquareImageURL), new LoaderContext(true));
		_loader.start();
		_loader.join();
		
		// 完了したら loadComplete
		next(loadComplete);
		// 割り込まれたら loadInterrupted
		interrupted(loadInterrupted);
		// エラーが起きたら loadError
		error(Error, loadError);
	}
	
	private function loadComplete():void
	{
		// 読み込んだ写真をキューに追加
		_queue.offer(_loader.loader);
		
		// LoaderThread 破棄
		_loader = null;
		
		// 次を読み込む
		run();
	}
	
	private function loadInterrupted():void
	{
		// LoaderThread にも割り込みをかけて終了
		_loader.interrupt();
		_loader = null;
	}
	
	private function loadError(e:Error, t:Thread):void
	{
		// 写真イメージの読み込みでエラーが起きた際には無視する
		_loader = null;
		// 何事も無かったかのように次へ
		run();
	}
}

/***********************************************************************************************
 * PhotoImageQueue - ロードした写真イメージをストックするためのキュー
 */
internal class PhotoImageQueue
{
	public function PhotoImageQueue()
	{
		_queue = [];
		_monitor = new Monitor();
	}
	
	private var _queue:Array;
	private var _monitor:IMonitor;
	
	/**
	 * キューが空であれば true、そうでなければ false を返します.
	 */
	public function get isEmpty():Boolean
	{
		return _queue.length == 0;
	}
	
	/**
	 * キューに指定されたイメージを追加します.
	 * 
	 * @param	image	追加するイメージ
	 */
	public function offer(image:Loader):void
	{
		// キューに追加
		_queue.push(image);
		// checkPoll でイメージを取得可能になるまで待機しているスレッドを起こす
		_monitor.notifyAll();
	}
	
	/**
	 * キューからイメージを取得可能かどうかをチェックし、可能でなければ取得可能になるまでスレッドを待機させます.
	 * 
	 * @return	スレッドが待機する場合に true、そうでなければ false
	 */
	public function checkPoll():Boolean
	{
		// キューが空であれば
		if (isEmpty) {
			// スレッドを待機させる
			_monitor.wait();
			return true;
		}
		return false;
	}
	
	/**
	 * キューからイメージを取得します.
	 * 
	 * @return	イメージ
	 */
	public function poll():Loader
	{
		// キューから取得
		return _queue.shift();
	}
}
	
/***********************************************************************************************
 * SearchFlickrPhotoThread - Flickrから写真を検索。
 */
internal class SearchFlickrPhotoThread extends Thread
{
	private static const REST_URL:String = 'http://api.flickr.com/services/rest/';
	private static const REST_METHOD_NAME:String = 'flickr.photos.search';
	public const FLICKR_APIKEY:String = 'cfc81e109140b97151488162030ced4b';
	
	/**
	 * @param	keyword	検索キーワード
	 */
	public function SearchFlickrPhotoThread(keyword:String)
	{
		_keyword = keyword;
		_photos = [];
	}
	
	private var _keyword:String;
	private var _loader:URLLoaderThread;
	private var _photos:Array;
	
	/**
	 * 読み込んだ写真の FlickrPhoto の配列を返します.
	 */
	public function get photos():Array
	{
		return _photos;
	}
	
	/**
	 * API を呼び出すための URLRequest を生成して返します.
	 * 
	 * @return	URLRequest
	 * @private
	 */
	private function createURLRequest():URLRequest
	{
		var req:URLRequest = new URLRequest(REST_URL);
		req.data = createURLVariables();
		return req;
	}
	
	/**
	 * API を呼び出すための URLVariables を生成して返します.
	 * 
	 * @return	URLVariables
	 * @private
	 */
	private function createURLVariables():URLVariables
	{
		var val:URLVariables = new URLVariables();
		val['api_key'] = FLICKR_APIKEY;
		val['method'] = REST_METHOD_NAME;
		val['text'] = _keyword;
		return val;
	}
	
	override protected function run():void
	{

		_loader = new URLLoaderThread(createURLRequest());
		_loader.start();
		_loader.join();
		// 完了
		next(loadComplete);
		// 割り込み
		interrupted(loadInterrupted);
	}
	
	private function loadInterrupted():void
	{
		// URLLoaderThread に割り込み
		_loader.interrupt();
		_loader = null;
	}
	
	private function loadComplete():void
	{
		// XML 取得
		var xml:XML = XML(_loader.loader.data);
		
		// REST レスポンスが正常であれば
		if ('@stat' in xml && String(xml.@stat) == 'ok') {
			_photos.length = 0;
			// 写真データを FlickrPhoto クラスに詰め込んで配列に入れる
			for each (var photoXML:XML in xml.photos.photo) {
				var photo:FlickrPhoto = new FlickrPhoto();
				photo.id = String(photoXML.@id);
				photo.secret = String(photoXML.@secret);
				photo.serverId = String(photoXML.@server);
				photo.farmId = String(photoXML.@farm);
				_photos.push(photo);
			}
		}
		else {
			// 正常でなければエラー
			throw new Error('flickr.photos.search');
		}
	}
}

/***********************************************************************************************
 * FlickrPhoto - Flickr の写真データのモデルクラス
 */
internal class FlickrPhoto
{
	private var _id:String = '';
	private var _secret:String = '';
	private var _serverId:String = '';
	private var _farmId:String = '';
	
	public function get id():String
	{
		return _id;
	}
	
	public function set id(value:String):void
	{
		_id = value;
	}
	
	public function get secret():String
	{
		return _secret;
	}
	
	public function set secret(value:String):void
	{
		_secret = value;
	}
	
	public function get serverId():String
	{
		return _serverId;
	}
	
	public function set serverId(value:String):void
	{
		_serverId = value;
	}
	
	public function get farmId():String
	{
		return _farmId;
	}
	
	public function set farmId(value:String):void
	{
		_farmId = value;
	}
	
	public function get smallSquareImageURL():String
	{
		return 'http://farm' + farmId + '.static.flickr.com/' + serverId + '/' + id + '_' + secret + '_s.jpg';
	}
}