PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/yarn-blocks/blockly/core/renderers/common/marker_svg.js

https://gitlab.com/then-try-this/penelopean-robotics
JavaScript | 688 lines | 354 code | 78 blank | 256 comment | 48 complexity | c30f4c0c9b66f5cea1d5b244e3bc3eff MD5 | raw file
  1. /**
  2. * @license
  3. * Copyright 2019 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @fileoverview Methods for graphically rendering a marker as SVG.
  8. * @author samelh@microsoft.com (Sam El-Husseini)
  9. */
  10. 'use strict';
  11. goog.provide('Blockly.blockRendering.MarkerSvg');
  12. goog.require('Blockly.ASTNode');
  13. goog.require('Blockly.constants');
  14. goog.require('Blockly.utils.dom');
  15. goog.require('Blockly.utils.Svg');
  16. /**
  17. * Class for a marker.
  18. * @param {!Blockly.WorkspaceSvg} workspace The workspace the marker belongs to.
  19. * @param {!Blockly.blockRendering.ConstantProvider} constants The constants for
  20. * the renderer.
  21. * @param {!Blockly.Marker} marker The marker to draw.
  22. * @constructor
  23. */
  24. Blockly.blockRendering.MarkerSvg = function(workspace, constants, marker) {
  25. /**
  26. * The workspace the marker belongs to.
  27. * @type {!Blockly.WorkspaceSvg}
  28. * @private
  29. */
  30. this.workspace_ = workspace;
  31. /**
  32. * The marker to draw.
  33. * @type {!Blockly.Marker}
  34. * @private
  35. */
  36. this.marker_ = marker;
  37. /**
  38. * The workspace, field, or block that the marker SVG element should be
  39. * attached to.
  40. * @type {Blockly.IASTNodeLocationSvg}
  41. * @private
  42. */
  43. this.parent_ = null;
  44. /**
  45. * The constants necessary to draw the marker.
  46. * @type {Blockly.blockRendering.ConstantProvider}
  47. * @protected
  48. */
  49. this.constants_ = constants;
  50. /**
  51. * The current SVG element for the marker.
  52. * @type {Element}
  53. */
  54. this.currentMarkerSvg = null;
  55. var defaultColour = this.isCursor() ? this.constants_.CURSOR_COLOUR :
  56. this.constants_.MARKER_COLOUR;
  57. /**
  58. * The colour of the marker.
  59. * @type {string}
  60. */
  61. this.colour_ = marker.colour || defaultColour;
  62. };
  63. /**
  64. * The name of the CSS class for a cursor.
  65. * @const {string}
  66. */
  67. Blockly.blockRendering.MarkerSvg.CURSOR_CLASS = 'blocklyCursor';
  68. /**
  69. * The name of the CSS class for a marker.
  70. * @const {string}
  71. */
  72. Blockly.blockRendering.MarkerSvg.MARKER_CLASS = 'blocklyMarker';
  73. /**
  74. * What we multiply the height by to get the height of the marker.
  75. * Only used for the block and block connections.
  76. * @const {number}
  77. */
  78. Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER = 3 / 4;
  79. /**
  80. * Return the root node of the SVG or null if none exists.
  81. * @return {SVGElement} The root SVG node.
  82. */
  83. Blockly.blockRendering.MarkerSvg.prototype.getSvgRoot = function() {
  84. return this.svgGroup_;
  85. };
  86. /**
  87. * Get the marker.
  88. * @return {!Blockly.Marker} The marker to draw for.
  89. */
  90. Blockly.blockRendering.MarkerSvg.prototype.getMarker = function() {
  91. return this.marker_;
  92. };
  93. /**
  94. * True if the marker should be drawn as a cursor, false otherwise.
  95. * A cursor is drawn as a flashing line. A marker is drawn as a solid line.
  96. * @return {boolean} True if the marker is a cursor, false otherwise.
  97. */
  98. Blockly.blockRendering.MarkerSvg.prototype.isCursor = function() {
  99. return this.marker_.type == 'cursor';
  100. };
  101. /**
  102. * Create the DOM element for the marker.
  103. * @return {!SVGElement} The marker controls SVG group.
  104. * @package
  105. */
  106. Blockly.blockRendering.MarkerSvg.prototype.createDom = function() {
  107. var className = this.isCursor() ?
  108. Blockly.blockRendering.MarkerSvg.CURSOR_CLASS :
  109. Blockly.blockRendering.MarkerSvg.MARKER_CLASS;
  110. this.svgGroup_ = Blockly.utils.dom.createSvgElement(
  111. Blockly.utils.Svg.G, {
  112. 'class': className
  113. }, null);
  114. this.createDomInternal_();
  115. return this.svgGroup_;
  116. };
  117. /**
  118. * Attaches the SVG root of the marker to the SVG group of the parent.
  119. * @param {!Blockly.IASTNodeLocationSvg} newParent The workspace, field, or
  120. * block that the marker SVG element should be attached to.
  121. * @protected
  122. */
  123. Blockly.blockRendering.MarkerSvg.prototype.setParent_ = function(newParent) {
  124. if (!this.isCursor()) {
  125. if (this.parent_) {
  126. this.parent_.setMarkerSvg(null);
  127. }
  128. newParent.setMarkerSvg(this.getSvgRoot());
  129. } else {
  130. if (this.parent_) {
  131. this.parent_.setCursorSvg(null);
  132. }
  133. newParent.setCursorSvg(this.getSvgRoot());
  134. }
  135. this.parent_ = newParent;
  136. };
  137. /**
  138. * Update the marker.
  139. * @param {Blockly.ASTNode} oldNode The previous node the marker was on or null.
  140. * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for.
  141. */
  142. Blockly.blockRendering.MarkerSvg.prototype.draw = function(oldNode, curNode) {
  143. if (!curNode) {
  144. this.hide();
  145. return;
  146. }
  147. this.constants_ = this.workspace_.getRenderer().getConstants();
  148. var defaultColour = this.isCursor() ? this.constants_.CURSOR_COLOUR :
  149. this.constants_.MARKER_COLOUR;
  150. this.colour_ = this.marker_.colour || defaultColour;
  151. this.applyColour_(curNode);
  152. this.showAtLocation_(curNode);
  153. this.fireMarkerEvent_(oldNode, curNode);
  154. // Ensures the marker will be visible immediately after the move.
  155. var animate = this.currentMarkerSvg.childNodes[0];
  156. if (animate !== undefined) {
  157. animate.beginElement && animate.beginElement();
  158. }
  159. };
  160. /**
  161. * Update the marker's visible state based on the type of curNode..
  162. * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for.
  163. * @protected
  164. */
  165. Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) {
  166. var curNodeAsConnection =
  167. /** @type {!Blockly.Connection} */ (curNode.getLocation());
  168. if (curNode.getType() == Blockly.ASTNode.types.BLOCK) {
  169. this.showWithBlock_(curNode);
  170. } else if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) {
  171. this.showWithOutput_(curNode);
  172. } else if (curNodeAsConnection.type == Blockly.INPUT_VALUE) {
  173. this.showWithInput_(curNode);
  174. } else if (curNodeAsConnection.type == Blockly.NEXT_STATEMENT) {
  175. this.showWithNext_(curNode);
  176. } else if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS) {
  177. this.showWithPrevious_(curNode);
  178. } else if (curNode.getType() == Blockly.ASTNode.types.FIELD) {
  179. this.showWithField_(curNode);
  180. } else if (curNode.getType() == Blockly.ASTNode.types.WORKSPACE) {
  181. this.showWithCoordinates_(curNode);
  182. } else if (curNode.getType() == Blockly.ASTNode.types.STACK) {
  183. this.showWithStack_(curNode);
  184. }
  185. };
  186. /**************************
  187. * Display
  188. **************************/
  189. /**
  190. * Show the marker as a combination of the previous connection and block,
  191. * the output connection and block, or just the block.
  192. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  193. * @private
  194. */
  195. Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function(
  196. curNode) {
  197. var block = /** @type {!Blockly.BlockSvg} */ (curNode.getSourceBlock());
  198. var width = block.width;
  199. var height = block.height;
  200. var markerHeight = height * Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER;
  201. var markerOffset = this.constants_.CURSOR_BLOCK_PADDING;
  202. if (block.previousConnection) {
  203. var connectionShape = this.constants_.shapeFor(block.previousConnection);
  204. this.positionPrevious_(width, markerOffset, markerHeight, connectionShape);
  205. } else if (block.outputConnection) {
  206. var connectionShape = this.constants_.shapeFor(block.outputConnection);
  207. this.positionOutput_(width, height, connectionShape);
  208. } else {
  209. this.positionBlock_(width, markerOffset, markerHeight);
  210. }
  211. this.setParent_(block);
  212. this.showCurrent_();
  213. };
  214. /**
  215. * Position and display the marker for a block.
  216. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  217. * @protected
  218. */
  219. Blockly.blockRendering.MarkerSvg.prototype.showWithBlock_ = function(curNode) {
  220. this.showWithBlockPrevOutput_(curNode);
  221. };
  222. /**
  223. * Position and display the marker for a previous connection.
  224. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  225. * @protected
  226. */
  227. Blockly.blockRendering.MarkerSvg.prototype.showWithPrevious_ = function(
  228. curNode) {
  229. this.showWithBlockPrevOutput_(curNode);
  230. };
  231. /**
  232. * Position and display the marker for an output connection.
  233. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  234. * @protected
  235. */
  236. Blockly.blockRendering.MarkerSvg.prototype.showWithOutput_ = function(curNode) {
  237. this.showWithBlockPrevOutput_(curNode);
  238. };
  239. /**
  240. * Position and display the marker for a workspace coordinate.
  241. * This is a horizontal line.
  242. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  243. * @protected
  244. */
  245. Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function(
  246. curNode) {
  247. var wsCoordinate = curNode.getWsCoordinate();
  248. var x = wsCoordinate.x;
  249. var y = wsCoordinate.y;
  250. if (this.workspace_.RTL) {
  251. x -= this.constants_.CURSOR_WS_WIDTH;
  252. }
  253. this.positionLine_(x, y, this.constants_.CURSOR_WS_WIDTH);
  254. this.setParent_(this.workspace_);
  255. this.showCurrent_();
  256. };
  257. /**
  258. * Position and display the marker for a field.
  259. * This is a box around the field.
  260. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  261. * @protected
  262. */
  263. Blockly.blockRendering.MarkerSvg.prototype.showWithField_ = function(curNode) {
  264. var field = /** @type {Blockly.Field} */ (curNode.getLocation());
  265. var width = field.getSize().width;
  266. var height = field.getSize().height;
  267. this.positionRect_(0, 0, width, height);
  268. this.setParent_(field);
  269. this.showCurrent_();
  270. };
  271. /**
  272. * Position and display the marker for an input.
  273. * This is a puzzle piece.
  274. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  275. * @protected
  276. */
  277. Blockly.blockRendering.MarkerSvg.prototype.showWithInput_ = function(curNode) {
  278. var connection = /** @type {Blockly.RenderedConnection} */
  279. (curNode.getLocation());
  280. var sourceBlock = /** @type {!Blockly.BlockSvg} */ (connection.getSourceBlock());
  281. this.positionInput_(connection);
  282. this.setParent_(sourceBlock);
  283. this.showCurrent_();
  284. };
  285. /**
  286. * Position and display the marker for a next connection.
  287. * This is a horizontal line.
  288. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  289. * @protected
  290. */
  291. Blockly.blockRendering.MarkerSvg.prototype.showWithNext_ = function(curNode) {
  292. var connection =
  293. /** @type {!Blockly.RenderedConnection} */ (curNode.getLocation());
  294. var targetBlock =
  295. /** @type {Blockly.BlockSvg} */ (connection.getSourceBlock());
  296. var x = 0;
  297. var y = connection.getOffsetInBlock().y;
  298. var width = targetBlock.getHeightWidth().width;
  299. if (this.workspace_.RTL) {
  300. x = -width;
  301. }
  302. this.positionLine_(x, y, width);
  303. this.setParent_(targetBlock);
  304. this.showCurrent_();
  305. };
  306. /**
  307. * Position and display the marker for a stack.
  308. * This is a box with extra padding around the entire stack of blocks.
  309. * @param {!Blockly.ASTNode} curNode The node to draw the marker for.
  310. * @protected
  311. */
  312. Blockly.blockRendering.MarkerSvg.prototype.showWithStack_ = function(curNode) {
  313. var block = /** @type {Blockly.BlockSvg} */ (curNode.getLocation());
  314. // Gets the height and width of entire stack.
  315. var heightWidth = block.getHeightWidth();
  316. // Add padding so that being on a stack looks different than being on a block.
  317. var width = heightWidth.width + this.constants_.CURSOR_STACK_PADDING;
  318. var height = heightWidth.height + this.constants_.CURSOR_STACK_PADDING;
  319. // Shift the rectangle slightly to upper left so padding is equal on all sides.
  320. var xPadding = -this.constants_.CURSOR_STACK_PADDING / 2;
  321. var yPadding = -this.constants_.CURSOR_STACK_PADDING / 2;
  322. var x = xPadding;
  323. var y = yPadding;
  324. if (this.workspace_.RTL) {
  325. x = -(width + xPadding);
  326. }
  327. this.positionRect_(x, y, width, height);
  328. this.setParent_(block);
  329. this.showCurrent_();
  330. };
  331. /**
  332. * Show the current marker.
  333. * @protected
  334. */
  335. Blockly.blockRendering.MarkerSvg.prototype.showCurrent_ = function() {
  336. this.hide();
  337. this.currentMarkerSvg.style.display = '';
  338. };
  339. /**************************
  340. * Position
  341. **************************/
  342. /**
  343. * Position the marker for a block.
  344. * Displays an outline of the top half of a rectangle around a block.
  345. * @param {number} width The width of the block.
  346. * @param {number} markerOffset The extra padding for around the block.
  347. * @param {number} markerHeight The height of the marker.
  348. * @protected
  349. */
  350. Blockly.blockRendering.MarkerSvg.prototype.positionBlock_ = function(
  351. width, markerOffset, markerHeight) {
  352. var markerPath = Blockly.utils.svgPaths.moveBy(-markerOffset, markerHeight) +
  353. Blockly.utils.svgPaths.lineOnAxis('V', -markerOffset) +
  354. Blockly.utils.svgPaths.lineOnAxis('H', width + markerOffset * 2) +
  355. Blockly.utils.svgPaths.lineOnAxis('V', markerHeight);
  356. this.markerBlock_.setAttribute('d', markerPath);
  357. if (this.workspace_.RTL) {
  358. this.flipRtl_(this.markerBlock_);
  359. }
  360. this.currentMarkerSvg = this.markerBlock_;
  361. };
  362. /**
  363. * Position the marker for an input connection.
  364. * Displays a filled in puzzle piece.
  365. * @param {!Blockly.RenderedConnection} connection The connection to position
  366. * marker around.
  367. * @protected
  368. */
  369. Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(
  370. connection) {
  371. var x = connection.getOffsetInBlock().x;
  372. var y = connection.getOffsetInBlock().y;
  373. var path = Blockly.utils.svgPaths.moveTo(0, 0) +
  374. this.constants_.shapeFor(connection).pathDown;
  375. this.markerInput_.setAttribute('d', path);
  376. this.markerInput_.setAttribute('transform',
  377. 'translate(' + x + ',' + y + ')' +
  378. (this.workspace_.RTL ? ' scale(-1 1)' : ''));
  379. this.currentMarkerSvg = this.markerInput_;
  380. };
  381. /**
  382. * Move and show the marker at the specified coordinate in workspace units.
  383. * Displays a horizontal line.
  384. * @param {number} x The new x, in workspace units.
  385. * @param {number} y The new y, in workspace units.
  386. * @param {number} width The new width, in workspace units.
  387. * @protected
  388. */
  389. Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function(
  390. x, y, width) {
  391. this.markerSvgLine_.setAttribute('x', x);
  392. this.markerSvgLine_.setAttribute('y', y);
  393. this.markerSvgLine_.setAttribute('width', width);
  394. this.currentMarkerSvg = this.markerSvgLine_;
  395. };
  396. /**
  397. * Position the marker for an output connection.
  398. * Displays a puzzle outline and the top and bottom path.
  399. * @param {number} width The width of the block.
  400. * @param {number} height The height of the block.
  401. * @param {!Object} connectionShape The shape object for the connection.
  402. * @protected
  403. */
  404. Blockly.blockRendering.MarkerSvg.prototype.positionOutput_ = function(
  405. width, height, connectionShape) {
  406. var markerPath = Blockly.utils.svgPaths.moveBy(width, 0) +
  407. Blockly.utils.svgPaths.lineOnAxis(
  408. 'h', -(width - connectionShape.width)) +
  409. Blockly.utils.svgPaths.lineOnAxis(
  410. 'v', this.constants_.TAB_OFFSET_FROM_TOP) +
  411. connectionShape.pathDown +
  412. Blockly.utils.svgPaths.lineOnAxis('V', height) +
  413. Blockly.utils.svgPaths.lineOnAxis('H', width);
  414. this.markerBlock_.setAttribute('d', markerPath);
  415. if (this.workspace_.RTL) {
  416. this.flipRtl_(this.markerBlock_);
  417. }
  418. this.currentMarkerSvg = this.markerBlock_;
  419. };
  420. /**
  421. * Position the marker for a previous connection.
  422. * Displays a half rectangle with a notch in the top to represent the previous
  423. * connection.
  424. * @param {number} width The width of the block.
  425. * @param {number} markerOffset The offset of the marker from around the block.
  426. * @param {number} markerHeight The height of the marker.
  427. * @param {!Object} connectionShape The shape object for the connection.
  428. * @protected
  429. */
  430. Blockly.blockRendering.MarkerSvg.prototype.positionPrevious_ = function(
  431. width, markerOffset, markerHeight, connectionShape) {
  432. var markerPath = Blockly.utils.svgPaths.moveBy(-markerOffset, markerHeight) +
  433. Blockly.utils.svgPaths.lineOnAxis('V', -markerOffset) +
  434. Blockly.utils.svgPaths.lineOnAxis(
  435. 'H', this.constants_.NOTCH_OFFSET_LEFT) +
  436. connectionShape.pathLeft +
  437. Blockly.utils.svgPaths.lineOnAxis(
  438. 'H', width + markerOffset * 2) +
  439. Blockly.utils.svgPaths.lineOnAxis('V', markerHeight);
  440. this.markerBlock_.setAttribute('d', markerPath);
  441. if (this.workspace_.RTL) {
  442. this.flipRtl_(this.markerBlock_);
  443. }
  444. this.currentMarkerSvg = this.markerBlock_;
  445. };
  446. /**
  447. * Move and show the marker at the specified coordinate in workspace units.
  448. * Displays a filled in rectangle.
  449. * @param {number} x The new x, in workspace units.
  450. * @param {number} y The new y, in workspace units.
  451. * @param {number} width The new width, in workspace units.
  452. * @param {number} height The new height, in workspace units.
  453. * @protected
  454. */
  455. Blockly.blockRendering.MarkerSvg.prototype.positionRect_ = function(
  456. x, y, width, height) {
  457. this.markerSvgRect_.setAttribute('x', x);
  458. this.markerSvgRect_.setAttribute('y', y);
  459. this.markerSvgRect_.setAttribute('width', width);
  460. this.markerSvgRect_.setAttribute('height', height);
  461. this.currentMarkerSvg = this.markerSvgRect_;
  462. };
  463. /**
  464. * Flip the SVG paths in RTL.
  465. * @param {!SVGElement} markerSvg The marker that we want to flip.
  466. * @private
  467. */
  468. Blockly.blockRendering.MarkerSvg.prototype.flipRtl_ = function(markerSvg) {
  469. markerSvg.setAttribute('transform', 'scale(-1 1)');
  470. };
  471. /**
  472. * Hide the marker.
  473. */
  474. Blockly.blockRendering.MarkerSvg.prototype.hide = function() {
  475. this.markerSvgLine_.style.display = 'none';
  476. this.markerSvgRect_.style.display = 'none';
  477. this.markerInput_.style.display = 'none';
  478. this.markerBlock_.style.display = 'none';
  479. };
  480. /**
  481. * Fire event for the marker or marker.
  482. * @param {Blockly.ASTNode} oldNode The old node the marker used to be on.
  483. * @param {!Blockly.ASTNode} curNode The new node the marker is currently on.
  484. * @private
  485. */
  486. Blockly.blockRendering.MarkerSvg.prototype.fireMarkerEvent_ = function(
  487. oldNode, curNode) {
  488. var curBlock = curNode.getSourceBlock();
  489. var eventType = this.isCursor() ? 'cursorMove' : 'markerMove';
  490. var event = new Blockly.Events.Ui(curBlock, eventType, oldNode, curNode);
  491. if (curNode.getType() == Blockly.ASTNode.types.WORKSPACE) {
  492. event.workspaceId =
  493. (/** @type {!Blockly.Workspace} */ (curNode.getLocation())).id;
  494. }
  495. Blockly.Events.fire(event);
  496. };
  497. /**
  498. * Get the properties to make a marker blink.
  499. * @return {!Object} The object holding attributes to make the marker blink.
  500. * @protected
  501. */
  502. Blockly.blockRendering.MarkerSvg.prototype.getBlinkProperties_ = function() {
  503. return {
  504. 'attributeType': 'XML',
  505. 'attributeName': 'fill',
  506. 'dur': '1s',
  507. 'values': this.colour_ + ';transparent;transparent;',
  508. 'repeatCount': 'indefinite'
  509. };
  510. };
  511. /**
  512. * Create the marker SVG.
  513. * @return {Element} The SVG node created.
  514. * @protected
  515. */
  516. Blockly.blockRendering.MarkerSvg.prototype.createDomInternal_ = function() {
  517. /* This markup will be generated and added to the .svgGroup_:
  518. <g>
  519. <rect width="100" height="5">
  520. <animate attributeType="XML" attributeName="fill" dur="1s"
  521. values="transparent;transparent;#fff;transparent" repeatCount="indefinite" />
  522. </rect>
  523. </g>
  524. */
  525. this.markerSvg_ = Blockly.utils.dom.createSvgElement(
  526. Blockly.utils.Svg.G,
  527. {
  528. 'width': this.constants_.CURSOR_WS_WIDTH,
  529. 'height': this.constants_.WS_CURSOR_HEIGHT
  530. }, this.svgGroup_);
  531. // A horizontal line used to represent a workspace coordinate or next
  532. // connection.
  533. this.markerSvgLine_ = Blockly.utils.dom.createSvgElement(
  534. Blockly.utils.Svg.RECT,
  535. {
  536. 'width': this.constants_.CURSOR_WS_WIDTH,
  537. 'height': this.constants_.WS_CURSOR_HEIGHT,
  538. 'style': 'display: none'
  539. },
  540. this.markerSvg_);
  541. // A filled in rectangle used to represent a stack.
  542. this.markerSvgRect_ = Blockly.utils.dom.createSvgElement(
  543. Blockly.utils.Svg.RECT,
  544. {
  545. 'class': 'blocklyVerticalMarker',
  546. 'rx': 10, 'ry': 10,
  547. 'style': 'display: none'
  548. },
  549. this.markerSvg_);
  550. // A filled in puzzle piece used to represent an input value.
  551. this.markerInput_ = Blockly.utils.dom.createSvgElement(
  552. Blockly.utils.Svg.PATH,
  553. {
  554. 'transform': '',
  555. 'style': 'display: none'
  556. },
  557. this.markerSvg_);
  558. // A path used to represent a previous connection and a block, an output
  559. // connection and a block, or a block.
  560. this.markerBlock_ = Blockly.utils.dom.createSvgElement(
  561. Blockly.utils.Svg.PATH,
  562. {
  563. 'transform': '',
  564. 'style': 'display: none',
  565. 'fill': 'none',
  566. 'stroke-width': this.constants_.CURSOR_STROKE_WIDTH
  567. },
  568. this.markerSvg_);
  569. // Markers and stack markers don't blink.
  570. if (this.isCursor()) {
  571. var blinkProperties = this.getBlinkProperties_();
  572. Blockly.utils.dom.createSvgElement(
  573. Blockly.utils.Svg.ANIMATE, blinkProperties,
  574. this.markerSvgLine_);
  575. Blockly.utils.dom.createSvgElement(
  576. Blockly.utils.Svg.ANIMATE, blinkProperties,
  577. this.markerInput_);
  578. blinkProperties['attributeName'] = 'stroke';
  579. Blockly.utils.dom.createSvgElement(
  580. Blockly.utils.Svg.ANIMATE, blinkProperties,
  581. this.markerBlock_);
  582. }
  583. return this.markerSvg_;
  584. };
  585. /**
  586. * Apply the marker's colour.
  587. * @param {!Blockly.ASTNode} _curNode The node that we want to draw the marker
  588. * for.
  589. * @protected
  590. */
  591. Blockly.blockRendering.MarkerSvg.prototype.applyColour_ = function(_curNode) {
  592. this.markerSvgLine_.setAttribute('fill', this.colour_);
  593. this.markerSvgRect_.setAttribute('stroke', this.colour_);
  594. this.markerInput_.setAttribute('fill', this.colour_);
  595. this.markerBlock_.setAttribute('stroke', this.colour_);
  596. if (this.isCursor()) {
  597. var values = this.colour_ + ';transparent;transparent;';
  598. this.markerSvgLine_.firstChild.setAttribute('values', values);
  599. this.markerInput_.firstChild.setAttribute('values', values);
  600. this.markerBlock_.firstChild.setAttribute('values', values);
  601. }
  602. };
  603. /**
  604. * Dispose of this marker.
  605. */
  606. Blockly.blockRendering.MarkerSvg.prototype.dispose = function() {
  607. if (this.svgGroup_) {
  608. Blockly.utils.dom.removeNode(this.svgGroup_);
  609. }
  610. };