/*
 * $Id: gnuplot_mouse.js,v 1.7 2009/05/30 17:55:42 sfeam Exp $
 */
// Mousing code for use with gnuplot's 'canvas' terminal driver.
// The functions defined here assume that the javascript plot produced by
// gnuplot initializes the plot boundary and scaling parameters.

var mousex = 0;
var mousey = 0;
var plotx = 0;
var ploty = 0;
var scaled_x = 0;
var scaled_y = 0;

// These will be initialized by the gnuplot canvas-drawing function
var plot_xmin = 0;
var plot_xmax = 0;
var plot_ybot = 0;
var plot_ytop = 0;
var plot_width  = 0
var plot_height = 0
var plot_term_ymax = 0;
var plot_axis_xmin = 0;
var plot_axis_xmax = 0;
var plot_axis_width  = 0;
var plot_axis_height = 0;
var plot_axis_ymin = 0;
var plot_axis_ymax = 0;
var plot_axis_x2min = "none";
var plot_axis_y2min = "none";
var plot_logaxis_x = 0;
var plot_logaxis_y = 0;
var grid_lines = true;
var zoom_text = false;

// These are the equivalent parameters while zooming
var zoom_axis_xmin = 0;
var zoom_axis_xmax = 0;
var zoom_axis_ymin = 0;
var zoom_axis_ymax = 0;
var zoom_axis_x2min = 0;
var zoom_axis_x2max = 0;
var zoom_axis_y2min = 0;
var zoom_axis_y2max = 0;
var zoom_axis_width = 0;
var zoom_axis_height = 0;
var zoom_temp_xmin = 0;
var zoom_temp_ymin = 0;
var zoom_temp_x2min = 0;
var zoom_temp_y2min = 0;
var zoom_in_progress = false;

function gnuplot_init()
{
  if (document.getElementById("gnuplot_canvas"))
      document.getElementById("gnuplot_canvas").onmousemove = mouse_update;
  if (document.getElementById("gnuplot_canvas"))
      document.getElementById("gnuplot_canvas").onmouseup = zoom_in;
  if (document.getElementById("gnuplot_canvas"))
      document.getElementById("gnuplot_canvas").onmousedown = saveclick;
  if (document.getElementById("gnuplot_canvas"))
      document.getElementById("gnuplot_canvas").onkeypress = do_hotkey;
  if (document.getElementById("gnuplot_grid_icon"))
      document.getElementById("gnuplot_grid_icon").onmouseup = toggle_grid;
  if (document.getElementById("gnuplot_textzoom_icon"))
      document.getElementById("gnuplot_textzoom_icon").onmouseup = toggle_zoom_text;
  if (document.getElementById("gnuplot_rezoom_icon"))
      document.getElementById("gnuplot_rezoom_icon").onmouseup = rezoom;
  if (document.getElementById("gnuplot_unzoom_icon"))
      document.getElementById("gnuplot_unzoom_icon").onmouseup = unzoom;
  mouse_update();
}

function getMouseCoordsWithinTarget(event)
{
	var coords = { x: 0, y: 0};

	if(!event) // then we're in a non-DOM (probably IE) browser
	{
		event = window.event;
		if (event) {
			coords.x = event.offsetX;
			coords.y = event.offsetY;
		}
	}
	else		// we assume DOM modeled javascript
	{
		var Element = event.target ;
		var CalculatedTotalOffsetLeft = 0;
		var CalculatedTotalOffsetTop = 0 ;

		while (Element.offsetParent)
 		{
 			CalculatedTotalOffsetLeft += Element.offsetLeft ;     
			CalculatedTotalOffsetTop += Element.offsetTop ;
 			Element = Element.offsetParent ;
 		}

		coords.x = event.pageX - CalculatedTotalOffsetLeft ;
		coords.y = event.pageY - CalculatedTotalOffsetTop ;
	}

	mousex = coords.x;
	mousey = coords.y;
}


