Flex——命令管理,Undo来Redo去

前言

Undo,Redo是编辑环境里常见的并且非常重要的功能,下面介绍【命令模式】在Flex/AS3下的实现。

ICommand接口

定义ICommand接口,其中Execute和UnExecute是相反的2个操作,Title属性用于命令显示,例如显示在操作历史列表里。

package cwn.wb.ui.core.command

{

    import cwn.core.IDispose;

    public interface ICommand extends IDispose

    {

        function get Title():String

        function Execute():void

        function UnExecute():void

    }

}

CommandBase基类

CommandBase类主要实现ICommand接口,所有Command类都将继承CommandBase类。

package cwn.wb.ui.core.command

{

    import cwn.core.IDispose;

    public class CommandBase implements ICommand

    {

        public function CommandBase()

        {

        }

        //===================ICommand========================

        protected var _Title:String;

        public function get Title():String

        {

            return _Title;

        }

        public function Execute():void

        {

            throw new Error("Not implementation.");

        }

        public function UnExecute():void

        {

            throw new Error("Not implementation.");

        }

        //========================IDispose==========================

        private var _Disposed:Boolean = false;

        protected function Disposing():void

        {

        }

        public function Dispose():void

        {

            if (_Disposed)

                return;

            Disposing();

            _Disposed = true;

        }

    }

}

AddCommand类

AddCommand用于处理向界面容器添加子元件的操作,定义如下:

package cwn.wb.ui.core.command

{

    import mx.core.UIComponent;

 

    public class AddCommand extends CommandBase

    {

        private var _Parent:UIComponent;

        private var _Target:UIComponent;

        private var _Index:int;

        public function AddCommand(parent:UIComponent, target:UIComponent)

        {

            _Parent = parent;

            _Target = target;

            _Index = _Parent.numChildren;

            if (_Parent.contains(_Target))

                _Index = _Parent.getChildIndex(_Target);

            _Title = "添加" + _Target.name;

        }

        override public function Execute():void

        {

            if(_Parent.contains(_Target))

                return;

            _Parent.addChildAt(_Target, Math.min(_Parent.numChildren, _Index));    

        }

        override public function UnExecute():void

        {

            if(!_Parent.contains(_Target))

                return;

            _Parent.removeChild(_Target);    

        }

        override protected function Disposing():void

        {

            _Parent = null;

            _Target = null;

            super.Disposing();

        }

    }

}

DeleteCommand类

DeleteCommand用于处理向界面容器删除子元件的操作,效果与AddCommand相反,定义如下:

package cwn.wb.ui.core.command

{

    import mx.core.UIComponent;

 

    public class DeleteCommand extends CommandBase

    {

        private var _Parent:UIComponent;

        private var _Target:UIComponent;

        private var _Index:int;

        public function DeleteCommand(parent:UIComponent, target:UIComponent)

        {

            _Parent = parent;

            _Target = target;

            _Index = _Parent.numChildren;

            if (_Parent.contains(_Target))

                _Index = _Parent.getChildIndex(_Target);

            _Title = "删除" + _Target.name;

        }

        override public function Execute():void

        {

            if (!_Parent.contains(_Target))

                return;

            _Parent.removeChild(_Target);

        }

        override public function UnExecute():void

        {

            if (_Parent.contains(_Target))

                return;

            _Parent.addChildAt(_Target, Math.min(_Parent.numChildren, _Index));

        }

        override protected function Disposing():void

        {

            _Parent = null;

            _Target = null;

            super.Disposing();

        }

    }

}

EditCommand类

EditCommand用于处理元件的属性编辑操作,定义如下:

package cwn.wb.ui.core.command

{

    import mx.core.UIComponent;

 

    public class EditCommand extends CommandBase

    {

        private var _Property:String;

        private var _Target:Object;

        private var _OldValue:Object;

        private var _NewValue:Object;

        public function EditCommand(property:String, target:Object, oldValue:Object, newValue:Object)

        {

            _Property = property;

            _Target = target;

            _OldValue = oldValue;

            _NewValue = newValue;

            _Title = "编辑" + _Property;

        }

        override public function Execute():void

        {

            _Target[_Property] = _NewValue;

        }

        override public function UnExecute():void

        {

            _Target[_Property] = _OldValue;

        }

        override protected function Disposing():void

        {

            _Target = null;

            _OldValue = null;

            _NewValue = null;

            super.Disposing();

        }

    }

}

