﻿/********************************************************************
FileName:       CanvasObjects.js
FileRelation:   CanvasHomeDisplay.js
Author:         Allen Chen
Created On:     2/25/2011
Update On:      3/7/2011 [Allen] fix image fail to load
                4/6/2011 [Allen] make image clickable
Description:    Defines objects and respective DrawObjects class
Technology:     HTML5 Canvas
********************************************************************/
//****************************** CanvasImage ******************************* START
function CanvasImage(intX, intY, intWidth, intHeight, fltRotateDegree, intBorderWidth, strBorderColor
	                        , intShadowOffsetX, intShadowOffsetY, imgDisplay, strURL) {
    this.intX = (intX == null) ? 0 : intX;
    this.intY = (intY == null) ? 0 : intY;
    this.intWidth = (intWidth == null) ? 0 : intWidth;
    this.intHeight = (intHeight == null) ? 0 : intHeight;
    this.fltRotateDegree = (fltRotateDegree == null) ? 0 : fltRotateDegree;
    this.intBorderWidth = (intBorderWidth == null) ? 0 : intBorderWidth;
    this.strBorderColor = (strBorderColor == null) ? "white" : strBorderColor;
    this.intShadowOffsetX = (intShadowOffsetX == null) ? 0 : intShadowOffsetX;
    this.intShadowOffsetY = (intShadowOffsetY == null) ? 0 : intShadowOffsetY;
    this.image = imgDisplay;
    this.strURL = (strURL == null || strURL.toLowerCase() == "null") ? null : strURL;

    //Private initialization
    this.fltRotateRadian = DegreeToRadian(this.fltRotateDegree);
    function DegreeToRadian(fltDegree) {
        return (fltDegree * Math.PI) / 180;
    }

    //Debugging functions
    function DebugCanvasImage(objCanvasImage) {
        var div = document.getElementById("divDimension");
        if (document.getElementById("divDimension") == null) {
            div = document.createElement("div");
            div.setAttribute("id", "divDimension");
            document.body.appendChild(div);
        }
        spaces = "&nbsp&nbsp&nbsp";
        div.innerHTML =
                "<p>"
                    + "X : " + objCanvasImage.intX + spaces + " Y : " + objCanvasImage.intY + "<br/>"
                    + "Width : " + objCanvasImage.intWidth + spaces + " Height : " + objCanvasImage.intHeight + "<br/>"
                    + "BorderWidth : " + objCanvasImage.intBorderWidth + spaces + " BorderColor : " + objCanvasImage.strBorderColor + "<br/>"
                    + "ShadowOffsetX : " + objCanvasImage.intShadowOffsetX + spaces + " ShadowOffsetY : " + objCanvasImage.intShadowOffsetY + "<br/>"
                + "</p>";
    }
}
//****************************** CanvasImage ******************************* END