function mouse_update(e)
{
  getMouseCoordsWithinTarget(e);

  plotx = mousex - plot_xmin;
  ploty = -(mousey - plot_ybot);

  // Limit tracking to the interior of the plot
  if (plotx < 0 || ploty < 0) return;
  if (mousex > plot_xmax || mousey < plot_ytop) return;

  var axis_xmin = (zoomed) ? zoom_axis_xmin : plot_axis_xmin;
  var axis_xmax = (zoomed) ? zoom_axis_xmax : plot_axis_xmax;
  var axis_ymin = (zoomed) ? zoom_axis_ymin : plot_axis_ymin;
  var axis_ymax = (zoomed) ? zoom_axis_ymax : plot_axis_ymax;

    if (plot_logaxis_x != 0) {
	x = Math.log(axis_xmax) - Math.log(axis_xmin);
	x = x * (plotx / (plot_xmax-plot_xmin)) + Math.log(axis_xmin);
	x = Math.exp(x);
    } else {
	x =  axis_xmin + (plotx / (plot_xmax-plot_xmin)) * (axis_xmax - axis_xmin);
    }

    if (plot_logaxis_y != 0) {
	y = Math.log(axis_ymax) - Math.log(axis_ymin);
	y = y * (-ploty / (plot_ytop-plot_ybot)) + Math.log(axis_ymin);
	y = Math.exp(y);
    } else {
	y =  axis_ymin - (ploty / (plot_ytop-plot_ybot)) * (axis_ymax - axis_ymin);
    }

    if (plot_axis_x2min != "none") {
	axis_x2min = (zoomed) ? zoom_axis_x2min : plot_axis_x2min;
	axis_x2max = (zoomed) ? zoom_axis_x2max : plot_axis_x2max;
	x2 =  axis_x2min + (plotx / (plot_xmax-plot_xmin)) * (axis_x2max - axis_x2min);
	if (document.getElementById(active_plot_name + "_x2"))
	    document.getElementById(active_plot_name + "_x2").innerHTML = x2.toPrecision(4);
    }
    if (plot_axis_y2min != "none") {
	axis_y2min = (zoomed) ? zoom_axis_y2min : plot_axis_y2min;
	axis_y2max = (zoomed) ? zoom_axis_y2max : plot_axis_y2max;
	y2 = axis_y2min - (ploty / (plot_ytop-plot_ybot)) * (axis_y2max - axis_y2min);
	if (document.getElementById(active_plot_name + "_y2"))
	    document.getElementById(active_plot_name + "_y2").innerHTML = y2.toPrecision(4);
    }

  if (document.getElementById(active_plot_name + "_x"))
      document.getElementById(active_plot_name + "_x").innerHTML = x.toPrecision(4);
  if (document.getElementById(active_plot_name + "_y"))
      document.getElementById(active_plot_name + "_y").innerHTML = y.toPrecision(4);

  // Echo the zoom box interactively
  if (zoom_in_progress) {
    ctx.strokeStyle="rgba(128,128,128,0.20)";
    ctx.strokeRect(
	plot_xmin + zoom_temp_plotx,  plot_ybot - zoom_temp_ploty,
	plotx - zoom_temp_plotx, -(ploty - zoom_temp_ploty));
  }
}

