//----------------------------------------------------------------------------
//
//  Defines the layer object
//  Copyright (c) 2000-2001 Glimpse
//  To be used with the Glimpse PHP Library
//
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
//  LAYERS MANAGEMENT ENGINE OBJECT
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
function GLIMPSE_LAYERS_ENGINE() {
  this.layers = new Array()
}


//----------------------------------------------------------------------------
function GLIMPSE_LAYERS_ENGINE_init() {
  for (var i=0; i<this.layers.length; i++) this.layers[i].initObjects()
}
GLIMPSE_LAYERS_ENGINE.prototype.init = GLIMPSE_LAYERS_ENGINE_init


//----------------------------------------------------------------------------
//  LAYER OBJECT
//----------------------------------------------------------------------------


function GLayer(layerID, x, y, w, h, zIndex) {
  this.objName = _layersEngineObjectName+'.'+layerID
  this.id = layerID
  this.x = x
  this.y = y
  this.width = w
  this.height = h
  this.zIndex = zIndex
  this.x2 = this.x + this.width
  this.y2 = this.y + this.height
  this.layer = null
  this.visible = true

  // Clipping attributes
  this.clipLeft = 0
  this.clipRight = this.width
  this.clipTop = 0
  this.clipBottom = this.height

  // Drag'n drop attributes
  this.isDraggable = false
  this.dragX = 0
  this.dragY = 0
  this.dragW = w
  this.dragH = h
  this.clickX = 0
  this.clickY = 0
  this.mustDrag = false
  this._onBeforeDrag = new Array()
  this._onDrag = new Array()
  this._onDrop = new Array()
  this.changeCursorOnDrag = true

  // Overlapping  attributes
  this.parent = null
  this.layers = new Array()
  this.overlapLevel = 0 // also indicates the number of parent layers

  // Scrolling attributes
  this.steps = 0
  this.speed = 0
  this.dx = 0
  this.dy = 0
  this.destx = 0
  this.desty = 0
  this.lastx = this.x
  this.lasty = this.y
  this.stepsDone = 0
  this._onBeforeScroll = new Array()
  this._onScroll = new Array()
  this._onAfterScroll = new Array()
  this._onMouseDown = new Array()
  this._followOnMouseDown = false
  this._onMouseUp = new Array()
  this._followOnMouseUp = false

  // Fade attributes
  this.alpha = 100
  this.fadeTo = 0
  this.fadeSteps = 10
  this.fadeSpeed = 5
}

//----------------------------------------------------------------------------
//  METHODS REGISTRATION
//----------------------------------------------------------------------------


GLayer.prototype.initObjects = GLayer_initObjects

GLayer.prototype.setX = GLayer_setX
GLayer.prototype.setY = GLayer_setY
GLayer.prototype.update = GLayer_update
GLayer.prototype.moveTo = GLayer_moveTo
GLayer.prototype.moveBy = GLayer_moveBy
GLayer.prototype.hide = GLayer_hide
GLayer.prototype.show = GLayer_show
GLayer.prototype.content = GLayer_content
GLayer.prototype.setBgImage = GLayer_setBgImage
GLayer.prototype.setBackground = GLayer_setBgImage
GLayer.prototype.setBgColor = GLayer_setBgColor
GLayer.prototype.setZIndex = GLayer_setZIndex
GLayer.prototype.getWidth = GLayer_getWidth
GLayer.prototype.getHeight = GLayer_getHeight

GLayer.prototype.updateClipping = GLayer_updateClipping

GLayer.prototype.fadeIn = GLayer_fadeIn
GLayer.prototype.fadeOut = GLayer_fadeOut
GLayer.prototype.doFade = GLayer_doFade
GLayer.prototype.updateAlpha = GLayer_updateAlpha
GLayer.prototype.setTransparency = GLayer_setTransparency


function GLayer_toggleVisibility() {
  if (this.visible) this.hide()
  else this.show()
}
GLayer.prototype.toggleVisibility = GLayer_toggleVisibility