//************* CanvasDrawImage(CanvasImageArray,strBackgroundColor) ********** START
function CanvasDrawImage(objCanvasImageArray, strBackgroundColor) {
    //Main
    canvas = document.getElementById("myCanvas");
    context = canvas.getContext("2d");
    var redirectArray = new Array();
    DrawBackground(strBackgroundColor);
    try {
        for (i = 0; i < objCanvasImageArray.length; i++) {
            Draw(objCanvasImageArray[i]);
        }
    }
    catch (e) {
        //Images may fail to load
    }

    //Methods
    function Draw(objCanvasImage) {
        //Border + Shadow needs to be drawn before image
        DrawShadow(objCanvasImage);
        DrawBorder(objCanvasImage);
        DrawImage(objCanvasImage);
        if (objCanvasImage.strURL != null)
            DefineClickableRegion(objCanvasImage);
    }
    function DefineClickableRegion(objCanvasImage) {
        x = objCanvasImage.intX;
        y = objCanvasImage.intY;
        w = objCanvasImage.intWidth;
        h = objCanvasImage.intHeight;
        degree = objCanvasImage.fltRotateRadian;
        cos = Math.cos(degree);
        sin = Math.sin(degree);

        coord1 = CoordRotationAboutOrigin(x, y, cos, sin);
        coord2 = CoordRotationAboutOrigin(x + w, y, cos, sin);
        coord3 = CoordRotationAboutOrigin(x + w, y + h, cos, sin);

        redirectArray.push({ c1: coord1, c2: coord2, c3: coord3, url: objCanvasImage.strURL });
    }
    function CoordRotationAboutOrigin(x, y, cos, sin) {
        newX = Math.round((x * cos) - (y * sin));
        newY = Math.round((x * sin) + (y * cos));
        return { rX: newX, rY: newY };
    }
    this.isPointInImage = function(x, y) {
        //DebugIsPointInImage(x, y);
        for (i = redirectArray.length - 1; i >= 0; i--) {
            y1 = redirectArray[i].c1.rY;
            y2 = redirectArray[i].c2.rY;
            y3 = redirectArray[i].c3.rY;
            x1 = redirectArray[i].c1.rX;
            x2 = redirectArray[i].c2.rX;
            x3 = redirectArray[i].c3.rX;
            slope1 = (y2 - y1) / (x2 - x1);
            slope2 = (y3 - y2) / (x3 - x2);
            //DebugPoints(x, y, y1, y2, y3, x1, x2, x3, slope1, slope2);
            if (isPointYTrue("greater", slope1, x, y, x1, y1)
                && isPointXTrue("less", slope2, x, y, x2, y2)
                && isPointYTrue("less", slope1, x, y, x3, y3)
                && isPointXTrue("greater", slope2, x, y, x1, y1)) {
                //div = document.getElementById("divPoints");
                //div.innerHTML += "<br/> Success";
                return redirectArray[i].url;
            }
        }
        return null;
    }
    function isPointYTrue(testCase, m, x, y, x1, y1) {
        testCase = testCase.toLowerCase();
        //DebugIsPointTrue(testCase, m, x, y, x1, y1);
        line = m * (x - x1) + y1;
        switch (testCase) {
            case "greater":
                return y >= line;
                break;
            case "less":
                return y <= line;
                break; 
        }
    }
    function isPointXTrue(testCase, m, x, y, x1, ya) {
        testCase = testCase.toLowerCase();
        //DebugIsPointTrue(testCase, m, x, y, x1, y1);
        line = ((y - y1) / m) + x1;
        switch (testCase) {
            case "greater":
                return x >= line;
                break;
            case "less":
                return x <= line;
                break;
        }
    }
    function DebugPoints(x, y, y1, y2, y3, x1, x2, x3, m1, m2) {
        var div = document.getElementById("divPoints");
        if (document.getElementById("divPoints") == null) {
            div = document.createElement("div");
            div.setAttribute("id", "divPoints");
            document.body.appendChild(div);
        }
        div.innerHTML = "(" + x1 + " , " + y1 + ") <br/>"
                + "(" + x2 + " , " + y2 + ") <br/>"
                + "(" + x3 + " , " + y3 + ") <br/>"
                + "Line1 : y >= " + m1 + " * (x - " + x1 + ") + " + y1 + "<br/>"
                + "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp " + y + " >= " + parseInt(m1 * (x - x1) + y1) + "<br/>"
                + "Line2 : x <= ((" + y + " - " + y2 + ")) / " + m2 + " + " + x2 + "<br/>"
                + "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp " + x + " <= " + parseInt(((y - y2) / m2) + x2) + "<br/>"
                + "Line3 : y <= " + m1 + " * (x - " + x3 + ") + " + y3 + "<br/>"
                + "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp " + y + " <= " + parseInt(m1 * (x - x3) + y3) + "<br/>"
                + "Line4 : x >= ((" + y + " - " + y1 + ")) / " + m2 + " + " + x1 + "<br/>"
                + "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp " + x + " >= " + parseInt(((y - y1) / m2) + x1) + "<br/>"
    }
    function DebugIsPointTrue(testCase, m, x, y, x1, y1) {
        var div = document.getElementById("divIsPointTrue");
        if (document.getElementById("divIsPointTrue") == null) {
            div = document.createElement("div");
            div.setAttribute("id", "divIsPointTrue");
            document.body.appendChild(div);
        }
        div.innerHTML += testCase + " : x = " + x + " y = " + y + "<br/>"
        + y + " = " + m + " * (" + x + " - " + x1 + ") + " + y1 + "<br/>"
        + y + " " + testCase + " " + parseInt(m * (x - x1) + y1) + "<br/>";
    }
    function DrawImage(objCanvasImage) {
        var width = objCanvasImage.intWidth;
        var height = objCanvasImage.intHeight;
        var rotate = objCanvasImage.fltRotateRadian;
        var x = objCanvasImage.intX;
        var y = objCanvasImage.intY;
        var borderWidth = objCanvasImage.intBorderWidth;
        if (borderWidth > 0) {
            //Shrinks image if border is defined
            width -= 2 * borderWidth;
            height -= 2 * borderWidth;
            x += borderWidth;
            y += borderWidth;
        }

        if (objCanvasImage.image.complete) {
            context.save();
            context.rotate(rotate);
            context.drawImage(objCanvasImage.image, x, y, width, height);
            context.restore();
        }
//        else {
//            objCanvasImage.image.onload = ClosureFunction(objCanvasImage.image, x, y, width
//                                                            , height, rotate, objCanvasImage);
//        }
        objCanvasImage.image.src = objCanvasImage.image.src;
    }
    function ClosureFunction(img, x, y, w, h, r, objCanvasImage) {
        return function() {
            context.save();
            context.rotate(r);
            context.drawImage(img, x, y, w, h);
            context.restore();
        }
    }
    function DrawBackground(color) {
        if (color == null || color == "") color = "white"; //default background to white
        context.save();
        context.beginPath();
        context.rect(0, 0, canvas.width, canvas.height);
        context.fillStyle = color;
        context.fill();
        context.restore();
    }
    function DrawShadow(objCanvasImage) {
        context.save();
        context.beginPath();
        context.rotate(objCanvasImage.fltRotateRadian);
        context.rect(objCanvasImage.intX, objCanvasImage.intY, objCanvasImage.intWidth, objCanvasImage.intHeight);
        context.shadowColor = "black";
        context.shadowOffsetX = objCanvasImage.intShadowOffsetX;
        context.shadowOffsetY = objCanvasImage.intShadowOffsetY;
        context.shadowBlur = 20;
        context.globalAlpha = 0.5;
        context.fill();
        context.restore();
    }
    function DrawBorder(objCanvasImage) {
        context.save();
        context.beginPath();
        context.rotate(objCanvasImage.fltRotateRadian);
        context.rect(objCanvasImage.intX, objCanvasImage.intY, objCanvasImage.intWidth, objCanvasImage.intHeight);
        context.fillStyle = objCanvasImage.strBorderColor;
        context.fill();
        context.restore();
    }
}
//************* CanvasDrawImage(CanvasImageArray,strBackgroundColor) ********** END