function saveclick(event)
{
  mouse_update(event);
  
  // Limit tracking to the interior of the plot
  if (plotx < 0 || ploty < 0) return;
  if (mousex > plot_xmax || mousey < plot_ytop) return;

  if (event.which == null) 	/* IE case */
    button= (event.button < 2) ? "LEFT" : ((event.button == 4) ? "MIDDLE" : "RIGHT");
  else				/* All others */
    button= (event.which < 2) ? "LEFT" : ((event.which == 2) ? "MIDDLE" : "RIGHT");

  if (button == "LEFT") {
    ctx.strokeStyle="black";
    ctx.strokeRect(mousex, mousey, 1, 1);
    click = " " + x.toPrecision(4) + ", " + y.toPrecision(4);
    ctx.drawText("sans", 9, mousex, mousey, click);
  }

  // Save starting corner of zoom box
  else {
    zoom_temp_xmin = x;
    zoom_temp_ymin = y;
    if (plot_axis_x2min != "none") zoom_temp_x2min = x2;
    if (plot_axis_y2min != "none") zoom_temp_y2min = y2;
    // Only used to echo the zoom box interactively
    zoom_temp_plotx = plotx;
    zoom_temp_ploty = ploty;
    zoom_in_progress = true;
  }
  return false; // Nobody else should respond to this event
}

function zoom_in(event)
{
  if (!zoom_in_progress)
    return false;

  mouse_update(event);
  
  if (event.which == null) 	/* IE case */
    button= (event.button < 2) ? "LEFT" : ((event.button == 4) ? "MIDDLE" : "RIGHT");
  else				/* All others */
    button= (event.which < 2) ? "LEFT" : ((event.which == 2) ? "MIDDLE" : "RIGHT");

  // Save ending corner of zoom box
  if (button != "LEFT") {
    if (x > zoom_temp_xmin) {
        zoom_axis_xmin = zoom_temp_xmin;
	zoom_axis_xmax = x;
	if (plot_axis_x2min != "none") {
            zoom_axis_x2min = zoom_temp_x2min;
	    zoom_axis_x2max = x2;
	}
    } else {
        zoom_axis_xmin = x;
	zoom_axis_xmax = zoom_temp_xmin;
	if (plot_axis_x2min != "none") {
            zoom_axis_x2min = x2;
	    zoom_axis_x2max = zoom_temp_x2min;
	}
    }
    if (y > zoom_temp_ymin) {
        zoom_axis_ymin = zoom_temp_ymin;
	zoom_axis_ymax = y;
	if (plot_axis_y2min != "none") {
            zoom_axis_y2min = zoom_temp_y2min;
	    zoom_axis_y2max = y2;
	}
    } else {
        zoom_axis_ymin = y;
	zoom_axis_ymax = zoom_temp_ymin;
	if (plot_axis_y2min != "none") {
            zoom_axis_y2min = y2;
	    zoom_axis_y2max = zoom_temp_y2min;
	}
    }
    zoom_axis_width = zoom_axis_xmax - zoom_axis_xmin;
    zoom_axis_height = zoom_axis_ymax - zoom_axis_ymin;
    zoom_in_progress = false;
    rezoom(event);
  }
  return false; // Nobody else should respond to this event
}

function toggle_grid(e)
{
  if (!grid_lines) grid_lines = true;
  else grid_lines = false;
  ctx.clearRect(0,0,plot_term_xmax,plot_term_ymax);
  gnuplot_canvas();
}

function toggle_zoom_text(e)
{
  if (!zoom_text) zoom_text = true;
  else zoom_text = false;
  ctx.clearRect(0,0,plot_term_xmax,plot_term_ymax);
  gnuplot_canvas();
}

function rezoom(e)
{
  if (zoom_axis_width > 0)
    zoomed = true;
  ctx.clearRect(0,0,plot_term_xmax,plot_term_ymax);
  gnuplot_canvas();
}

function unzoom(e)
{
  zoomed = false;
  ctx.clearRect(0,0,plot_term_xmax,plot_term_ymax);
  gnuplot_canvas();
}