//----------------------------------------------------------------------------
function GLayer_addLayer(layerID, x, y, w, h, zIndex) {
  var l = new GLayer(layerID, x, y, w, h, zIndex)
  l.parent = this
  this.layers[this.layers.length] = l
  this.layers[layerID] = l
}
GLayer.prototype.addLayer = GLayer_addLayer
GLayer.prototype.add = GLayer_addLayer


//----------------------------------------------------------------------------
function GLayer_setObjName(objName) {
	this.objName = objName
	this.obj = eval(this.objName)
}
GLayer.prototype.setObjName = GLayer_setObjName

//----------------------------------------------------------------------------
//  CLIPPING METHODS
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
function GLayer_clip(left, top, right, bottom) {
  this.setClipping(left, top, right, bottom)
  this.updateClipping()
}
GLayer.prototype.clip = GLayer_clip


//----------------------------------------------------------------------------
function GLayer_setClipping(left, top, right, bottom) {
  this.clipLeft = left
  this.clipRight = right
  this.clipTop = top
  this.clipBottom = bottom
}
GLayer.prototype.setClipping = GLayer_setClipping


//----------------------------------------------------------------------------
function GLayer_vclip(top, bottom) {
  this.clipTop = top
  this.clipBottom = bottom
  this.updateClipping()
}
GLayer.prototype.vclip = GLayer_vclip

//----------------------------------------------------------------------------
function GLayer_hclip(left, right) {
  this.clipLeft = left
  this.clipRight = right
  this.updateClipping()
}
GLayer.prototype.hclip = GLayer_hclip


//----------------------------------------------------------------------------
//  SCROLLING METHODS
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
function GLayer_setScroll(x, y, steps, speed) {
	if (x<this.dragAreaX) x = this.dragAreaX
	if (x>(this.dragAreaX+this.dragAreaW)) x = this.dragAreaX+this.dragAreaW
	if (y<this.dragAreaY) y = this.dragAreaY
	if (y>(this.dragAreaY+this.dragAreaH)) y = this.dragAreaY+this.dragAreaH
  this.steps = steps
  this.speed = speed
  this.timeoutId = null
  this.lastx = this.x
  this.lasty = this.y
  this.stepsDone = 0
  this.destx = x
  this.desty = y
  this.dx = (this.destx - this.x) / steps
  this.dy = (this.desty - this.y) / steps
}
GLayer.prototype.setScroll = GLayer_setScroll

//----------------------------------------------------------------------------
function GLayer_scroll (x, y, steps, speed) {
  if (GLayer_scroll.arguments.length == 4) this.setScroll(x, y, steps, speed)
  this.lastx = this.x
  this.lasty = this.y
  this.dx = (this.destx - this.x) / this.steps
  this.dy = (this.desty - this.y) / this.steps
  for (var j=0; j<this._onBeforeScroll.length; j++) eval(this._onBeforeScroll[j])
  this.doScroll()
}
GLayer.prototype.scroll = GLayer_scroll

//----------------------------------------------------------------------------
function GLayer_scrollBy (x, y, steps, speed) {
  this.scroll(this.x+x, this.y+y, steps, speed)
}
GLayer.prototype.scrollBy = GLayer_scrollBy


//----------------------------------------------------------------------------
function GLayer_doScroll () {
  this.lastx += this.dx
  this.lasty += this.dy
  this.moveTo(Math.round(this.lastx), Math.round(this.lasty))
  for (var j=0; j<this._onScroll.length; j++) eval(this._onScroll[j])
	if (++this.stepsDone >= this.steps) {
		this.stepsDone = 0
	  for (var j=0; j<this._onAfterScroll.length; j++) eval(this._onAfterScroll[j])
	  if (this.layer.style && this.changeCursorOnDrag) this.layer.style.cursor=''
	} else {
		setTimeout(this.objName+".doScroll()", this.speed)
	}

}
GLayer.prototype.doScroll = GLayer_doScroll