//****************************** CanvasText ******************************* START
function CanvasTitle(intX, intY, strText, strFont, strColor, strURL, intTextHeight) {
    this.intX = (intX == null) ? 0 : intX;
    this.intY = (intY == null) ? 0 : intY;
    this.strText = (strText == null) ? "" : strText;
    this.strFont = (strFont == null || strFont == "") ? "14pt Verdana bold" : strFont;
    this.strColor = (strColor == null) ? "black" : strColor;
    this.strURL = (strURL == null || strURL.toLowerCase() == "null") ? null : strURL;
    this.intTextHeight = (intTextHeight == null || intTextHeight == 0) ? null : intTextHeight;
}
//****************************** CanvasText ******************************* END

//****************************** CanvasDrawTitle(CanvasTitleArray) ***************** START
function CanvasDrawTitle(objCanvasTitleArray) {
    //Main
    canvas = document.getElementById("myCanvas");
    context = canvas.getContext("2d");
    redirectArray = new Array();
    try {
        for (i = 0; i < objCanvasTitleArray.length; i++) {
            Draw(objCanvasTitleArray[i]);
            FormatURL(objCanvasTitleArray[i]);
        }
    }
    catch (e) { ; }

    //Methods
    function Draw(objCanvasTitle) {
        context.save();
        context.font = objCanvasTitle.strFont;
        context.fillStyle = objCanvasTitle.strColor;
        context.fillText(objCanvasTitle.strText, objCanvasTitle.intX, objCanvasTitle.intY);
        context.restore();
    }
    function FormatURL(objCanvasTitle) {
        if (objCanvasTitle.strURL != null && objCanvasTitle.strURL != "null") {
            //Define region
            var height, width;
            dimension = MeasureText(objCanvasTitle.strText, objCanvasTitle.strFont);
            if (objCanvasTitle.intTextHeight != null && objCanvasTitle.intTextHeight > 0)
                height = objCanvasTitle.intTextHeight;
            else
                height = dimension.h;
            width = dimension.w;
            redirectArray.push({ x: objCanvasTitle.intX, y: objCanvasTitle.intY - height, w: width, h: height, url: objCanvasTitle.strURL });
        }
    }
    function MeasureText(text, font) {
        context.save();
        context.font = font;
        height = context.measureText("ee").width;  //Assumption : height = "ee".width
        width = context.measureText(text).width;
        context.restore();
        return { h: height, w: width };
    }
    this.isPointInText = function(x, y) {
        for (i = 0; i < redirectArray.length; i++) {
            if (x >= redirectArray[i].x && x <= (redirectArray[i].x + redirectArray[i].w)
                    && y >= redirectArray[i].y && y <= (redirectArray[i].y + redirectArray[i].h)) {
                return redirectArray[i].url;
            }
        }
        return null;
    }
}
//****************************** CanvasDrawTitle(CanvasTitleArray) ***************** END