例子:编辑宽度

var edit:EditCommand = new EditCommand("width", target, target.width, 500);

CommandManager类

添加,删除,编辑3个主要命令已经定义完成,现在要定义一个命令管理的类对命令进行管理,集中调用,其中Undo,Redo操作都在该类实现。

package cwn.wb.ui.core.command

{

    import cwn.core.DisposeUtil;

    import flash.events.EventDispatcher;

    import mx.collections.ArrayCollection;

    import mx.core.UIComponent;

    public class CommandManager extends EventDispatcher

    {

        private static var g_Created:Boolean = false;

        public static var Instance:CommandManager = new CommandManager();

        public function CommandManager()

        {

            super();

            if (g_Created)

                throw new Error("Singleton class. Please use Instance static filed.");

            g_Created = true;

        }

        //======================命令管理:UndoRedo=============================

        private var _UndoList:ArrayCollection = new ArrayCollection();

        private var _RedoList:ArrayCollection = new ArrayCollection();

        public function get CanRedo():Boolean

        {

            return _RedoList.length > 0;

        }

        public function get CanUndo():Boolean

        {

            return _UndoList.length > 0;

        }

        public function Redo():void

        {

            if (!CanRedo)

                return;

            var command:ICommand = _RedoList.removeItemAt(_RedoList.length - 1) as ICommand;

            command.Execute();

            _UndoList.addItem(command);

        }

        public function Undo():void

        {

            if (!CanUndo)

                return;

            var command:ICommand = _UndoList.removeItemAt(_UndoList.length - 1) as ICommand;

            command.UnExecute();

            _RedoList.addItem(command);

        }

//======================命令调用=============================

        private function ExecuteCommand(command:ICommand):void

        {

            command.Execute();

            AppendCommand(command);

        }

        private function AppendCommand(command:ICommand):void

        {

            //有新命令添加时清空RedoList

            DisposeUtil.Dispose(_RedoList);

            _UndoList.addItem(command);

        }

        //======================添加、删除、编辑命令=============================

        public function Add(parent:UIComponent, target:UIComponent):void

        {

            var command:ICommand = new AddCommand(parent, target);

            ExecuteCommand(command);

        }

        public function Delete(parent:UIComponent, target:UIComponent):void

        {

            var command:ICommand = new DeleteCommand(parent, target);

            ExecuteCommand(command);

        }

        public function Edit(property:String, target:Object, oldValue:Object, newValue:Object):void

        {

            var command:ICommand = new EditCommand(property, target, oldValue, newValue);

            ExecuteCommand(command);

        }

    }

}

进阶

一个命令管理的框架基本完成了,根据实际使用,再进行扩展。

复合命令

有时,一个操作就调用了多个命令,例如,同时删除多个元件,同时移动多个元件。这需要多个命令进行复合,可以定义一个MultiCommand命令来完成多个命令同时调用。

package cwn.wb.ui.core.command

{

    import cwn.core.DisposeUtil;

    import mx.collections.ArrayCollection;

 

    public class MultiCommand extends CommandBase

    {

        private var _Commands:ArrayCollection;

        public function MultiCommand(commands:ArrayCollection)

        {

            _Commands = commands;

            if (_Commands.length > 0)

                _Title = ICommand(_Commands[0]).Title + "...";

        }

        override public function Execute():void

        {

            for each (var cmd:ICommand in _Commands)

            {

                cmd.Execute();

            }

        }

        override public function UnExecute():void

        {

            for each (var cmd:ICommand in _Commands)

            {

                cmd.UnExecute();

            }

        }

        override protected function Disposing():void

        {

            cwn.core.DisposeUtil.Dispose(_Commands);

            super.Disposing();

        }

    }

}

事件通知

CommandManager是继承事件派发类EventDispatcher的,当有新的命令执行时还应该派发相应的事件,通知界面等进行刷新,数据同步。

相关资料

IDispose接口

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值