silverlight.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. define("dojox/gfx/silverlight", ["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/declare", "dojo/_base/Color",
  2. "dojo/_base/array", "dojo/dom-geometry", "dojo/dom", "dojo/_base/sniff",
  3. "./_base", "./shape", "./path"],
  4. function(kernel,lang,declare,color,arr,domGeom,dom,has,g,gs,pathLib){
  5. /*=====
  6. dojox.gfx.silverlight = {
  7. // module:
  8. // dojox/gfx/silverlight
  9. // summary:
  10. // This the graphics rendering bridge for the Microsoft Silverlight plugin.
  11. // Silverlight is a faster implementation on IE6-8 than the default 2d graphics, VML
  12. };
  13. g = dojox.gfx;
  14. pathLib.Path = dojox.gfx.path.Path;
  15. pathLib.TextPath = dojox.gfx.path.TextPath;
  16. sl.Shape = dojox.gfx.canvas.Shape;
  17. gs.Shape = dojox.gfx.shape.Shape;
  18. gs.Rect = dojox.gfx.shape.Rect;
  19. gs.Ellipse = dojox.gfx.shape.Ellipse;
  20. gs.Circle = dojox.gfx.shape.Circle;
  21. gs.Line = dojox.gfx.shape.Line;
  22. gs.PolyLine = dojox.gfx.shape.PolyLine;
  23. gs.Image = dojox.gfx.shape.Image;
  24. gs.Text = dojox.gfx.shape.Text;
  25. gs.Surface = dojox.gfx.shape.Surface;
  26. =====*/
  27. var sl = g.silverlight = {};
  28. kernel.experimental("dojox.gfx.silverlight");
  29. var dasharray = {
  30. solid: "none",
  31. shortdash: [4, 1],
  32. shortdot: [1, 1],
  33. shortdashdot: [4, 1, 1, 1],
  34. shortdashdotdot: [4, 1, 1, 1, 1, 1],
  35. dot: [1, 3],
  36. dash: [4, 3],
  37. longdash: [8, 3],
  38. dashdot: [4, 3, 1, 3],
  39. longdashdot: [8, 3, 1, 3],
  40. longdashdotdot: [8, 3, 1, 3, 1, 3]
  41. },
  42. fontweight = {
  43. normal: 400,
  44. bold: 700
  45. },
  46. caps = {butt: "Flat", round: "Round", square: "Square"},
  47. joins = {bevel: "Bevel", round: "Round"},
  48. fonts = {
  49. serif: "Times New Roman",
  50. times: "Times New Roman",
  51. "sans-serif": "Arial",
  52. helvetica: "Arial",
  53. monotone: "Courier New",
  54. courier: "Courier New"
  55. };
  56. function hexColor(/*String|Array|dojo.Color*/ color){
  57. // summary: converts a color object to a Silverlight hex color string (#aarrggbb)
  58. var c = g.normalizeColor(color),
  59. t = c.toHex(), a = Math.round(c.a * 255);
  60. a = (a < 0 ? 0 : a > 255 ? 255 : a).toString(16);
  61. return "#" + (a.length < 2 ? "0" + a : a) + t.slice(1); // String
  62. }
  63. declare("dojox.gfx.silverlight.Shape", gs.Shape, {
  64. // summary: Silverlight-specific implementation of dojox.gfx.Shape methods
  65. setFill: function(fill){
  66. // summary: sets a fill object (Silverlight)
  67. // fill: Object: a fill object
  68. // (see dojox.gfx.defaultLinearGradient,
  69. // dojox.gfx.defaultRadialGradient,
  70. // dojox.gfx.defaultPattern,
  71. // or dojo.Color)
  72. var p = this.rawNode.getHost().content, r = this.rawNode, f;
  73. if(!fill){
  74. // don't fill
  75. this.fillStyle = null;
  76. this._setFillAttr(null);
  77. return this; // self
  78. }
  79. if(typeof(fill) == "object" && "type" in fill){
  80. // gradient
  81. switch(fill.type){
  82. case "linear":
  83. this.fillStyle = f = g.makeParameters(g.defaultLinearGradient, fill);
  84. var lgb = p.createFromXaml("<LinearGradientBrush/>");
  85. lgb.mappingMode = "Absolute";
  86. lgb.startPoint = f.x1 + "," + f.y1;
  87. lgb.endPoint = f.x2 + "," + f.y2;
  88. arr.forEach(f.colors, function(c){
  89. var t = p.createFromXaml("<GradientStop/>");
  90. t.offset = c.offset;
  91. t.color = hexColor(c.color);
  92. lgb.gradientStops.add(t);
  93. });
  94. this._setFillAttr(lgb);
  95. break;
  96. case "radial":
  97. this.fillStyle = f = g.makeParameters(g.defaultRadialGradient, fill);
  98. var rgb = p.createFromXaml("<RadialGradientBrush/>"),
  99. c = g.matrix.multiplyPoint(g.matrix.invert(this._getAdjustedMatrix()), f.cx, f.cy),
  100. pt = c.x + "," + c.y;
  101. rgb.mappingMode = "Absolute";
  102. rgb.gradientOrigin = pt;
  103. rgb.center = pt;
  104. rgb.radiusX = rgb.radiusY = f.r;
  105. arr.forEach(f.colors, function(c){
  106. var t = p.createFromXaml("<GradientStop/>");
  107. t.offset = c.offset;
  108. t.color = hexColor(c.color);
  109. rgb.gradientStops.add(t);
  110. });
  111. this._setFillAttr(rgb);
  112. break;
  113. case "pattern":
  114. // don't fill: Silverlight doesn't define TileBrush for some reason
  115. this.fillStyle = null;
  116. this._setFillAttr(null);
  117. break;
  118. }
  119. return this; // self
  120. }
  121. // color object
  122. this.fillStyle = f = g.normalizeColor(fill);
  123. var scb = p.createFromXaml("<SolidColorBrush/>");
  124. scb.color = f.toHex();
  125. scb.opacity = f.a;
  126. this._setFillAttr(scb);
  127. return this; // self
  128. },
  129. _setFillAttr: function(f){
  130. this.rawNode.fill = f;
  131. },
  132. setStroke: function(stroke){
  133. // summary: sets a stroke object (Silverlight)
  134. // stroke: Object: a stroke object
  135. // (see dojox.gfx.defaultStroke)
  136. var p = this.rawNode.getHost().content, r = this.rawNode;
  137. if(!stroke){
  138. // don't stroke
  139. this.strokeStyle = null;
  140. r.stroke = null;
  141. return this;
  142. }
  143. // normalize the stroke
  144. if(typeof stroke == "string" || lang.isArray(stroke) || stroke instanceof color){
  145. stroke = {color: stroke};
  146. }
  147. var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
  148. s.color = g.normalizeColor(s.color);
  149. // generate attributes
  150. if(s){
  151. var scb = p.createFromXaml("<SolidColorBrush/>");
  152. scb.color = s.color.toHex();
  153. scb.opacity = s.color.a;
  154. r.stroke = scb;
  155. r.strokeThickness = s.width;
  156. r.strokeStartLineCap = r.strokeEndLineCap = r.strokeDashCap =
  157. caps[s.cap];
  158. if(typeof s.join == "number"){
  159. r.strokeLineJoin = "Miter";
  160. r.strokeMiterLimit = s.join;
  161. }else{
  162. r.strokeLineJoin = joins[s.join];
  163. }
  164. var da = s.style.toLowerCase();
  165. if(da in dasharray){ da = dasharray[da]; }
  166. if(da instanceof Array){
  167. da = lang.clone(da);
  168. var i;
  169. /*
  170. for(var i = 0; i < da.length; ++i){
  171. da[i] *= s.width;
  172. }
  173. */
  174. if(s.cap != "butt"){
  175. for(i = 0; i < da.length; i += 2){
  176. //da[i] -= s.width;
  177. --da[i]
  178. if(da[i] < 1){ da[i] = 1; }
  179. }
  180. for(i = 1; i < da.length; i += 2){
  181. //da[i] += s.width;
  182. ++da[i];
  183. }
  184. }
  185. r.strokeDashArray = da.join(",");
  186. }else{
  187. r.strokeDashArray = null;
  188. }
  189. }
  190. return this; // self
  191. },
  192. _getParentSurface: function(){
  193. var surface = this.parent;
  194. for(; surface && !(surface instanceof g.Surface); surface = surface.parent);
  195. return surface;
  196. },
  197. _applyTransform: function() {
  198. var tm = this._getAdjustedMatrix(), r = this.rawNode;
  199. if(tm){
  200. var p = this.rawNode.getHost().content,
  201. mt = p.createFromXaml("<MatrixTransform/>"),
  202. mm = p.createFromXaml("<Matrix/>");
  203. mm.m11 = tm.xx;
  204. mm.m21 = tm.xy;
  205. mm.m12 = tm.yx;
  206. mm.m22 = tm.yy;
  207. mm.offsetX = tm.dx;
  208. mm.offsetY = tm.dy;
  209. mt.matrix = mm;
  210. r.renderTransform = mt;
  211. }else{
  212. r.renderTransform = null;
  213. }
  214. return this;
  215. },
  216. setRawNode: function(rawNode){
  217. // summary:
  218. // assigns and clears the underlying node that will represent this
  219. // shape. Once set, transforms, gradients, etc, can be applied.
  220. // (no fill & stroke by default)
  221. rawNode.fill = null;
  222. rawNode.stroke = null;
  223. this.rawNode = rawNode;
  224. this.rawNode.tag = this.getUID();
  225. },
  226. // move family
  227. _moveToFront: function(){
  228. // summary: moves a shape to front of its parent's list of shapes (Silverlight)
  229. var c = this.parent.rawNode.children, r = this.rawNode;
  230. c.remove(r);
  231. c.add(r);
  232. return this; // self
  233. },
  234. _moveToBack: function(){
  235. // summary: moves a shape to back of its parent's list of shapes (Silverlight)
  236. var c = this.parent.rawNode.children, r = this.rawNode;
  237. c.remove(r);
  238. c.insert(0, r);
  239. return this; // self
  240. },
  241. _getAdjustedMatrix: function(){
  242. // summary: returns the adjusted ("real") transformation matrix
  243. return this.matrix; // dojox.gfx.Matrix2D
  244. }
  245. });
  246. declare("dojox.gfx.silverlight.Group", sl.Shape, {
  247. // summary: a group shape (Silverlight), which can be used
  248. // to logically group shapes (e.g, to propagate matricies)
  249. constructor: function(){
  250. gs.Container._init.call(this);
  251. },
  252. setRawNode: function(rawNode){
  253. // summary: sets a raw Silverlight node to be used by this shape
  254. // rawNode: Node: an Silverlight node
  255. this.rawNode = rawNode;
  256. this.rawNode.tag = this.getUID();
  257. }
  258. });
  259. sl.Group.nodeType = "Canvas";
  260. declare("dojox.gfx.silverlight.Rect", [sl.Shape, gs.Rect], {
  261. // summary: a rectangle shape (Silverlight)
  262. setShape: function(newShape){
  263. // summary: sets a rectangle shape object (Silverlight)
  264. // newShape: Object: a rectangle shape object
  265. this.shape = g.makeParameters(this.shape, newShape);
  266. this.bbox = null;
  267. var r = this.rawNode, n = this.shape;
  268. r.width = n.width;
  269. r.height = n.height;
  270. r.radiusX = r.radiusY = n.r;
  271. return this._applyTransform(); // self
  272. },
  273. _getAdjustedMatrix: function(){
  274. // summary: returns the adjusted ("real") transformation matrix
  275. var matrix = this.matrix, s = this.shape, delta = {dx: s.x, dy: s.y};
  276. return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
  277. }
  278. });
  279. sl.Rect.nodeType = "Rectangle";
  280. declare("dojox.gfx.silverlight.Ellipse", [sl.Shape, gs.Ellipse], {
  281. // summary: an ellipse shape (Silverlight)
  282. setShape: function(newShape){
  283. // summary: sets an ellipse shape object (Silverlight)
  284. // newShape: Object: an ellipse shape object
  285. this.shape = g.makeParameters(this.shape, newShape);
  286. this.bbox = null;
  287. var r = this.rawNode, n = this.shape;
  288. r.width = 2 * n.rx;
  289. r.height = 2 * n.ry;
  290. return this._applyTransform(); // self
  291. },
  292. _getAdjustedMatrix: function(){
  293. // summary: returns the adjusted ("real") transformation matrix
  294. var matrix = this.matrix, s = this.shape, delta = {dx: s.cx - s.rx, dy: s.cy - s.ry};
  295. return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
  296. }
  297. });
  298. sl.Ellipse.nodeType = "Ellipse";
  299. declare("dojox.gfx.silverlight.Circle", [sl.Shape, gs.Circle], {
  300. // summary: a circle shape (Silverlight)
  301. setShape: function(newShape){
  302. // summary: sets a circle shape object (Silverlight)
  303. // newShape: Object: a circle shape object
  304. this.shape = g.makeParameters(this.shape, newShape);
  305. this.bbox = null;
  306. var r = this.rawNode, n = this.shape;
  307. r.width = r.height = 2 * n.r;
  308. return this._applyTransform(); // self
  309. },
  310. _getAdjustedMatrix: function(){
  311. // summary: returns the adjusted ("real") transformation matrix
  312. var matrix = this.matrix, s = this.shape, delta = {dx: s.cx - s.r, dy: s.cy - s.r};
  313. return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
  314. }
  315. });
  316. sl.Circle.nodeType = "Ellipse";
  317. declare("dojox.gfx.silverlight.Line", [sl.Shape, gs.Line], {
  318. // summary: a line shape (Silverlight)
  319. setShape: function(newShape){
  320. // summary: sets a line shape object (Silverlight)
  321. // newShape: Object: a line shape object
  322. this.shape = g.makeParameters(this.shape, newShape);
  323. this.bbox = null;
  324. var r = this.rawNode, n = this.shape;
  325. r.x1 = n.x1; r.y1 = n.y1; r.x2 = n.x2; r.y2 = n.y2;
  326. return this; // self
  327. }
  328. });
  329. sl.Line.nodeType = "Line";
  330. declare("dojox.gfx.silverlight.Polyline", [sl.Shape, gs.Polyline], {
  331. // summary: a polyline/polygon shape (Silverlight)
  332. setShape: function(points, closed){
  333. // summary: sets a polyline/polygon shape object (Silverlight)
  334. // points: Object: a polyline/polygon shape object
  335. if(points && points instanceof Array){
  336. // branch
  337. // points: Array: an array of points
  338. this.shape = g.makeParameters(this.shape, {points: points});
  339. if(closed && this.shape.points.length){
  340. this.shape.points.push(this.shape.points[0]);
  341. }
  342. }else{
  343. this.shape = g.makeParameters(this.shape, points);
  344. }
  345. this.bbox = null;
  346. this._normalizePoints();
  347. var p = this.shape.points, rp = [];
  348. for(var i = 0; i < p.length; ++i){
  349. rp.push(p[i].x, p[i].y);
  350. }
  351. this.rawNode.points = rp.join(",");
  352. return this; // self
  353. }
  354. });
  355. sl.Polyline.nodeType = "Polyline";
  356. declare("dojox.gfx.silverlight.Image", [sl.Shape, gs.Image], {
  357. // summary: an image (Silverlight)
  358. setShape: function(newShape){
  359. // summary: sets an image shape object (Silverlight)
  360. // newShape: Object: an image shape object
  361. this.shape = g.makeParameters(this.shape, newShape);
  362. this.bbox = null;
  363. var r = this.rawNode, n = this.shape;
  364. r.width = n.width;
  365. r.height = n.height;
  366. r.source = n.src;
  367. return this._applyTransform(); // self
  368. },
  369. _getAdjustedMatrix: function(){
  370. // summary: returns the adjusted ("real") transformation matrix
  371. var matrix = this.matrix, s = this.shape, delta = {dx: s.x, dy: s.y};
  372. return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
  373. },
  374. setRawNode: function(rawNode){
  375. // summary:
  376. // assigns and clears the underlying node that will represent this
  377. // shape. Once set, transforms, gradients, etc, can be applied.
  378. // (no fill & stroke by default)
  379. this.rawNode = rawNode;
  380. this.rawNode.tag = this.getUID();
  381. }
  382. });
  383. sl.Image.nodeType = "Image";
  384. declare("dojox.gfx.silverlight.Text", [sl.Shape, gs.Text], {
  385. // summary: an anchored text (Silverlight)
  386. setShape: function(newShape){
  387. // summary: sets a text shape object (Silverlight)
  388. // newShape: Object: a text shape object
  389. this.shape = g.makeParameters(this.shape, newShape);
  390. this.bbox = null;
  391. var r = this.rawNode, s = this.shape;
  392. r.text = "" + s.text; // #14522
  393. r.textDecorations = s.decoration === "underline" ? "Underline" : "None";
  394. r["Canvas.Left"] = -10000;
  395. r["Canvas.Top"] = -10000;
  396. if(!this._delay){
  397. this._delay = window.setTimeout(lang.hitch(this, "_delayAlignment"), 10);
  398. }
  399. return this; // self
  400. },
  401. _delayAlignment: function(){
  402. // handle alignment
  403. var r = this.rawNode, s = this.shape, w, h;
  404. try{
  405. w = r.actualWidth;
  406. h = r.actualHeight;
  407. }catch(e){
  408. // bail out if the node is hidden
  409. return;
  410. }
  411. var x = s.x, y = s.y - h * 0.75;
  412. switch(s.align){
  413. case "middle":
  414. x -= w / 2;
  415. break;
  416. case "end":
  417. x -= w;
  418. break;
  419. }
  420. this._delta = {dx: x, dy: y};
  421. r["Canvas.Left"] = 0;
  422. r["Canvas.Top"] = 0;
  423. this._applyTransform();
  424. delete this._delay;
  425. },
  426. _getAdjustedMatrix: function(){
  427. // summary: returns the adjusted ("real") transformation matrix
  428. var matrix = this.matrix, delta = this._delta, x;
  429. if(matrix){
  430. x = delta ? [matrix, delta] : matrix;
  431. }else{
  432. x = delta ? delta : {};
  433. }
  434. return new g.Matrix2D(x);
  435. },
  436. setStroke: function(){
  437. // summary: ignore setting a stroke style
  438. return this; // self
  439. },
  440. _setFillAttr: function(f){
  441. this.rawNode.foreground = f;
  442. },
  443. setRawNode: function(rawNode){
  444. // summary:
  445. // assigns and clears the underlying node that will represent this
  446. // shape. Once set, transforms, gradients, etc, can be applied.
  447. // (no fill & stroke by default)
  448. this.rawNode = rawNode;
  449. this.rawNode.tag = this.getUID();
  450. },
  451. getTextWidth: function(){
  452. // summary: get the text width in pixels
  453. return this.rawNode.actualWidth;
  454. }
  455. });
  456. sl.Text.nodeType = "TextBlock";
  457. declare("dojox.gfx.silverlight.Path", [sl.Shape, pathLib.Path], {
  458. // summary: a path shape (Silverlight)
  459. _updateWithSegment: function(segment){
  460. // summary: updates the bounding box of path with new segment
  461. // segment: Object: a segment
  462. this.inherited(arguments);
  463. var p = this.shape.path;
  464. if(typeof(p) == "string"){
  465. this.rawNode.data = p ? p : null;
  466. }
  467. },
  468. setShape: function(newShape){
  469. // summary: forms a path using a shape (Silverlight)
  470. // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
  471. this.inherited(arguments);
  472. var p = this.shape.path;
  473. this.rawNode.data = p ? p : null;
  474. return this; // self
  475. }
  476. });
  477. sl.Path.nodeType = "Path";
  478. declare("dojox.gfx.silverlight.TextPath", [sl.Shape, pathLib.TextPath], {
  479. // summary: a textpath shape (Silverlight)
  480. _updateWithSegment: function(segment){
  481. // summary: updates the bounding box of path with new segment
  482. // segment: Object: a segment
  483. },
  484. setShape: function(newShape){
  485. // summary: forms a path using a shape (Silverlight)
  486. // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
  487. },
  488. _setText: function(){
  489. }
  490. });
  491. sl.TextPath.nodeType = "text";
  492. var surfaces = {}, nullFunc = new Function;
  493. declare("dojox.gfx.silverlight.Surface", gs.Surface, {
  494. // summary: a surface object to be used for drawings (Silverlight)
  495. constructor: function(){
  496. gs.Container._init.call(this);
  497. },
  498. destroy: function(){
  499. window[this._onLoadName] = nullFunc;
  500. delete surfaces[this._nodeName];
  501. this.inherited(arguments);
  502. },
  503. setDimensions: function(width, height){
  504. // summary: sets the width and height of the rawNode
  505. // width: String: width of surface, e.g., "100px"
  506. // height: String: height of surface, e.g., "100px"
  507. this.width = g.normalizedLength(width); // in pixels
  508. this.height = g.normalizedLength(height); // in pixels
  509. var p = this.rawNode && this.rawNode.getHost();
  510. if(p){
  511. p.width = width;
  512. p.height = height;
  513. }
  514. return this; // self
  515. },
  516. getDimensions: function(){
  517. // summary: returns an object with properties "width" and "height"
  518. var p = this.rawNode && this.rawNode.getHost();
  519. var t = p ? {width: p.content.actualWidth, height: p.content.actualHeight} : null;
  520. if(t.width <= 0){ t.width = this.width; }
  521. if(t.height <= 0){ t.height = this.height; }
  522. return t; // Object
  523. }
  524. });
  525. sl.createSurface = function(parentNode, width, height){
  526. // summary: creates a surface (Silverlight)
  527. // parentNode: Node: a parent node
  528. // width: String: width of surface, e.g., "100px"
  529. // height: String: height of surface, e.g., "100px"
  530. if(!width && !height){
  531. var pos = domGeom.position(parentNode);
  532. width = width || pos.w;
  533. height = height || pos.h;
  534. }
  535. if(typeof width == "number"){
  536. width = width + "px";
  537. }
  538. if(typeof height == "number"){
  539. height = height + "px";
  540. }
  541. var s = new sl.Surface();
  542. parentNode = dom.byId(parentNode);
  543. s._parent = parentNode;
  544. s._nodeName = g._base._getUniqueId();
  545. // create an empty canvas
  546. var t = parentNode.ownerDocument.createElement("script");
  547. t.type = "text/xaml";
  548. t.id = g._base._getUniqueId();
  549. t.text = "<?xml version='1.0'?><Canvas xmlns='http://schemas.microsoft.com/client/2007' Name='" +
  550. s._nodeName + "'/>";
  551. parentNode.parentNode.insertBefore(t, parentNode);
  552. s._nodes.push(t);
  553. // build the object
  554. var obj, pluginName = g._base._getUniqueId(),
  555. onLoadName = "__" + g._base._getUniqueId() + "_onLoad";
  556. s._onLoadName = onLoadName;
  557. window[onLoadName] = function(sender){
  558. if(!s.rawNode){
  559. s.rawNode = dom.byId(pluginName).content.root;
  560. // register the plugin with its parent node
  561. surfaces[s._nodeName] = parentNode;
  562. s.onLoad(s);
  563. }
  564. };
  565. if(has("safari")){
  566. obj = "<embed type='application/x-silverlight' id='" +
  567. pluginName + "' width='" + width + "' height='" + height +
  568. " background='transparent'" +
  569. " source='#" + t.id + "'" +
  570. " windowless='true'" +
  571. " maxFramerate='60'" +
  572. " onLoad='" + onLoadName + "'" +
  573. " onError='__dojoSilverlightError'" +
  574. " /><iframe style='visibility:hidden;height:0;width:0'/>";
  575. }else{
  576. obj = "<object type='application/x-silverlight' data='data:application/x-silverlight,' id='" +
  577. pluginName + "' width='" + width + "' height='" + height + "'>" +
  578. "<param name='background' value='transparent' />" +
  579. "<param name='source' value='#" + t.id + "' />" +
  580. "<param name='windowless' value='true' />" +
  581. "<param name='maxFramerate' value='60' />" +
  582. "<param name='onLoad' value='" + onLoadName + "' />" +
  583. "<param name='onError' value='__dojoSilverlightError' />" +
  584. "</object>";
  585. }
  586. parentNode.innerHTML = obj;
  587. var pluginNode = dom.byId(pluginName);
  588. if(pluginNode.content && pluginNode.content.root){
  589. // the plugin was created synchronously
  590. s.rawNode = pluginNode.content.root;
  591. // register the plugin with its parent node
  592. surfaces[s._nodeName] = parentNode;
  593. }else{
  594. // the plugin is being created asynchronously
  595. s.rawNode = null;
  596. s.isLoaded = false;
  597. }
  598. s._nodes.push(pluginNode);
  599. s.width = g.normalizedLength(width); // in pixels
  600. s.height = g.normalizedLength(height); // in pixels
  601. return s; // dojox.gfx.Surface
  602. };
  603. // the function below is meant to be global, it is called from
  604. // the Silverlight's error handler
  605. __dojoSilverlightError = function(sender, err){
  606. var t = "Silverlight Error:\n" +
  607. "Code: " + err.ErrorCode + "\n" +
  608. "Type: " + err.ErrorType + "\n" +
  609. "Message: " + err.ErrorMessage + "\n";
  610. switch(err.ErrorType){
  611. case "ParserError":
  612. t += "XamlFile: " + err.xamlFile + "\n" +
  613. "Line: " + err.lineNumber + "\n" +
  614. "Position: " + err.charPosition + "\n";
  615. break;
  616. case "RuntimeError":
  617. t += "MethodName: " + err.methodName + "\n";
  618. if(err.lineNumber != 0){
  619. t +=
  620. "Line: " + err.lineNumber + "\n" +
  621. "Position: " + err.charPosition + "\n";
  622. }
  623. break;
  624. }
  625. };
  626. // Extenders
  627. var Font = {
  628. _setFont: function(){
  629. // summary: sets a font object (Silverlight)
  630. var f = this.fontStyle, r = this.rawNode, t = f.family.toLowerCase();
  631. r.fontStyle = f.style == "italic" ? "Italic" : "Normal";
  632. r.fontWeight = f.weight in fontweight ? fontweight[f.weight] : f.weight;
  633. r.fontSize = g.normalizedLength(f.size);
  634. r.fontFamily = t in fonts ? fonts[t] : f.family;
  635. // update the transform
  636. if(!this._delay){
  637. this._delay = window.setTimeout(lang.hitch(this, "_delayAlignment"), 10);
  638. }
  639. }
  640. };
  641. var C = gs.Container, Container = {
  642. add: function(shape){
  643. // summary: adds a shape to a group/surface
  644. // shape: dojox.gfx.Shape: a Silverlight shape object
  645. if(this != shape.getParent()){
  646. C.add.apply(this, arguments);
  647. this.rawNode.children.add(shape.rawNode);
  648. }
  649. return this; // self
  650. },
  651. remove: function(shape, silently){
  652. // summary: remove a shape from a group/surface
  653. // shape: dojox.gfx.Shape: a Silverlight shape object
  654. // silently: Boolean?: if true, regenerate a picture
  655. if(this == shape.getParent()){
  656. var parent = shape.rawNode.getParent();
  657. if(parent){
  658. parent.children.remove(shape.rawNode);
  659. }
  660. C.remove.apply(this, arguments);
  661. }
  662. return this; // self
  663. },
  664. clear: function(){
  665. // summary: removes all shapes from a group/surface
  666. this.rawNode.children.clear();
  667. return C.clear.apply(this, arguments);
  668. },
  669. _moveChildToFront: C._moveChildToFront,
  670. _moveChildToBack: C._moveChildToBack
  671. };
  672. var Creator = {
  673. createObject: function(shapeType, rawShape){
  674. // summary: creates an instance of the passed shapeType class
  675. // shapeType: Function: a class constructor to create an instance of
  676. // rawShape: Object: properties to be passed in to the classes "setShape" method
  677. if(!this.rawNode){ return null; }
  678. var shape = new shapeType();
  679. var node = this.rawNode.getHost().content.createFromXaml("<" + shapeType.nodeType + "/>");
  680. shape.setRawNode(node);
  681. shape.setShape(rawShape);
  682. this.add(shape);
  683. return shape; // dojox.gfx.Shape
  684. }
  685. };
  686. lang.extend(sl.Text, Font);
  687. //dojo.extend(sl.TextPath, Font);
  688. lang.extend(sl.Group, Container);
  689. lang.extend(sl.Group, gs.Creator);
  690. lang.extend(sl.Group, Creator);
  691. lang.extend(sl.Surface, Container);
  692. lang.extend(sl.Surface, gs.Creator);
  693. lang.extend(sl.Surface, Creator);
  694. function mouseFix(s, a){
  695. var ev = {target: s, currentTarget: s, preventDefault: function(){}, stopPropagation: function(){}};
  696. try{
  697. if(a.source){
  698. // support silverlight 2.0
  699. ev.target = a.source;
  700. var gfxId = ev.target.tag;
  701. ev.gfxTarget = gs.byId(gfxId);
  702. }
  703. }catch(e){
  704. // a.source does not exist in 1.0
  705. }
  706. if(a){
  707. try{
  708. ev.ctrlKey = a.ctrl;
  709. ev.shiftKey = a.shift;
  710. var p = a.getPosition(null);
  711. ev.x = ev.offsetX = ev.layerX = p.x;
  712. ev.y = ev.offsetY = ev.layerY = p.y;
  713. // calculate clientX and clientY
  714. var parent = surfaces[s.getHost().content.root.name];
  715. var t = domGeom.position(parent);
  716. ev.clientX = t.x + p.x;
  717. ev.clientY = t.y + p.y;
  718. }catch(e){
  719. // squelch bugs in MouseLeave's implementation
  720. }
  721. }
  722. return ev;
  723. }
  724. function keyFix(s, a){
  725. var ev = {
  726. keyCode: a.platformKeyCode,
  727. ctrlKey: a.ctrl,
  728. shiftKey: a.shift
  729. };
  730. try{
  731. if(a.source){
  732. // source is defined from Silverlight 2+
  733. ev.target = a.source;
  734. ev.gfxTarget = gs.byId(ev.target.tag);
  735. }
  736. }catch(e){
  737. // a.source does not exist in 1.0
  738. }
  739. return ev;
  740. }
  741. var eventNames = {
  742. onclick: {name: "MouseLeftButtonUp", fix: mouseFix},
  743. onmouseenter: {name: "MouseEnter", fix: mouseFix},
  744. onmouseleave: {name: "MouseLeave", fix: mouseFix},
  745. onmouseover: {name: "MouseEnter", fix: mouseFix},
  746. onmouseout: {name: "MouseLeave", fix: mouseFix},
  747. onmousedown: {name: "MouseLeftButtonDown", fix: mouseFix},
  748. onmouseup: {name: "MouseLeftButtonUp", fix: mouseFix},
  749. onmousemove: {name: "MouseMove", fix: mouseFix},
  750. onkeydown: {name: "KeyDown", fix: keyFix},
  751. onkeyup: {name: "KeyUp", fix: keyFix}
  752. };
  753. var eventsProcessing = {
  754. connect: function(name, object, method){
  755. var token, n = name in eventNames ? eventNames[name] :
  756. {name: name, fix: function(){ return {}; }};
  757. if(arguments.length > 2){
  758. token = this.getEventSource().addEventListener(n.name,
  759. function(s, a){ lang.hitch(object, method)(n.fix(s, a)); });
  760. }else{
  761. token = this.getEventSource().addEventListener(n.name,
  762. function(s, a){ object(n.fix(s, a)); });
  763. }
  764. return {name: n.name, token: token};
  765. },
  766. disconnect: function(token){
  767. try{
  768. this.getEventSource().removeEventListener(token.name, token.token);
  769. }catch(e){
  770. // bail out if the node is hidden
  771. }
  772. }
  773. };
  774. lang.extend(sl.Shape, eventsProcessing);
  775. lang.extend(sl.Surface, eventsProcessing);
  776. // patch dojox.gfx
  777. g.equalSources = function(a, b){
  778. // summary: compares event sources, returns true if they are equal
  779. return a && b && a.equals(b);
  780. };
  781. return sl;
  782. });