/*global YAHOO,WireIt,window */
(function() {
var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event;
/**
* Widget to display a minimap on a layer
* @class LayerMap
* @namespace WireIt
* @extends WireIt.CanvasElement
* @constructor
* @param {WireIt.Layer} layer the layer object it is attached to
* @param {Obj} options configuration object
*/
WireIt.LayerMap = function(layer,options) {
/**
* @property layer
*/
this.layer = layer;
this.setOptions(options);
if(typeof options.parentEl == "string") {
this.parentEl = YAHOO.util.Dom.get(options.parentEl);
}
else if(this.layer && !this.parentEl) {
this.parentEl = this.layer.el;
}
// Create the canvas element
WireIt.LayerMap.superclass.constructor.call(this, this.parentEl);
// Set the className
this.element.className = this.className;
this.initEvents();
this.draw();
};
YAHOO.lang.extend(WireIt.LayerMap, WireIt.CanvasElement, {
/**
* @property className
* @description CSS class name for the layer map element
* @default "WireIt-LayerMap"
* @type String
*/
className: "WireIt-LayerMap",
/**
* @property style
* @description display style
* @default "WireIt-LayerMap"
* @type String
*/
style: "rgba(0, 0, 200, 0.5)",
/**
* @property parentEl
* @description DOM element that schould contain the layer
* @default null
* @type DOMElement
*/
parentEl: null,
/**
* @property lineWidth
* @description Line width
* @default 2
* @type Integer
*/
lineWidth: 2,
/**
* Set the options by putting them in this (so it overrides the prototype default)
* @method setOptions
*/
setOptions: function(options) {
for(var k in options) {
if( options.hasOwnProperty(k) ) {
this[k] = options[k];
}
}
},
/**
* Listen for various events that should redraw the layer map
* @method initEvents
*/
initEvents: function() {
var layer = this.layer;
Event.addListener(this.element, 'mousedown', this.onMouseDown, this, true);
Event.addListener(this.element, 'mouseup', this.onMouseUp, this, true);
Event.addListener(this.element, 'mousemove', this.onMouseMove, this, true);
Event.addListener(this.element, 'mouseout', this.onMouseUp, this, true);
layer.eventAddWire.subscribe(this.draw, this, true);
layer.eventRemoveWire.subscribe(this.draw, this, true);
layer.eventAddContainer.subscribe(this.draw, this, true);
layer.eventRemoveContainer.subscribe(this.draw, this, true);
layer.eventContainerDragged.subscribe(this.draw, this, true);
layer.eventContainerResized.subscribe(this.draw, this, true);
Event.addListener(this.layer.el, "scroll", this.onLayerScroll, this, true);
},
/**
* When a mouse move is received
* @method onMouseMove
* @param {Event} e Original event
* @param {Array} args event parameters
*/
onMouseMove: function(e, args) {
Event.stopEvent(e);
if(this.isMouseDown) {
this.scrollLayer(e.clientX,e.clientY);
}
},
/**
* When a mouseup or mouseout is received
* @method onMouseUp
* @param {Event} e Original event
* @param {Array} args event parameters
*/
onMouseUp: function(e, args) {
Event.stopEvent(e);
this.isMouseDown = false;
},
/**
* When a mouse down is received
* @method onMouseDown
* @param {Event} e Original event
* @param {Array} args event parameters
*/
onMouseDown: function(e, args) {
Event.stopEvent(e);
this.scrollLayer(e.clientX,e.clientY);
this.isMouseDown = true;
},
/**
* Scroll the layer from mousedown/mousemove
* @method scrollLayer
* @param {Integer} clientX mouse event x coordinate
* @param {Integer} clientY mouse event y coordinate
*/
scrollLayer: function(clientX, clientY) {
var canvasPos = Dom.getXY(this.element);
var click = [ clientX-canvasPos[0], clientY-canvasPos[1] ];
// Canvas Region
var canvasRegion = Dom.getRegion(this.element);
var canvasWidth = canvasRegion.right-canvasRegion.left-4;
var canvasHeight = canvasRegion.bottom-canvasRegion.top-4;
// Calculate ratio
var layerWidth = this.layer.el.scrollWidth;
var layerHeight = this.layer.el.scrollHeight;
var hRatio = Math.floor(100*canvasWidth/layerWidth)/100;
var vRatio = Math.floor(100*canvasHeight/layerHeight)/100;
// Center position:
var center = [ click[0]/hRatio, click[1]/vRatio ];
// Region
var region = Dom.getRegion(this.layer.el);
var viewportWidth = region.right-region.left;
var viewportHeight = region.bottom-region.top;
// Calculate the scroll position of the layer
var topleft = [ Math.max(Math.floor(center[0]-viewportWidth/2),0) , Math.max(Math.floor(center[1]-viewportHeight/2), 0) ];
if( topleft[0]+viewportWidth > layerWidth ) {
topleft[0] = layerWidth-viewportWidth;
}
if( topleft[1]+viewportHeight > layerHeight ) {
topleft[1] = layerHeight-viewportHeight;
}
this.layer.el.scrollLeft = topleft[0];
this.layer.el.scrollTop = topleft[1];
},
/**
* Redraw after a timeout
* @method onLayerScroll
*/
onLayerScroll: function() {
if(this.scrollTimer) { window.clearTimeout(this.scrollTimer); }
var that = this;
this.scrollTimer = window.setTimeout(function() {
that.draw();
},50);
},
/**
* Redraw the layer map
* @method draw
*/
draw: function() {
var ctxt=this.getContext();
// Canvas Region
var canvasRegion = Dom.getRegion(this.element);
var canvasWidth = canvasRegion.right-canvasRegion.left-4;
var canvasHeight = canvasRegion.bottom-canvasRegion.top-4;
// Clear Rect
ctxt.clearRect(0,0, canvasWidth, canvasHeight);
// Calculate ratio
var layerWidth = this.layer.el.scrollWidth;
var layerHeight = this.layer.el.scrollHeight;
var hRatio = Math.floor(100*canvasWidth/layerWidth)/100;
var vRatio = Math.floor(100*canvasHeight/layerHeight)/100;
// Draw the viewport
var region = Dom.getRegion(this.layer.el);
var viewportWidth = region.right-region.left;
var viewportHeight = region.bottom-region.top;
var viewportX = this.layer.el.scrollLeft;
var viewportY = this.layer.el.scrollTop;
ctxt.strokeStyle= "rgb(200, 50, 50)";
ctxt.lineWidth=1;
ctxt.strokeRect(viewportX*hRatio, viewportY*vRatio, viewportWidth*hRatio, viewportHeight*vRatio);
// Draw containers and wires
ctxt.fillStyle = this.style;
ctxt.strokeStyle= this.style;
ctxt.lineWidth=this.lineWidth;
this.drawContainers(ctxt, hRatio, vRatio);
this.drawWires(ctxt, hRatio, vRatio);
},
/**
* Subroutine to draw the containers
* @method drawContainers
*/
drawContainers: function(ctxt, hRatio, vRatio) {
var containers = this.layer.containers;
var n = containers.length,i,gIS = WireIt.getIntStyle,containerEl;
for(i = 0 ; i < n ; i++) {
containerEl = containers[i].el;
ctxt.fillRect(gIS(containerEl, "left")*hRatio, gIS(containerEl, "top")*vRatio,
gIS(containerEl, "width")*hRatio, gIS(containerEl, "height")*vRatio);
}
},
/**
* Subroutine to draw the wires
* @method drawWires
*/
drawWires: function(ctxt, hRatio, vRatio) {
var wires = this.layer.wires;
var n = wires.length,i,wire;
for(i = 0 ; i < n ; i++) {
wire = wires[i];
var pos1 = wire.terminal1.getXY(),
pos2 = wire.terminal2.getXY();
// Stroked line
// TODO:
ctxt.beginPath();
ctxt.moveTo(pos1[0]*hRatio,pos1[1]*vRatio);
ctxt.lineTo(pos2[0]*hRatio,pos2[1]*vRatio);
ctxt.closePath();
ctxt.stroke();
}
}
});
})();