function zoomXY(x,y)
{
  zoom = new Object;
  var xreal, yreal;

  zoom.x = x; zoom.y = y; zoom.clip = false;

  if (plot_logaxis_x != 0) {
	xreal = Math.log(plot_axis_xmax) - Math.log(plot_axis_xmin);
	xreal = Math.log(plot_axis_xmin) + (x - plot_xmin) * xreal/plot_width;
	zoom.x = Math.log(zoom_axis_xmax) - Math.log(zoom_axis_xmin);
	zoom.x = plot_xmin + (xreal - Math.log(zoom_axis_xmin)) * plot_width/zoom.x;
  } else {
	xreal = plot_axis_xmin + (x - plot_xmin) * (plot_axis_width/plot_width);
	zoom.x = plot_xmin + (xreal - zoom_axis_xmin) * (plot_width/zoom_axis_width);
  }
  if (plot_logaxis_y != 0) {
	yreal = Math.log(plot_axis_ymax) - Math.log(plot_axis_ymin);
	yreal = Math.log(plot_axis_ymin) + (plot_ybot - y) * yreal/plot_height;
	zoom.y = Math.log(zoom_axis_ymax) - Math.log(zoom_axis_ymin);
	zoom.y = plot_ybot - (yreal - Math.log(zoom_axis_ymin)) * plot_height/zoom.y;
  } else {
	yreal = plot_axis_ymin + (plot_ybot - y) * (plot_axis_height/plot_height);
	zoom.y = plot_ybot - (yreal - zoom_axis_ymin) * (plot_height/zoom_axis_height);
  }

  // Limit the zoomed plot to the original plot area
  if (x > plot_xmax) {
    zoom.x = x;
    if (plot_axis_y2min == "none") {
      zoom.y = y;
      return zoom;
    }
    if (plot_ybot <= y && y <= plot_ybot + 15)
      zoom.clip = true;
  }

  else if (x < plot_xmin)
    zoom.x = x;
  else if (zoom.x < plot_xmin)
    { zoom.x = plot_xmin; zoom.clip = true; }
  else if (zoom.x > plot_xmax)
    { zoom.x = plot_xmax; zoom.clip = true; }

  if (y < plot_ytop) {
    zoom.y = y;
    if (plot_axis_x2min == "none") {
      zoom.x = x; zoom.clip = false;
      return zoom;
    }
  }

  else if (y > plot_ybot)
    zoom.y = y;
  else if (zoom.y > plot_ybot)
    { zoom.y = plot_ybot; zoom.clip = true; }
  else if (zoom.y < plot_ytop)
    { zoom.y = plot_ytop; zoom.clip = true; }

  return zoom;
}

function zoomW(w) { return (w*plot_axis_width/zoom_axis_width); }
function zoomH(h) { return (h*plot_axis_height/zoom_axis_height); }

function do_hotkey(event) {
    keychar = String.fromCharCode(event.charCode ? event.charCode : event.keyCode);
    switch (keychar) {
    case 'e':	ctx.clearRect(0,0,plot_term_xmax,plot_term_ymax);
		gnuplot_canvas();
		break;
    case 'g':	toggle_grid();
		break;
    case 'n':	rezoom();
		break;
    case 'r':
		ctx.lineWidth = 0.5;
		ctx.strokeStyle="rgba(128,128,128,0.50)";
		ctx.moveTo(plot_xmin, mousey); ctx.lineTo(plot_xmax, mousey);
		ctx.moveTo(mousex, plot_ybot); ctx.lineTo(mousex, plot_ytop);
		ctx.stroke();
		break;
    case 'p':
    case 'u':	unzoom();
		break;
    case '':	zoom_in_progress = false;
		break;

// Arrow keys
    case '%':	// ctx.drawText("sans", 10, mousex, mousey, "<");
		break;
    case '\'':	// ctx.drawText("sans", 10, mousex, mousey, ">");
		break;
    case '&':	// ctx.drawText("sans", 10, mousex, mousey, "^");
		break;
    case '(':	// ctx.drawText("sans", 10, mousex, mousey, "v");
		break;

    default:	// ctx.drawText("sans", 10, mousex, mousey, keychar);
		return true; // Let someone else handle it
		break;
    }
    return false; // Nobody else should respond to this keypress
}
