模型
主画布组件:com/components/graph/GraphContainer.mxml
<?xml version="1.0" encoding="utf-8"?> <s:Group 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="init(event)" width="100%" height="100%"> <fx:Script> <![CDATA[ import com.components.model.ShapeModel; import com.roguedevelopment.objecthandles.Flex4ChildManager; import com.roguedevelopment.objecthandles.Flex4HandleFactory; import com.roguedevelopment.objecthandles.HandleClickedEvent; import com.roguedevelopment.objecthandles.ObjectChangedEvent; import com.roguedevelopment.objecthandles.ObjectHandles; import com.roguedevelopment.objecthandles.SelectionEvent; import com.components.shape.BaseShape; import com.components.shape.IShape; import com.components.shape.ShapeLoad; import com.components.shape.SimpleRect; import mx.controls.Alert; import mx.controls.Button; import mx.core.UIComponent; import mx.events.DragEvent; import mx.events.FlexEvent; import mx.managers.DragManager; [Bindable] public var objecthandles:ObjectHandles = null; override protected function initializationComplete() : void { objecthandles = new ObjectHandles( mainGroup , null, new Flex4HandleFactory() , new Flex4ChildManager() ); super.initializationComplete(); } private function init(event:FlexEvent):void { this.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void{ if(event.target is IShape) { if(objecthandles.selectionManager.currentlySelected.length > 1){ objecthandles.selectionManager.clearSelection(); } }else{ objecthandles.selectionManager.clearSelection(); } event.stopPropagation(); }); } protected function mainGroup_dragDropHandler(event:DragEvent):void { // TODO Auto-generated method stub } public function addShapeUI(shape:ShapeModel):void { var ishape:IShape = ShapeLoad.getShape(shape.shapeType); ishape.graph = this; ishape.model = shape; shape.ishape = ishape; if (shape.owner) { var container:IShape = shape.owner.ishape if (container) { // Alert.show(container.model.label);//alert Test var oh:ObjectHandles = new ObjectHandles(container as Sprite, objecthandles.selectionManager, new Flex4HandleFactory(), new Flex4ChildManager()); oh.registerComponent(shape, ishape, []); container.addShape(ishape); } else { Alert.show("null"); } } else { mainGroup.addElement(ishape); objecthandles.registerComponent(shape, ishape); //shapeModel Bindable #1069 } if (shape.children && shape.children.length > 0) { for (var i:int=0;i<shape.children.length;i++) { var child:ShapeModel = shape.children[i]; addShapeUI(child); } } ishape.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void { // ishape.objectHandles.selectionManager.setSelected(shape); event.stopPropagation(); //important }); ishape.addEventListener(MouseEvent.MOUSE_DOWN, function(event:MouseEvent):void{ // ishape.objectHandles.selectionManager.setSelected(shape); event.stopPropagation(); //important }); } public function removeShapeUI(shape:ShapeModel):void { if (shape.owner) { var container:IShape = shape.owner.ishape container.removeChildByModel(shape); } else { for (var i:int=0;i<mainGroup.numElements;i++) { var ishape:IShape = mainGroup.getElementAt(i) as IShape; if (ishape.model == shape) { objecthandles.unregisterComponent(ishape); mainGroup.removeElement(ishape); } } } } ]]> </fx:Script> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <s:Scroller width="100%" height="100%" > <s:Group width="100%" height="100%" id="mainGroup"> </s:Group> </s:Scroller> </s:Group>
GraphModel.as: com/components/model/
package com.components.model { public class GraphModel { public function GraphModel() { } } }
ShapeModel.as: 图形模型类,用于设置图形宽、高、坐标等参数
package com.components.model { import com.roguedevelopment.objecthandles.IMoveable; import com.roguedevelopment.objecthandles.IResizeable; import com.components.shape.IShape; import flash.events.EventDispatcher; import flash.events.MouseEvent; import mx.messaging.AbstractConsumer; public class ShapeModel extends EventDispatcher implements IResizeable, IMoveable { [Bindable] private var _Number = 0; [Bindable] private var _height:Number = 0; [Bindable] private var _x:Number = 0; [Bindable] private var _y:Number = 0; [Bindable] private var _rotation:Number = 0; [Bindable] private var _label:String = ''; [Bindable] private var _isLocked:Boolean = false; [Bindable] private var _color:uint = 0xffffff; [Bindable] private var _image:String; [Bindable] private var _ishape:IShape; [Bindable] private var _owner:ShapeModel = null; [Bindable] private var _children:Array; [Bindable] private var _shapeType:int = 0; public function ShapeModel() { } public function set width(value:Number):void { this._width = value; } [Bindable] public function get width():Number { return this._width; } public function set height(value:Number):void { this._height = value; } [Bindable] public function get height():Number { return this._height; } public function set x(value:Number):void { this._x = value; } [Bindable] public function get x():Number { return this._x; } public function set y(value:Number):void { this._y = value; } [Bindable] public function get y():Number { return this._y; } public function set rotation(value:Number):void { this._rotation = value; } [Bindable] public function get rotation():Number { return this._rotation; } public function set label(value:String):void { this._label = value; } [Bindable] public function get label():String { return this._label; } public function set isLocked(value:Boolean):void { this._isLocked = value; } [Bindable] public function get isLocked():Boolean { return this._isLocked; } //-------------------- [Bindable] public function get ishape():IShape { return this._ishape; } public function set ishape(value:IShape):void { this._ishape = value; } public function set children(childs:Array):void { this._children = childs; if (childs && childs.length > 0) { var c:* = childs[0]; //检测是不是ShapeModel类型 if (c is ShapeModel){ for each(var itm:ShapeModel in childs) { itm.owner = this; } } } } [Bindable] public function get children():Array { return this._children; } public function set owner(value:ShapeModel):void { this._owner = value; } [Bindable] public function get owner():ShapeModel { return this._owner; } // public function set color(value:uint):void { this._color = value; } [Bindable] public function get color():uint { return this._color; } public function set image(value:String):void { this._image = value; } [Bindable] public function get image():String { return this._image; } public function set shapeType(value:int):void { this._shapeType = value; } [Bindable] public function get shapeType():int { return this._shapeType; } public function setSelected(flag:Boolean):void { if (this._ishape) { if (flag) { this._ishape.objectHandles.selectionManager.setSelected(this); } else { this._ishape.objectHandles.selectionManager.removeFromSelected(this); } } } } }
图形基组件: com/components/shape/BaseShape.mxml
<?xml version="1.0" encoding="utf-8"?> <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" implements="com.components.shape.IShape" creationComplete="init(event)" width="{_model.width}" height="{_model.height}" x="{_model.x}" y="{_model.y}" rotation="{_model.rotation}" > <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> <s:SolidColor id="backColor" color="0xdcdcdc" alpha="1" /> <s:SolidColorStroke id="borderStroke" color="0x000000" weight="1" alpha="1" /> </fx:Declarations> <fx:Script> <![CDATA[ import com.components.graph.GraphContainer; import com.components.model.ShapeModel; import com.events.ShapeEvent; import com.roguedevelopment.objecthandles.Flex4ChildManager; import com.roguedevelopment.objecthandles.Flex4HandleFactory; import com.roguedevelopment.objecthandles.ObjectHandles; import com.utils.ShapeUtils; import mx.controls.Alert; import mx.events.FlexEvent; [Bindable]private var _objectHandles:ObjectHandles ; [Bindable]private var _graph:GraphContainer; [Bindable]private var _model:ShapeModel; [Bindable]private var _showLabel:Boolean; [Bindable]private var _selected:Boolean; private var _state:int = 0; private var _rx:Number = 0; private var _ry:Number = 0; private function init(event:FlexEvent):void { var that:IShape = this; this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandle); this.addEventListener(MouseEvent.MOUSE_OUT, mousOutHandle); this.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandle); //this.addEventListener(MouseEvent.MOUSE_WHEEL, mouWheelHandle); //从没出现 this.addEventListener(MouseEvent.ROLL_OUT, mouRolOutHandle); this.addEventListener(MouseEvent.ROLL_OVER, mouRolOverHandle); //this.addEventListener(MouseEvent.RELEASE_OUTSIDE, mouseOutsideHandle);//从没出现 } private function mouseDownHandle(event:MouseEvent):void { _rx = this.mouseX; _ry = this.mouseY; this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandle); this.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandle); } // private function mousOutHandle(event:MouseEvent):void { var cm:ShapeModel = this.model; if (cm) { if (cm.x < 0) { cm.x = 0; } if (cm.y < 0) { cm.y = 0 } } this.model.label = "MouseOut"; } private function mouseOutsideHandle(event:MouseEvent):void { this.model.label = "Outside"; } private function mouseOverHandle(event:MouseEvent):void { this.model.label = "MouseOver"; ResizeContainer(this); } private function mouWheelHandle(event:MouseEvent):void { this.model.label = "MouseWheel"; } private function mouRolOutHandle(event:MouseEvent):void { var cm:ShapeModel = this.model; if (cm) { if (cm.x < 0) { cm.x = 0; } if (cm.y < 0) { cm.y = 0 } } this.model.label = "RollOut"; ResizeContainer(this); } private function mouRolOverHandle(event:MouseEvent):void { this.model.label = "MouseRollOver"; } private function mouseMoveHandle(event:MouseEvent):void { if (_state != 6) { _state = 6; } this.model.label = "MouseMove"; ResizeContainer(this, event); } private function mouseUpHandle(event:MouseEvent):void { if (_state != 7) { _state = 7; } this.model.label = "UP"; this.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandle); this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseMoveHandle); // this.removeEventListener(MouseEvent.MOUSE_OUT, mousOutHandle); // this.removeEventListener(MouseEvent.ROLL_OUT, mouRolOutHandle); // this.removeEventListener(MouseEvent.MOUSE_OVER, mouseOverHandle); var cm:ShapeModel = this.model; if (!cm || !cm.owner) return; /* var xy:Object = ShapeUtils.getRealShapePosition(cm); var _pw:Number = cm.owner.width; var _ph:Number = cm.owner.height; var _px:Number = cm.owner.x; var _py:Number = cm.owner.y; if (cm.x<0) { cm.owner.x = Number(xy.x); cm.owner.width = _pw + (_px - Number(xy.x)); cm.x = 0; } if (cm.y <0) { cm.owner.y = Number(xy.y); cm.owner.height = _ph + (_py - Number(xy.y)); cm.y = 0; }*/ } private function ResizeContainer(shapeui:IShape, event:MouseEvent = null):void { var cm:ShapeModel = shapeui.model; if (cm && cm.owner) { var _x:Number = cm.x; var _y:Number = cm.y; var _w:Number = cm.width; var _h:Number = cm.height; var _pw:Number = cm.owner.width; var _ph:Number = cm.owner.height; var _px:Number = cm.owner.x; var _py:Number = cm.owner.y; var xy:Object = ShapeUtils.getRealShapePosition(cm); this.model.label = "Rs"; /* //Resize Right, Down if ((_x+_w) > _pw) { cm.owner.width = _x + _w; } if ((_y + _h) > _ph) { cm.owner.height = _y + _h; } //Resize Left , UP if (_x < 0) { cm.owner.x = _px + (_x); cm.owner.width = _pw + (-_x); } if (_y < 0) { cm.owner.y = _py + (_y); cm.owner.height = _ph + (-_y); } */ } else { this.model.label = "Where"; } } public function get objectHandles():ObjectHandles { if (!this._objectHandles) { this._objectHandles = new ObjectHandles(this, null, new Flex4HandleFactory(), new Flex4ChildManager()); } return this._objectHandles; } public function set graph(value:GraphContainer):void { this._graph = value; if (this._graph) { this._objectHandles = this._graph.objecthandles; } } public function get graph():GraphContainer { return this._graph; } public function set model(value:ShapeModel):void { this._model = value; } [Bindable] public function get model():ShapeModel { return this._model; } public function set selected(value:Boolean):void { this._selected = value; } public function get selected():Boolean { return this._selected; } public function addShape(shapeui:IShape):void { ResizeContainer(shapeui); } public function removeChildByModel(shape:ShapeModel):void { } public function set showLabel(value:Boolean):void { this._showLabel = value; } public function get showLabel():Boolean { return this._showLabel; } ]]> </fx:Script> </s:Group>
Shape图形接口: IShape.as
package com.components.shape { import com.components.graph.GraphContainer; import com.components.model.ShapeModel; import com.roguedevelopment.objecthandles.ObjectHandles; import mx.core.IUIComponent; import mx.core.IVisualElement; import mx.core.IVisualElementContainer; public interface IShape extends IUIComponent, IVisualElement, IVisualElementContainer { function set graph(value:GraphContainer):void; function get graph():GraphContainer; function set model(value:ShapeModel):void; function get model():ShapeModel; function addShape(shapeui:IShape):void; function removeChildByModel(shape:ShapeModel):void; function set showLabel(value:Boolean):void; function get showLabel():Boolean; function get objectHandles():ObjectHandles; // function set selected(value:Boolean):void; function get selected():Boolean; } }
图形ShapeModel与具体图形如SimpleRect.mxml[IShape]转换: ShapeLoad.as
package com.components.shape { public class ShapeLoad { public function ShapeLoad() { } public static function getShape(stype:int):IShape { var shape:BaseShape; switch (stype) { case 0: shape = new SimpleRect(); break; case 1: shape = new SimpleEllipse(); break; default: break; } return shape; } } }
一个矩形图组件: com/components/shape/SimpleRect.mxml
<?xml version="1.0" encoding="utf-8"?> <shape:BaseShape xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:shape="com.components.shape.*" width="{model.width}" height="{model.height}" x="{model.x}" y="{model.y}" rotation="{model.rotation}" > <fx:Script> <![CDATA[ import com.components.model.ShapeModel; import mx.controls.Alert; import mx.core.IVisualElement; import mx.core.UIComponent; import mx.events.FlexEvent; override public function addShape(shapeui:IShape):void { container.addElement(shapeui); super.addShape(shapeui); } override public function removeChildByModel(shape:ShapeModel):void { for (var i:int = 0; i<container.numElements;i++) { var ishape:IShape = container.getElementAt(i) as IShape; if (ishape && ishape.model == shape) { objectHandles.unregisterComponent(ishape); container.removeElement(ishape); } } } override public function set showLabel(value:Boolean):void { super.showLabel = value; } [Bindable] override public function get showLabel():Boolean { return true; } protected function scrollDown_clickHandler(event:MouseEvent):void { // TODO Auto-generated method stub var itm:Object = event.target as DisplayObject; var tyName:String = itm.name; if (tyName && tyName.indexOf('Button') >= 0) { event.stopPropagation(); objectHandles.selectionManager.clearSelection(); } } protected function scrollUp_clickHandler(event:MouseEvent):void { } ]]> </fx:Script> <s:Rect width="100%" height="100%" stroke="{borderStroke}" fill="{backColor}" /> <s:Scroller width="100%" height="100%" mouseDown="scrollDown_clickHandler(event)" mouseUp="scrollUp_clickHandler(event)"> <s:Group id="container" width="100%" height="100%" horizontalCenter="0" verticalCenter="0" /> </s:Scroller> <s:Label text="{model.label}" horizontalCenter="0" verticalCenter="0" color="#000000" /> </shape:BaseShape>
使用方法Application: Flex4objectHandles.mxml
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%" xmlns:graph="com.components.graph.*" creationComplete="init(event)" > <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <fx:Script> <![CDATA[ import com.components.model.ShapeModel; import mx.controls.Alert; import mx.events.FlexEvent; private function init(event:FlexEvent):void { var shape:ShapeModel = new ShapeModel(); shape.shapeType = 1; shape.width = 400; shape.height = 300; shape.x = 15; shape.y = 30; shape.label = "Test"; shape.rotation = 0; var childs:Array = []; var child:ShapeModel = new ShapeModel(); child.shapeType = 0; child.width = 100; child.height = 100; child.x = 60; child.y = 90; child.label = "child1"; child.rotation = 0; childs.push(child); var _child:ShapeModel = new ShapeModel(); _child.shapeType = 0; _child.width = 50; _child.height = 50; _child.x = 60; _child.y = 90; _child.label = "child1"; _child.rotation = 0; child.children = [_child]; child = new ShapeModel(); child.shapeType = 1; child.width = 50; child.height = 50; child.x = 70; child.y = 10; child.label = "child2"; child.rotation = 0; childs.push(child); shape.children = childs; graph.addShapeUI(shape); } ]]> </fx:Script> <s:SpriteVisualElement width="100%" height="100%" id="drawingLayer" /> <s:Group width="100%" height="100%"> <graph:GraphContainer id="graph" width="100%" height="100%"></graph:GraphContainer> </s:Group> </s:Application>
资源源码下载