as3 生态树
直接上代码:
package cn.ndl.ui { import flash.display.GradientType; import flash.display.Shape; import flash.display.SpreadMethod; import flash.display.Sprite; import flash.geom.Matrix; import flash.text.TextField; public class EcoRect extends Sprite { private var ttf:TextField; private var text:String; public function EcoRect(text:String="") { super(); this.text=text; this.init(); } private function init():void { this.addChild(this.getBgRect()); this.ttf=new TextField(); this.ttf.width=80; this.ttf.height=20; this.ttf.mouseEnabled=false; this.addChild(this.ttf); } public function setText(v:String):void { this.ttf.text=v; } public function getText():String { return this.ttf.text; } private function getBgRect():Shape { var matr:Matrix=new Matrix(); matr.createGradientBox(80, 20, 0, 0, 0); var sp:Shape=new Shape(); sp.graphics.beginGradientFill(GradientType.LINEAR, [0xaab00d, 0xffffff], [1, 1], [0, 255], matr); sp.graphics.lineStyle(1, 0x7a7e16); sp.graphics.drawRoundRect(0, 0, 80, 20, 10, 10); sp.graphics.endFill(); return sp; } public function clone():EcoRect { var r:EcoRect=new EcoRect(); r.setText(this.getText()); r.x=this.x; r.y=this.y; return r; } } }
package cn.ndl.ui { import flash.display.DisplayObject; import flash.display.SpreadMethod; import flash.display.Sprite; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.geom.Point; public class EcoNode extends Sprite { private static var shiftkey:Boolean=false; private var rec:EcoRect; public var childSpr:Sprite; private var _treeItem:EcoTreeItem; public var id:int=0; public var type:uint=0x00ff00; private var oldP:Point; private var newP:Point; private var move:Boolean=false; private var cpdata:EcoNode; public function EcoNode() { super(); this.init(); } private function init():void { rec=new EcoRect(); this.addChild(this.rec); this.childSpr=new Sprite(); this.addChild(this.childSpr); this.childSpr.x=this.rec.x + this.rec.width + 10; this.childSpr.y=0; this.rec.addEventListener(MouseEvent.CLICK, onClick); this.rec.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); this.rec.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); this.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); this.rec.buttonMode=true; } private function onMouseMove(e:MouseEvent):void { move=true; e.stopImmediatePropagation(); } private function onMouseDown(e:MouseEvent):void { move=false; shiftkey=e.shiftKey; DrageManager.getInstance().startDrag(this); e.stopImmediatePropagation(); } private function onMouseUp(e:MouseEvent):void { if (!move) return; if (e.target is EcoRect) { var data:EcoNode=DrageManager.getInstance().data as EcoNode; var item:EcoTreeItem; if (this.childSpr.numChildren == 0) { item=new EcoTreeItem(this); } else { item=EcoNode(this.childSpr.getChildAt(this.childSpr.numChildren - 1)).treeItem; } item.addItem(data.getMainRect().getText(), data.type); //副本 cpdata=item.getItem(item.getItems().length - 1); //递归添加 forAdd(data, EcoNode(this.childSpr.getChildAt(this.childSpr.numChildren - 1))); // trace(data.getMainRect().getText(), "success"); //是否按下shift if (!shiftkey) { data.parent.removeChild(data); data.treeItem.updatePs(); } shiftkey=false; } move=false; } private function forAdd(e:EcoNode, target:EcoNode):void { // trace("--------------------------"); if (e == cpdata) return; if (e.childSpr.numChildren > 0) { var item:EcoTreeItem=new EcoTreeItem(target); var node:EcoNode; var i:int=0; // trace("1111111111111"); for (; i < e.childSpr.numChildren; i++) { if (i == 0) { item=new EcoTreeItem(target); } else { item=EcoNode(target.childSpr.getChildAt(target.childSpr.numChildren - 1)).treeItem; } node=e.childSpr.getChildAt(i) as EcoNode; item.addItem(node.getMainRect().getText(), node.type); //trace(node.getMainRect().getText(), "==="); forAdd(node, item.getItem(item.getItems().length - 1)); } } } private function onClick(e:MouseEvent):void { if (this.childSpr.numChildren > 0) { if (this.childSpr.parent != null) { this.removeChild(this.childSpr); } else { this.addChild(this.childSpr); } this.updateRectPosition(); if (EcoNode(this.childSpr.getChildAt(0))._treeItem != null) EcoNode(this.childSpr.getChildAt(0))._treeItem.updatePs(); } } public function getHeight():Number { if (this.childSpr.parent == null) return this.rec.height; return this.height; } public function set treeItem(v:EcoTreeItem):void { this._treeItem=v; } public function get treeItem():EcoTreeItem { return this._treeItem; } public function setText(v:String):void { this.rec.setText(v); } public function getMainRect():EcoRect { return this.rec; } public function mainRectPos(p:Number):void { this.rec.y=p; this.updateRectPosition(); } public function updateRectPosition():void { var sp:Number=this.rec.height / 2; var sx:Number=this.rec.x + this.rec.width; var sy:Number=this.rec.y + sp; var dio:EcoRect; var node:EcoNode; var tP:Point; this.graphics.clear(); if (this.childSpr.stage != null) { for (var i:int=0; i < this.childSpr.numChildren; i++) { node=EcoNode(this.childSpr.getChildAt(i)); dio=node.getMainRect(); tP=this.globalToLocal(this.childSpr.getChildAt(i).localToGlobal(new Point(dio.x, dio.y + sp))); this.graphics.lineStyle(0, EcoEnum["ECOLINE_TYPE" + node.type]); this.graphics.moveTo(sx, sy); this.graphics.cubicCurveTo(sx + 20, sy, tP.x - 30, tP.y, tP.x, tP.y); } } } public function clone():EcoNode { var node:EcoNode=new EcoNode(); node.rec=this.rec; node._treeItem=this._treeItem; node.childSpr=this.childSpr; node.id=this.id; return node; } } }
package cn.ndl.ui { import flash.display.Sprite; public class EcoTreeItem extends Sprite { private var space:Number=30; private var items:Vector.<EcoNode>; private var parentItem:EcoNode; private var id:int=0; public function EcoTreeItem(parent:EcoNode) { super(); this.init(); this.parentItem=parent; } private function init():void { this.items=new Vector.<EcoNode>(); } /** * * @param str * @param type 颜色 * @return * */ public function addItem(str:String, type:int=0):EcoNode { if (str == null) return null; var item:EcoNode=new EcoNode(); this.parentItem.childSpr.addChild(item); item.setText(str); item.treeItem=this; item.type=type; item.x=space; item.y=this.items.length * (item.height + 10); item.id=this.items.length; this.items.push(item); updatePs(); return item; } /** * * @param str * @param i index * */ public function addItemAt(str:String, i:int=-1):void { if (str == null) return; var item:EcoNode=new EcoNode(); this.parentItem.childSpr.addChild(item); item.setText(str); item.treeItem=this; item.x=space; item.y=this.items.length * (item.height + 10); item.id=i + 1; this.items.splice(i, 0, item); updatePs(); } /** * 更新位置 * */ public function updatePs():void { this.parentItem.mainRectPos((this.parentItem.getHeight() - this.parentItem.getMainRect().height) / 2); if (this.parentItem.treeItem == null) return; var hh:Number=0; var rec:EcoNode; var pit:Vector.<EcoNode>=this.parentItem.treeItem.getItems(); for each (rec in pit) { rec.y=hh; rec.updateRectPosition(); hh+=rec.getHeight() + 15; } this.parentItem.treeItem.updatePs(); } public function getItem(i:int):EcoNode { return this.items[i]; } public function getItems():Vector.<EcoNode> { return this.items; } } }
package cn.ndl.ui { import flash.display.Sprite; import flash.events.Event; import flash.filesystem.File; import flash.filesystem.FileMode; import flash.filesystem.FileStream; import flash.net.URLLoader; import flash.net.URLRequest; import flash.utils.Dictionary; public class EcoTree extends Sprite { public var items:Dictionary; public var nodes:Dictionary; private var tree:EcoTreeItem; private var node:EcoNode; private var txtXML:String; private var forindex:int=0; public function EcoTree() { super(); this.init(); } private function init():void { node=new EcoNode(); this.addChild(node); this.items=new Dictionary(); this.nodes=new Dictionary(); this.addEventListener(Event.ADDED_TO_STAGE, onAddstage); } private function onAddstage(e:Event):void { DrageManager.getInstance().setup(this.stage); } public function setText(v:String):void { node.setText(v); } public function getEcoRect():EcoNode { return this.node; } public function add(id:int, pid:int, str:String):void { var _node:EcoNode; if (pid == -1) { _node=this.node; } else { _node=this.nodes[pid]; } var item:EcoTreeItem; if (pid == -1) { item=new EcoTreeItem(_node); this.items[id]=item; } else if ((this.items[id] == null && this.items[pid] == null)) { item=new EcoTreeItem(_node); this.items[id]=item; } else if (this.items[pid] != null) { item=this.items[pid]; } if (pid == -1) this.nodes[pid]=item.addItem(str); else this.nodes[id]=item.addItem(str); } /** * 导出xml */ public function exportXML(path:String):void { txtXML="<Root>"; txtXML+="<Node id='" + forindex + "' name='" + this.node.getMainRect().getText() + "' type='2' owner='0' fun='0' parameters='' des='描述信息'>"; forAdd(this.node); txtXML+="</Node>"; txtXML+="</Root>"; var xml:XML=XML(txtXML); trace(xml.toString()) var fs:FileStream=new FileStream(); fs.openAsync(new File(path), FileMode.WRITE); fs.writeUTFBytes("<?xml version='1.0'?>\n" + xml.toString()); fs.close(); } private function forAdd(n:EcoNode):void { if (n.childSpr.numChildren > 0) { var nd:EcoNode; for (var i:int=0; i < n.childSpr.numChildren; i++) { nd=EcoNode(n.childSpr.getChildAt(i)); txtXML+="<Node id='" + forindex + "' name='" + nd.getMainRect().getText() + "' type='" + nd.type + "' owner='0' fun='0' parameters='' des='描述信息'>"; forindex++; forAdd(nd); txtXML+="</Node>"; } } } public function importXML(filepath:String):void { var urlLoader:URLLoader=new URLLoader(new URLRequest(filepath)); urlLoader.addEventListener(Event.COMPLETE, onComplete); } private function onComplete(e:Event):void { var xml:XML=XML(e.target.data); // trace(xml,xml.Node, "----"); while (this.node.childSpr.numChildren) this.node.childSpr.removeChildAt(0); xml=XML(xml.Node); this.node.setText(xml.@name); parseXML(xml.Node as XMLList, this.node); } private function parseXML(xmllist:XMLList, target:EcoNode):void { var item:EcoTreeItem=new EcoTreeItem(target); var xml:XML; for each (xml in xmllist) { item.addItem(xml.@name, xml.@type); parseXML(xml.Node as XMLList, item.getItem(item.getItems().length - 1)); } } } }
package cn.ndl.ui { import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.Sprite; import flash.display.Stage; import flash.events.MouseEvent; import flash.geom.Point; import flash.utils.ByteArray; public class DrageManager { private static var _instance:DrageManager; public var data:*; private var _data:Sprite; private var _stg:Stage; public function DrageManager() { } public static function getInstance():DrageManager { if (_instance == null) _instance=new DrageManager(); return _instance; } public function setup(stg:Stage):void { _stg=stg; _data=new Sprite(); _data.mouseChildren=false; _data.mouseEnabled=false; _stg.addChild(_data); _stg.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); } public function startDrag(d:*):void { var p:Point=_stg.globalToLocal(d.parent.localToGlobal(new Point(d.x, d.y))); data=null; data=d; _data.addChild(data.clone().getMainRect().clone()); _data.x=p.x; _data.y=p.y; _data.startDrag(); } private function onMouseUp(e:MouseEvent):void { _data.stopDrag(); if (_data.numChildren > 0) _data.removeChildAt(0); data=null; } private function copyObj(d:*):* { var by:ByteArray=new ByteArray(); by.writeObject(d); by.position=0; return by.readObject(); } } }
package cn.ndl.ui { public class EcoEnum { public static const ECOLINE_TYPE1:uint=0xffff00; public static const ECOLINE_TYPE2:uint=0xff0000; public static const ECOLINE_TYPE3:uint=0x000000; public static const ECOLINE_TYPE4:uint=0x00ff00; public static const ECOLINE_TYPE5:uint=0x00ffff; public static const ECOLINE_TYPE6:uint=0x0000ff; public static const ECOLINE_TYPE7:uint=0xffff00; public static const ECOLINE_TYPE8:uint=0x0f0f0f; public static const ECOLINE_TYPE9:uint=0xf0f0f0; public static const ECOLINE_TYPE10:uint=0xf0f000; public function EcoEnum() { } } }
测试代码:
<?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="windowedapplication1_creationCompleteHandler(event)"> <fx:Script> <![CDATA[ import cn.ndl.ui.EcoTree; import mx.core.UIComponent; import mx.events.FlexEvent; private var tree:cn.ndl.ui.EcoTree protected function button1_clickHandler(event:MouseEvent):void { // TODO Auto-generated method stub var f:File=new File(); f.addEventListener(Event.SELECT, onSaveSelect); f.browseForSave("select a file"); } private function onSaveSelect(e:Event):void { var f:File=File(e.target); // trace(f.nativePath); var path:String=f.nativePath.replace(/\\+/g, "/"); // trace(path); tree.exportXML(path+".xml"); } protected function button2_clickHandler(event:MouseEvent):void { // TODO Auto-generated method stub var f:File=new File(); f.addEventListener(Event.SELECT, onOpenSelect); f.browseForOpen("select a file",[new FileFilter("xml","*.xml")]); } private function onOpenSelect(e:Event):void { var f:File=File(e.target); // trace(f.nativePath); var path:String=f.nativePath.replace(/\\+/g, "/"); // trace(path); tree.importXML(path); } protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void { // TODO Auto-generated method stub tree=new cn.ndl.ui.EcoTree(); tree.y=50; var ui:UIComponent=new UIComponent(); ui.addChild(tree); this.addElement(ui); } ]]> </fx:Script> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <s:Button x="220" y="10" label="导出" click="button1_clickHandler(event)"/> <s:Button x="320" y="10" label="导入" click="button2_clickHandler(event)"/> </s:WindowedApplication>
运行结果: