forked from: MVC ってこういうこと?

by kinoppy forked from MVC ってこういうこと? (diff: 1)
解説は http://aquioux.blog48.fc2.com/blog-entry-640.html
♥0 | Line 172 | Modified 2010-12-09 15:42:05 | MIT License
play

ActionScript3 source code

/**
 * Copyright kinoppy ( http://wonderfl.net/user/kinoppy )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tJJs
 */

// forked from Aquioux's MVC ってこういうこと?
/**
 * 解説は 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;
        }
    }