remove dependence on PlotKit.Base as well
[dygraphs.git] / plotkit_v091 / PlotKit / Canvas.js
index d263192..a3a1e09 100644 (file)
@@ -1,57 +1,3 @@
-/* 
-    PlotKit Canvas
-    ==============
-    
-    Provides HTML Canvas Renderer. This is supported under:
-    
-    - Safari 2.0
-    - Mozilla Firefox 1.5
-    - Opera 9.0 preview 2
-    - IE 6 (via VML Emulation)
-    
-    It uses DIVs for labels.
-    
-    Copyright
-    ---------
-    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
-    For use under the BSD license. <http://www.liquidx.net/plotkit>
-    
-*/
-// --------------------------------------------------------------------
-// Check required components
-// --------------------------------------------------------------------
-
-try {    
-    if ((typeof(PlotKit.Base) == 'undefined') ||
-        (typeof(PlotKit.Layout) == 'undefined'))
-    {
-        throw "";    
-    }
-} 
-catch (e) {    
-    throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Base,Layout}"
-}
-
-
-// ------------------------------------------------------------------------
-//  Defines the renderer class
-// ------------------------------------------------------------------------
-
-if (typeof(PlotKit.CanvasRenderer) == 'undefined') {
-    PlotKit.CanvasRenderer = {};
-}
-
-PlotKit.CanvasRenderer.NAME = "PlotKit.CanvasRenderer";
-PlotKit.CanvasRenderer.VERSION = PlotKit.VERSION;
-
-PlotKit.CanvasRenderer.__repr__ = function() {
-    return "[" + this.NAME + " " + this.VERSION + "]";
-};
-
-PlotKit.CanvasRenderer.toString = function() {
-    return this.__repr__();
-}
-
 PlotKit.CanvasRenderer = function(element, layout, options) {
     if (arguments.length  > 0)
         this.__init__(element, layout, options);
@@ -63,15 +9,7 @@ PlotKit.CanvasRenderer.prototype.__init__ = function(element, layout, options) {
     
     // default options
     this.options = {
-        "drawBackground": true,
-        "backgroundColor": Color.whiteColor(),
-        "padding": {left: 30, right: 30, top: 5, bottom: 10},
-        "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),
-        "strokeColor": Color.whiteColor(),
-        "strokeColorTransform": "asStrokeColor",
         "strokeWidth": 0.5,
-        "shouldFill": true,
-        "shouldStroke": true,
         "drawXAxis": true,
         "drawYAxis": true,
         "axisLineColor": Color.blackColor(),
@@ -80,9 +18,7 @@ PlotKit.CanvasRenderer.prototype.__init__ = function(element, layout, options) {
         "axisLabelColor": Color.blackColor(),
         "axisLabelFont": "Arial",
         "axisLabelFontSize": 9,
-               "axisLabelWidth": 50,
-               "pieRadius": 0.4,
-        "enableEvents": true
+        "axisLabelWidth": 50,
     };
     MochiKit.Base.update(this.options, options ? options : {});
 
@@ -118,112 +54,17 @@ PlotKit.CanvasRenderer.prototype.__init__ = function(element, layout, options) {
     // internal state
     this.xlabels = new Array();
     this.ylabels = new Array();
-    this.isFirstRender = true;
 
     this.area = {
-        x: this.options.padding.left,
-        y: this.options.padding.top,
-        w: this.width - this.options.padding.left - this.options.padding.right,
-        h: this.height - this.options.padding.top - this.options.padding.bottom
+        x: this.options.yAxisLabelWidth + 2 * this.options.axisTickSize,
+        y: 0
     };
+    this.area.w = this.width - this.area.x - this.options.rightGap;
+    this.area.h = this.height - this.options.axisLabelFontSize -
+                  2 * this.options.axisTickSize;
 
     MochiKit.DOM.updateNodeAttributes(this.container, 
     {"style":{ "position": "relative", "width": this.width + "px"}});
-
-    // load event system if we have Signals
-    /* Disabled until we have a proper implementation
-    try {
-        this.event_isinside = null;
-        if (MochiKit.Signal && this.options.enableEvents) {
-            this._initialiseEvents();
-        }
-    }
-    catch (e) {
-        // still experimental
-    }
-    */
-};
-
-PlotKit.CanvasRenderer.prototype.render = function() {
-    if (this.isIE) {
-        // VML takes a while to start up, so we just poll every this.IEDelay
-        try {
-            if (this.renderDelay) {
-                this.renderDelay.cancel();
-                this.renderDelay = null;
-            }
-            var context = this.element.getContext("2d");
-        }
-        catch (e) {
-            this.isFirstRender = false;
-            if (this.maxTries-- > 0) {
-                this.renderDelay = MochiKit.Async.wait(this.IEDelay);
-                this.renderDelay.addCallback(bind(this.render, this));
-            }
-            return;
-        }
-    }
-
-    if (this.options.drawBackground)
-        this._renderBackground();
-
-    if (this.layout.style == "line") {
-        this._renderLineChart();
-               this._renderLineAxis();
-       }
-};
-
-PlotKit.CanvasRenderer.prototype._renderLineChart = function() {
-    var context = this.element.getContext("2d");
-    var colorCount = this.options.colorScheme.length;
-    var colorScheme = this.options.colorScheme;
-    var setNames = MochiKit.Base.keys(this.layout.datasets);
-    var setCount = setNames.length;
-    var bind = MochiKit.Base.bind;
-    var partial = MochiKit.Base.partial;
-
-    for (var i = 0; i < setCount; i++) {
-        var setName = setNames[i];
-        var color = colorScheme[i%colorCount];
-        var strokeX = this.options.strokeColorTransform;
-
-        // setup graphics context
-        context.save();
-        context.fillStyle = color.toRGBString();
-        if (this.options.strokeColor)
-            context.strokeStyle = this.options.strokeColor.toRGBString();
-        else if (this.options.strokeColorTransform) 
-            context.strokeStyle = color[strokeX]().toRGBString();
-        
-        context.lineWidth = this.options.strokeWidth;
-        
-        // create paths
-        var makePath = function(ctx) {
-            ctx.beginPath();
-            ctx.moveTo(this.area.x, this.area.y + this.area.h);
-            var addPoint = function(ctx_, point) {
-                if (point.name == setName)
-                    ctx_.lineTo(this.area.w * point.x + this.area.x,
-                                this.area.h * point.y + this.area.y);
-            };
-            MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
-            ctx.lineTo(this.area.w + this.area.x,
-                           this.area.h + this.area.y);
-            ctx.lineTo(this.area.x, this.area.y + this.area.h);
-            ctx.closePath();
-        };
-
-        if (this.options.shouldFill) {
-            bind(makePath, this)(context);
-            context.fill();
-        }
-        if (this.options.shouldStroke) {
-            bind(makePath, this)(context);
-            context.stroke();
-        }
-
-        context.restore();
-    }
 };
 
 
@@ -267,15 +108,33 @@ PlotKit.CanvasRenderer.prototype._renderAxis = function() {
                 context.stroke();
 
                 var label = DIV(labelStyle, tick[1]);
-                label.style.top = (y - this.options.axisLabelFontSize) + "px";
-                label.style.left = (x - this.options.padding.left - this.options.axisTickSize) + "px";
+                var top = (y - this.options.axisLabelFontSize / 2);
+                if (top < 0) top = 0;
+
+                if (top + this.options.axisLabelFontSize + 3 > this.height) {
+                  label.style.bottom = "0px";
+                } else {
+                  label.style.top = top + "px";
+                }
+                label.style.left = "0px";
                 label.style.textAlign = "right";
-                label.style.width = (this.options.padding.left - this.options.axisTickSize * 2) + "px";
+                label.style.width = this.options.yAxisLabelWidth + "px";
                 MochiKit.DOM.appendChildNodes(this.container, label);
                 this.ylabels.push(label);
             };
             
             MochiKit.Iter.forEach(this.layout.yticks, bind(drawTick, this));
+
+            // The lowest tick on the y-axis often overlaps with the leftmost
+            // tick on the x-axis. Shift the bottom tick up a little bit to
+            // compensate if necessary.
+            var bottomTick = this.ylabels[0];
+            var fontSize = this.options.axisLabelFontSize;
+            var bottom = parseInt(bottomTick.style.top) + fontSize;
+            if (bottom > this.height - fontSize) {
+              bottomTick.style.top = (parseInt(bottomTick.style.top) -
+                                      fontSize / 2) + "px";
+            }
         }
 
         context.beginPath();
@@ -299,10 +158,21 @@ PlotKit.CanvasRenderer.prototype._renderAxis = function() {
                 context.stroke();
 
                 var label = DIV(labelStyle, tick[1]);
-                label.style.top = (y + this.options.axisTickSize) + "px";
-                label.style.left = (x - this.options.axisLabelWidth/2) + "px";
                 label.style.textAlign = "center";
-                label.style.width = this.options.axisLabelWidth + "px";
+                label.style.bottom = "0px";
+
+                var left = (x - this.options.axisLabelWidth/2);
+                if (left + this.options.axisLabelWidth > this.width) {
+                  left = this.width - this.options.xAxisLabelWidth;
+                  label.style.textAlign = "right";
+                }
+                if (left < 0) {
+                  left = 0;
+                  label.style.textAlign = "left";
+                }
+
+                label.style.left = left + "px";
+                label.style.width = this.options.xAxisLabelWidth + "px";
                 MochiKit.DOM.appendChildNodes(this.container, label);
                 this.xlabels.push(label);
             };
@@ -321,14 +191,6 @@ PlotKit.CanvasRenderer.prototype._renderAxis = function() {
 
 };
 
-PlotKit.CanvasRenderer.prototype._renderBackground = function() {
-    var context = this.element.getContext("2d");
-    context.save();
-    context.fillStyle = this.options.backgroundColor.toRGBString();
-    context.fillRect(0, 0, this.width, this.height);
-    context.restore();
-};
-
 PlotKit.CanvasRenderer.prototype.clear = function() {
     if (this.isIE) {
         // VML takes a while to start up, so we just poll every this.IEDelay
@@ -340,7 +202,6 @@ PlotKit.CanvasRenderer.prototype.clear = function() {
             var context = this.element.getContext("2d");
         }
         catch (e) {
-            this.isFirstRender = false;
             this.clearDelay = MochiKit.Async.wait(this.IEDelay);
             this.clearDelay.addCallback(bind(this.clear, this));
             return;
@@ -360,87 +221,6 @@ PlotKit.CanvasRenderer.prototype.clear = function() {
 //  Everything below here is experimental and undocumented.
 // ----------------------------------------------------------------
 
-PlotKit.CanvasRenderer.prototype._initialiseEvents = function() {
-    var connect = MochiKit.Signal.connect;
-    var bind = MochiKit.Base.bind;
-    //MochiKit.Signal.registerSignals(this, ['onmouseover', 'onclick', 'onmouseout', 'onmousemove']);
-    //connect(this.element, 'onmouseover', bind(this.onmouseover, this));
-    //connect(this.element, 'onmouseout', bind(this.onmouseout, this));
-    //connect(this.element, 'onmousemove', bind(this.onmousemove, this));
-    connect(this.element, 'onclick', bind(this.onclick, this));
-};
-
-PlotKit.CanvasRenderer.prototype._resolveObject = function(e) {
-    // does not work in firefox
-       //var x = (e.event().offsetX - this.area.x) / this.area.w;
-       //var y = (e.event().offsetY - this.area.y) / this.area.h;
-
-    var x = (e.mouse().page.x - PlotKit.Base.findPosX(this.element) - this.area.x) / this.area.w;
-    var y = (e.mouse().page.y - PlotKit.Base.findPosY(this.element) - this.area.y) / this.area.h;
-       
-    //log(x, y);
-
-    var isHit = this.layout.hitTest(x, y);
-    if (isHit)
-        return isHit;
-    return null;
-};
-
-PlotKit.CanvasRenderer.prototype._createEventObject = function(layoutObj, e) {
-    if (layoutObj == null) {
-        return null;
-    }
-
-    e.chart = layoutObj
-    return e;
-};
-
-
-PlotKit.CanvasRenderer.prototype.onclick = function(e) {
-    var layoutObject = this._resolveObject(e);
-    var eventObject = this._createEventObject(layoutObject, e);
-    if (eventObject != null)
-        MochiKit.Signal.signal(this, "onclick", eventObject);
-};
-
-PlotKit.CanvasRenderer.prototype.onmouseover = function(e) {
-    var layoutObject = this._resolveObject(e);
-    var eventObject = this._createEventObject(layoutObject, e);
-    if (eventObject != null) 
-        signal(this, "onmouseover", eventObject);
-};
-
-PlotKit.CanvasRenderer.prototype.onmouseout = function(e) {
-    var layoutObject = this._resolveObject(e);
-    var eventObject = this._createEventObject(layoutObject, e);
-    if (eventObject == null)
-        signal(this, "onmouseout", e);
-    else 
-        signal(this, "onmouseout", eventObject);
-
-};
-
-PlotKit.CanvasRenderer.prototype.onmousemove = function(e) {
-    var layoutObject = this._resolveObject(e);
-    var eventObject = this._createEventObject(layoutObject, e);
-
-    if ((layoutObject == null) && (this.event_isinside == null)) {
-        // TODO: should we emit an event anyway?
-        return;
-    }
-
-    if ((layoutObject != null) && (this.event_isinside == null))
-        signal(this, "onmouseover", eventObject);
-
-    if ((layoutObject == null) && (this.event_isinside != null))
-        signal(this, "onmouseout", eventObject);
-
-    if ((layoutObject != null) && (this.event_isinside != null))
-        signal(this, "onmousemove", eventObject);
-
-    this.event_isinside = layoutObject;
-    //log("move", x, y);    
-};
 
 PlotKit.CanvasRenderer.isSupported = function(canvasName) {
     var canvas = null;
@@ -460,31 +240,3 @@ PlotKit.CanvasRenderer.isSupported = function(canvasName) {
     }
     return true;
 };
-
-// Namespace Iniitialisation
-
-PlotKit.Canvas = {}
-PlotKit.Canvas.CanvasRenderer = PlotKit.CanvasRenderer;
-
-PlotKit.Canvas.EXPORT = [
-    "CanvasRenderer"
-];
-
-PlotKit.Canvas.EXPORT_OK = [
-    "CanvasRenderer"
-];
-
-PlotKit.Canvas.__new__ = function() {
-    var m = MochiKit.Base;
-    
-    m.nameFunctions(this);
-    
-    this.EXPORT_TAGS = {
-        ":common": this.EXPORT,
-        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
-    };
-};
-
-PlotKit.Canvas.__new__();
-MochiKit.Base._exportSymbols(this, PlotKit.Canvas);
-