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

MVCTest for AS3

AS3に慣れた感じに書き換えてみた。

Observableクラスを廃止し、便宜上Modelインターフェイスを定義してIEventDispatcherを継承した。

ClockUpdateをClockEventに置き換えEventによって変更を伝播させる。

ControllerがModelへの窓口となる以外あんまり役割がなさそうなのと、
ModelとViewの紐付けを誰がやるべきかがちょっとあいまい…。
Get Adobe Flash player
by yd_niku 15 Sep 2010
/**
 * Copyright yd_niku ( http://wonderfl.net/user/yd_niku )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wfHK
 */

// forked from yd_niku's MVCTest
/**
* http://moock.org/lectures/mvc/ 
*/
package {
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
        public function FlashTest() {
            var m:ClockModel = new ClockModel();
            var tool:ClockTool = new ClockTool(m);
            var clock:ClockView = new ClockView(m);
            
            // この紐付けはView内部でやってもよさそうな気がするけど?
            m.addEventListener(ClockEvent.UPDATE, tool.update);
            m.addEventListener(ClockEvent.UPDATE, clock.update);
            
            m.setTime(10,0,0);
            m.start();
            
            tool.y = 100;
            addChild(clock)
            addChild(tool);
        }
    }
}

////////////////////////////////////////////////////////////////
import com.bit101.components.*;
import flash.events.*;
import flash.display.*;

interface Model extends IEventDispatcher{
}

interface View{
    function get model():Model;
    function set model(m:Model):void;
    function get controller():Controller;
    function set controller(c:Controller):void;
    function defaultController(m:Model):Controller;
}

interface Controller{
    function get model():Model;
    function set model(m:Model):void;
    function get view():View;
    function set view(v:View):void;
}

class AbstructView extends Sprite implements View{
    private var _model:Model;
    private var _controller:Controller;
    
    public function AbstructView(m:Model, c:Controller=null){
        model = m;
        if(c!=null) controller = c;
    }
    
    public function get model():Model{ return _model; }
    public function set model(m:Model):void{ _model = m; }
    
    public function get controller():Controller{ 
        if(_controller==null){
            controller = defaultController(model);
        }
        return _controller;
    }
    public function set controller(c:Controller):void{
         _controller = c;
         controller.view = this;
    }
    
    public function defaultController(m:Model):Controller{
        return null;
    }
    
    //フレームワーク的にAbstructに定義しておくだけ
    public function update(info:Event):void{
        
    }
}

class AbstructCotnroller implements Controller {
    private var _model:Model;
    private var _view:View;
    
    public function AbstructCotnroller(m:Model){
        model = m;
    }
    public function get model():Model{ return _model; }
    public function set model(m:Model):void{ _model = m; }
    
    public function get view():View{ return _view; }
    public function set view(v:View):void{ _view = v; }
}

//////////////////////////////////////////////////////////
import flash.utils.setInterval;
import flash.utils.clearInterval;

// Modelが発行するEventのサブクラス
class ClockEvent extends Event {
    public static const UPDATE:String = 'ClockEvent.update';
    
    public var hour:int;
    public var minute:int;
    public var second:int;
    public var isRunning:Boolean;
    public function ClockEvent( type:String, h:int,m:int,s:int,isRunning:Boolean){
        super(type);
        hour = h;
        minute = m;
        second = s;
        this.isRunning = isRunning;
    }
    override public function clone():Event{
        return new ClockEvent(type,hour,minute,second,isRunning);
    }
}

// イベントを発行するModelの実装
class ClockModel extends EventDispatcher implements Model{
    private var _hour:int;
    private var _minute:int;
    private var _second:int;
    
    private var _tickInterval:int;
    private var _isRunning:Boolean;
    public function ClockModel(){
        super();
        var now:Date = new Date();
        setTime(now.getHours(),now.getMinutes(),now.getSeconds());
    }
    public function setTime(h:int,m:int,s:int):void{
        if( h != _hour && isValidHour(h) ) {
            _hour = h;
            //setChanged();
        }
        if( m != _minute && isValidMinute(m) ) {
            _minute = m;
            //setChanged();
        }
        if( s != _second && isValidSecond(s) ) {
            _second = s;
            //setChanged();
        }
        
        if(willTrigger(ClockEvent.UPDATE)){
            var info:ClockEvent = new ClockEvent(ClockEvent.UPDATE, _hour,_minute,_second,_isRunning);
            dispatchEvent(info);
        }
    }
    
    public function start():void{
        if( !_isRunning ) {
            _isRunning = true;
            _tickInterval = setInterval( tick, 1000);
            
            var info:ClockEvent = new ClockEvent(ClockEvent.UPDATE, _hour,_minute,_second,_isRunning);
            //setChanged();
            dispatchEvent(info);
        }
    }
    public function stop():void{
        if( _isRunning ) {
            _isRunning = false;
            clearInterval(_tickInterval);
            
            var info:ClockEvent = new ClockEvent(ClockEvent.UPDATE, _hour,_minute,_second,_isRunning);
            //setChanged();
            dispatchEvent(info);
        }
    }
    
    private function isValidHour(value:int):Boolean{
        return value >= 0 && value < 24;
    }
    private function isValidMinute(value:int):Boolean{
        return value >= 0 && value < 60;
    }
    private function isValidSecond(value:int):Boolean{
        return value >= 0 && value < 60;
    }
    
    private function tick():void{
        var h:int = _hour;
        var m:int = _minute;
        var s:int = _second;

        s += 1;
        if (s > 59) {
            s = 0;
            m += 1;
            if (m > 59) {
                m = 0;
                h += 1;
                if (h > 23) {
                    h = 0;
                }
            }
        }
        setTime(h, m, s);
    }
}

// Modelを操作し、Viewのサブクラスに操作されるControllerの実装
class ClockController extends AbstructCotnroller{
    public function ClockController(m:Model){
        super(m);
    }
    
    public function startClock():void{
        ClockModel(model).start();
    }
    public function stopClock():void{
        ClockModel(model).stop();
    }
    public function resetClock():void{
       setTime(0,0,0);
    }
    
    public function setTime (h:int, m:int, s:int):void {
        ClockModel(model).setTime(h, m, s);
    }
}

import flash.text.TextField;

// 表示のみのViewの実装
class ClockView extends AbstructView{
    public var textField:TextField;
    public function ClockView(m:Model,c:Controller=null){
        super(m,c);
        
        addChild(textField = new TextField());
    }
    override public function update(info:Event):void{
        var update:ClockEvent = info as ClockEvent;
        if( update == null ) return;
        textField.text = [ update.hour, update.minute, update.second ].join(':');
    }
}

// Controllerを操作するUIをもったViewのサブクラス
class ClockTool extends AbstructView {
    public var btnStart:PushButton;
    public var btnStop:PushButton;
    public var btnReset:PushButton;
    public function ClockTool(m:Model,c:Controller=null){
        super(m,c);
        var ctrl:ClockController = ClockController(controller);
        
        btnStart = new PushButton(this,0,0,'start',function():void{ctrl.startClock();});
        btnStop = new PushButton(this,110,0,'stop',function():void{ctrl.stopClock();});
        btnReset = new PushButton(this,220,0,'reset',function():void{ctrl.resetClock();});
    }
    
    override public function update(info:Event):void{
        var update:ClockEvent = info as ClockEvent;
        if(update.isRunning){
            btnStart.mouseEnabled = false;
            btnStop.mouseEnabled = true;
        }
        else {
            btnStart.mouseEnabled = true;
            btnStop.mouseEnabled = false;
        }
    }
    override public function defaultController(m:Model):Controller{
         return new ClockController(m);
    }
}