//****************************** CanvasTab ***************** START
function CanvasTab(strText, strFont, strTextColor, strTabColor, strTabSelectedColor, intTabWidth, intTabHeight
                            , intPadding, intSpacing) {
    this.strText = (strText == null) ? "" : strText;
    this.strFont = (strFont == null || strFont == "") ? "8pt Verdana bold" : strFont;
    this.strTextColor = (strTextColor == null || strTextColor == "") ? "black" : strTextColor;
    this.strTabColor = (strTabColor == null || strTabColor == "") ? "white" : strTabColor;
    this.strTabSelectedColor = (strTabSelectedColor == null || strTabSelectedColor == "")
                ? "red" : strTabSelectedColor;
    this.intTabWidth = (intTabWidth == null || intTabWidth == 0) ? null : intTabWidth; //Default : Dynamic
    this.intTabHeight = (intTabHeight == null || intTabHeight == 0) ? null : intTabHeight; //Default : Dynamic
    this.intPadding = (intPadding == null || intPadding == 0) ? 3 : intPadding; //Default : Dynamic
    this.intSpacing = (intSpacing == null || intSpacing == 0) ? null : intSpacing; //Default : Dynamic
}
//****************************** CanvasTab ***************** END

//*************** CanvasDrawTab(CanvasTabArray,intX,intY,intPadding,intSpacing) *********** START
function CanvasDrawTab(objCanvasTabArray, intX, intY, selectedIndex) {
    //Global variables
    posX = intX;
    posY = intY;
    tabDimension = new Array(); //stores dimension of tabs : used for mouseEvents

    //Main
    canvas = document.getElementById("myCanvas");
    context = canvas.getContext("2d");
    try {
        for (i = 0; i < objCanvasTabArray.length; i++) {
            if (selectedIndex == i)
                Draw(objCanvasTabArray[i], i, true);
            else
                Draw(objCanvasTabArray[i], i, false);
        }
    }
    catch (e) { ; }

    //Methods
    function Draw(objCanvasTab, index, blnHighlight) {
        context.font = objCanvasTab.strFont;
        tabWidth = context.measureText(objCanvasTab.strText).width;
        if (objCanvasTab.intTabWidth != null && objCanvasTab.intTabWidth > tabWidth) {
            textWidth = objCanvasTab.intTabWidth;
        }
        tabWidth += (objCanvasTab.intPadding == null) ? 0 : objCanvasTab.intPadding;
        tabHeight = (objCanvasTab.intTabHeight == null) ? 20 : objCanvasTab.intTabHeight; //Static Tab Height 20
        tabSpacing = (objCanvasTab.intSpacing == null) ? 1 : objCanvasTab.intSpacing; //Static Tab Spacing
        tabPadding = objCanvasTab.intPadding;
        //Add padding to tab
        tabWidth += 2 * tabPadding
        tabHeight += 2 * tabPadding
        //Add spacing to left
        posX += tabSpacing;

        if (blnHighlight == true) DrawRoundRect(posX, posY, tabWidth, tabHeight, objCanvasTab.strTabSelectedColor);
        else DrawRoundRect(posX, posY, tabWidth, tabHeight, objCanvasTab.strTabColor);
        DrawText(objCanvasTab.strText, posX + tabPadding, posY + tabPadding, objCanvasTab.strTextColor, objCanvasTab.strFont);
        tabDimension.push({ x: posX, y: posY, w: tabWidth, h: tabHeight }); //Define dimension

        //Move to next x
        posX += tabWidth;
    }
    function DrawRoundRect(posX, posY, width, height, color) {
        radius = 8;

        context.save();
        context.beginPath();
        context.moveTo(posX + radius, posY);
        context.lineTo(posX + width - radius, posY);
        context.quadraticCurveTo(posX + width, posY, posX + width, posY + radius);
        context.lineTo(posX + width, posY + height - radius);
        context.quadraticCurveTo(posX + width, posY + height, posX + width - radius, posY + height);
        context.lineTo(posX + radius, posY + height);
        context.quadraticCurveTo(posX, posY + height, posX, posY + height - radius);
        context.lineTo(posX, posY + radius);
        context.quadraticCurveTo(posX, posY, posX + radius, posY);
        context.closePath();
        context.globalAlpha = 0.6;
        context.fillStyle = color;
        context.fill();
        context.restore();

    }
    function DrawText(text, x, y, color, font) {
        context.save();
        context.fillStyle = color;
        context.font = font;
        context.textBaseline = "top";
        context.fillText(text, x, y);
        context.restore();
    }
    this.isPointInTab = function(x, y) {
        for (i = 0; i < tabDimension.length; i++) {
            if (x >= tabDimension[i].x && x <= (tabDimension[i].x + tabDimension[i].w)
                     && y >= tabDimension[i].y && y <= (tabDimension[i].y + tabDimension[i].h)) {
                return i;
            }
        }
        return -1;
    }
}
//*************** CanvasDrawTab(CanvasTabArray,intX,intY,intPadding,intSpacing) ************ END
