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

Mediator パターンによるプログラム構築例(1)

Mediator パターンによるプログラム構築例(1)
@author Aquioux(Yoshida, Akio)
Get Adobe Flash player
by Aquioux 16 May 2010
    Embed
/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/2Rqo
 */

package {
	import flash.display.Sprite;
	[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#FFFFFF")]
	/**
	 * Mediator パターンによるプログラム構築例(1)
	 * @author Aquioux(Yoshida, Akio)
	 */
	public class Main extends Sprite {
		public function Main():void {
			var mediator:Mediator = new Mediator();
			mediator.setup(stage);
		}
	}
}


	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Stage;
	import flash.geom.Point;
	/**
	 * Mediator
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class Mediator {
		// ---------- パブリックプロパティ ----------
		// 共用されるデータは Mediator が保持する
		//
		// BitmapData
		public function get bitmapData():BitmapData { return _bitmapData; }
		public function set bitmapData(value:BitmapData):void { _bitmapData = value; }
		private var _bitmapData:BitmapData;
		
		// スライダーの値
		public function get value():Number { return _value; }
		public function set value(value:Number):void { _value = value; }
		private var _value:Number = 0;

		// 処理状態
		public function get state():String { return _state; }
		public function set state(value:String):void { _state = value; }
		private var _state:String;
		// 処理状態の種類
		public const LOAD:String = "load";
		public const SAVE:String = "save";
		
		
		// ---------- ローカルプロパティ ----------
		//
		// 各 Colleague
		private var loadButton_:ExPushButton;
		private var saveButton_:ExPushButton;
		private var slider_:ExHSlider;
		private var fileRefUnit_:FileRefUnit;
		private var processer_:ImageProcesser;
		private var viewer_:ExBitmap;
		
		// ステージサイズ
		private var sw_:uint;
		private var sh_:uint;
		
		// スライダーのパラメータ
		private const MIN:Number = -1;
		private const MAX:Number = 1;
		private const DEF:Number = 0;
		
		// 読み込んだ BitmapData の待避
		private var saveBmd_:BitmapData;
		
		
		// ---------- パブリックメソッド ----------
		//
		/**
		 * コンストラクタ
		 */
		public function Mediator() {
		}
		/**
		 * セットアップ
		 */
		public function setup(stage:Stage):void {
			// 各 Colleague の生成
			loadButton_  = new ExPushButton(LOAD.toUpperCase(), stage);
			saveButton_  = new ExPushButton(SAVE.toUpperCase(), stage);
			slider_      = new ExHSlider(stage);
			fileRefUnit_ = new FileRefUnit();
			processer_   = new ImageProcesser();
			viewer_      = new ExBitmap();
			
			// 各 Colleague に mediator をセット
			loadButton_.mediator  = this;
			saveButton_.mediator  = this;
			slider_.mediator      = this;
			fileRefUnit_.mediator = this;
			processer_.mediator   = this;
			viewer_.mediator      = this;
			
			// 個別 Colleague のセットアップ
			// ボタン
			saveButton_.width = loadButton_.width = 50;
			saveButton_.x     = loadButton_.width;
			saveButton_.enabled = false;
			// スライダー
			slider_.width = stage.stageWidth;
			slider_.y = stage.stageHeight - slider_.height;
			slider_.enabled = false;
			// ビューア
			stage.addChild(viewer_);

			// 処理状態更新
			_state = LOAD;
			
			// ステージサイズ
			sw_ = stage.stageWidth;
			sh_ = stage.stageHeight;
		}
		/**
		 * 各 Colleague から呼び出されるメソッド
		 */
		public function notify(colleague:IColleague):void {
			// 呼び出し元が ExPushButton
			if (colleague is ExPushButton) {
				// FileRefUnit に通知
				fileRefUnit_.update();
			}
			// 呼び出し元が FileRefUnit
			if (colleague is FileRefUnit) {
				if (_state == LOAD) {
					// 読み込んだ BitmapData を待避
					saveBmd_ = _bitmapData.clone();
					// ImageProcesser に通知
					processer_.update();
					// 処理状態更新
					_state = SAVE;
					// ボタン更新
					loadButton_.enabled = false;
					saveButton_.enabled = true;
					// スライダー更新
					slider_.enabled = true;
					slider_.setParams(MIN, MAX, DEF);
				} else if (_state == SAVE) {
					// 処理状態更新
					_state = LOAD;
					// ボタン更新
					loadButton_.enabled = true;
					saveButton_.enabled = false;
					// スライダー更新
					slider_.enabled = false;
				}
			}
			// 呼び出し元が ImageProcesser
			if (colleague is ImageProcesser) {
				// ExBitmap 位置調節
				viewer_.x = (sw_ - _bitmapData.width)  / 2;
				viewer_.y = (sh_ - _bitmapData.height) / 2;
				// ExBitmap に通知
				viewer_.update();
			}
			// 呼び出し元が ExHSlider
			if (colleague is ExHSlider) {
				// 待避していた BitmapData を読込
				_bitmapData = saveBmd_.clone();
				// ImageProcesser に通知
				processer_.update();
			}
		}
	}


	/**
	 * Colleague の interface
	 * @author Aquioux
	 */
	interface IColleague {
		// Mediator の参照
		function set mediator(value:Mediator):void;
		// Mediator が呼び出すこの Colleague のメソッド
		function update():void;
	}


	import com.bit101.components.PushButton;
	import flash.display.DisplayObjectContainer;
	import flash.events.MouseEvent;
	/**
	 * Button
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class ExPushButton extends PushButton implements IColleague {
		// ---------- パブリックプロパティ ----------
		//
		// Mediator の参照
		public function set mediator(value:Mediator):void { _mediator = value; }
		private var _mediator:Mediator;
		
		
		// ---------- パブリックメソッド ----------
		//
		/**
		 * コンストラクタ
		 */
		public function ExPushButton(label:String, container:DisplayObjectContainer) {
			super(container, 0, 0, label, buttonHandler);
		}
		/**
		 * Mediator から呼び出される
		 */
		public function update():void {
		}
		
		// ---------- ローカルメソッド ----------
		//
		// ボタンクリックイベントのハンドラ
		private function buttonHandler(e:MouseEvent):void {
			_mediator.notify(this);
		}
	}


	import com.bit101.components.HSlider;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	/**
	 * Slider
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class ExHSlider extends HSlider implements IColleague {
		// ---------- パブリックプロパティ ----------
		//
		// Mediator の参照
		public function set mediator(value:Mediator):void { _mediator = value; }
		private var _mediator:Mediator;
		
		
		// ---------- ローカルプロパティ ----------
		//
		private const RENGE:uint = 10;	// スライド値の小数点有効桁数


		// ---------- パブリックメソッド ----------
		//
		/**
		 * コンストラクタ
		 */
		public function ExHSlider(container:DisplayObjectContainer) {
			super(container, 0, 0, sliderHandler);
		}
		/**
		 * パラメータのセット
		 */
		public function setParams(min:Number, max:Number, def:Number):void {
			super.setSliderParams(min * RENGE, max * RENGE, def);
		}
		/**
		 * Mediator から呼び出される
		 */
		public function update():void {
		}
		
		// ---------- ローカルメソッド ----------
		//
		// ボタンクリックイベントのハンドラ
		private function sliderHandler(e:Event):void {
			_mediator.value = e.target.value / RENGE;
			_mediator.notify(this);
		}
	}


	import com.adobe.images.PNGEncoder;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.net.FileReference;
	import flash.utils.ByteArray;
	/**
	 * FileRefUnit
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class FileRefUnit implements IColleague {
		// ---------- パブリックプロパティ ----------
		//
		// Mediator の参照
		public function set mediator(value:Mediator):void { _mediator = value; }
		private var _mediator:Mediator;

		// 表示する縦 or 横の長い方の最大値
		static public const MAX_SIZE:uint = 300;


		// ---------- ローカルプロパティ ----------
		//
		private var fileRef_:FileReference;
		private var loader_:Loader;
		

		// ---------- パブリックメソッド ----------
		//
		/**
		 * コンストラクタ
		 */
		public function FileRefUnit() {
			fileRef_ = new FileReference();
			loader_  = new Loader();
		}
		/**
		 * Mediator から呼び出される
		 */
		public function update():void {
			if (_mediator.state == _mediator.LOAD) load1Handler();
			if (_mediator.state == _mediator.SAVE) save1Handler();
		}

		
		// ---------- ローカルメソッド ----------
		//
		// 画像ロード step 1 ファイル選択
		private function load1Handler():void {
			fileRef_.addEventListener(Event.SELECT, load2Handler);
			fileRef_.browse();
		}
		// 画像ロード step 2 ファイル読込
		private function load2Handler(e:Event):void {
			fileRef_.removeEventListener(Event.SELECT, arguments.callee);
			fileRef_.addEventListener(Event.COMPLETE, load3Handler);
			fileRef_.load();
		}
		// 画像ロード step 3 ファイル読込完了
		private function load3Handler(e:Event):void {
			fileRef_.removeEventListener(Event.COMPLETE, arguments.callee);
			loader_.loadBytes(fileRef_.data);
			loader_.contentLoaderInfo.addEventListener(Event.COMPLETE, load4Handler);
		}
		// 画像ロード step 4 ファイル読込後の処理
		private function load4Handler(e:Event):void {
			loader_.contentLoaderInfo.removeEventListener(Event.COMPLETE, arguments.callee);
			getBitmapData(Bitmap(loader_.content).bitmapData);
		}
		// bitmapData の取得
		private function getBitmapData(bmd1:BitmapData):void {
			// 読み込んだ画像ファイルの BitmapData の処理
			var w:uint = bmd1.width;
			var h:uint = bmd1.height;
			var scale:Number = Math.min(MAX_SIZE / w, MAX_SIZE / h);
			if (scale > 1) scale = 1;
			
			var bmd2:BitmapData = new BitmapData(w * scale, h * scale);
			bmd2.draw(bmd1, new Matrix(scale, 0, 0, scale));
			
			_mediator.bitmapData = bmd2.clone();
			_mediator.notify(this);

			bmd1.dispose();
			bmd2.dispose();
		}
		
		
		// 画像セーブ step 1 ファイル選択
		private function save1Handler():void {
			var png:ByteArray = PNGEncoder.encode(_mediator.bitmapData);
			fileRef_.addEventListener(Event.SELECT, save2Handler);
			fileRef_.save(png, "save.png");
		}
		// 画像セーブ step 2 
		private function save2Handler(event:Event):void {
			fileRef_.removeEventListener(Event.SELECT, arguments.callee);
			_mediator.notify(this);
		}
	}


	import flash.display.BitmapData;
	/**
	 * ImageProcesser
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class ImageProcesser implements IColleague {
		// ---------- パブリックプロパティ ----------
		//
		// Mediator の参照
		public function set mediator(value:Mediator):void { _mediator = value; }
		private var _mediator:Mediator;
		

		// ---------- ローカルプロパティ ----------
		//
		private var contrast_:Contrast;


		// ---------- パブリックメソッド ----------
		//
		/**
		 * コンストラクタ
		 */
		public function ImageProcesser() {
			contrast_ = new Contrast();
		}
		/**
		 * Mediator から呼び出される
		 */
		public function update():void {
			var bmd:BitmapData = _mediator.bitmapData;
			
			contrast_.strength = _mediator.value;
			contrast_.applyEffect(bmd);
			
			_mediator.bitmapData = bmd;
			_mediator.notify(this);
		}
	}


	import flash.display.Bitmap;
	
	/**
	 * ExBitmap
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class ExBitmap extends Bitmap implements IColleague {
		// ---------- パブリックプロパティ ----------
		//
		// Mediator の参照
		public function set mediator(value:Mediator):void { _mediator = value; }
		private var _mediator:Mediator;

		
		// ---------- パブリックメソッド ----------
		//
		/**
		 * コンストラクタ
		 */
		public function ExBitmap() {
		}
		/**
		 * Mediator から呼び出される
		 */
		public function update():void {
			bitmapData = _mediator.bitmapData;
		}
	}
	import flash.geom.Point;
	/**
	 * bitmapDataEffector パッケージ内のクラスで共通に使う定数など
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class EffectorUtils {
		// ---------- パブリックプロパティ ----------
		//
		// BitmapData が備える各種メソッドの destPoint 用
		static public const ZERO_POINT:Point = new Point(0, 0);
		
		// グレイスケール用の各チャンネルの重みづけ
		static public const LUM_R:Number = 0.298912;
		static public const LUM_G:Number = 0.586611;
		static public const LUM_B:Number = 0.114478;

		
		// ---------- パブリックメソッド ----------
		//
		// 一つのチャンネルにおける濃度の平均値を求める(引数のヒストグラムで調整する)
		static public function getAverageOfBrightness1(hist:Vector.<Number>):uint {
			var sum:uint = 0;
			var numOfPixel:uint = 0;
			for (var i:int = 0; i < 256; i++) {
				sum        += i * hist[i];
				numOfPixel += hist[i];
			}
			return sum / numOfPixel >> 0;
		}
		// RGB チャンネルにおける濃度の各平均値を求める
		static public function getAverageOfBrightness3(hist:Vector.<Vector.<Number>>):Vector.<uint> {
			var rSum:uint = 0;
			var gSum:uint = 0;
			var bSum:uint = 0;
			var numOfPixel:uint = 0;
			for (var i:int = 0; i < 256; i++) {
				rSum += i * hist[0][i];
				gSum += i * hist[1][i];
				bSum += i * hist[2][i];
				numOfPixel += hist[0];
			}
			return Vector.<uint>([rSum / numOfPixel >> 0, gSum / numOfPixel >> 0, bSum / numOfPixel >> 0]);
		}
		
		// 一つのチャンネルにおける濃度の平均値を求める(引数のヒストグラムで調整する)
		static public function getSumOfBrightness1(hist:Vector.<Number>):uint {
			var sum:uint = 0;
			for (var i:int = 0; i < 256; i++) {
				sum += i * hist[i];
			}
			return sum;
		}
		// RGB チャンネルにおける濃度の各平均値を求める
		static public function getSumOfBrightness3(hist:Vector.<Vector.<Number>>):Vector.<uint> {
			var rSum:uint = 0;
			var gSum:uint = 0;
			var bSum:uint = 0;
			for (var i:int = 0; i < 256; i++) {
				rSum += i * hist[0][i];
				gSum += i * hist[1][i];
				bSum += i * hist[2][i];
			}
			return Vector.<uint>([rSum, gSum, bSum]);
		}
	}


	import flash.display.BitmapData;
	/**
	 * BitmapDataEffector 用 interface
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	interface IEffector {
		function applyEffect(value:BitmapData):BitmapData;
	}


	import flash.display.BitmapData;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.Point;
	/**
	 * コントラスト
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	class Contrast implements IEffector {
		// ---------- パブリックプロパティ ----------
		//
		/*
		 * コントラストの強さ
		 * @param	value	強さ
		 */
		public function set strength(value:Number):void {
			// value の有効範囲は -1 ~ 1
			if (value < -1) value = -1;
			if (value >  1) value =  1;
		
			value += 1;
			matrix_ = [
				value, 0,     0,     0, 128 * (1 - value),
				0,     value, 0,     0, 128 * (1 - value),
				0,     0,     value, 0, 128 * (1 - value),
				0,     0,     0,     1, 0
			];
			filter_.matrix = matrix_;
		}

		// ---------- ローカルプロパティ ----------
		//
		private var matrix_:Array = [
			1, 0, 0, 0, 0,
			0, 1, 0, 0, 0,
			0, 0, 1, 0, 0,
			0, 0, 0, 1, 0
		];
		private var filter_:ColorMatrixFilter = new ColorMatrixFilter(matrix_);

		private const ZERO_POINT:Point = EffectorUtils.ZERO_POINT;

		
		// ---------- パブリックメソッド ----------
		//
		/*
		 * コンストラクタ
		 */
		public function Contrast() {
		}
		
		/*
		 * 効果適用
		 * @param	value	効果対象 BitmapData
		 */
		public function applyEffect(value:BitmapData):BitmapData {
			value.applyFilter(value, value.rect, ZERO_POINT, filter_);
			return value;
		}
	}