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

news/2024/5/19 17:35:43 标签: flex, command, object, string, cmd, delete

前言

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接口


http://www.niftyadmin.cn/n/1574755.html

相关文章

减少前端代码耦合

什么是代码耦合?代码耦合的表现是改了一点毛发而牵动了全身,或者是想要改点东西,需要在一堆代码里面找半天。由于前端需要组织js/css/html,耦合的问题可能会更加明显,下面按照耦合的情况分别说明: 1. 避免全…

Flex通信篇——构建企业级HTTP通信层

概述 RIA和SOA是一对绝配。SOA强调把业务以接口方式向外界提供不关注前端的呈现,而RIA则强调用户体现,结合两者优势能够设计出用户体现良好、灵活的、易扩展、易集成的系统。要处理好RIA前端和SOA后端,需要搭建一个健壮的企业级通信层&#…

一篇非常好的Spring教程

发现了一个Spring入门系列的教程,讲的比较细致和透彻。 Liu Lixiang的博客转载于:https://www.cnblogs.com/qinhao517/p/9123269.html

【Elasticsearch】第3篇:Elasticsearch-head插件安装

为什么要使用elasticsearch-head 访问http://127.0.0.1:9200/看的的web界面并不是很友好,此时我可以使用elasticsearch-head插件来提供友好的web界面。 安装elasticsearch-head插件 1.登录github.com搜索elasticsearch-head然后下载: wget https://githu…

45个好习惯

态度篇 1. 做实事 不要抱怨,发牢骚,指责他人,找出问题所在,想办法解决。对问题和错误,要勇于承担。 2. 欲速则不达 用小聪明、权宜之计解决问题,求快而不顾代码质量,会给项目留下要命的死…

学了那么长的Python,Python面试题长啥样?[面试题整理]

2019独角兽企业重金招聘Python工程师标准>>> 从去年开始接触Python到如今大概是一年半左右,这一年半我已经深深的陷在Python的世界里无法自拔。她是一门神奇的语言,她很神奇,她很火,她很受欢迎。早些时候,我…

产品开发实录(2)——打造时间轴

概述 时间轴在课件工具的主要作用: 便于查看、编辑页面各个元件的播放顺序(音频同步),播放时长,对页面播放效果有整体的了解。 便于查看页面各个元件的层次顺序。 便于选择页面元件,可以避免由于层次遮挡而无法选择较下层的元…

for循环、while循环、break跳出循环、continue结束本次循环、exit退出整个脚本​

for 循环范围的符号用 seq 范围 1.测试脚本:(1加到100)内容:结果:2.遍历/etc/下的目录:内容:结果:for i in seq 1 3 for i 1 2 3for循环会以空格或回车作为分隔符例如&#xff1…