Round Corners Widget for GWT : Round Corner « GWT « Java

Home
Java
1.2D Graphics GUI
2.3D
3.Advanced Graphics
4.Ant
5.Apache Common
6.Chart
7.Class
8.Collections Data Structure
9.Data Type
10.Database SQL JDBC
11.Design Pattern
12.Development Class
13.EJB3
14.Email
15.Event
16.File Input Output
17.Game
18.Generics
19.GWT
20.Hibernate
21.I18N
22.J2EE
23.J2ME
24.JavaFX
25.JDK 6
26.JDK 7
27.JNDI LDAP
28.JPA
29.JSP
30.JSTL
31.Language Basics
32.Network Protocol
33.PDF RTF
34.Reflection
35.Regular Expressions
36.Scripting
37.Security
38.Servlets
39.Spring
40.Swing Components
41.Swing JFC
42.SWT JFace Eclipse
43.Threads
44.Tiny Application
45.Velocity
46.Web Services SOA
47.XML
Java » GWT » Round Corner 




Round Corners Widget for GWT



// Copyright 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// Known Issues:
//
// * Patterns are not implemented.
// * Radial gradient are not implemented. The VML version of these look very
//   different from the canvas one.
// * Clipping paths are not implemented.
// * Coordsize. The width and height attribute have higher priority than the
//   width and height style values which isn't correct.
// * Painting mode isn't implemented.
// * Canvas width/height should is using content-box by default. IE in
//   Quirks mode will draw the canvas using border-box. Either change your
//   doctype to HTML5
//   (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
//   or use Box Sizing Behavior from WebFX
//   (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
// * Optimize. There is always room for speed improvements.