//----------------------------------------------------------------------------
//  DRAG'N DROP METHODS
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
function GLayer_isUnder(mx, my) {
	if (mx >= (this.x+this.dragX) && mx <= (this.x+this.dragX+this.dragW) && my >= (this.y+this.dragY) && my <= (this.y+this.dragY+this.dragH)) {
		return true
	} else {
	  return false
	}
}
GLayer.prototype.isUnder = GLayer_isUnder


//----------------------------------------------------------------------------
function GLayer_draggable () {
	var argv = GLayer_draggable.arguments
	var argc = argv.length
	this.isDraggable = true
	if (argc == 4) {
    this.dragX = argv[0]
    this.dragY = argv[1]
    this.dragW = argv[2]
    this.dragH = argv[3]
	}
}
GLayer.prototype.draggable = GLayer_draggable


//----------------------------------------------------------------------------
function GLayer_setDraggableArea(x, y, w, h) {
  this.dragAreaX = x
  this.dragAreaY = y
  this.dragAreaW = w
  this.dragAreaH = h
}
GLayer.prototype.setDraggableArea = GLayer_setDraggableArea


//----------------------------------------------------------------------------
//  EVENTS HANDLERS
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
function GLayer_onMouseDown(code) {
	for (var i=0; i<this.onMouseDown.length; i++) if (this._onMouseDown[i] == code) return
	this._onMouseDown[this._onMouseDown.length] = code
}
GLayer.prototype.onMouseDown = GLayer_onMouseDown
GLayer.prototype.onClick = GLayer_onMouseDown


//----------------------------------------------------------------------------
function GLayer_onMouseUp(code) {
	for (var i=0; i<this.onMouseUp.length; i++) if (this._onMouseUp[i] == code) return
	this._onMouseUp[this._onMouseUp.length] = code
}
GLayer.prototype.onMouseUp = GLayer_onMouseUp
GLayer.prototype.onAfterClick = GLayer_onMouseUp


//----------------------------------------------------------------------------
function GLayer_onBeforeDrag(code) {
	for (var i=0; i<this.onBeforeDrag.length; i++) if (this._onBeforeDrag[i] == code) return
	this._onBeforeDrag[this._onBeforeDrag.length] = code
}
GLayer.prototype.onBeforeDrag = GLayer_onBeforeDrag


//----------------------------------------------------------------------------
function GLayer_onDrag(code) {
	for (var i=0; i<this.onDrag.length; i++) if (this._onDrag[i] == code) return
	this._onDrag[this._onDrag.length] = code
}
GLayer.prototype.onDrag = GLayer_onDrag


//----------------------------------------------------------------------------
function GLayer_onDrop(code) {
	for (var i=0; i<this._onDrop.length; i++) if (this._onDrop[i] == code) return
	this._onDrop[this._onDrop.length] = code
}
GLayer.prototype.onDrop = GLayer_onDrop


//----------------------------------------------------------------------------
function GLayer_onBeforeScroll(code) {
	for (var i=0; i<this._onBeforeScroll.length; i++) if (this._onBeforeScroll[i] == code) return
	this._onBeforeScroll[this._onBeforeScroll.length] = code
}
GLayer.prototype.onBeforeScroll = GLayer_onBeforeScroll


//----------------------------------------------------------------------------
function GLayer_onScroll(code) {
	for (var i=0; i<this._onScroll.length; i++) if (this._onScroll[i] == code) return
	this._onScroll[this._onScroll.length] = code
}
GLayer.prototype.onScroll = GLayer_onScroll


//----------------------------------------------------------------------------
function GLayer_onAfterScroll(code) {
	for (var i=0; i<this._onAfterScroll.length; i++) if (this._onAfterScroll[i] == code) return
	this._onAfterScroll[this._onAfterScroll.length] = code
}
GLayer.prototype.onAfterScroll = GLayer_onAfterScroll


