<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-draw-engine-Vml'>/**
|
</span> * Provides specific methods to draw with VML.
|
*/
|
Ext.define('Ext.draw.engine.Vml', {
|
|
/* Begin Definitions */
|
|
extend: 'Ext.draw.Surface',
|
|
requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'],
|
|
<span id='Ext-draw-engine-Vml-property-engine'> /* End Definitions */
|
</span>
|
engine: 'Vml',
|
|
<span id='Ext-draw-engine-Vml-property-map'> map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
|
</span><span id='Ext-draw-engine-Vml-property-bitesRe'> bitesRe: /([clmz]),?([^clmz]*)/gi,
|
</span><span id='Ext-draw-engine-Vml-property-valRe'> valRe: /-?[^,\s\-]+/g,
|
</span><span id='Ext-draw-engine-Vml-property-fillUrlRe'> fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i,
|
</span><span id='Ext-draw-engine-Vml-property-pathlike'> pathlike: /^(path|rect)$/,
|
</span><span id='Ext-draw-engine-Vml-property-partialPathRe'><span id='Ext-draw-engine-Vml-property-NonVmlPathRe'> NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops
|
</span></span> partialPathRe: /[clmz]/g,
|
<span id='Ext-draw-engine-Vml-property-fontFamilyRe'> fontFamilyRe: /^['"]+|['"]+$/g,
|
</span><span id='Ext-draw-engine-Vml-property-baseVmlCls'> baseVmlCls: Ext.baseCSSPrefix + 'vml-base',
|
</span><span id='Ext-draw-engine-Vml-property-vmlGroupCls'> vmlGroupCls: Ext.baseCSSPrefix + 'vml-group',
|
</span><span id='Ext-draw-engine-Vml-property-spriteCls'> spriteCls: Ext.baseCSSPrefix + 'vml-sprite',
|
</span><span id='Ext-draw-engine-Vml-property-measureSpanCls'> measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span',
|
</span><span id='Ext-draw-engine-Vml-property-zoom'> zoom: 21600,
|
</span><span id='Ext-draw-engine-Vml-property-coordsize'> coordsize: 1000,
|
</span><span id='Ext-draw-engine-Vml-property-coordorigin'> coordorigin: '0 0',
|
</span><span id='Ext-draw-engine-Vml-property-zIndexShift'> zIndexShift: 0,
|
</span><span id='Ext-draw-engine-Vml-property-orderSpritesByZIndex'> // VML uses CSS z-index and therefore doesn't need sprites to be kept in zIndex order
|
</span> orderSpritesByZIndex: false,
|
|
<span id='Ext-draw-engine-Vml-method-path2vml'> // @private
|
</span> // Convert an SVG standard path into a VML path
|
path2vml: function (path) {
|
var me = this,
|
nonVML = me.NonVmlPathRe,
|
map = me.map,
|
val = me.valRe,
|
zoom = me.zoom,
|
bites = me.bitesRe,
|
command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw),
|
res, pa, p, r, i, ii, j, jj;
|
if (String(path).match(nonVML)) {
|
command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw);
|
} else if (!String(path).match(me.partialPathRe)) {
|
res = String(path).replace(bites, function (all, command, args) {
|
var vals = [],
|
isMove = command.toLowerCase() == "m",
|
res = map[command];
|
args.replace(val, function (value) {
|
if (isMove && vals.length === 2) {
|
res += vals + map[command == "m" ? "l" : "L"];
|
vals = [];
|
}
|
vals.push(Math.round(value * zoom));
|
});
|
return res + vals;
|
});
|
return res;
|
}
|
pa = command(path);
|
res = [];
|
for (i = 0, ii = pa.length; i < ii; i++) {
|
p = pa[i];
|
r = pa[i][0].toLowerCase();
|
if (r == "z") {
|
r = "x";
|
}
|
for (j = 1, jj = p.length; j < jj; j++) {
|
r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : "");
|
}
|
res.push(r);
|
}
|
return res.join(" ");
|
},
|
|
<span id='Ext-draw-engine-Vml-property-translateAttrs'> // @private - set of attributes which need to be translated from the sprite API to the native browser API
|
</span> translateAttrs: {
|
radius: "r",
|
radiusX: "rx",
|
radiusY: "ry",
|
lineWidth: "stroke-width",
|
fillOpacity: "fill-opacity",
|
strokeOpacity: "stroke-opacity",
|
strokeLinejoin: "stroke-linejoin"
|
},
|
|
<span id='Ext-draw-engine-Vml-property-minDefaults'> // @private - Minimun set of defaults for different types of sprites.
|
</span> minDefaults: {
|
circle: {
|
fill: "none",
|
stroke: null,
|
"stroke-width": null,
|
opacity: null,
|
"fill-opacity": null,
|
"stroke-opacity": null
|
},
|
ellipse: {
|
cx: 0,
|
cy: 0,
|
rx: 0,
|
ry: 0,
|
fill: "none",
|
stroke: null,
|
"stroke-width": null,
|
opacity: null,
|
"fill-opacity": null,
|
"stroke-opacity": null
|
},
|
rect: {
|
x: 0,
|
y: 0,
|
width: 0,
|
height: 0,
|
rx: 0,
|
ry: 0,
|
fill: "none",
|
stroke: null,
|
"stroke-width": null,
|
opacity: null,
|
"fill-opacity": null,
|
"stroke-opacity": null
|
},
|
text: {
|
x: 0,
|
y: 0,
|
"text-anchor": "start",
|
font: '10px "Arial"',
|
fill: "#000",
|
stroke: null,
|
"stroke-width": null,
|
opacity: null,
|
"fill-opacity": null,
|
"stroke-opacity": null
|
},
|
path: {
|
d: "M0,0",
|
fill: "none",
|
stroke: null,
|
"stroke-width": null,
|
opacity: null,
|
"fill-opacity": null,
|
"stroke-opacity": null
|
},
|
image: {
|
x: 0,
|
y: 0,
|
width: 0,
|
height: 0,
|
preserveAspectRatio: "none",
|
opacity: null
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-onMouseEnter'> // private
|
</span> onMouseEnter: function (e) {
|
this.fireEvent("mouseenter", e);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-onMouseLeave'> // private
|
</span> onMouseLeave: function (e) {
|
this.fireEvent("mouseleave", e);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-processEvent'> // @private - Normalize a delegated single event from the main container to each sprite and sprite group
|
</span> processEvent: function (name, e) {
|
var target = e.getTarget(),
|
surface = this.surface,
|
sprite;
|
this.fireEvent(name, e);
|
sprite = this.items.get(target.id);
|
if (sprite) {
|
sprite.fireEvent(name, sprite, e);
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-createSpriteElement'> // Create the VML element/elements and append them to the DOM
|
</span> createSpriteElement: function (sprite) {
|
var me = this,
|
attr = sprite.attr,
|
type = sprite.type,
|
zoom = me.zoom,
|
vml = sprite.vml || (sprite.vml = {}),
|
round = Math.round,
|
el = (type === 'image') ? me.createNode('image') : me.createNode('shape'),
|
path, skew, textPath;
|
|
el.coordsize = zoom + ' ' + zoom;
|
el.coordorigin = attr.coordorigin || "0 0";
|
Ext.get(el).addCls(me.spriteCls);
|
if (type == "text") {
|
vml.path = path = me.createNode("path");
|
path.textpathok = true;
|
vml.textpath = textPath = me.createNode("textpath");
|
textPath.on = true;
|
el.appendChild(textPath);
|
el.appendChild(path);
|
}
|
el.id = sprite.id;
|
sprite.el = Ext.get(el);
|
sprite.el.setStyle('zIndex', -me.zIndexShift);
|
me.el.appendChild(el);
|
if (type !== 'image') {
|
skew = me.createNode("skew");
|
skew.on = true;
|
el.appendChild(skew);
|
sprite.skew = skew;
|
}
|
sprite.matrix = new Ext.draw.Matrix();
|
sprite.bbox = {
|
plain: null,
|
transform: null
|
};
|
|
this.applyAttrs(sprite);
|
this.applyTransformations(sprite);
|
sprite.fireEvent("render", sprite);
|
return sprite.el;
|
},
|
|
<span id='Ext-draw-engine-Vml-method-getBBoxText'> getBBoxText: function (sprite) {
|
</span> var vml = sprite.vml;
|
return {
|
x: vml.X + (vml.bbx || 0) - vml.W / 2,
|
y: vml.Y - vml.H / 2,
|
width: vml.W,
|
height: vml.H
|
};
|
},
|
|
<span id='Ext-draw-engine-Vml-method-applyAttrs'> applyAttrs: function (sprite) {
|
</span> var me = this,
|
vml = sprite.vml,
|
group = sprite.group,
|
spriteAttr = sprite.attr,
|
el = sprite.el,
|
dom = el.dom,
|
style, name, groups, i, ln, scrubbedAttrs, font, key,
|
cx, cy, rx, ry;
|
|
if (group) {
|
groups = [].concat(group);
|
ln = groups.length;
|
for (i = 0; i < ln; i++) {
|
group = groups[i];
|
me.getGroup(group).add(sprite);
|
}
|
delete sprite.group;
|
}
|
scrubbedAttrs = me.scrubAttrs(sprite) || {};
|
|
if (sprite.zIndexDirty) {
|
me.setZIndex(sprite);
|
}
|
|
// Apply minimum default attributes
|
Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]);
|
|
if (sprite.type == 'image') {
|
Ext.apply(sprite.attr, {
|
x: scrubbedAttrs.x,
|
y: scrubbedAttrs.y,
|
width: scrubbedAttrs.width,
|
height: scrubbedAttrs.height
|
});
|
el.setStyle({
|
width: scrubbedAttrs.width + 'px',
|
height: scrubbedAttrs.height + 'px'
|
});
|
dom.src = scrubbedAttrs.src;
|
}
|
|
if (dom.href) {
|
dom.href = scrubbedAttrs.href;
|
}
|
if (dom.title) {
|
dom.title = scrubbedAttrs.title;
|
}
|
if (dom.target) {
|
dom.target = scrubbedAttrs.target;
|
}
|
if (dom.cursor) {
|
dom.cursor = scrubbedAttrs.cursor;
|
}
|
|
// Change visibility
|
if (sprite.dirtyHidden) {
|
(scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
|
sprite.dirtyHidden = false;
|
}
|
|
// Update path
|
if (sprite.dirtyPath) {
|
if (sprite.type == "circle" || sprite.type == "ellipse") {
|
cx = scrubbedAttrs.x;
|
cy = scrubbedAttrs.y;
|
rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0;
|
ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0;
|
dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}",
|
Math.round((cx - rx) * me.zoom),
|
Math.round((cy - ry) * me.zoom),
|
Math.round((cx + rx) * me.zoom),
|
Math.round((cy + ry) * me.zoom),
|
Math.round(cx * me.zoom));
|
sprite.dirtyPath = false;
|
}
|
else if (sprite.type !== "text" && sprite.type !== 'image') {
|
sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path;
|
dom.path = me.path2vml(scrubbedAttrs.path);
|
sprite.dirtyPath = false;
|
}
|
}
|
|
// Apply clipping
|
if ("clip-rect" in scrubbedAttrs) {
|
me.setClip(sprite, scrubbedAttrs);
|
}
|
|
// Handle text (special handling required)
|
if (sprite.type == "text") {
|
me.setTextAttributes(sprite, scrubbedAttrs);
|
}
|
|
// Handle fill and opacity
|
if (scrubbedAttrs.opacity || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
|
me.setFill(sprite, scrubbedAttrs);
|
}
|
|
// Handle stroke (all fills require a stroke element)
|
if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
|
me.setStroke(sprite, scrubbedAttrs);
|
}
|
|
//set styles
|
style = spriteAttr.style;
|
if (style) {
|
el.setStyle(style);
|
}
|
|
sprite.dirty = false;
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setZIndex'> setZIndex: function (sprite) {
|
</span> var me = this,
|
zIndex = sprite.attr.zIndex,
|
shift = me.zIndexShift,
|
items, iLen, item, i;
|
|
if (zIndex < shift) {
|
// This means bad thing happened.
|
// The algorithm below will guarantee O(n) time.
|
items = me.items.items;
|
iLen = items.length;
|
|
for (i = 0; i < iLen; i++) {
|
if ((zIndex = items[i].attr.zIndex) && zIndex < shift) { // zIndex is no longer useful this case
|
shift = zIndex;
|
}
|
}
|
|
me.zIndexShift = shift;
|
for (i = 0; i < iLen; i++) {
|
item = items[i];
|
if (item.el) {
|
item.el.setStyle('zIndex', item.attr.zIndex - shift);
|
}
|
item.zIndexDirty = false;
|
}
|
} else if (sprite.el) {
|
sprite.el.setStyle('zIndex', zIndex - shift);
|
sprite.zIndexDirty = false;
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setPaths'> // Normalize all virtualized types into paths.
|
</span> setPaths: function (sprite, params) {
|
var spriteAttr = sprite.attr, thickness = sprite.attr['stroke-width'] || 1;
|
// Clear bbox cache
|
sprite.bbox.plain = null;
|
sprite.bbox.transform = null;
|
if (sprite.type == 'circle') {
|
spriteAttr.rx = spriteAttr.ry = params.r;
|
return Ext.draw.Draw.ellipsePath(sprite);
|
}
|
else if (sprite.type == 'ellipse') {
|
spriteAttr.rx = params.rx;
|
spriteAttr.ry = params.ry;
|
return Ext.draw.Draw.ellipsePath(sprite);
|
}
|
else if (sprite.type == 'rect') {
|
spriteAttr.rx = spriteAttr.ry = params.r;
|
return Ext.draw.Draw.rectPath(sprite);
|
}
|
else if (sprite.type == 'path' && spriteAttr.path) {
|
return Ext.draw.Draw.pathToAbsolute(spriteAttr.path);
|
}
|
return false;
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setFill'> setFill: function (sprite, params) {
|
</span> var me = this,
|
el = sprite.el.dom,
|
fillEl = el.fill,
|
newfill = false,
|
opacity, gradient, fillUrl, rotation, angle;
|
|
if (!fillEl) {
|
// NOT an expando (but it sure looks like one)...
|
fillEl = el.fill = me.createNode("fill");
|
newfill = true;
|
}
|
if (Ext.isArray(params.fill)) {
|
params.fill = params.fill[0];
|
}
|
if (params.fill == "none") {
|
fillEl.on = false;
|
}
|
else {
|
if (typeof params.opacity == "number") {
|
fillEl.opacity = params.opacity;
|
}
|
if (typeof params["fill-opacity"] == "number") {
|
fillEl.opacity = params["fill-opacity"];
|
}
|
fillEl.on = true;
|
if (typeof params.fill == "string") {
|
fillUrl = params.fill.match(me.fillUrlRe);
|
if (fillUrl) {
|
fillUrl = fillUrl[1];
|
// If the URL matches one of the registered gradients, render that gradient
|
if (fillUrl.charAt(0) == "#") {
|
gradient = me.gradientsColl.getByKey(fillUrl.substring(1));
|
}
|
if (gradient) {
|
// VML angle is offset and inverted from standard, and must be adjusted to match rotation transform
|
rotation = params.rotation;
|
angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360;
|
// IE will flip the angle at 0 degrees...
|
if (angle === 0) {
|
angle = 180;
|
}
|
fillEl.angle = angle;
|
fillEl.type = "gradient";
|
fillEl.method = "sigma";
|
if (fillEl.colors) {
|
fillEl.colors.value = gradient.colors;
|
} else {
|
fillEl.colors = gradient.colors;
|
}
|
}
|
// Otherwise treat it as an image
|
else {
|
fillEl.src = fillUrl;
|
fillEl.type = "tile";
|
}
|
}
|
else {
|
fillEl.color = Ext.draw.Color.toHex(params.fill);
|
fillEl.src = "";
|
fillEl.type = "solid";
|
}
|
}
|
}
|
if (newfill) {
|
el.appendChild(fillEl);
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setStroke'> setStroke: function (sprite, params) {
|
</span> var me = this,
|
el = sprite.el.dom,
|
strokeEl = sprite.strokeEl,
|
newStroke = false,
|
width, opacity;
|
|
if (!strokeEl) {
|
strokeEl = sprite.strokeEl = me.createNode("stroke");
|
newStroke = true;
|
}
|
if (Ext.isArray(params.stroke)) {
|
params.stroke = params.stroke[0];
|
}
|
if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) {
|
strokeEl.on = false;
|
}
|
else {
|
strokeEl.on = true;
|
if (params.stroke && !params.stroke.match(me.fillUrlRe)) {
|
// VML does NOT support a gradient stroke :(
|
strokeEl.color = Ext.draw.Color.toHex(params.stroke);
|
}
|
strokeEl.dashstyle = params["stroke-dasharray"] ? "dash" : "solid";
|
strokeEl.joinstyle = params["stroke-linejoin"];
|
strokeEl.endcap = params["stroke-linecap"] || "round";
|
strokeEl.miterlimit = params["stroke-miterlimit"] || 8;
|
width = parseFloat(params["stroke-width"] || 1) * 0.75;
|
opacity = params["stroke-opacity"] || 1;
|
// VML Does not support stroke widths under 1, so we're going to fiddle with stroke-opacity instead.
|
if (Ext.isNumber(width) && width < 1) {
|
strokeEl.weight = 1;
|
strokeEl.opacity = opacity * width;
|
}
|
else {
|
strokeEl.weight = width;
|
strokeEl.opacity = opacity;
|
}
|
}
|
if (newStroke) {
|
el.appendChild(strokeEl);
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setClip'> setClip: function (sprite, params) {
|
</span> var me = this,
|
el = sprite.el,
|
clipEl = sprite.clipEl,
|
rect = String(params["clip-rect"]).split(me.separatorRe);
|
if (!clipEl) {
|
clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div"));
|
clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite');
|
}
|
if (rect.length == 4) {
|
rect[2] = +rect[2] + (+rect[0]);
|
rect[3] = +rect[3] + (+rect[1]);
|
clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3]));
|
clipEl.setSize(me.el.width, me.el.height);
|
}
|
else {
|
clipEl.setStyle("clip", "");
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setTextAttributes'> setTextAttributes: function (sprite, params) {
|
</span> var me = this,
|
vml = sprite.vml,
|
textStyle = vml.textpath.style,
|
spanCacheStyle = me.span.style,
|
zoom = me.zoom,
|
round = Math.round,
|
fontObj = {
|
fontSize: "font-size",
|
fontWeight: "font-weight",
|
fontStyle: "font-style"
|
},
|
fontProp,
|
paramProp;
|
if (sprite.dirtyFont) {
|
if (params.font) {
|
textStyle.font = spanCacheStyle.font = params.font;
|
}
|
if (params["font-family"]) {
|
textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"';
|
spanCacheStyle.fontFamily = params["font-family"];
|
}
|
|
for (fontProp in fontObj) {
|
paramProp = params[fontObj[fontProp]];
|
if (paramProp) {
|
textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp;
|
}
|
}
|
|
me.setText(sprite, params.text);
|
|
if (vml.textpath.string) {
|
me.span.innerHTML = String(vml.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br/>");
|
}
|
vml.W = me.span.offsetWidth;
|
vml.H = me.span.offsetHeight + 2; // TODO handle baseline differences and offset in VML Textpath
|
|
// text-anchor emulation
|
if (params["text-anchor"] == "middle") {
|
textStyle["v-text-align"] = "center";
|
}
|
else if (params["text-anchor"] == "end") {
|
textStyle["v-text-align"] = "right";
|
vml.bbx = -Math.round(vml.W / 2);
|
}
|
else {
|
textStyle["v-text-align"] = "left";
|
vml.bbx = Math.round(vml.W / 2);
|
}
|
}
|
vml.X = params.x;
|
vml.Y = params.y;
|
vml.path.v = Ext.String.format("m{0},{1}l{2},{1}", Math.round(vml.X * zoom), Math.round(vml.Y * zoom), Math.round(vml.X * zoom) + 1);
|
// Clear bbox cache
|
sprite.bbox.plain = null;
|
sprite.bbox.transform = null;
|
sprite.dirtyFont = false;
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setText'> setText: function (sprite, text) {
|
</span> sprite.vml.textpath.string = Ext.htmlDecode(text);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-hide'> hide: function () {
|
</span> this.el.hide();
|
},
|
|
<span id='Ext-draw-engine-Vml-method-show'> show: function () {
|
</span> this.el.show();
|
},
|
|
<span id='Ext-draw-engine-Vml-method-hidePrim'> hidePrim: function (sprite) {
|
</span> sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility');
|
},
|
|
<span id='Ext-draw-engine-Vml-method-showPrim'> showPrim: function (sprite) {
|
</span> sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility');
|
},
|
|
<span id='Ext-draw-engine-Vml-method-setSize'> setSize: function (width, height) {
|
</span> var me = this;
|
width = width || me.width;
|
height = height || me.height;
|
me.width = width;
|
me.height = height;
|
|
if (me.el) {
|
// Size outer div
|
if (width != undefined) {
|
me.el.setWidth(width);
|
}
|
if (height != undefined) {
|
me.el.setHeight(height);
|
}
|
}
|
|
me.callParent(arguments);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-applyViewBox'> /**
|
</span> * @private Using the current viewBox property and the surface's width and height, calculate the
|
* appropriate viewBoxShift that will be applied as a persistent transform to all sprites.
|
*/
|
applyViewBox: function () {
|
var me = this,
|
viewBox = me.viewBox,
|
width = me.width,
|
height = me.height,
|
items,
|
iLen,
|
i;
|
|
me.callParent();
|
|
if (viewBox && (width || height)) {
|
items = me.items.items;
|
iLen = items.length;
|
|
for (i = 0; i < iLen; i++) {
|
me.applyTransformations(items[i]);
|
}
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-onAdd'> onAdd: function (item) {
|
</span> this.callParent(arguments);
|
if (this.el) {
|
this.renderItem(item);
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-onRemove'> onRemove: function (sprite) {
|
</span> if (sprite.el) {
|
sprite.el.remove();
|
delete sprite.el;
|
}
|
this.callParent(arguments);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-render'> render: function (container) {
|
</span> var me = this,
|
doc = Ext.getDoc().dom,
|
el;
|
// VML Node factory method (createNode)
|
if (!me.createNode) {
|
try {
|
if (!doc.namespaces.rvml) {
|
doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
|
}
|
me.createNode = function (tagName) {
|
return doc.createElement("<rvml:" + tagName + ' class="rvml">');
|
};
|
} catch (e) {
|
me.createNode = function (tagName) {
|
return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
|
};
|
}
|
}
|
|
if (!me.el) {
|
el = doc.createElement("div");
|
me.el = Ext.get(el);
|
me.el.addCls(me.baseVmlCls);
|
|
// Measuring span (offscrren)
|
me.span = doc.createElement("span");
|
Ext.get(me.span).addCls(me.measureSpanCls);
|
el.appendChild(me.span);
|
me.el.setSize(me.width || 0, me.height || 0);
|
container.appendChild(el);
|
me.el.on({
|
scope: me,
|
mouseup: me.onMouseUp,
|
mousedown: me.onMouseDown,
|
mouseover: me.onMouseOver,
|
mouseout: me.onMouseOut,
|
mousemove: me.onMouseMove,
|
mouseenter: me.onMouseEnter,
|
mouseleave: me.onMouseLeave,
|
click: me.onClick,
|
dblclick: me.onDblClick
|
});
|
}
|
me.renderAll();
|
},
|
|
<span id='Ext-draw-engine-Vml-method-renderAll'> renderAll: function () {
|
</span> this.items.each(this.renderItem, this);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-redraw'> redraw: function (sprite) {
|
</span> sprite.dirty = true;
|
this.renderItem(sprite);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-renderItem'> renderItem: function (sprite) {
|
</span> // Does the surface element exist?
|
if (!this.el) {
|
return;
|
}
|
|
// Create sprite element if necessary
|
if (!sprite.el) {
|
this.createSpriteElement(sprite);
|
}
|
|
if (sprite.dirty) {
|
this.applyAttrs(sprite);
|
if (sprite.dirtyTransform) {
|
this.applyTransformations(sprite);
|
}
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-rotationCompensation'> rotationCompensation: function (deg, dx, dy) {
|
</span> var matrix = new Ext.draw.Matrix();
|
matrix.rotate(-deg, 0.5, 0.5);
|
return {
|
x: matrix.x(dx, dy),
|
y: matrix.y(dx, dy)
|
};
|
},
|
|
<span id='Ext-draw-engine-Vml-method-transform'> transform: function (sprite, matrixOnly) {
|
</span> var me = this,
|
bbox = me.getBBox(sprite, true),
|
cx = bbox.x + bbox.width * 0.5,
|
cy = bbox.y + bbox.height * 0.5,
|
matrix = new Ext.draw.Matrix(),
|
transforms = sprite.transformations,
|
transformsLength = transforms.length,
|
i = 0,
|
deltaDegrees = 0,
|
deltaScaleX = 1,
|
deltaScaleY = 1,
|
flip = "",
|
el = sprite.el,
|
dom = el.dom,
|
domStyle = dom.style,
|
zoom = me.zoom,
|
skew = sprite.skew,
|
shift = me.viewBoxShift,
|
deltaX, deltaY, transform, type, compensate, y, fill, newAngle, zoomScaleX, zoomScaleY, newOrigin, offset;
|
|
|
for (; i < transformsLength; i++) {
|
transform = transforms[i];
|
type = transform.type;
|
if (type == "translate") {
|
matrix.translate(transform.x, transform.y);
|
}
|
else if (type == "rotate") {
|
matrix.rotate(transform.degrees, transform.x, transform.y);
|
deltaDegrees += transform.degrees;
|
}
|
else if (type == "scale") {
|
matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
|
deltaScaleX *= transform.x;
|
deltaScaleY *= transform.y;
|
}
|
}
|
|
sprite.matrix = matrix.clone();
|
|
if (matrixOnly) {
|
return;
|
}
|
|
if (shift) {
|
matrix.prepend(shift.scale, 0, 0, shift.scale, shift.dx * shift.scale, shift.dy * shift.scale);
|
}
|
|
// Hide element while we transform
|
if (sprite.type != "image" && skew) {
|
skew.origin = "0,0";
|
// matrix transform via VML skew
|
skew.matrix = matrix.toString();
|
// skew.offset = '32767,1' OK
|
// skew.offset = '32768,1' Crash
|
// M$, R U kidding??
|
offset = matrix.offset();
|
if (offset[0] > 32767) {
|
offset[0] = 32767;
|
} else if (offset[0] < -32768) {
|
offset[0] = -32768;
|
}
|
if (offset[1] > 32767) {
|
offset[1] = 32767;
|
} else if (offset[1] < -32768) {
|
offset[1] = -32768;
|
}
|
skew.offset = offset;
|
}
|
else {
|
domStyle.filter = matrix.toFilter();
|
domStyle.left = Math.min(
|
matrix.x(bbox.x, bbox.y),
|
matrix.x(bbox.x + bbox.width, bbox.y),
|
matrix.x(bbox.x, bbox.y + bbox.height),
|
matrix.x(bbox.x + bbox.width, bbox.y + bbox.height)) + 'px';
|
domStyle.top = Math.min(
|
matrix.y(bbox.x, bbox.y),
|
matrix.y(bbox.x + bbox.width, bbox.y),
|
matrix.y(bbox.x, bbox.y + bbox.height),
|
matrix.y(bbox.x + bbox.width, bbox.y + bbox.height)) + 'px';
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-createItem'> createItem: function (config) {
|
</span> return Ext.create('Ext.draw.Sprite', config);
|
},
|
|
<span id='Ext-draw-engine-Vml-method-getRegion'> getRegion: function () {
|
</span> return this.el.getRegion();
|
},
|
|
<span id='Ext-draw-engine-Vml-method-addCls'> addCls: function (sprite, className) {
|
</span> if (sprite && sprite.el) {
|
sprite.el.addCls(className);
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-removeCls'> removeCls: function (sprite, className) {
|
</span> if (sprite && sprite.el) {
|
sprite.el.removeCls(className);
|
}
|
},
|
|
<span id='Ext-draw-engine-Vml-method-addGradient'> /**
|
</span> * Adds a definition to this Surface for a linear gradient. We convert the gradient definition
|
* to its corresponding VML attributes and store it for later use by individual sprites.
|
* @param {Object} gradient
|
*/
|
addGradient: function (gradient) {
|
var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')),
|
colors = [],
|
stops = Ext.create('Ext.util.MixedCollection'),
|
keys,
|
items,
|
iLen,
|
key,
|
item,
|
i;
|
|
// Build colors string
|
stops.addAll(gradient.stops);
|
stops.sortByKey("ASC", function (a, b) {
|
a = parseInt(a, 10);
|
b = parseInt(b, 10);
|
return a > b ? 1 : (a < b ? -1 : 0);
|
});
|
|
keys = stops.keys;
|
items = stops.items;
|
iLen = keys.length;
|
|
for (i = 0; i < iLen; i++) {
|
key = keys[i];
|
item = items[i];
|
colors.push(key + '% ' + item.color);
|
}
|
|
gradients.add(gradient.id, {
|
colors: colors.join(","),
|
angle: gradient.angle
|
});
|
},
|
|
<span id='Ext-draw-engine-Vml-method-destroy'> destroy: function () {
|
</span> var me = this;
|
|
me.callParent(arguments);
|
if (me.el) {
|
me.el.remove();
|
}
|
delete me.el;
|
}
|
});
|
</pre>
|
</body>
|
</html>
|