
dojo.require("dojo.lang");
dojo.require("dojo.style");
dojo.require("dojo.event");
dojo.require("dojo.math");
dojo.require("dojo.math.curves");
dojo.require("dojo.animation.*");


// Visual effect -- rectangle that "flies" from one element to another
// and then disappears.  This constructs a specialized
// dojo.animation.Animation.
// 
function IW_FlyEffect(from, to, duration) {
  var eFrom = iw_element(from);
  var fromX = iw_pageLeft(eFrom);
  var fromY = iw_pageTop(eFrom);
  var fromX2 = fromX+eFrom.offsetWidth;
  var fromY2 = fromY+eFrom.offsetHeight;
  if (to.tagName) {
    var eTo = iw_element(to);
    var toX = iw_pageLeft(eTo);
    var toY = iw_pageTop(eTo);
    var toX2 = toX+eTo.offsetWidth;
    var toY2 = toY+eTo.offsetHeight;
  } else {
    toX = to[0];
    toY = to[1];
    toX2 = to[2] || (toX+(fromX2-fromX));
    toY2 = to[3] || (toY+(fromY2-fromY));
  }
  var handle = document.createElement("ins");
  document.body.appendChild(handle);
  handle.innerHTML
    = '<div style="position: absolute; border: 1px solid black;"></div>';
  var div = handle.firstChild;
  var ds = div.style;
  ds.left = fromX+"px";
  ds.top = fromY+"px";
  ds.width = eFrom.offsetWidth+"px";
  ds.height = eFrom.offsetHeight+"px";

  dojo.animation.Animation.call
  (this, new dojo.math.curves.Line([fromX, fromY, fromX2, fromY2],
                                   [toX, toY, toX2, toY2]),
   duration, 0);
  dojo.event.connect(this, "onAnimate", function(e) {
    var coords = e.coords;
    ds.left = coords[0]+"px";
    ds.top = coords[1]+"px";
    ds.width = (coords[2]-coords[0])+"px";
    ds.height = (coords[3]-coords[1])+"px";
  });
  dojo.event.connect(this, "onEnd", function(e) {
    document.body.removeChild(handle);
  });
}

// dojo.inherits(IW_FlyEffect, dojo.animation.Animation);


// Visual effect constructor.  This builds a specialized
// dojo.animation.Animation that makes a node fade in.
// 
function IW_FadeIn(node, duration) {
  dojo.animation.Animation.call
    (this, new dojo.math.curves.Line([0],[1]), duration);
  // Override that 0 with the actual current opacity.
  dojo.event.connect(this, "onBegin", function(e) {
    iw_bkpoint("beginning fadein");
    e.animation.curve.start = [dojo.style.getOpacity(node)];
  });
  dojo.event.connect(this, "onAnimate", function(e) {
    dojo.style.setOpacity(node, e.x);
  });
}
dojo.inherits(IW_FadeIn, dojo.animation.Animation);


// Visual effect constructor.  This builds a specialized
// dojo.animation.Animation that makes a node appear by turning off
// display: none, then fades it in over the duration.
// 
function IW_FadeShow(node, duration) {
  dojo.animation.Animation.call
    (this, new dojo.math.curves.Line([0],[1]), duration);
  dojo.event.connect(this, "onBegin", function(e) {
    dojo.style.setOpacity(node, 0);
    iw_setStyle(node, "display", "");
  });
  dojo.event.connect(this, "onAnimate", function(e) {
    dojo.style.setOpacity(node, e.x);
  });
}


// Visual effect constructor.  This builds a specialized
// dojo.animation.Animation that makes a node fade out.
// 
function IW_FadeOut(node, duration) {
  dojo.animation.Animation.call
  (this, new dojo.math.curves.Line([1],[0]), duration);
  dojo.event.connect(this, "onBegin", function(e) {
    iw_bkpoint("beginning fadeout");
    // Override that 1 with the actual current opacity.
    e.animation.curve.start = [dojo.style.getOpacity(node)];
  });
  dojo.event.connect(this, "onAnimate", function(e) {
    dojo.style.setOpacity(node, e.x);
  });
}
dojo.inherits(IW_FadeOut, dojo.animation.Animation);


// Visual effect constructor.  This builds a specialized
// dojo.animation.Animation that makes a node fade out and then
// removes it from layout with display: none.
// 
function IW_FadeHide(node, duration) {
  dojo.animation.Animation.call
  (this, new dojo.math.curves.Line([1],[0]), duration);
  dojo.event.connect(this, "onBegin", function(e) {
    // Use current opacity rather than 1
    e.animation.curve.start = [dojo.style.getOpacity(node)];
  });
  dojo.event.connect(this, "onEnd", function(e) {
    iw_setStyle(node, "display", "none");
  });
  dojo.event.connect(this, "onAnimate", function(e) {
    dojo.style.setOpacity(node, e.x);
  });
}


// Constructor for the "Sweep" curve that traces out the projection of
// a circular motion onto a line from start to end.
// 
function Sweep(start, end) {
  this.start = start;
  this.end = end;
  this.radius = (this.end-this.start)/2;
  this.mid = (this.start+this.end)/2;
  this.getValue = function(n) {
    return [this.mid + this.radius*Math.cos(Math.PI*(n-1))];
  }
}

var Animation = dojo.animation.Animation;

// Slides the given HTML over the contents of target, which may be
// given by ID.
//
// The new HTML must have an opaque background, or it
// won't cover the old stuff as it comes in.
//
// The target should contain a single element, and the new HTML should
// constitute a single element, which will replace the old one after
// sliding in.
// 
function slideIn(target, html, duration, from) {
  from = from || "left";
  var el = iw_element(target);
  var wwwidth = el.offsetWidth;   // Plus or minus padding, etc.?
  var container = document.createElement("div");
  with (container.style) {
    switch (from) {
    case "left":
      position = "absolute";
      top = "0px";
      width = wwwidth+"px";
      left = -wwwidth+"px";
      break;
    default:
      throw new Error("No such slide direction: "+from);
    }
  }
  iw_setContents(container, html);

  // Hide any out-of-bounds new (or old) content.
  el.style.overflow = "hidden";
  // Container will position relative to "el".
  el.style.position = "relative";
  // Put the new content in there!
  var old = iw_firstE(el);
  el.appendChild(container);
  var animHeight = new Animation
    (new dojo.math.curves.Line
     ([el.offsetHeight],[container.offsetHeight]), duration);
  dojo.event.connect(animHeight, "onAnimate", function(e) {
    el.style.height = e.x+"px";
  });
  animHeight.play(true);
  
  if (old) {
    el.removeChild(old);
  }
  // var anim = new Animation(new Sweep(-wwwidth, 0), duration);
  var anim = new Animation(new dojo.math.curves.Line
                           ([-wwwidth], [0]), duration);
  dojo.event.connect(anim, "onAnimate", function(e) {
    container.style.left = e.x+"px";
  });
  dojo.event.connect(anim, "onEnd", function(e) {
  });
  anim.play(true); 
}


