UNPKG

sku-pg

Version:

Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!

971 lines (842 loc) 32.5 kB
// Copyright 2007 The Closure Library Authors. All Rights Reserved. // // 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. /** * @fileoverview Class definitions for imageless rounded corners. * * NOTE: This technique uses one Canvas or VML element per corner, and is quite * slow. The border-radius CSS property is preferable, but not available in all * browsers. ImagelessRoundedCorner should be avoided where performance is * critical. * * @supported IE 6.0+, Safari 2.0+, Firefox 1.5+, Opera 9.2+. * * @see ../demos/imagelessroundedcorner.html */ goog.provide('goog.ui.AbstractImagelessRoundedCorner'); goog.provide('goog.ui.CanvasRoundedCorner'); goog.provide('goog.ui.ImagelessRoundedCorner'); goog.provide('goog.ui.VmlRoundedCorner'); goog.require('goog.dom.DomHelper'); goog.require('goog.graphics.SolidFill'); goog.require('goog.graphics.Stroke'); goog.require('goog.graphics.VmlGraphics'); goog.require('goog.userAgent'); /** * Returns an instance of goog.ui.ImagelessRoundedCorner that can render a * rounded corner, with the implementation varying depending on the current * platform. The rounded corner contains 3 components: horizontal filler, arc, * and vertical filler. Horizontal and/or vertical fillers are added if the * radius of the rounded corner is less than the width and/or height of the * containing element. This is a factory method for image-less rounded corner * classes. * @param {!Element} element The container element for the rounded corner. * @param {number} width The width of the element excluding the border, in * pixels. * @param {number} height The height of the element excluding the border, in * pixels. * @param {number} borderWidth The thickness of the rounded corner, in pixels. * @param {number} radius The radius of the rounded corner, in pixels. The * radius must be less than or equal to the width or height (whichever * is greater). * @param {goog.ui.ImagelessRoundedCorner.Corner} location Location of the * rounded corner. * @param {string} borderColor The color of the rounded corner. * @param {string=} opt_backgroundColor The background color of the rounded * corner. * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the * document we want to render in. * @return {goog.ui.AbstractImagelessRoundedCorner|undefined} Imageless rounded * corner instance. */ goog.ui.ImagelessRoundedCorner.create = function(element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper) { // Check for invalid values. if (width <= 0 || height <= 0 || borderWidth <= 0 || radius < 0) { return; } // Instantiate the proper rounded corner, based on user-agent. var roundedCorner; var version = parseFloat(goog.userAgent.VERSION); if (goog.userAgent.IE) { roundedCorner = new goog.ui.VmlRoundedCorner(element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper); } else { roundedCorner = new goog.ui.CanvasRoundedCorner(element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper); } return roundedCorner; }; /** * Enum for specifying which corners to render. * @enum {number} */ goog.ui.ImagelessRoundedCorner.Corner = { TOP_LEFT: 1, TOP_RIGHT: 2, BOTTOM_LEFT: 4, BOTTOM_RIGHT: 8 }; /** * Specifies the top-left and bottom-left corners. * @type {number} * @private */ goog.ui.ImagelessRoundedCorner.LEFT_ = goog.ui.ImagelessRoundedCorner.Corner.TOP_LEFT | goog.ui.ImagelessRoundedCorner.Corner.BOTTOM_LEFT; /** * Specifies the top-left and top-right corners. * @type {number} * @private */ goog.ui.ImagelessRoundedCorner.TOP_ = goog.ui.ImagelessRoundedCorner.Corner.TOP_LEFT | goog.ui.ImagelessRoundedCorner.Corner.TOP_RIGHT; /** * Base class for various image-less rounded corner classes. Do not create * instances of this class. Instead, utilize * goog.ui.ImagelessRoundedCorner.create(). * @param {!Element} element The container element for the rounded corner. * @param {number} width The width of the element excluding the border, in * pixels. * @param {number} height The height of the element excluding the border, in * pixels. * @param {number} borderWidth The thickness of the rounded corner, in pixels. * @param {number} radius The radius of the rounded corner, in pixels. The * radius must be less than or equal to the width or height (whichever * is greater). * @param {goog.ui.ImagelessRoundedCorner.Corner} location Location of the * rounded corner. * @param {string} borderColor The color of the rounded corner. * @param {string=} opt_backgroundColor The background color of the * rounded corner. * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the * document we want to render in. * @constructor */ goog.ui.AbstractImagelessRoundedCorner = function(element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper) { /** * The container element for the rounded corner. * @type {!Element} * @private */ this.element_ = element; /** * The width of the container element for the rounded corner, in pixels. * @type {number} * @private */ this.width_ = width; /** * The height of the container element for the rounded corner, in pixels. * @type {number} * @private */ this.height_ = height; /** * The color of the rounded corner. * @type {string} * @private */ this.borderColor_ = borderColor; /** * The background color of the rounded corner. * @type {string|undefined} * @private */ this.backgroundColor_ = opt_backgroundColor; /** * The thickness of the rounded corner, in pixels. * @type {number} * @private */ this.borderWidth_ = borderWidth; /** * The radius of the rounded corner, in pixels. * @type {number} * @private */ this.radius_ = radius; /** * Indicates if this is a left rounded corner (ex. top left or bottom left). * @type {boolean} * @private */ this.isLeft_ = !!(location & goog.ui.ImagelessRoundedCorner.LEFT_); /** * Indicates if this is a top rounded corner (ex. top left or top right). * @type {boolean} * @private */ this.isTop_ = !!(location & goog.ui.ImagelessRoundedCorner.TOP_); /** * The DOM helper object for the document we want to render in. * @type {!goog.dom.DomHelper} * @private */ this.domHelper_ = opt_domHelper || goog.dom.getDomHelper(this.element_); /** * The start angle of the rounded corner arc * @type {number} * @private */ this.startAngle_ = this.getStartAngle(); /** * The end angle of the rounded corner arc * @type {number} * @private */ this.endAngle_ = this.getEndAngle(); /** * The x and y coordinates indicating where to begin drawing. * @type {!Array.<number>} * @private */ this.start_ = []; /** * The x and y coordinates indicating where to stop drawing. * @type {!Array.<number>} * @private */ this.end_ = []; // Define the circle center of the arc, and the start/end points. The // start/end points, and the circle center for the arc are moved inward, // depending on the borderWidth of the stroke. var borderWidthOffset = this.getBorderWidthOffset(); if (this.isLeft_) { this.start_[0] = this.width_; this.xCenter_ = this.radius_ + borderWidthOffset; this.end_[0] = borderWidthOffset; } else { this.start_[0] = 0; this.xCenter_ = this.width_ - this.radius_ - borderWidthOffset; this.end_[0] = this.width_ - borderWidthOffset; } if (this.isTop_) { this.start_[1] = borderWidthOffset; this.yCenter_ = this.radius_ + borderWidthOffset; this.end_[1] = this.height_; } else { this.start_[1] = this.height_ - borderWidthOffset; this.yCenter_ = this.height_ - this.radius_ - borderWidthOffset; this.end_[1] = 0; } }; /** * X-axis coordinate of the circle center that the rounded corner arc is * based on. * @type {number} * @private */ goog.ui.AbstractImagelessRoundedCorner.prototype.xCenter_; /** * Y-axis coordinate of the circle center that the rounded corner arc is * based on. * @type {number} * @private */ goog.ui.AbstractImagelessRoundedCorner.prototype.yCenter_; /** * Thickness constant used as an offset to help determine where to start * rendering. * @type {number} */ goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR = 1 / 2; /** * Returns the end angle of the arc for the rounded corner. * @return {number} The end angle, in degrees or radians. * @protected */ goog.ui.AbstractImagelessRoundedCorner.prototype.getEndAngle = goog.abstractMethod; /** * Returns the start angle of the arc for the rounded corner. * @return {number} The start angle, in degrees or radians. * @protected */ goog.ui.AbstractImagelessRoundedCorner.prototype.getStartAngle = goog.abstractMethod; /** * Returns the thickness offset used for accurately rendering the corner * within its container. * @return {number} The thickness offset, in pixels. * @protected */ goog.ui.AbstractImagelessRoundedCorner.prototype.getBorderWidthOffset = function() { return this.borderWidth_ * goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; }; /** * Returns the underlying DOM element containing the rounded corner. * @return {!Element} The underlying DOM element. * @protected */ goog.ui.AbstractImagelessRoundedCorner.prototype.getElement = goog.abstractMethod; /** * Renders the rounded corner. */ goog.ui.AbstractImagelessRoundedCorner.prototype.draw = goog.abstractMethod; /** * Returns the height of the element containing the rounded corner. * @return {number} The height of the element, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.getHeight = function() { return this.height_; }; /** * Sets the height of the element containing the rounded corner. * @param {number} height The height of the element, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.setHeight = function(height) { this.height_ = height; }; /** * Returns the width of the element containing the rounded corner. * @return {number} The width of the element, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.getWidth = function() { return this.width_; }; /** * Sets the width of the element containing the rounded corner. * @param {number} width The width of the element, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.setWidth = function(width) { this.width_ = width; }; /** * Returns the thickness of the rounded corner. * @return {number} The thickness of the rounded corner, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.getLineWidth = function() { return this.borderWidth_; }; /** * Sets the thickness of the rounded corner. * @param {number} thickness The thickness of the rounded corner, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.setLineWidth = function(thickness) { this.borderWidth_ = thickness; }; /** * Returns the radius of the rounded corner. * @return {number} The radius of the rounded corner, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.getRadius = function() { return this.radius_; }; /** * Sets the radius of the rounded corner. * @param {number} radius The radius of the rounded corner, in pixels. */ goog.ui.AbstractImagelessRoundedCorner.prototype.setRadius = function(radius) { this.radius_ = radius; }; /** * Returns the color of the rounded corner. * @return {string} The color of the rounded corner. */ goog.ui.AbstractImagelessRoundedCorner.prototype.getBorderColor = function() { return this.borderColor_; }; /** * Sets the color of the rounded corner. * @param {string} borderColor The color of the rounded corner. */ goog.ui.AbstractImagelessRoundedCorner.prototype.setBorderColor = function(borderColor) { this.borderColor_ = borderColor; }; /** * Returns the background color of the rounded corner. * @return {string|undefined} The background color of the rounded corner. */ goog.ui.AbstractImagelessRoundedCorner.prototype.getBackgroundColor = function() { return this.backgroundColor_; }; /** * Sets the background color of the rounded corner. * @param {string} backgroundColor The background color of the rounded corner. */ goog.ui.AbstractImagelessRoundedCorner.prototype.setBackgroundColor = function(backgroundColor) { this.backgroundColor_ = backgroundColor; }; /** * Class for rendering a Canvas-based rounded corner (Gecko and Safari3+). * Horizontal and/or vertical fillers are added if the radius of the rounded * corner is less than the width and/or height of the containing element. * The line is drawn as a single, continuous line, starting with the horizontal * filler, then the arc, then finishing with the vertical filler. * Do not instantiate this class directly. Instead, use * goog.ui.ImagelessRoundedCorner.create(). * @param {!Element} element The element to be turned into a rounded corner. * @param {number} width The width of the element excluding the border, in * pixels. * @param {number} height The height of the element excluding the border, in * pixels. * @param {number} borderWidth The thickness of the rounded corner, in pixels. * @param {number} radius The radius of the rounded corner, in pixels. The * radius must be less than or equal to the width or height (whichever * is greater). * @param {goog.ui.ImagelessRoundedCorner.Corner} location Location of the * rounded corner. * @param {string} borderColor The color of the rounded corner. * @param {string=} opt_backgroundColor The background color of the rounded * corner. * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the * document we want to render in. * @constructor * @extends {goog.ui.AbstractImagelessRoundedCorner} */ goog.ui.CanvasRoundedCorner = function(element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper) { goog.ui.AbstractImagelessRoundedCorner.call(this, element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper); /** * The canvas containing the rounded corner. * @type {!Element} * @private */ this.canvas_ = this.domHelper_.createDom('canvas', { 'height' : height, 'width' : width }); // If background color is defined, adjust the current end point, define the // opposite corner, and end at the start offset. Account for thickness // offsets in these calculations. The enclosed area will be filled by // backgroundColor if (this.backgroundColor_) { var borderWidthOffset = this.getBorderWidthOffset(); this.oppositeCorner_ = []; // Move one pixel more in the direction the line is being drawn. Then draw // a line to the opposite corner + the diagonal offset. Then draw a line // to the start, offset by 1px. if (this.isLeft_) { this.oppositeCorner_[0] = this.width_ + borderWidthOffset; this.xStartOffset_ = this.start_[0] + borderWidthOffset; } else { this.oppositeCorner_[0] = -borderWidthOffset; this.xStartOffset_ = -borderWidthOffset; } if (this.isTop_) { this.end_[1] += borderWidthOffset; this.oppositeCorner_[1] = this.height_ + borderWidthOffset; } else { this.end_[1] -= borderWidthOffset; this.oppositeCorner_[1] = -borderWidthOffset; } } // Safari requires the canvas to be added to the DOM before defining the // graphics context. Otherwise, rendering will fail. this.domHelper_.appendChild(this.element_, this.canvas_); }; goog.inherits(goog.ui.CanvasRoundedCorner, goog.ui.AbstractImagelessRoundedCorner); /** * The x and y coordinates of the corner opposite the rounded corner arc, * with the stroke thickness offset added. This is defined if * backgroundColor_ is defined. * @type {Array.<number>} * @private */ goog.ui.CanvasRoundedCorner.prototype.oppositeCorner_; /** * The x coordinate of the path's end, when enclosing the path. This is * defined if backgroundColor_ is defined. * @type {number} * @private */ goog.ui.CanvasRoundedCorner.prototype.xStartOffset_; /** * Half a radian. * @type {number} * @private */ goog.ui.CanvasRoundedCorner.RADIANS_HALF_ = Math.PI / 2; /** * One radian. * @type {number} * @private */ goog.ui.CanvasRoundedCorner.RADIANS_ONE_ = Math.PI; /** * Three halves of a radian. * @type {number} * @private */ goog.ui.CanvasRoundedCorner.RADIANS_THREE_HALVES_ = 1.5 * Math.PI; /** * Two radians. * @type {number} * @private */ goog.ui.CanvasRoundedCorner.RADIANS_TWO_ = 2 * Math.PI; /** @inheritDoc */ goog.ui.CanvasRoundedCorner.prototype.getEndAngle = function() { return this.isLeft_ ? goog.ui.CanvasRoundedCorner.RADIANS_ONE_ : goog.ui.CanvasRoundedCorner.RADIANS_TWO_; }; /** @inheritDoc */ goog.ui.CanvasRoundedCorner.prototype.getStartAngle = function() { return this.isTop_ ? goog.ui.CanvasRoundedCorner.RADIANS_THREE_HALVES_ : goog.ui.CanvasRoundedCorner.RADIANS_HALF_; }; /** @inheritDoc */ goog.ui.CanvasRoundedCorner.prototype.getElement = function() { return this.canvas_; }; /** @inheritDoc */ goog.ui.CanvasRoundedCorner.prototype.draw = function() { // Determine which direction to draw, and obtain the context. var counterClockwise = this.isLeft_ && this.isTop_ || !this.isLeft_ && !this.isTop_; var context = this.canvas_.getContext('2d'); var version = parseFloat(goog.userAgent.VERSION); if (goog.userAgent.WEBKIT && goog.userAgent.isVersion('500') && this.oppositeCorner_ && this.xStartOffset_) { // For Safari2, we must render the rounded corner differently when // backgroundColor_ is specified. Safari2 cannot render the stroke using // one color, while filling the enclosed path with another color. this.drawSafari2WithBackground_(context, counterClockwise); } else { // Specify the stroke style and line width. context.strokeStyle = this.borderColor_; context.lineWidth = this.borderWidth_; // Draw the defined path. context.beginPath(); context.moveTo(this.start_[0], this.start_[1]); context.arc(this.xCenter_, this.yCenter_, this.radius_, this.startAngle_, this.endAngle_, counterClockwise); context.lineTo(this.end_[0], this.end_[1]); // If backgroundColor_ is defined, render and enclose the rest of the path, // and fill the background. if (this.oppositeCorner_ && this.xStartOffset_) { context.lineTo(this.oppositeCorner_[0], this.oppositeCorner_[1]); context.lineTo(this.xStartOffset_, this.start_[1]); context.closePath(); context.fillStyle = this.backgroundColor_; context.fill(); } // Render the defined path. context.stroke(); } }; /** * Safari2-specific implementation for rendering a rounded corner with * a background color. The background is filled, followed by the rounded * corner path. * @param {Object} context Graphics context used for drawing. * @param {boolean} counterClockwise Specify true to draw in a * counter-clockwise direction, and false to draw clockwise. * @private */ goog.ui.CanvasRoundedCorner.prototype.drawSafari2WithBackground_ = function(context, counterClockwise) { // If backgroundColor_ is defined, outline the path, // and fill the enclosed area. if (this.oppositeCorner_ && this.xStartOffset_) { // Draw the defined path. context.strokeStyle = this.backgroundColor_; context.lineWidth = 1; context.beginPath(); context.moveTo(this.start_[0], this.start_[1]); context.arc(this.xCenter_, this.yCenter_, this.radius_, this.startAngle_, this.endAngle_, counterClockwise); context.lineTo(this.end_[0], this.end_[1]); context.lineTo(this.oppositeCorner_[0], this.oppositeCorner_[1]); context.lineTo(this.xStartOffset_, this.start_[1]); context.closePath(); context.fillStyle = this.backgroundColor_; context.fill(); } // Draw the rounded corner arc and filler(s). context.strokeStyle = this.borderColor_; context.borderWidth = this.borderWidth_; context.beginPath(); context.moveTo(this.start_[0], this.start_[1]); context.arc(this.xCenter_, this.yCenter_, this.radius_, this.startAngle_, this.endAngle_, counterClockwise); context.lineTo(this.end_[0], this.end_[1]); context.stroke(); }; /** * Class for rendering an imageless, VML-based rounded corner. Horizontal * and/or vertical fillers are added if the radius of the rounded corner is less * than the width and/or height of the containing element. The line is drawn as * a single, continuous line, starting with the horizontal filler, then the arc, * then finishing with the vertical filler. Do not instantiate this class * directly. Instead, use goog.ui.ImagelessRoundedCorner.create(). * @param {!Element} element The element to be turned into a rounded corner. * @param {number} width The width of the element excluding the border, in * pixels. * @param {number} height The height of the element excluding the border, in * pixels. * @param {number} borderWidth The thickness of the rounded corner, in pixels. * @param {number} radius The radius of the rounded corner, in pixels. The * radius must be less than or equal to the width or height (whichever * is greater). * @param {goog.ui.ImagelessRoundedCorner.Corner} location Location of the * rounded corner. * @param {string} borderColor The color of the rounded corner. * @param {string=} opt_backgroundColor The background color of the rounded * corner. * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the * document we want to render in. * @constructor * @extends {goog.ui.AbstractImagelessRoundedCorner} */ goog.ui.VmlRoundedCorner = function(element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper) { goog.ui.AbstractImagelessRoundedCorner.call(this, element, width, height, borderWidth, radius, location, borderColor, opt_backgroundColor, opt_domHelper); // An offset is subtracted to accommodate the subpixel rendering calculations // specific to VmlGraphics. this.start_[0] -= goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; this.end_[0] -= goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; this.xCenter_ -= goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; this.start_[1] -= goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; this.end_[1] -= goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; this.yCenter_ -= goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; /** * VML wrapper API object. * @type {!goog.graphics.VmlGraphics} * @private */ this.graphics_ = new goog.graphics.VmlGraphics(this.width_, this.height_, this.width_, this.height_, this.domHelper_); /** * Container element that will contain the actual rounded corner. * @type {!Element} * @private */ this.container_ = this.domHelper_.createDom('div', { 'style' : 'overflow:hidden;position:relative;' + 'width:' + this.width_ + 'px;' + 'height:' + this.height_ + 'px;' }); }; goog.inherits(goog.ui.VmlRoundedCorner, goog.ui.AbstractImagelessRoundedCorner); /** @inheritDoc */ goog.ui.VmlRoundedCorner.prototype.getEndAngle = function() { return this.isLeft_ ? 180 : 360; }; /** @inheritDoc */ goog.ui.VmlRoundedCorner.prototype.getStartAngle = function() { return this.isTop_ ? 270 : 90; }; /** @inheritDoc */ goog.ui.VmlRoundedCorner.prototype.getElement = function() { return this.container_; }; /** @inheritDoc */ goog.ui.VmlRoundedCorner.prototype.draw = function() { // Determine which direction to draw, and enable VML. var clockwise = this.isLeft_ && !this.isTop_ || !this.isLeft_ && this.isTop_; this.graphics_.createDom(); // If needed, fill the background color. if (this.backgroundColor_) { this.drawBackground_(clockwise); } // Draw the defined path. var path = this.graphics_.createPath(); path.moveTo(this.start_[0], this.start_[1]); path.arc(this.xCenter_, this.yCenter_, this.radius_, this.radius_, this.startAngle_, clockwise ? 90 : -90, true); path.lineTo(this.end_[0], this.end_[1]); var stroke = new goog.graphics.Stroke(this.borderWidth_, this.borderColor_); this.graphics_.drawPath(path, stroke, null); // Extract the shape node, append it to the container, and set the // container styles. Then append the container to the DOM. var shapeNode = this.extractShapeNode_(); this.domHelper_.appendChild(this.container_, shapeNode); this.domHelper_.appendChild(this.element_, this.container_); }; /** * Renders a 1-coordinate wide path, following the same path as the rounded * corner, then going along the adjacent horizontal edge, then along the * adjacent vertical edge, and back to the start of the rounded corner path. * @param {boolean} clockwise Use true to render the arc in a clockwise * direction, and false in the counter-clockwise direction. * @private */ goog.ui.VmlRoundedCorner.prototype.drawBackground_ = function(clockwise) { // Calculate key points in the path: the end of the arc, the corner opposite // the arc, and the end of the path. var arcEnd = []; arcEnd[0] = this.isLeft_ ? goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR : this.width_ - goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; arcEnd[1] = this.isTop_ ? this.height_ - goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR: goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; var oppositeCorner = []; oppositeCorner[0] = this.isLeft_ ? this.width_ - goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR : goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; oppositeCorner[1] = arcEnd[1]; var endX = this.isLeft_ ? this.start_[0] - goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR : goog.ui.AbstractImagelessRoundedCorner.BORDER_WIDTH_FACTOR; var path = this.graphics_.createPath(); // Draw out the path according to the points just defined. path.moveTo(this.start_[0], this.start_[1]); path.arc(this.xCenter_, this.yCenter_, this.radius_, this.radius_, this.startAngle_, clockwise ? 90 : -90, true); path.lineTo(arcEnd[0], arcEnd[1]); path.lineTo(oppositeCorner[0], oppositeCorner[1]); path.lineTo(endX, this.start_[1]); // Render the path and fill, then append the generated path to the DOM. var stroke = new goog.graphics.Stroke(1, /** @type {string} */ (this.backgroundColor_)); var fill = new goog.graphics.SolidFill( /** @type {string} */ (this.backgroundColor_), 1); this.graphics_.drawPath(path, stroke, fill); var shapeNode = this.extractShapeNode_(); this.domHelper_.appendChild(this.container_, shapeNode); }; /** * Helper method that extracts the 'shape' node from the private * goog.graphics.VmlGraphics instance, sets the size to this.width_ and * this.height_, and sets the position to (0, 0). * @return {Element} The VML shape element. * @private */ goog.ui.VmlRoundedCorner.prototype.extractShapeNode_ = function() { var shapeNode = /** @type {Element} */ ( goog.dom.findNode(this.graphics_.getElement(), goog.ui.VmlRoundedCorner.isShapeNode_)); goog.style.setSize(shapeNode, this.width_, this.height_); goog.style.setPosition(shapeNode, 0, 0); return shapeNode; }; /** * Indicates if the specified node is a 'shape' node. * @param {Node} node The DOM node to inspect. * @return {boolean} true if the node is an element node with the name 'shape', * and false otherwise. * @private */ goog.ui.VmlRoundedCorner.isShapeNode_ = function(node) { return node.nodeType == goog.dom.NodeType.ELEMENT && node.nodeName == 'shape'; };