// only add this code if we do not already have a canvas implementation
if (!window.CanvasRenderingContext2D) {

(function () {

  // alias some functions to make (compiled) code shorter
  var m = Math;
  var mr = m.round;
  var ms = m.sin;
  var mc = m.cos;

  // this is used for sub pixel precision
  var Z = 10;
  var Z2 = Z / 2;

  var G_vmlCanvasManager_ = {
    init: function (opt_doc) {
      var doc = opt_doc || document;
      if (/MSIE/.test(navigator.userAgent&& !window.opera) {
        var self = this;
        doc.attachEvent("onreadystatechange"function () {
          self.init_(doc);
        });
      }
    },

    init_: function (doc) {
      if (doc.readyState == "complete") {
        // create xmlns
        if (!doc.namespaces["g_vml_"]) {
          doc.namespaces.add("g_vml_""urn:schemas-microsoft-com:vml");
        }

        // setup default css
        var ss = doc.createStyleSheet();
        ss.cssText = "canvas{display:inline-block;overflow:hidden;" +
            // default size is 300x150 in Gecko and Opera
            "text-align:left;width:300px;height:150px}" +
            "g_vml_\\:*{behavior:url(#default#VML)}";

        // find all canvas elements
        var els = doc.getElementsByTagName("canvas");
        for (var i = 0; i < els.length; i++) {
          if (!els[i].getContext) {
            this.initElement(els[i]);
          }
        }
      }
    },

    fixElement_: function (el) {
      // in IE before version 5.5 we would need to add HTML: to the tag name
      // but we do not care about IE before version 6
      var outerHTML = el.outerHTML;

      var newEl = el.ownerDocument.createElement(outerHTML);
      // if the tag is still open IE has created the children as siblings and
      // it has also created a tag with the name "/FOO"
      if (outerHTML.slice(-2!= "/>") {
        var tagName = "/" + el.tagName;
        var ns;
        // remove content
        while ((ns = el.nextSibling&& ns.tagName != tagName) {
          ns.removeNode();
        }
        // remove the incorrect closing tag
        if (ns) {
          ns.removeNode();
        }
      }
      el.parentNode.replaceChild(newEl, el);
      return newEl;
    },

    /**
     * Public initializes a canvas element so that it can be used as canvas
     * element from now on. This is called automatically before the page is
     * loaded but if you are creating elements using createElement you need to
     * make sure this is called on the element.
     @param {HTMLElement} el The canvas element to initialize.
     @return {HTMLElement} the element that was created.
     */
    initElement: function (el) {
      el = this.fixElement_(el);
      el.getContext = function () {
        if (this.context_) {
          return this.context_;
        }
        return this.context_ = new CanvasRenderingContext2D_(this);
      };

      // do not use inline function because that will leak memory
      el.attachEvent('onpropertychange', onPropertyChange);
      el.attachEvent('onresize', onResize);

      var attrs = el.attributes;
      if (attrs.width && attrs.width.specified) {
        // TODO: use runtimeStyle and coordsize
        // el.getContext().setWidth_(attrs.width.nodeValue);
        el.style.width = attrs.width.nodeValue + "px";
      else {
        el.width = el.clientWidth;
      }
      if (attrs.height && attrs.height.specified) {
        // TODO: use runtimeStyle and coordsize
        // el.getContext().setHeight_(attrs.height.nodeValue);
        el.style.height = attrs.height.nodeValue + "px";
      else {
        el.height = el.clientHeight;
      }
      //el.getContext().setCoordsize_()
      return el;
    }
  };

  function onPropertyChange(e) {
    var el = e.srcElement;

    switch (e.propertyName) {
      case 'width':
        el.style.width = el.attributes.width.nodeValue + "px";
        el.getContext().clearRect();
        break;
      case 'height':
        el.style.height = el.attributes.height.nodeValue + "px";
        el.getContext().clearRect();
        break;
    }
  }

  function onResize(e) {
    var el = e.srcElement;
    if (el.firstChild) {
      el.firstChild.style.width =  el.clientWidth + 'px';
      el.firstChild.style.height = el.clientHeight + 'px';
    }
  }

  G_vmlCanvasManager_.init();

  // precompute "00" to "FF"
  var dec2hex = [];
  for (var i = 0; i < 16; i++) {
    for (var j = 0; j < 16; j++) {
      dec2hex[i * 16 + j= i.toString(16+ j.toString(16);
    }
  }

  function createMatrixIdentity() {
    return [
      [100],
      [010],
      [001]
    ];
  }

  function matrixMultiply(m1, m2) {
    var result = createMatrixIdentity();

    for (var x = 0; x < 3; x++) {
      for (var y = 0; y < 3; y++) {
        var sum = 0;

        for (var z = 0; z < 3; z++) {
          sum += m1[x][z* m2[z][y];
        }

        result[x][y= sum;
      }
    }
    return result;
  }

  function copyState(o1, o2) {
    o2.fillStyle     = o1.fillStyle;
    o2.lineCap       = o1.lineCap;
    o2.lineJoin      = o1.lineJoin;
    o2.lineWidth     = o1.lineWidth;
    o2.miterLimit    = o1.miterLimit;
    o2.shadowBlur    = o1.shadowBlur;
    o2.shadowColor   = o1.shadowColor;
    o2.shadowOffsetX = o1.shadowOffsetX;
    o2.shadowOffsetY = o1.shadowOffsetY;
    o2.strokeStyle   = o1.strokeStyle;
    o2.arcScaleX_    = o1.arcScaleX_;
    o2.arcScaleY_    = o1.arcScaleY_;
  }

  function processStyle(styleString) {
    var str, alpha = 1;

    styleString = String(styleString);
    if (styleString.substring(03== "rgb") {
      var start = styleString.indexOf("("3);
      var end = styleString.indexOf(")", start + 1);
      var guts = styleString.substring(start + 1end).split(",");

      str = "#";
      for (var i = 0; i < 3; i++) {
        str += dec2hex[Number(guts[i])];
      }

      if ((guts.length == 4&& (styleString.substr(31== "a")) {
        alpha = guts[3];
      }
    else {
      str = styleString;
    }

    return [str, alpha];
  }

  function processLineCap(lineCap) {
    switch (lineCap) {
      case "butt":
        return "flat";
      case "round":
        return "round";
      case "square":
      default:
        return "square";
    }
  }

  /**
   * This class implements CanvasRenderingContext2D interface as described by
   * the WHATWG.
   @param {HTMLElement} surfaceElement The element that the 2D context should
   * be associated with
   */
   function CanvasRenderingContext2D_(surfaceElement) {
    this.m_ = createMatrixIdentity();

    this.mStack_ = [];
    this.aStack_ = [];
    this.currentPath_ = [];

    // Canvas context properties
    this.strokeStyle = "#000";
    this.fillStyle = "#000";

    this.lineWidth = 1;
    this.lineJoin = "miter";
    this.lineCap = "butt";
    this.miterLimit = Z * 1;
    this.globalAlpha = 1;
    this.canvas = surfaceElement;

    var el = surfaceElement.ownerDocument.createElement('div');
    el.style.width =  surfaceElement.clientWidth + 'px';
    el.style.height = surfaceElement.clientHeight + 'px';
    el.style.overflow = 'hidden';
    el.style.position = 'absolute';
    surfaceElement.appendChild(el);

    this.element_ = el;
    this.arcScaleX_ = 1;
    this.arcScaleY_ = 1;
  };

  var contextPrototype = CanvasRenderingContext2D_.prototype;
  contextPrototype.clearRect = function() {
    this.element_.innerHTML = "";
    this.currentPath_ = [];
  };

  contextPrototype.beginPath = function() {
    // TODO: Branch current matrix so that save/restore has no effect
    //       as per safari docs.

    this.currentPath_ = [];
  };

  contextPrototype.moveTo = function(aX, aY) {
    this.currentPath_.push({type: "moveTo", x: aX, y: aY});
    this.currentX_ = aX;
    this.currentY_ = aY;
  };

  contextPrototype.lineTo = function(aX, aY) {
    this.currentPath_.push({type: "lineTo", x: aX, y: aY});
    this.currentX_ = aX;
    this.currentY_ = aY;
  };

  contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
                                            aCP2x, aCP2y,
                                            aX, aY) {
    this.currentPath_.push({type: "bezierCurveTo",
                           cp1x: aCP1x,
                           cp1y: aCP1y,
                           cp2x: aCP2x,
                           cp2y: aCP2y,
                           x: aX,
                           y: aY});
    this.currentX_ = aX;
    this.currentY_ = aY;
  };

  contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
    // the following is lifted almost directly from
    // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
    var cp1x = this.currentX_ + 2.0 3.0 (aCPx - this.currentX_);
    var cp1y = this.currentY_ + 2.0 3.0 (aCPy - this.currentY_);
    var cp2x = cp1x + (aX - this.currentX_3.0;
    var cp2y = cp1y + (aY - this.currentY_3.0;
    this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, aX, aY);
  };

  contextPrototype.arc = function(aX, aY, aRadius,
                                  aStartAngle, aEndAngle, aClockwise) {
    aRadius *= Z;
    var arcType = aClockwise ? "at" "wa";

    var xStart = aX + (mc(aStartAngle* aRadius- Z2;
    var yStart = aY + (ms(aStartAngle* aRadius- Z2;

    var xEnd = aX + (mc(aEndAngle* aRadius- Z2;
    var yEnd = aY + (ms(aEndAngle* aRadius- Z2;

    // IE won't render arches drawn counter clockwise if xStart == xEnd.
    if (xStart == xEnd && !aClockwise) {
      xStart += 0.125// Offset xStart by 1/80 of a pixel. Use something
                       // that can be represented in binary
    }

    this.currentPath_.push({type: arcType,
                           x: aX,
                           y: aY,
                           radius: aRadius,
                           xStart: xStart,
                           yStart: yStart,
                           xEnd: xEnd,
                           yEnd: yEnd});

  };

  contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
  };

  contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
    // Will destroy any existing path (same as FF behaviour)
    this.beginPath();
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.stroke();
  };

  contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
    // Will destroy any existing path (same as FF behaviour)
    this.beginPath();
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.fill();
  };

  contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
    var gradient = new CanvasGradient_("gradient");
    return gradient;
  };

  contextPrototype.createRadialGradient = function(aX0, aY0,
                                                   aR0, aX1,
                                                   aY1, aR1) {
    var gradient = new CanvasGradient_("gradientradial");
    gradient.radius1_ = aR0;
    gradient.radius2_ = aR1;
    gradient.focus_.x = aX0;
    gradient.focus_.y = aY0;
    return gradient;
  };

  contextPrototype.drawImage = function (image, var_args) {
    var dx, dy, dw, dh, sx, sy, sw, sh;

    // to find the original width we overide the width and height
    var oldRuntimeWidth = image.runtimeStyle.width;
    var oldRuntimeHeight = image.runtimeStyle.height;
    image.runtimeStyle.width = 'auto';
    image.runtimeStyle.height = 'auto';

    // get the original size
    var w = image.width;
    var h = image.height;

    // and remove overides
    image.runtimeStyle.width = oldRuntimeWidth;
    image.runtimeStyle.height = oldRuntimeHeight;

    if (arguments.length == 3) {
      dx = arguments[1];
      dy = arguments[2];
      sx = sy = 0;
      sw = dw = w;
      sh = dh = h;
    else if (arguments.length == 5) {
      dx = arguments[1];
      dy = arguments[2];
      dw = arguments[3];
      dh = arguments[4];
      sx = sy = 0;
      sw = w;
      sh = h;
    else if (arguments.length == 9) {
      sx = arguments[1];
      sy = arguments[2];
      sw = arguments[3];
      sh = arguments[4];
      dx = arguments[5];
      dy = arguments[6];
      dw = arguments[7];
      dh = arguments[8];
    else {
      throw "Invalid number of arguments";
    }

    var d = this.getCoords_(dx, dy);

    var w2 = sw / 2;
    var h2 = sh / 2;

    var vmlStr = [];

    var W = 10;
    var H = 10;

    // For some reason that I've now forgotten, using divs didn't work
    vmlStr.push(' <g_vml_:group',
                ' coordsize="', Z * W, ',', Z * H, '"',
                ' coordorigin="0,0"' ,
                ' style="width:', W, ';height:', H, ';position:absolute;');

    // If filters are necessary (rotation exists), create them
    // filters are bog-slow, so only create them if abbsolutely necessary
    // The following check doesn't account for skews (which don't exist
    // in the canvas spec (yet) anyway.

    if (this.m_[0][0] != 1 || this.m_[0][1]) {
      var filter = [];

      // Note the 12/21 reversal
      filter.push("M11='", this.m_[0][0]"',",
                  "M12='"this.m_[1][0]"',",
                  "M21='"this.m_[0][1]"',",
                  "M22='"this.m_[1][1]"',",
                  "Dx='", mr(d.x / Z)"',",
                  "Dy='", mr(d.y / Z)"'");

      // Bounding box calculation (need to minimize displayed area so that
      // filters don't waste time on unused pixels.
      var max = d;
      var c2 = this.getCoords_(dx + dw, dy);
      var c3 = this.getCoords_(dx, dy + dh);
      var c4 = this.getCoords_(dx + dw, dy + dh);

      max.x = Math.max(max.x, c2.x, c3.x, c4.x);
      max.y = Math.max(max.y, c2.y, c3.y, c4.y);

      vmlStr.push("padding:0 ", mr(max.x / Z)"px ", mr(max.y / Z),
                  "px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",
                  filter.join("")", sizingmethod='clip');")
    else {
      vmlStr.push("top:", mr(d.y / Z)"px;left:", mr(d.x / Z)"px;")
    }

    vmlStr.push(' ">' ,
                '<g_vml_:image src="', image.src, '"',
                ' style="width:', Z * dw, ';',
                ' height:', Z * dh, ';"',
                ' cropleft="', sx / w, '"',
                ' croptop="', sy / h, '"',
                ' cropright="', (w - sx - sw) / w, '"',
                ' cropbottom="', (h - sy - sh) / h, '"',
                ' />',
                '</g_vml_:group>');

    this.element_.insertAdjacentHTML("BeforeEnd",
                                    vmlStr.join(""));
  };

  contextPrototype.stroke = function(aFill) {
    var lineStr = [];
    var lineOpen = false;
    var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
    var color = a[0];
    var opacity = a[1this.globalAlpha;

    var W = 10;
    var H = 10;

    lineStr.push('<g_vml_:shape',
                 ' fillcolor="', color, '"',
                 ' filled="', Boolean(aFill), '"',
                 ' style="position:absolute;width:', W, ';height:', H, ';"',
                 ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
                 ' stroked="', !aFill, '"',
                 ' strokeweight="', this.lineWidth, '"',
                 ' strokecolor="', color, '"',
                 ' path="');

    var newSeq = false;
    var min = {x: null, y: null};
    var max = {x: null, y: null};

    for (var i = 0; i < this.currentPath_.length; i++) {
      var p = this.currentPath_[i];

      if (p.type == "moveTo") {
        lineStr.push(" ");
        var c = this.getCoords_(p.x, p.y);
        lineStr.push(mr(c.x), ",", mr(c.y));
      } else if (p.type == "lineTo") {
        lineStr.push(" ");
        var c = this.getCoords_(p.x, p.y);
        lineStr.push(mr(c.x), ",", mr(c.y));
      } else if (p.type == "close") {
        lineStr.push(" ");
      } else if (p.type == "bezierCurveTo") {
        lineStr.push(" ");
        var c = this.getCoords_(p.x, p.y);
        var c1 = this.getCoords_(p.cp1x, p.cp1y);
        var c2 = this.getCoords_(p.cp2x, p.cp2y);
        lineStr.push(mr(c1.x), ",", mr(c1.y), ",",
                     mr(c2.x), ",", mr(c2.y), ",",
                     mr(c.x), ",", mr(c.y));
      } else if (p.type == "at" || p.type == "wa") {
        lineStr.push(" ", p.type, " ");
        var c  = this.getCoords_(p.x, p.y);
        var cStart = this.getCoords_(p.xStart, p.yStart);
        var cEnd = this.getCoords_(p.xEnd, p.yEnd);

        lineStr.push(mr(c.x - this.arcScaleX_ * p.radius), ",",
                     mr(c.y - this.arcScaleY_ * p.radius), " ",
                     mr(c.x + this.arcScaleX_ * p.radius), ",",
                     mr(c.y + this.arcScaleY_ * p.radius), " ",
                     mr(cStart.x), ",", mr(cStart.y), " ",
                     mr(cEnd.x), ",", mr(cEnd.y));
      }


      // TODO: Following is broken for curves due to
      //       move to proper paths.

      // Figure out dimensions so we can do gradient fills
      // properly
      if(c) {
        if (min.x == null || c.x < min.x) {
          min.x = c.x;
        }
        if (max.x == null || c.x > max.x) {
          max.x = c.x;
        }
        if (min.y == null || c.y < min.y) {
          min.y = c.y;
        }
        if (max.y == null || c.y > max.y) {
          max.y = c.y;
        }
      }
    }
    lineStr.push(' ">');

    if (typeof this.fillStyle == "object") {
      var focus = {x: "50%", y: "50%"};
      var width = (max.x - min.x);
      var height = (max.y - min.y);
      var dimension = (width > height? width : height;

      focus.x = mr((this.fillStyle.focus_.x / width100 50"%";
      focus.y = mr((this.fillStyle.focus_.y / height100 50"%";

      var colors = [];

      // inside radius (%)
      if (this.fillStyle.type_ == "gradientradial") {
        var inside = (this.fillStyle.radius1_ / dimension * 100);

        // percentage that outside radius exceeds inside radius
        var expansion = (this.fillStyle.radius2_ / dimension * 100- inside;
      else {
        var inside = 0;
        var expansion = 100;
      }

      var insidecolor = {offset: null, color: null};
      var outsidecolor = {offset: null, color: null};

      // We need to sort 'colors' by percentage, from 0 > 100 otherwise ie
      // won't interpret it correctly
      this.fillStyle.colors_.sort(function (cs1, cs2) {
        return cs1.offset - cs2.offset;
      });

      for (var i = 0; i < this.fillStyle.colors_.length; i++) {
        var fs = this.fillStyle.colors_[i];

        colors.push( (fs.offset * expansion+ inside, "% ", fs.color, ",");

        if (fs.offset > insidecolor.offset || insidecolor.offset == null) {
          insidecolor.offset = fs.offset;
          insidecolor.color = fs.color;
        }

        if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) {
          outsidecolor.offset = fs.offset;
          outsidecolor.color = fs.color;
        }
      }
      colors.pop();

      lineStr.push('<g_vml_:fill',
                   ' color="', outsidecolor.color, '"',
                   ' color2="', insidecolor.color, '"',
                   ' type="', this.fillStyle.type_, '"',
                   ' focusposition="', focus.x, ', ', focus.y, '"',
                   ' colors="', colors.join(""), '"',
                   ' opacity="', opacity, '" />');
    else if (aFill) {
      lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, '" />');
    else {
      lineStr.push(
        '<g_vml_:stroke',
        ' opacity="', opacity,'"',
        ' joinstyle="', this.lineJoin, '"',
        ' miterlimit="', this.miterLimit, '"',
        ' endcap="', processLineCap(this.lineCap) ,'"',
        ' weight="', this.lineWidth, 'px"',
        ' color="', color,'" />'
      );
    }

    lineStr.push("</g_vml_:shape>");

    this.element_.insertAdjacentHTML("beforeEnd", lineStr.join(""));

    this.currentPath_ = [];
  };

  contextPrototype.fill = function() {
    this.stroke(true);
  }

  contextPrototype.closePath = function() {
    this.currentPath_.push({type: "close"});
  };

  /**
   * @private
   */
  contextPrototype.getCoords_ = function(aX, aY) {
    return {
      x: Z * (aX * this.m_[0][0+ aY * this.m_[1][0this.m_[2][0]) - Z2,
      y: Z * (aX * this.m_[0][1+ aY * this.m_[1][1this.m_[2][1]) - Z2
    }
  };

  contextPrototype.save = function() {
    var o = {};
    copyState(this, o);
    this.aStack_.push(o);
    this.mStack_.push(this.m_);
    this.m_ = matrixMultiply(createMatrixIdentity()this.m_);
  };

  contextPrototype.restore = function() {
    copyState(this.aStack_.pop()this);
    this.m_ = this.mStack_.pop();
  };

  contextPrototype.translate = function(aX, aY) {
    var m1 = [
      [1,  0,  0],
      [0,  1,  0],
      [aX, aY, 1]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  contextPrototype.rotate = function(aRot) {
    var c = mc(aRot);
    var s = ms(aRot);

    var m1 = [
      [c,  s, 0],
      [-s, c, 0],
      [0,  01]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  contextPrototype.scale = function(aX, aY) {
    this.arcScaleX_ *= aX;
    this.arcScaleY_ *= aY;
    var m1 = [
      [aX, 0,  0],
      [0,  aY, 0],
      [0,  0,  1]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  /******** STUBS ********/
  contextPrototype.clip = function() {
    // TODO: Implement
  };

  contextPrototype.arcTo = function() {
    // TODO: Implement
  };

  contextPrototype.createPattern = function() {
    return new CanvasPattern_;
  };

  // Gradient / Pattern Stubs
  function CanvasGradient_(aType) {
    this.type_ = aType;
    this.radius1_ = 0;
    this.radius2_ = 0;
    this.colors_ = [];
    this.focus_ = {x: 0, y: 0};
  }

  CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
    aColor = processStyle(aColor);
    this.colors_.push({offset: 1-aOffset, color: aColor});
  };

  function CanvasPattern_() {}

  // set up externs
  G_vmlCanvasManager = G_vmlCanvasManager_;
  CanvasRenderingContext2D = CanvasRenderingContext2D_;
  CanvasGradient = CanvasGradient_;
  CanvasPattern = CanvasPattern_;

})();

// if
//////////////////////////////////////////////////////

First, include this code on your HTML host page:

<!--[if IE]><script src="js/excanvas.js" type="text/javascript"></script><![endif]--> 

//////////////////////////////////////////////////////

/* how to use it

final Canvas ctx = new Canvas(200, 200);
           
ctx.beginPath();
ctx.arc(75,75,50,0,(float)Math.PI*2,true); // Outer circle
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,(float)Math.PI,false);   // Mouth (clockwise)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,(float)Math.PI*2,true);  // Left eye
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,(float)Math.PI*2,true);  // Right eye
ctx.stroke();

*/
Canvas.java:

/*
Round Corners Widget for GWT
Copyright (C) 2006 Alexei Sokolov http://gwt.components.googlepages.com/

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

*/

package com.gwt.components.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;

public class Canvas extends Widget {

    public static class DrawingStyle extends JavaScriptObject {
        protected DrawingStyle(int opaque) {
            super(opaque);
        }
    }

    public static class Gradient extends DrawingStyle {
        public Gradient(int opaque) {
            super(opaque);
        }

        protected static native void addColorStop(JavaScriptObject obj,
                float offset, String color/*-{
         obj.addColorStop(offset, color);
        }-*/;
    }

    public static class LinearGradient extends Gradient {
        public LinearGradient(int opaque) {
            super(opaque);
        }

        public LinearGradient addColorStop(float offset, String color) {
            Gradient.addColorStop(this, offset, color);
            return this;
        }
    }

    public static class RadialGradient extends Gradient {
        public RadialGradient(int opaque) {
            super(opaque);
        }

        public RadialGradient addColorStop(float offset, String color) {
            Gradient.addColorStop(this, offset, color);
            return this;
        }
    }

    public static class Pattern extends DrawingStyle {
        protected Pattern(int opaque) {
            super(opaque);
        }

    }

    private JavaScriptObject context;

    public Canvas(int width, int height) {
        setElement(DOM.createDiv());
        Element canvas = DOM.createElement("canvas");
        DOM.setAttribute(canvas, "width", String.valueOf(width));
        DOM.setAttribute(canvas, "height", String.valueOf(height));
        DOM.appendChild(getElement(), canvas);
        setStyleName("gwt-Canvas");

        init();

        setFillStyle("black");
        setStrokeColor("black");
    }

    public native static boolean isEmulation() /*-{
     return (typeof $wnd.G_vmlCanvasManager != "undefined");
    }-*/;

    protected native void init() /*-{
     var el = [email protected]::getElement()().firstChild;
     if (typeof $wnd.G_vmlCanvasManager != "undefined") {
     
     var parent = el.parent;
     
     el = $wnd.G_vmlCanvasManager.fixElement_(el);
     el.getContext = function () {
     if (this.context_) {
     return this.context_;
     }
     return this.context_ = new $wnd.CanvasRenderingContext2D(el);
     };

     el.attachEvent("onpropertychange", function (e) {
     // we need to watch changes to width and height
     switch (e.propertyName) {
     case "width":
     case "height":
     // coord size changed?
     break;
     }
     });

     // if style.height is set

     var attrs = el.attributes;
     if (attrs.width && attrs.width.specified) {
     // TODO: use runtimeStyle and coordsize
     // el.getContext().setWidth_(attrs.width.nodeValue);
     el.style.width = attrs.width.nodeValue + "px";
     }
     if (attrs.height && attrs.height.specified) {
     // TODO: use runtimeStyle and coordsize
     // el.getContext().setHeight_(attrs.height.nodeValue);
     el.style.height = attrs.height.nodeValue + "px";
     }
     }
     [email protected]::context = el.getContext("2d");
    }-*/;

    public native void saveContext() /*-{
     [email protected]::context.save();
    }-*/;

    public native void restoreContext() /*-{
     [email protected]::context.restore();
    }-*/;

    public native void scale(float x, float y/*-{
     [email protected]::context.scale(x, y);   
    }-*/;

    public native void rotate(float angle)/*-{
     [email protected]::context.rotate(angle);   
    }-*/;

    public native void translate(float x, float y/*-{
     [email protected]::context.translate(x, y);   
    }-*/;

    public native void transform(float m11, float m12, float m21, float m22,
            float dx, float dy/*-{
     [email protected]::context.transform(
      m11, m12, m21, m22, dx, dy);   
    }-*/;

    public native void setTransform(float m11, float m12, float m21, float m22,
            float dx, float dy/*-{
     [email protected]::context.setTransform(
      m11, m12, m21, m22, dx, dy);   
    }-*/;

    public native float getGlobalAlpha() /*-{
     return [email protected]::context.globalAlpha;
    }-*/;

    public native void setGlobalAlpha(float alpha/*-{
     [email protected]::context.globalAlpha = alpha;
    }-*/;

    public native String getGlobalCompositeOperation() /*-{
     return [email protected]::context.globalCompositeOperation;
    }-*/;

    public native void setGlobalCompositeOperation(String operation/*-{
     [email protected]::context.globalCompositeOperation = 
      operation;
    }-*/;

    public native void setStrokeStyle(DrawingStyle style/*-{
     [email protected]::context.strokeStyle = style;
    }-*/;

    public native void setStrokeColor(String color/*-{
     [email protected]::context.strokeStyle = color;
    }-*/;

    public native void setFillStyle(DrawingStyle style/*-{
     [email protected]::context.fillStyle = style;
    }-*/;

    public native void setFillStyle(String style/*-{
     [email protected]::context.fillStyle = style;
    }-*/;

    public native LinearGradient createLinearGradient(float x0, float y0,
            float x1, float y1/*-{
     return [email protected]::context.createLinearGradient(
      x0, y0, x1, y1);   
    }-*/;

    public native RadialGradient createRadialGradient(float x0, float y0,
            float r0, float x1, float y1, float r1/*-{
     return [email protected]::context.createRadialGradient(
      x0, y0, r0, x1, y1, r1);   
    }-*/;

    public native Pattern createPattern(Image img, String repetition/*-{
     var elem = [email protected]::getElement()();
     var ctx = [email protected]::context;
     if (ctx.createPattern)
     return ctx.createPattern(elem, repetition);
     return null;   
    }-*/;

    public native float getLineWidth() /*-{
     return [email protected]::context.lineWidth;
    }-*/;

    public native void setLineWidth(float lineWidth/*-{
     [email protected]::context.lineWidth = lineWidth;
    }-*/;

    public native String getLineCap() /*-{
     return [email protected]::context.lineCap;
    }-*/;

    public native void setLineCap(String lineCap/*-{
     [email protected]::context.lineCap = lineCap;
    }-*/;

    public native String getLineJoin() /*-{
     return [email protected]::context.lineJoin;
    }-*/;

    public native void setLineJoin(String lineJoin/*-{
     [email protected]::context.lineJoin = lineJoin;
    }-*/;

    public native float getMiterLimit() /*-{
     return [email protected]::context.miterLimit;
    }-*/;

    public native void setMiterLimit(float miterLimit/*-{
     [email protected]::context.miterLimit = miterLimit;
    }-*/;

    public native float getShadowOffsetX() /*-{
     return [email protected]::context.shadowOffsetX;
    }-*/;

    public native void setShadowOffsetX(float x/*-{
     [email protected]::context.shadowOffsetX = x;
    }-*/;

    public native float getShadowOffsetY() /*-{
     return [email protected]::context.shadowOffsetY;
    }-*/;

    public native void setShadowOffsetY(float y/*-{
     [email protected]::context.shadowOffsetY = y;
    }-*/;

    public native float getShadowBlur() /*-{
     return [email protected]::context.shadowBlur;
    }-*/;

    public native void setShadowBlur(float blur/*-{
     [email protected]::context.shadowBlur = blur;
    }-*/;

    public native String getShadowColor() /*-{
     return [email protected]::context.shadowColor;
    }-*/;

    public native void setShadowColor(String style/*-{
     [email protected]::context.shadowColor = style;
    }-*/;

    public native void clearRect(float x, float y, float w, float h/*-{
     var ctx = [email protected]::context;
     if (typeof $wnd.G_vmlCanvasManager != "undefined") {
     var el = [email protected]::getElement()();
     if (el.currentStyle) {
     var color = el.currentStyle['background-color'];
     if (!color) {
     color = '#ffffff';
     }
     ctx.save();
     ctx.fillStyle = color;
     ctx.fillRect(x, y, w, h);
     ctx.restore();
     }
     } else {
     ctx.clearRect(x, y, w, h);
     }
    }-*/;

    public native void fillRect(float x, float y, float w, float h/*-{
     [email protected]::context.fillRect(x, y, w, h);
    }-*/;

    public native void strokeRect(float x, float y, float w, float h/*-{
     [email protected]::context.strokeRect(x, y, w, h);
    }-*/;

    public native void beginPath() /*-{
     [email protected]::context.beginPath();
    }-*/;

    public native void closePath() /*-{
     [email protected]::context.closePath();
    }-*/;

    public native void moveTo(float x, float y/*-{
     [email protected]::context.moveTo(x,y);
    }-*/;

    public native void lineTo(float x, float y/*-{
     [email protected]::context.lineTo(x,y);
    }-*/;

    public native void quadraticCurveTo(float cpx, float cpy, float x, float y/*-{
     [email protected]::context.quadraticCurveTo(cpx, cpy, x, y);
    }-*/;

    public native void bezierCurveTo(float cp1x, float cp1y, float cp2x,
            float cp2y, float x, float y/*-{
     [email protected]::context.bezierCurveTo(
      cp1x, cp1y, cp2x, cp2y, x, y);
    }-*/;

    public native void arcTo(float x1, float y1, float x2, float y2,
            float radius/*-{
     [email protected]::context.arcTo(x1, y1, x2, y2, radius);
    }-*/;

    public native void rect(float x, float y, float w, float h/*-{
     [email protected]::context.rect(x, y, w, h);
    }-*/;

    public native void arc(float x, float y, float radius, float startAngle,
            float endAngle, boolean anticlockwise/*-{
     [email protected]::context.arc(
      x, y, radius, startAngle, endAngle, anticlockwise);
    }-*/;

    public native void fill() /*-{
     [email protected]::context.fill();
    }-*/;

    public native void stroke() /*-{
     [email protected]::context.stroke();
    }-*/;

    public native void clip() /*-{
     [email protected]::context.clip();
    }-*/;

    public native boolean isPointInPath(float x, float y/*-{
     [email protected]::context.isPointInPath(x, y);
    }-*/;
}

/*
Canvas.css:

.gwt-Canvas {
    width:400px;
    height:400px;
    border: 1px solid black;
}
*/
           
       














Related examples in the same category
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.