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

你可能感兴趣的:(Flex)