warning.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. * @license
  3. * Visual Blocks Editor
  4. *
  5. * Copyright 2012 Google Inc.
  6. * https://developers.google.com/blockly/
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. /**
  21. * @fileoverview Object representing a warning.
  22. * @author fraser@google.com (Neil Fraser)
  23. */
  24. 'use strict';
  25. goog.provide('Blockly.Warning');
  26. goog.require('Blockly.Bubble');
  27. goog.require('Blockly.Icon');
  28. /**
  29. * Class for a warning.
  30. * @param {!Blockly.Block} block The block associated with this warning.
  31. * @extends {Blockly.Icon}
  32. * @constructor
  33. */
  34. Blockly.Warning = function(block) {
  35. Blockly.Warning.superClass_.constructor.call(this, block);
  36. this.createIcon();
  37. // The text_ object can contain multiple warnings.
  38. this.text_ = {};
  39. };
  40. goog.inherits(Blockly.Warning, Blockly.Icon);
  41. /**
  42. * Does this icon get hidden when the block is collapsed.
  43. */
  44. Blockly.Warning.prototype.collapseHidden = false;
  45. /**
  46. * Draw the warning icon.
  47. * @param {!Element} group The icon group.
  48. * @private
  49. */
  50. Blockly.Warning.prototype.drawIcon_ = function(group) {
  51. // Triangle with rounded corners.
  52. Blockly.createSvgElement('path',
  53. {'class': 'blocklyIconShape',
  54. 'd': 'M2,15Q-1,15 0.5,12L6.5,1.7Q8,-1 9.5,1.7L15.5,12Q17,15 14,15z'},
  55. group);
  56. // Can't use a real '!' text character since different browsers and operating
  57. // systems render it differently.
  58. // Body of exclamation point.
  59. Blockly.createSvgElement('path',
  60. {'class': 'blocklyIconSymbol',
  61. 'd': 'm7,4.8v3.16l0.27,2.27h1.46l0.27,-2.27v-3.16z'},
  62. group);
  63. // Dot of exclamation point.
  64. Blockly.createSvgElement('rect',
  65. {'class': 'blocklyIconSymbol',
  66. 'x': '7', 'y': '11', 'height': '2', 'width': '2'},
  67. group);
  68. };
  69. /**
  70. * Create the text for the warning's bubble.
  71. * @param {string} text The text to display.
  72. * @return {!SVGTextElement} The top-level node of the text.
  73. * @private
  74. */
  75. Blockly.Warning.textToDom_ = function(text) {
  76. var paragraph = /** @type {!SVGTextElement} */ (
  77. Blockly.createSvgElement('text',
  78. {'class': 'blocklyText blocklyBubbleText',
  79. 'y': Blockly.Bubble.BORDER_WIDTH},
  80. null));
  81. var lines = text.split('\n');
  82. for (var i = 0; i < lines.length; i++) {
  83. var tspanElement = Blockly.createSvgElement('tspan',
  84. {'dy': '1em', 'x': Blockly.Bubble.BORDER_WIDTH}, paragraph);
  85. var textNode = document.createTextNode(lines[i]);
  86. tspanElement.appendChild(textNode);
  87. }
  88. return paragraph;
  89. };
  90. /**
  91. * Show or hide the warning bubble.
  92. * @param {boolean} visible True if the bubble should be visible.
  93. */
  94. Blockly.Warning.prototype.setVisible = function(visible) {
  95. if (visible == this.isVisible()) {
  96. // No change.
  97. return;
  98. }
  99. Blockly.Events.fire(
  100. new Blockly.Events.Ui(this.block_, 'warningOpen', !visible, visible));
  101. if (visible) {
  102. // Create the bubble to display all warnings.
  103. var paragraph = Blockly.Warning.textToDom_(this.getText());
  104. this.bubble_ = new Blockly.Bubble(
  105. /** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace),
  106. paragraph, this.block_.svgPath_, this.iconXY_, null, null);
  107. if (this.block_.RTL) {
  108. // Right-align the paragraph.
  109. // This cannot be done until the bubble is rendered on screen.
  110. var maxWidth = paragraph.getBBox().width;
  111. for (var i = 0, textElement; textElement = paragraph.childNodes[i]; i++) {
  112. textElement.setAttribute('text-anchor', 'end');
  113. textElement.setAttribute('x', maxWidth + Blockly.Bubble.BORDER_WIDTH);
  114. }
  115. }
  116. this.updateColour();
  117. // Bump the warning into the right location.
  118. var size = this.bubble_.getBubbleSize();
  119. this.bubble_.setBubbleSize(size.width, size.height);
  120. } else {
  121. // Dispose of the bubble.
  122. this.bubble_.dispose();
  123. this.bubble_ = null;
  124. this.body_ = null;
  125. }
  126. };
  127. /**
  128. * Bring the warning to the top of the stack when clicked on.
  129. * @param {!Event} e Mouse up event.
  130. * @private
  131. */
  132. Blockly.Warning.prototype.bodyFocus_ = function(e) {
  133. this.bubble_.promote_();
  134. };
  135. /**
  136. * Set this warning's text.
  137. * @param {string} text Warning text (or '' to delete).
  138. * @param {string} id An ID for this text entry to be able to maintain
  139. * multiple warnings.
  140. */
  141. Blockly.Warning.prototype.setText = function(text, id) {
  142. if (this.text_[id] == text) {
  143. return;
  144. }
  145. if (text) {
  146. this.text_[id] = text;
  147. } else {
  148. delete this.text_[id];
  149. }
  150. if (this.isVisible()) {
  151. this.setVisible(false);
  152. this.setVisible(true);
  153. }
  154. };
  155. /**
  156. * Get this warning's texts.
  157. * @return {string} All texts concatenated into one string.
  158. */
  159. Blockly.Warning.prototype.getText = function() {
  160. var allWarnings = [];
  161. for (var id in this.text_) {
  162. allWarnings.push(this.text_[id]);
  163. }
  164. return allWarnings.join('\n');
  165. };
  166. /**
  167. * Dispose of this warning.
  168. */
  169. Blockly.Warning.prototype.dispose = function() {
  170. this.block_.warning = null;
  171. Blockly.Icon.prototype.dispose.call(this);
  172. };