//----------------------------------------------------------------------------
//  LAYERS MANAGEMENT ENGINE METHODS ( including drag'n drop methods )
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
function GLIMPSE_LAYERS_ENGINE_add(layerID, x, y, w, h, zIndex) {
  var l = new GLayer(layerID, x, y, w, h, zIndex)
  this.layers[this.layers.length] = l
  this.layers[layerID] = l
  if (!eval("this."+layerID)) eval ("this."+layerID+" = l")
}
GLIMPSE_LAYERS_ENGINE.prototype.add = GLIMPSE_LAYERS_ENGINE_add


//----------------------------------------------------------------------------
function GLIMPSE_LAYERS_ENGINE_testDragNDropMouseDown() {
  var mouse = eval(_mouseObjectName)
  var le = eval(_layersEngineObjectName)
  var follow = true
  for (var i=0; i<le.layers.length; i++) {
		var l = le.layers[i]
//alert(mouse.x+', '+mouse.y)
  	if (l.visible && l.isUnder(mouse.x, mouse.y)) {
  		l.clickX = mouse.x-l.x
  		l.clickY = mouse.y-l.y
    	if (l.isDraggable == true) {
  		  for (var j=0; j<l._onBeforeDrag.length; j++) eval(l._onBeforeDrag[j])
  		  l.mustDrag = true
  		  if (l.layer.style) if (l.changeCursorOnDrag) l.layer.style.cursor='move'
  		}
  		if (follow) for (var j=0; j<l._onMouseDown.length; j++) eval(l._onMouseDown[j])
  		follow = l._followOnMouseDown
  	}
  }
}
GLIMPSE_LAYERS_ENGINE.prototype.testDragNDropMouseDown = GLIMPSE_LAYERS_ENGINE_testDragNDropMouseDown


//----------------------------------------------------------------------------
function GLIMPSE_LAYERS_ENGINE_testDragNDropMouseUp() {
  var le = eval(_layersEngineObjectName)
  var follow = true
  for (var i=0; i<le.layers.length; i++) {
		var l = le.layers[i]
  	if (l.mustDrag == true) {
      if (l.layer.style) if (l.changeCursorOnDrag) l.layer.style.cursor=''
      for (var j=0; j<l._onDrop.length; j++) eval(l._onDrop[j])
  	}
  	le.layers[i].mustDrag = false
		if (follow) for (var j=0; j<l._onMouseUp.length; j++) eval(l._onMouseUp[j])
 		follow = l._followOnMouseUp
  }
}
GLIMPSE_LAYERS_ENGINE.prototype.testDragNDropMouseUp = GLIMPSE_LAYERS_ENGINE_testDragNDropMouseUp


//----------------------------------------------------------------------------
function GLIMPSE_LAYERS_ENGINE_dragLayers() {
  var mouse = eval(_mouseObjectName)
  var le = eval(_layersEngineObjectName)
  for (var i=0; i<le.layers.length; i++) {
		var l = le.layers[i]
		if (l.mustDrag == true) {
			if (!l.isUnder(mouse.x, mouse.y) && _layers_strict_drag_n_drop) {
				l.mustDrag = false
				continue
			}
			var x = mouse.x-l.clickX
			var y = mouse.y-l.clickY
			if (x<l.dragAreaX) x = l.dragAreaX
			if (x>(l.dragAreaX+l.dragAreaW)) x = l.dragAreaX+l.dragAreaW
			if (y<l.dragAreaY) y = l.dragAreaY
			if (y>(l.dragAreaY+l.dragAreaH)) y = l.dragAreaY+l.dragAreaH
			l.moveTo(x, y)
			if (x>=l.dragAreaX && x<=(l.dragAreaX+l.dragAreaW)) l.moveTo(x, y)
      for (var j=0; j<l._onDrag.length; j++) {
      	eval(l._onDrag[j])
      }
	    if (document.selection) document.selection.empty()
	    else if (window.getSelection) window.getSelection().removeAllRanges()
	  }
	}
}
GLIMPSE_LAYERS_ENGINE.prototype.dragLayers = GLIMPSE_LAYERS_ENGINE_dragLayers
