/* --------------- // Connector Class // --------------- // // AUTHOR: Sammy Joe Osborne // DATE: 07/15/2007 // // DESCRIPTION: Creates a connection between two display objects. The first parameter is considered the parent. */ package { import flash.display.Sprite; import flash.display.Shape; import flash.display.DisplayObject; import flash.events.Event; public class Connector extends Sprite { private var line:Shape = new Shape; private var triangle:Shape = new Shape; private var _obj1:DisplayObject; private var _obj2:DisplayObject; private var _obj1X:Number; private var _obj2X:Number; private var _obj1Y:Number; private var _obj2Y:Number; private const ARROW_SPACE = 8; private var _lineColor:uint; private var _lineThickness:uint; private var _usePointer:Boolean; public function Connector(obj1:DisplayObject, obj2:DisplayObject):void { _obj1 = obj1; _obj2 = obj2; init(); } private function init():void { _obj1X = _obj1.x; _obj1Y = _obj1.y; _obj2X = _obj2.x; _obj2Y = _obj2.y; _lineColor = 0x000000; _lineThickness = 2; _usePointer = true; addChild(line); addChild(triangle); drawConnector(); drawTriangle(); //constantly checking to see if either display objects have moved _obj1.addEventListener(Event.ENTER_FRAME, checkForMove); _obj2.addEventListener(Event.ENTER_FRAME, checkForMove); } private function checkForMove(event:Event):void { if((_obj1X!=_obj1.x)||(_obj1Y!=_obj1.y)||(_obj2X!=_obj2.x)||(_obj2Y!=_obj2.y)){ drawConnector(); _obj1X = _obj1.x; _obj1Y = _obj1.y; _obj2X = _obj2.x; _obj2Y = _obj2.y; } } private function drawConnector(){ line.graphics.clear(); line.graphics.lineStyle(_lineThickness, _lineColor, 1); if(isFullyLeftOf(_obj1, _obj2)){ if(isFullyAbove(_obj1, _obj2)){ bottomToTop(); } else if(isFullyBelow(_obj1, _obj2)){ topToBottom(); } else{ rightToLeft(); } } else if(isFullyRightOf(_obj1, _obj2)){ if(isFullyAbove(_obj1, _obj2)){ bottomToTop(); } else if(isFullyBelow(_obj1, _obj2)){ topToBottom(); } else{ leftToRight(); } } else if(isFullyAbove(_obj1, _obj2)){ bottomToTop(); } else if(isFullyBelow(_obj1, _obj2)){ topToBottom(); } else{ centerToCenter(); } } //this is the arrow on the end of the line private function drawTriangle():void { triangle.graphics.clear(); triangle.graphics.beginFill(lineColor, 1); triangle.graphics.moveTo(lineThickness+1.5, 0); triangle.graphics.lineTo(-(lineThickness+1.5), 0); triangle.graphics.lineTo(0, ARROW_SPACE); triangle.graphics.lineTo(lineThickness+1.5, 0); triangle.graphics.endFill(); } public function reverse():void { var temp:DisplayObject = _obj1; _obj1 = _obj2; _obj2 = temp; } public function set lineThickness(value:uint):void { _lineThickness = value; drawTriangle(); drawConnector(); } public function get lineThickness():uint { return _lineThickness; } public function set lineColor(value:uint):void { _lineColor = value; drawTriangle(); drawConnector(); } public function get lineColor():uint { return _lineColor; } public function getParent():DisplayObject { return _obj1; } public function setParent(value:DisplayObject):void { _obj1 = value; drawTriangle(); drawConnector(); } public function getChild():DisplayObject { return _obj2; } public function setChild(value:DisplayObject):void { _obj2 = value; drawTriangle(); drawConnector(); } public function set usePointer(value:Boolean):void { _usePointer = value; drawTriangle(); drawConnector(); } public function get usePointer():Boolean { return _usePointer; } //from the right side of obj1 to the left side of obj2 private function rightToLeft():void { line.graphics.moveTo(_obj1.x + _obj1.width, _obj1.y + (_obj1.height/2)); if(_usePointer) { line.graphics.lineTo((_obj1.x + _obj1.width) + .5*(_obj2.x - (_obj1.x + _obj1.width)) - ARROW_SPACE, _obj1.y + (_obj1.height/2)); line.graphics.lineTo((_obj1.x + _obj1.width) + .5*(_obj2.x - (_obj1.x + _obj1.width)) - ARROW_SPACE, _obj2.y + (_obj2.height/2)); line.graphics.lineTo(_obj2.x - ARROW_SPACE+1, _obj2.y + (_obj2.height/2)); triangle.visible = true; triangle.x = _obj2.x - ARROW_SPACE; triangle.y = _obj2.y + (_obj2.height/2); triangle.rotation = -90; } else { line.graphics.lineTo((_obj1.x + _obj1.width) + .5*(_obj2.x - (_obj1.x + _obj1.width)), _obj1.y + (_obj1.height/2)); line.graphics.lineTo((_obj1.x + _obj1.width) + .5*(_obj2.x - (_obj1.x + _obj1.width)), _obj2.y + (_obj2.height/2)); line.graphics.lineTo(_obj2.x, _obj2.y + (_obj2.height/2)); triangle.visible = false; } } //from the left side of obj1 to the right side of obj2 private function leftToRight():void { line.graphics.moveTo(_obj1.x, _obj1.y + (_obj1.height/2)); if(_usePointer){ line.graphics.lineTo((_obj2.x + _obj2.width) + .5*(_obj1.x - (_obj2.x + _obj2.width)) + ARROW_SPACE, _obj1.y + (_obj1.height/2)); line.graphics.lineTo((_obj2.x + _obj2.width) + .5*(_obj1.x - (_obj2.x + _obj2.width)) + ARROW_SPACE, _obj2.y + (_obj2.height/2)); line.graphics.lineTo((_obj2.x + _obj2.width) + ARROW_SPACE-1, _obj2.y + _obj2.height/2); triangle.visible = true; triangle.x = (_obj2.x + _obj2.width) + ARROW_SPACE; triangle.y = _obj2.y + _obj2.height/2; triangle.rotation = 90; } else{ line.graphics.lineTo((_obj2.x + _obj2.width) + .5*(_obj1.x - (_obj2.x + _obj2.width)), _obj1.y + (_obj1.height/2)); line.graphics.lineTo((_obj2.x + _obj2.width) + .5*(_obj1.x - (_obj2.x + _obj2.width)), _obj2.y + (_obj2.height/2)); line.graphics.lineTo((_obj2.x + _obj2.width), _obj2.y + _obj2.height/2); triangle.visible = false; } } //from the top of obj1 to the bottom of obj2 private function topToBottom():void { line.graphics.moveTo(_obj1.x + (_obj1.width/2), _obj1.y); if(_usePointer){ line.graphics.lineTo(_obj1.x + (_obj1.width/2), _obj1.y + .5*((_obj2.y + _obj2.height) - _obj1.y)); line.graphics.lineTo(_obj2.x+(_obj2.width/2), _obj1.y + .5*((_obj2.y + _obj2.height) - _obj1.y)); line.graphics.lineTo(_obj2.x+(_obj2.width/2), (_obj2.y + _obj2.height)+ ARROW_SPACE-1); triangle.visible = true; triangle.x = _obj2.x+(_obj2.width/2); triangle.y = (_obj2.y + _obj2.height)+ ARROW_SPACE; triangle.rotation = 180; } else{ line.graphics.lineTo(_obj1.x + (_obj1.width/2), _obj1.y + .5*((_obj2.y + _obj2.height) - _obj1.y)); line.graphics.lineTo(_obj2.x+(_obj2.width/2), _obj1.y + .5*((_obj2.y + _obj2.height) - _obj1.y)); line.graphics.lineTo(_obj2.x+(_obj2.width/2), (_obj2.y + _obj2.height)); triangle.visible = false; } } //from the bottom of obj1 to the top of obj2 private function bottomToTop():void { line.graphics.moveTo(_obj1.x + (_obj1.width/2), _obj1.y + _obj1.height); if(_usePointer) { line.graphics.lineTo(_obj1.x + (_obj1.width/2), (_obj1.y + _obj1.height) + .5*(_obj2.y - (_obj1.y + _obj1.height))); line.graphics.lineTo(_obj2.x + (_obj2.width/2), (_obj1.y + _obj1.height) + .5*(_obj2.y - (_obj1.y + _obj1.height))); line.graphics.lineTo(_obj2.x + (_obj2.width/2), _obj2.y - ARROW_SPACE+1); triangle.visible = true; triangle.x = (_obj2.x + (_obj2.width/2)); triangle.y = _obj2.y - ARROW_SPACE; triangle.rotation = 0; } else { line.graphics.lineTo(_obj1.x + (_obj1.width/2), (_obj1.y + _obj1.height) + .5*(_obj2.y - (_obj1.y + _obj1.height))); line.graphics.lineTo(_obj2.x + (_obj2.width/2), (_obj1.y + _obj1.height) + .5*(_obj2.y - (_obj1.y + _obj1.height))); line.graphics.lineTo(_obj2.x + (_obj2.width/2), _obj2.y); triangle.visible = false; } } //from the center of _obj1 to the center of _obj2 private function centerToCenter():void { line.graphics.moveTo(_obj1.x + (_obj1.width/2), _obj1.y + (_obj1.height/2)); line.graphics.lineTo(_obj2.x + (_obj2.width/2), _obj2.y + (_obj2.height/2)); triangle.visible = false; } //checks if obj1 is fully above obj2 (this includes the space for the arrow) private function isFullyAbove(obj1:DisplayObject, obj2:DisplayObject):Boolean { return (obj1.y + obj1.height + ARROW_SPACE) < obj2.y; } //checks if obj1 is fully below obj2 (this includes the space for the arrow) private function isFullyBelow(obj1:DisplayObject, obj2:DisplayObject):Boolean { return obj1.y > (obj2.y + obj2.height + ARROW_SPACE); } //checks if obj1 is fully to the left of obj2 (this includes the space for the arrow) private function isFullyLeftOf(obj1:DisplayObject, obj2:DisplayObject):Boolean { return (obj1.x + obj1.width + ARROW_SPACE) < obj2.x; } //checks if obj1 is fully to the right of obj2 (this includes the space for the arrow) private function isFullyRightOf(obj1:DisplayObject, obj2:DisplayObject):Boolean { return obj1.x > (obj2.x + obj2.width + ARROW_SPACE); } } }