From beff5e19bf5e8fab93a7fac6d5f76a34e6ee0c3b Mon Sep 17 00:00:00 2001 From: kozbial Date: Tue, 27 Jul 2021 15:41:33 -0700 Subject: [PATCH] Combine workspace_comment_render_svg.js with workspace_comment_svg.js --- core/requires.js | 1 - core/workspace_comment_render_svg.js | 463 --------------------- core/workspace_comment_svg.js | 450 ++++++++++++++++++++ tests/deps.js | 3 +- tests/playground.html | 1 - tests/playgrounds/advanced_playground.html | 1 - 6 files changed, 451 insertions(+), 468 deletions(-) delete mode 100644 core/workspace_comment_render_svg.js diff --git a/core/requires.js b/core/requires.js index 2ca295441..cc67f564a 100644 --- a/core/requires.js +++ b/core/requires.js @@ -42,7 +42,6 @@ goog.require('Blockly.Trashcan'); goog.require('Blockly.VariablesDynamic'); // Only need to require these two if you're using workspace comments. // goog.require('Blockly.WorkspaceCommentSvg'); -// goog.require('Blockly.WorkspaceCommentSvg.render'); // If zoom controls aren't required, then Blockly.inject's // "zoom"/"controls" configuration must be false. goog.require('Blockly.ZoomControls'); diff --git a/core/workspace_comment_render_svg.js b/core/workspace_comment_render_svg.js deleted file mode 100644 index 5097f0c92..000000000 --- a/core/workspace_comment_render_svg.js +++ /dev/null @@ -1,463 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Methods for rendering a workspace comment as SVG - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -goog.provide('Blockly.WorkspaceCommentSvg.render'); - -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); - - -/** - * Size of the resize icon. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.RESIZE_SIZE = 8; - -/** - * Radius of the border around the comment. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.BORDER_RADIUS = 3; - -/** - * Offset from the foreignobject edge to the textarea edge. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET = 2; - -/** - * Offset from the top to make room for a top bar. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.TOP_OFFSET = 10; - -/** - * Returns a bounding box describing the dimensions of this comment. - * @return {!{height: number, width: number}} Object with height and width - * properties in workspace units. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.getHeightWidth = function() { - return { width: this.getWidth(), height: this.getHeight() }; -}; - -/** - * Renders the workspace comment. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.render = function() { - if (this.rendered_) { - return; - } - - var size = this.getHeightWidth(); - - // Add text area - this.createEditor_(); - this.svgGroup_.appendChild(this.foreignObject_); - - this.svgHandleTarget_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { - 'class': 'blocklyCommentHandleTarget', - 'x': 0, - 'y': 0 - }); - this.svgGroup_.appendChild(this.svgHandleTarget_); - this.svgRectTarget_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { - 'class': 'blocklyCommentTarget', - 'x': 0, - 'y': 0, - 'rx': Blockly.WorkspaceCommentSvg.BORDER_RADIUS, - 'ry': Blockly.WorkspaceCommentSvg.BORDER_RADIUS - }); - this.svgGroup_.appendChild(this.svgRectTarget_); - - // Add the resize icon - this.addResizeDom_(); - if (this.isDeletable()) { - // Add the delete icon - this.addDeleteDom_(); - } - - this.setSize_(size.width, size.height); - - // Set the content - this.textarea_.value = this.content_; - - this.rendered_ = true; - - if (this.resizeGroup_) { - Blockly.browserEvents.conditionalBind( - this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_); - } - - if (this.isDeletable()) { - Blockly.browserEvents.conditionalBind( - this.deleteGroup_, 'mousedown', this, this.deleteMouseDown_); - Blockly.browserEvents.conditionalBind( - this.deleteGroup_, 'mouseout', this, this.deleteMouseOut_); - Blockly.browserEvents.conditionalBind( - this.deleteGroup_, 'mouseup', this, this.deleteMouseUp_); - } -}; - -/** - * Create the text area for the comment. - * @return {!Element} The top-level node of the editor. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.createEditor_ = function() { - /* Create the editor. Here's the markup that will be generated: - - - - - - */ - this.foreignObject_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FOREIGNOBJECT, - { - 'x': 0, - 'y': Blockly.WorkspaceCommentSvg.TOP_OFFSET, - 'class': 'blocklyCommentForeignObject' - }, - null); - var body = document.createElementNS(Blockly.utils.dom.HTML_NS, 'body'); - body.setAttribute('xmlns', Blockly.utils.dom.HTML_NS); - body.className = 'blocklyMinimalBody'; - var textarea = document.createElementNS(Blockly.utils.dom.HTML_NS, 'textarea'); - textarea.className = 'blocklyCommentTextarea'; - textarea.setAttribute('dir', this.RTL ? 'RTL' : 'LTR'); - textarea.readOnly = !this.isEditable(); - body.appendChild(textarea); - this.textarea_ = textarea; - this.foreignObject_.appendChild(body); - // Don't zoom with mousewheel. - Blockly.browserEvents.conditionalBind(textarea, 'wheel', this, function(e) { - e.stopPropagation(); - }); - Blockly.browserEvents.conditionalBind( - textarea, 'change', this, - function( - /* eslint-disable no-unused-vars */ e - /* eslint-enable no-unused-vars */) { - this.setContent(textarea.value); - }); - return this.foreignObject_; -}; - -/** - * Add the resize icon to the DOM - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.addResizeDom_ = function() { - this.resizeGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - { - 'class': this.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE' - }, - this.svgGroup_); - var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE; - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.POLYGON, - {'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())}, - this.resizeGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'class': 'blocklyResizeLine', - 'x1': resizeSize / 3, 'y1': resizeSize - 1, - 'x2': resizeSize - 1, 'y2': resizeSize / 3 - }, this.resizeGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'class': 'blocklyResizeLine', - 'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1, - 'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3 - }, this.resizeGroup_); -}; - -/** - * Add the delete icon to the DOM - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.addDeleteDom_ = function() { - this.deleteGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - { - 'class': 'blocklyCommentDeleteIcon' - }, - this.svgGroup_); - this.deleteIconBorder_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CIRCLE, - { - 'class': 'blocklyDeleteIconShape', - 'r': '7', - 'cx': '7.5', - 'cy': '7.5' - }, - this.deleteGroup_); - // x icon. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'x1': '5', 'y1': '10', - 'x2': '10', 'y2': '5', - 'stroke': '#fff', - 'stroke-width': '2' - }, - this.deleteGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'x1': '5', 'y1': '5', - 'x2': '10', 'y2': '10', - 'stroke': '#fff', - 'stroke-width': '2' - }, - this.deleteGroup_); -}; - -/** - * Handle a mouse-down on comment's resize corner. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeMouseDown_ = function(e) { - this.unbindDragEvents_(); - if (Blockly.utils.isRightButton(e)) { - // No right-click. - e.stopPropagation(); - return; - } - // Left-click (or middle click) - this.workspace.startDrag(e, new Blockly.utils.Coordinate( - this.workspace.RTL ? -this.width_ : this.width_, this.height_)); - - this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind( - document, 'mouseup', this, this.resizeMouseUp_); - this.onMouseMoveWrapper_ = Blockly.browserEvents.conditionalBind( - document, 'mousemove', this, this.resizeMouseMove_); - Blockly.hideChaff(); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Handle a mouse-down on comment's delete icon. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.deleteMouseDown_ = function(e) { - // Highlight the delete icon. - Blockly.utils.dom.addClass( - /** @type {!Element} */ (this.deleteIconBorder_), - 'blocklyDeleteIconHighlighted'); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Handle a mouse-out on comment's delete icon. - * @param {!Event} _e Mouse out event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.deleteMouseOut_ = function(_e) { - // Restore highlight on the delete icon. - Blockly.utils.dom.removeClass( - /** @type {!Element} */ (this.deleteIconBorder_), - 'blocklyDeleteIconHighlighted'); -}; - -/** - * Handle a mouse-up on comment's delete icon. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.deleteMouseUp_ = function(e) { - // Delete this comment. - this.dispose(true, true); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Stop binding to the global mouseup and mousemove events. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.unbindDragEvents_ = function() { - if (this.onMouseUpWrapper_) { - Blockly.browserEvents.unbind(this.onMouseUpWrapper_); - this.onMouseUpWrapper_ = null; - } - if (this.onMouseMoveWrapper_) { - Blockly.browserEvents.unbind(this.onMouseMoveWrapper_); - this.onMouseMoveWrapper_ = null; - } -}; - -/** - * Handle a mouse-up event while dragging a comment's border or resize handle. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeMouseUp_ = function(/* e */) { - Blockly.Touch.clearTouchIdentifier(); - this.unbindDragEvents_(); -}; - -/** - * Resize this comment to follow the mouse. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeMouseMove_ = function(e) { - this.autoLayout_ = false; - var newXY = this.workspace.moveDrag(e); - this.setSize_(this.RTL ? -newXY.x : newXY.x, newXY.y); -}; - -/** - * Callback function triggered when the comment has resized. - * Resize the text area accordingly. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeComment_ = function() { - var size = this.getHeightWidth(); - var topOffset = Blockly.WorkspaceCommentSvg.TOP_OFFSET; - var textOffset = Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET * 2; - - this.foreignObject_.setAttribute('width', size.width); - this.foreignObject_.setAttribute('height', size.height - topOffset); - if (this.RTL) { - this.foreignObject_.setAttribute('x', -size.width); - } - this.textarea_.style.width = (size.width - textOffset) + 'px'; - this.textarea_.style.height = (size.height - textOffset - topOffset) + 'px'; -}; - -/** - * Set size - * @param {number} width width of the container - * @param {number} height height of the container - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.setSize_ = function(width, height) { - // Minimum size of a comment. - width = Math.max(width, 45); - height = Math.max(height, 20 + Blockly.WorkspaceCommentSvg.TOP_OFFSET); - this.width_ = width; - this.height_ = height; - this.svgRect_.setAttribute('width', width); - this.svgRect_.setAttribute('height', height); - this.svgRectTarget_.setAttribute('width', width); - this.svgRectTarget_.setAttribute('height', height); - this.svgHandleTarget_.setAttribute('width', width); - this.svgHandleTarget_.setAttribute('height', - Blockly.WorkspaceCommentSvg.TOP_OFFSET); - if (this.RTL) { - this.svgRect_.setAttribute('transform', 'scale(-1 1)'); - this.svgRectTarget_.setAttribute('transform', 'scale(-1 1)'); - } - - var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE; - if (this.resizeGroup_) { - if (this.RTL) { - // Mirror the resize group. - this.resizeGroup_.setAttribute('transform', 'translate(' + - (-width + resizeSize) + ',' + (height - resizeSize) + ') scale(-1 1)'); - this.deleteGroup_.setAttribute('transform', 'translate(' + - (-width + resizeSize) + ',' + (-resizeSize) + ') scale(-1 1)'); - } else { - this.resizeGroup_.setAttribute('transform', 'translate(' + - (width - resizeSize) + ',' + - (height - resizeSize) + ')'); - this.deleteGroup_.setAttribute('transform', 'translate(' + - (width - resizeSize) + ',' + - (-resizeSize) + ')'); - } - } - - // Allow the contents to resize. - this.resizeComment_(); -}; - -/** - * Dispose of any rendered comment components. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.disposeInternal_ = function() { - this.textarea_ = null; - this.foreignObject_ = null; - this.svgRectTarget_ = null; - this.svgHandleTarget_ = null; - this.disposed_ = true; -}; - -/** - * Set the focus on the text area. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.setFocus = function() { - var comment = this; - this.focused_ = true; - // Defer CSS changes. - setTimeout(function() { - if (comment.disposed_) { - return; - } - comment.textarea_.focus(); - comment.addFocus(); - Blockly.utils.dom.addClass( - comment.svgRectTarget_, 'blocklyCommentTargetFocused'); - Blockly.utils.dom.addClass( - comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); - }, 0); -}; - -/** - * Remove focus from the text area. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.blurFocus = function() { - var comment = this; - this.focused_ = false; - // Defer CSS changes. - setTimeout(function() { - if (comment.disposed_) { - return; - } - - comment.textarea_.blur(); - comment.removeFocus(); - Blockly.utils.dom.removeClass( - comment.svgRectTarget_, 'blocklyCommentTargetFocused'); - Blockly.utils.dom.removeClass( - comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); - }, 0); -}; diff --git a/core/workspace_comment_svg.js b/core/workspace_comment_svg.js index 401b840e1..84864422b 100644 --- a/core/workspace_comment_svg.js +++ b/core/workspace_comment_svg.js @@ -12,6 +12,9 @@ goog.provide('Blockly.WorkspaceCommentSvg'); +goog.require('Blockly'); +goog.require('Blockly.browserEvents'); +goog.require('Blockly.ContextMenu'); goog.require('Blockly.Css'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ @@ -22,6 +25,7 @@ goog.require('Blockly.Events.CommentDelete'); goog.require('Blockly.Events.CommentMove'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.Selected'); +goog.require('Blockly.Touch'); goog.require('Blockly.utils'); goog.require('Blockly.utils.Coordinate'); goog.require('Blockly.utils.dom'); @@ -30,9 +34,11 @@ goog.require('Blockly.utils.Rect'); goog.require('Blockly.utils.Svg'); goog.require('Blockly.WorkspaceComment'); +goog.requireType('Blockly.BlockDragSurfaceSvg'); goog.requireType('Blockly.IBoundedElement'); goog.requireType('Blockly.IBubble'); goog.requireType('Blockly.ICopyable'); +goog.requireType('Blockly.Workspace'); /** @@ -116,6 +122,38 @@ Blockly.utils.object.inherits( */ Blockly.WorkspaceCommentSvg.DEFAULT_SIZE = 100; +/** + * Size of the resize icon. + * @type {number} + * @const + * @private + */ +Blockly.WorkspaceCommentSvg.RESIZE_SIZE = 8; + +/** + * Radius of the border around the comment. + * @type {number} + * @const + * @private + */ +Blockly.WorkspaceCommentSvg.BORDER_RADIUS = 3; + +/** + * Offset from the foreignobject edge to the textarea edge. + * @type {number} + * @const + * @private + */ +Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET = 2; + +/** + * Offset from the top to make room for a top bar. + * @type {number} + * @const + * @private + */ +Blockly.WorkspaceCommentSvg.TOP_OFFSET = 10; + /** * Dispose of this comment. * @package @@ -646,6 +684,418 @@ Blockly.WorkspaceCommentSvg.prototype.toCopyData = function() { return {xml: this.toXmlWithXY(), source: this.workspace, typeCounts: null}; }; +/** + * Returns a bounding box describing the dimensions of this comment. + * @return {!{height: number, width: number}} Object with height and width + * properties in workspace units. + * @package + */ +Blockly.WorkspaceCommentSvg.prototype.getHeightWidth = function() { + return { width: this.getWidth(), height: this.getHeight() }; +}; + +/** + * Renders the workspace comment. + * @package + */ +Blockly.WorkspaceCommentSvg.prototype.render = function() { + if (this.rendered_) { + return; + } + + var size = this.getHeightWidth(); + + // Add text area + this.createEditor_(); + this.svgGroup_.appendChild(this.foreignObject_); + + this.svgHandleTarget_ = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.RECT, + { + 'class': 'blocklyCommentHandleTarget', + 'x': 0, + 'y': 0 + }); + this.svgGroup_.appendChild(this.svgHandleTarget_); + this.svgRectTarget_ = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.RECT, + { + 'class': 'blocklyCommentTarget', + 'x': 0, + 'y': 0, + 'rx': Blockly.WorkspaceCommentSvg.BORDER_RADIUS, + 'ry': Blockly.WorkspaceCommentSvg.BORDER_RADIUS + }); + this.svgGroup_.appendChild(this.svgRectTarget_); + + // Add the resize icon + this.addResizeDom_(); + if (this.isDeletable()) { + // Add the delete icon + this.addDeleteDom_(); + } + + this.setSize_(size.width, size.height); + + // Set the content + this.textarea_.value = this.content_; + + this.rendered_ = true; + + if (this.resizeGroup_) { + Blockly.browserEvents.conditionalBind( + this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_); + } + + if (this.isDeletable()) { + Blockly.browserEvents.conditionalBind( + this.deleteGroup_, 'mousedown', this, this.deleteMouseDown_); + Blockly.browserEvents.conditionalBind( + this.deleteGroup_, 'mouseout', this, this.deleteMouseOut_); + Blockly.browserEvents.conditionalBind( + this.deleteGroup_, 'mouseup', this, this.deleteMouseUp_); + } +}; + +/** + * Create the text area for the comment. + * @return {!Element} The top-level node of the editor. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.createEditor_ = function() { + /* Create the editor. Here's the markup that will be generated: + + + + + + */ + this.foreignObject_ = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.FOREIGNOBJECT, + { + 'x': 0, + 'y': Blockly.WorkspaceCommentSvg.TOP_OFFSET, + 'class': 'blocklyCommentForeignObject' + }, + null); + var body = document.createElementNS(Blockly.utils.dom.HTML_NS, 'body'); + body.setAttribute('xmlns', Blockly.utils.dom.HTML_NS); + body.className = 'blocklyMinimalBody'; + var textarea = document.createElementNS(Blockly.utils.dom.HTML_NS, 'textarea'); + textarea.className = 'blocklyCommentTextarea'; + textarea.setAttribute('dir', this.RTL ? 'RTL' : 'LTR'); + textarea.readOnly = !this.isEditable(); + body.appendChild(textarea); + this.textarea_ = textarea; + this.foreignObject_.appendChild(body); + // Don't zoom with mousewheel. + Blockly.browserEvents.conditionalBind(textarea, 'wheel', this, function(e) { + e.stopPropagation(); + }); + Blockly.browserEvents.conditionalBind( + textarea, 'change', this, + function( + /* eslint-disable no-unused-vars */ e + /* eslint-enable no-unused-vars */) { + this.setContent(textarea.value); + }); + return this.foreignObject_; +}; + +/** + * Add the resize icon to the DOM + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.addResizeDom_ = function() { + this.resizeGroup_ = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.G, + { + 'class': this.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE' + }, + this.svgGroup_); + var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE; + Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.POLYGON, + {'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())}, + this.resizeGroup_); + Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.LINE, + { + 'class': 'blocklyResizeLine', + 'x1': resizeSize / 3, 'y1': resizeSize - 1, + 'x2': resizeSize - 1, 'y2': resizeSize / 3 + }, this.resizeGroup_); + Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.LINE, + { + 'class': 'blocklyResizeLine', + 'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1, + 'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3 + }, this.resizeGroup_); +}; + +/** + * Add the delete icon to the DOM + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.addDeleteDom_ = function() { + this.deleteGroup_ = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.G, + { + 'class': 'blocklyCommentDeleteIcon' + }, + this.svgGroup_); + this.deleteIconBorder_ = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.CIRCLE, + { + 'class': 'blocklyDeleteIconShape', + 'r': '7', + 'cx': '7.5', + 'cy': '7.5' + }, + this.deleteGroup_); + // x icon. + Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.LINE, + { + 'x1': '5', 'y1': '10', + 'x2': '10', 'y2': '5', + 'stroke': '#fff', + 'stroke-width': '2' + }, + this.deleteGroup_); + Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.LINE, + { + 'x1': '5', 'y1': '5', + 'x2': '10', 'y2': '10', + 'stroke': '#fff', + 'stroke-width': '2' + }, + this.deleteGroup_); +}; + +/** + * Handle a mouse-down on comment's resize corner. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.resizeMouseDown_ = function(e) { + this.unbindDragEvents_(); + if (Blockly.utils.isRightButton(e)) { + // No right-click. + e.stopPropagation(); + return; + } + // Left-click (or middle click) + this.workspace.startDrag(e, new Blockly.utils.Coordinate( + this.workspace.RTL ? -this.width_ : this.width_, this.height_)); + + this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind( + document, 'mouseup', this, this.resizeMouseUp_); + this.onMouseMoveWrapper_ = Blockly.browserEvents.conditionalBind( + document, 'mousemove', this, this.resizeMouseMove_); + Blockly.hideChaff(); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Handle a mouse-down on comment's delete icon. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.deleteMouseDown_ = function(e) { + // Highlight the delete icon. + Blockly.utils.dom.addClass( + /** @type {!Element} */ (this.deleteIconBorder_), + 'blocklyDeleteIconHighlighted'); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Handle a mouse-out on comment's delete icon. + * @param {!Event} _e Mouse out event. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.deleteMouseOut_ = function(_e) { + // Restore highlight on the delete icon. + Blockly.utils.dom.removeClass( + /** @type {!Element} */ (this.deleteIconBorder_), + 'blocklyDeleteIconHighlighted'); +}; + +/** + * Handle a mouse-up on comment's delete icon. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.deleteMouseUp_ = function(e) { + // Delete this comment. + this.dispose(true, true); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.unbindDragEvents_ = function() { + if (this.onMouseUpWrapper_) { + Blockly.browserEvents.unbind(this.onMouseUpWrapper_); + this.onMouseUpWrapper_ = null; + } + if (this.onMouseMoveWrapper_) { + Blockly.browserEvents.unbind(this.onMouseMoveWrapper_); + this.onMouseMoveWrapper_ = null; + } +}; + +/** + * Handle a mouse-up event while dragging a comment's border or resize handle. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.resizeMouseUp_ = function(/* e */) { + Blockly.Touch.clearTouchIdentifier(); + this.unbindDragEvents_(); +}; + +/** + * Resize this comment to follow the mouse. + * @param {!Event} e Mouse move event. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.resizeMouseMove_ = function(e) { + this.autoLayout_ = false; + var newXY = this.workspace.moveDrag(e); + this.setSize_(this.RTL ? -newXY.x : newXY.x, newXY.y); +}; + +/** + * Callback function triggered when the comment has resized. + * Resize the text area accordingly. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.resizeComment_ = function() { + var size = this.getHeightWidth(); + var topOffset = Blockly.WorkspaceCommentSvg.TOP_OFFSET; + var textOffset = Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET * 2; + + this.foreignObject_.setAttribute('width', size.width); + this.foreignObject_.setAttribute('height', size.height - topOffset); + if (this.RTL) { + this.foreignObject_.setAttribute('x', -size.width); + } + this.textarea_.style.width = (size.width - textOffset) + 'px'; + this.textarea_.style.height = (size.height - textOffset - topOffset) + 'px'; +}; + +/** + * Set size + * @param {number} width width of the container + * @param {number} height height of the container + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.setSize_ = function(width, height) { + // Minimum size of a comment. + width = Math.max(width, 45); + height = Math.max(height, 20 + Blockly.WorkspaceCommentSvg.TOP_OFFSET); + this.width_ = width; + this.height_ = height; + this.svgRect_.setAttribute('width', width); + this.svgRect_.setAttribute('height', height); + this.svgRectTarget_.setAttribute('width', width); + this.svgRectTarget_.setAttribute('height', height); + this.svgHandleTarget_.setAttribute('width', width); + this.svgHandleTarget_.setAttribute('height', + Blockly.WorkspaceCommentSvg.TOP_OFFSET); + if (this.RTL) { + this.svgRect_.setAttribute('transform', 'scale(-1 1)'); + this.svgRectTarget_.setAttribute('transform', 'scale(-1 1)'); + } + + var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE; + if (this.resizeGroup_) { + if (this.RTL) { + // Mirror the resize group. + this.resizeGroup_.setAttribute('transform', 'translate(' + + (-width + resizeSize) + ',' + (height - resizeSize) + ') scale(-1 1)'); + this.deleteGroup_.setAttribute('transform', 'translate(' + + (-width + resizeSize) + ',' + (-resizeSize) + ') scale(-1 1)'); + } else { + this.resizeGroup_.setAttribute('transform', 'translate(' + + (width - resizeSize) + ',' + + (height - resizeSize) + ')'); + this.deleteGroup_.setAttribute('transform', 'translate(' + + (width - resizeSize) + ',' + + (-resizeSize) + ')'); + } + } + + // Allow the contents to resize. + this.resizeComment_(); +}; + +/** + * Dispose of any rendered comment components. + * @private + */ +Blockly.WorkspaceCommentSvg.prototype.disposeInternal_ = function() { + this.textarea_ = null; + this.foreignObject_ = null; + this.svgRectTarget_ = null; + this.svgHandleTarget_ = null; + this.disposed_ = true; +}; + +/** + * Set the focus on the text area. + * @package + */ +Blockly.WorkspaceCommentSvg.prototype.setFocus = function() { + var comment = this; + this.focused_ = true; + // Defer CSS changes. + setTimeout(function() { + if (comment.disposed_) { + return; + } + comment.textarea_.focus(); + comment.addFocus(); + Blockly.utils.dom.addClass( + comment.svgRectTarget_, 'blocklyCommentTargetFocused'); + Blockly.utils.dom.addClass( + comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); + }, 0); +}; + +/** + * Remove focus from the text area. + * @package + */ +Blockly.WorkspaceCommentSvg.prototype.blurFocus = function() { + var comment = this; + this.focused_ = false; + // Defer CSS changes. + setTimeout(function() { + if (comment.disposed_) { + return; + } + + comment.textarea_.blur(); + comment.removeFocus(); + Blockly.utils.dom.removeClass( + comment.svgRectTarget_, 'blocklyCommentTargetFocused'); + Blockly.utils.dom.removeClass( + comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); + }, 0); +}; + /** * CSS for workspace comment. See css.js for use. */ diff --git a/tests/deps.js b/tests/deps.js index f17d995b9..a729ae7b9 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -204,8 +204,7 @@ goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.u goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.IASTNodeLocation', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math']); goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly', 'Blockly.ContextMenu', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.Touch', 'Blockly.WorkspaceComment', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom']); goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate']); goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.IASTNodeLocationSvg', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); diff --git a/tests/playground.html b/tests/playground.html index 11179a0db..b53e76ea8 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -71,7 +71,6 @@