MVC ってこういうこと?
解説は http://aquioux.blog48.fc2.com/blog-entry-640.html
/**
* Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/d9wo
*/
/**
* 解説は http://aquioux.blog48.fc2.com/blog-entry-640.html
*/
package {
import flash.display.Sprite;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#FFCCCC")]
public class Main extends Sprite {
public function Main() {
// Model を生成
var model:Model = new Model();
// View を生成
var view:View = new View(model);
view.x = stage.stageWidth / 2;
view.y = stage.stageHeight / 2;
addChild(view);
// Controller を生成
var controller:Controller = new Controller(model);
// ユーザ入力用の View を生成
const signs:Array = ["position", "scale", "rotation"];
var n:uint = signs.length;
for (var i:int = 0; i < n; i++) {
var inputView:Button = new Button(signs[i]);
inputView.controller = controller;
inputView.x = inputView.width * i;
inputView.y = 0;
addChild(inputView);
}
}
}
}
// Model
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;
class Model extends EventDispatcher {
// ----- View へ通知するメンバ変数 -----
public function get value1():Number { return _value1; }
private var _value1:Number;
public function get value2():Number { return _value2; }
private var _value2:Number;
public function get value3():Number { return _value3; }
private var _value3:Number;
// ----- View へ通知するためのメンバ変数 -----
// ----- View へ向けたイベント発効 (Model -> View)-----
// イベント発効
internal function notifyFromModelToListener():void {
dispatchEvent(new Event(Event.CHANGE));
}
// ----- View へ向けたイベント発効 (Model -> View)-----
// ----- Controller から呼び出される関数 (Controller -> Model)-----
internal function update1():void {
// value1 の変化と通知
_value1 += RATE;
notifyFromModelToListener();
}
internal function update2():void {
// value2 の変化と通知
_value2 += RATE;
notifyFromModelToListener();
}
internal function update3():void {
// value3 の変化と通知
_value3 += RATE;
notifyFromModelToListener();
}
// ----- Controller から呼び出される関数 (Controller -> Model)-----
private const RATE:uint = 15; // 変化量
public function Model() {
// 各データ初期化
_value1 = 0;
_value2 = 0;
_value3 = 0;
var timer:Timer = new Timer(25);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
}
private function timerHandler(e:TimerEvent):void {
_value1 += 0.5;
_value2 += 0.5;
_value3 += 0.5;
notifyFromModelToListener();
}
}
// View
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
class View extends Sprite {
// ----- Model への参照 -----
private var _model:Model;
// ----- Model からのイベントを捕捉 (Model -> View という流れ)-----
private function changeHandler(event:Event):void {
// 自分の各プロパティの値を Model のそれによって更新する
x = Math.sin(_model.value1 * Math.PI / 180) * 200 + 465 / 2;
scaleY = Math.cos(_model.value2 * Math.PI / 180);
rotation = _model.value3;
}
// ----- Model からのイベントを捕捉 (Model -> View という流れ)-----
public function View(model:Model) {
_model = model;
_model.addEventListener(Event.CHANGE, changeHandler);
draw();
}
[Embed(systemFont = "sansserif", fontName = "myFont", mimeType = "application/x-font")]
private static const myFont:Class;
private function draw():void {
graphics.beginFill(0xFFFFFF);
graphics.drawRect( -100, -100, 100, 200);
graphics.beginFill(0x000000);
graphics.drawRect(0, -100, 100, 200);
graphics.endFill();
var textFormat:TextFormat = new TextFormat("myFont", 40);
textFormat.align = TextFormatAlign.CENTER;
var textField:TextField = new TextField();
textField.defaultTextFormat = textFormat;
textField.text = "ABCDEFG\nHIJKLMN";
textField.autoSize = TextFieldAutoSize.LEFT;
textField.embedFonts = true;
textField.selectable = false;
textField.x = -textField.width / 2;
textField.y = -textField.height / 2;
textField.blendMode = BlendMode.INVERT;
addChild(textField);
}
}
// Controller
class Controller {
// ----- Model への参照 -----
private var _model:Model;
// ----- Model の関数を呼び出す (Controller -> Model という流れ)-----
internal function notifyFromControllerToModel(inputView:Button):void {
// ユーザ入力に基づいて Model へ変更を要求する
switch(inputView.sign) {
case "position": {
_model.update1();
break;
}
case "scale": {
_model.update2();
break;
}
case "rotation": {
_model.update3();
break;
}
}
}
// ----- Model の関数を呼び出す (Controller -> Model という流れ)-----
public function Controller(model:Model) {
_model = model;
}
}
// Button (入力用 View)
import flash.display.BlendMode;
import flash.display.Shape;
import flash.display.SimpleButton;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
class Button extends Sprite {
// ----- Controller への参照 -----
public function set controller(value:Controller):void { _controller = value; }
private var _controller:Controller;
// ----- Controller へ通知するためのメンバ変数 -----
public function get sign():String { return _sign; }
private var _sign:String;
// ----- Controller へ通知するためのメンバ変数 -----
// ----- Controller の関数を呼び出す (入力用 View -> Controller という流れ)-----
private function clickHandler(event:MouseEvent):void {
_controller.notifyFromControllerToModel(this);
}
// ----- Controller の関数を呼び出す (入力用 View -> Controller という流れ)-----
private const WIDTH:uint = 100;
private const HEIGHT:uint = 20;
public function Button(sign:String) {
// ボタンサインの保持
_sign = sign;
// ボタンシェイプ
var up:Shape = createButtonShape(0xCCCCCC);
var over:Shape = createButtonShape(0xFFFFFF);
var down:Shape = createButtonShape(0x000000);
var button:SimpleButton = new SimpleButton(up, over, down, up);
addChild(button);
// ラベル
var label:TextField = new TextField();
label.text = sign + " boost";
label.autoSize = TextFieldAutoSize.LEFT;
label.selectable = false;
label.x = (WIDTH - label.width) / 2;
label.y = (HEIGHT - label.height) / 2;
label.blendMode = BlendMode.INVERT;
label.mouseEnabled = false;
addChild(label);
button.addEventListener(MouseEvent.CLICK, clickHandler);
}
private function createButtonShape(color:uint):Shape {
var shape:Shape = new Shape();
shape.graphics.lineStyle(0, 0x000000);
shape.graphics.beginFill(color);
shape.graphics.drawRect(0, 0, WIDTH, HEIGHT);
shape.graphics.endFill();
return shape;
}
}