// USAGE
// This is a greasemonkey script for annotating web pages.  You can draw
// lines by holding down ALT and clicking and dragging anywhere on the page. 
// Pressing CTRL+SHIFT+K will clear all the lines on the page.
//
// Annotations are automatically stored on your computer when you browse
// away from the page and reappear when you come back to the page.
//
// There appears to be a bug in the canvas element in that you can't click
// through it unless the HTML elements under it have position:absolute
// set.  At times, this makes it impossible to click links, etc.  To
// work around this, pressing CTRL+SHIFT+T will toggle the visibility of the
// annotations.

// CHANGES
//
// 20050911 - first version
//
// This file is licensed under the BSD-new license:
// http://www.opensource.org/licenses/bsd-license.php
//
// Comments or questions about this script can be sent to 
// tony@ponderer.org

// ==UserScript==
// @name          scribbly
// @namespace     http://ponderer.org
// @description   draw on web sites and store it locally
// @include       http://*
// ==/UserScript==

var lastpos;
var isDrawing = false;
var CANVAS_ID = '__gm_canvas';
var color = 'rgba(200, 0, 0, 0.8)';
var line; // an array of points
var lines = []; // an array of line
var hasOldData = false;


function onMouseDown(e) {
  if (e.altKey) {
    GM_log('start line');
    isDrawing = true;
    lastpos = {x: e.pageX, y: e.pageY};
    line = [lastpos];
    
    // make sure we can see the canvas
    var elt = document.getElementById(CANVAS_ID);
    if (elt) {
      elt.style.display = '';
    }
  }
  return false;
}

// this is where all the drawing happens
function onMouseMove(e) {
  if (!isDrawing) return;
  
  var pos = {x: e.pageX, y: e.pageY};
  var ctx = getContext();
  
  ctx.moveTo(lastpos.x, lastpos.y);
  ctx.lineTo(pos.x, pos.y);
  ctx.stroke();

  line.push(pos);
  lastpos = pos;
}

function onMouseUp(e) {
  if (isDrawing) {
    isDrawing = false;
    lines.push(line);
  }
}

function getContext() {
  var elt = document.getElementById(CANVAS_ID);
  if (!elt) {
    GM_log('create canvas element');
    
    // canvas doesn't exist, create it
    var elt = document.createElement('canvas');
    elt.id = CANVAS_ID;
    // prevent scrollbar resizing by adding padding
    elt.width = parseInt(document.width) - 20;
    elt.height = parseInt(document.height);
    elt.style.top = 0;
    elt.style.left = 0;
    elt.style.position = 'absolute';
    document.body.insertBefore(elt, document.body.firstChild);
    
    // set context values
    var ctx = elt.getContext("2d");
    ctx.strokeStyle = color;
    ctx.lineWidth = 2.0;
  }
  return ctx || elt.getContext('2d');
}

// keyboard keys
function onKeyDown(e) {
  if (e.shiftKey && e.ctrlKey) {
    var key = String.fromCharCode(e.which);
    var canvas = document.getElementById(CANVAS_ID);
    switch(key) {
      case 'K':
        // clear the canvas
        canvas.parentNode.removeChild(canvas);
        lines = [];
        break;
      case 'T':
        // toggle canvas visibility
        canvas.style.display = canvas.style.display ? '' : 'none';
        break
    }
  }
}

function onUnload(e) {
  // save lines
  if (lines.length > 0) {
    GM_log('saving');
    GM_setValue(document.location.href, uneval(lines));
  } else if (hasOldData) {
    GM_log('saving');
    GM_setValue(document.location.href, '[]');
  }
}

function onLoad(e) {
  // load previously drawn data if it exists
  var str = GM_getValue(document.location.href);
  if (str) {
    lines = eval(str);
    if (lines.length > 0) {
      hasOldData = true;
      var ln, pt;
      var ctx = getContext();
      for (var i = 0; ln = lines[i]; ++i) {
        ctx.moveTo(ln[0].x, ln[0].y);
        for (var j = 1; pt = ln[j]; ++j) {
          ctx.lineTo(pt.x, pt.y);
        }
        ctx.stroke();
      }
    }
  }
}

// TODO: window resize (change size of canvas)
addEventListener('mousedown', onMouseDown, false);
addEventListener('mouseup', onMouseUp, false);
addEventListener('mousemove', onMouseMove, false);
addEventListener('keydown', onKeyDown, false);
addEventListener('load', onLoad, false);
addEventListener('unload', onUnload, false);

