mirror of
https://github.com/google/blockly.git
synced 2026-01-10 18:37:09 +01:00
Merge branch 'goog_module' into connection
This commit is contained in:
35
.github/workflows/tag_module_cleanup.yml
vendored
Normal file
35
.github/workflows/tag_module_cleanup.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# For new pull requests against the goog_module branch, adds the 'type: cleanup'
|
||||
# label and sets the milestone to q3 2021 release.
|
||||
|
||||
name: Tag module cleanup
|
||||
|
||||
# Trigger on pull requests against goog_module branch only
|
||||
# Uses pull_request_target to get write permissions so that it can write labels.
|
||||
on:
|
||||
pull_request_target:
|
||||
branches:
|
||||
- goog_module
|
||||
|
||||
jobs:
|
||||
tag-module-cleanup:
|
||||
|
||||
# Add the type: cleanup label
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@a3e7071a34d7e1f219a8a4de9a5e0a34d1ee1293
|
||||
with:
|
||||
script: |
|
||||
// 2021 q3 release milestone.
|
||||
// https://github.com/google/blockly/milestone/18
|
||||
const milestoneNumber = 18;
|
||||
// Note that pull requests are accessed through the issues API.
|
||||
const issuesUpdateParams = {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
// Adds the milestone
|
||||
milestone: milestoneNumber,
|
||||
issue_number: context.issue.number,
|
||||
// Sets the labels
|
||||
labels: ['type: cleanup']
|
||||
}
|
||||
await github.issues.update(issuesUpdateParams)
|
||||
@@ -10,50 +10,52 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.BubbleDragger');
|
||||
goog.module('Blockly.BubbleDragger');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
const BlockDragSurfaceSvg = goog.requireType('Blockly.BlockDragSurfaceSvg');
|
||||
const ComponentManager = goog.require('Blockly.ComponentManager');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
const IBubble = goog.requireType('Blockly.IBubble');
|
||||
const IDeleteArea = goog.requireType('Blockly.IDeleteArea');
|
||||
const IDragTarget = goog.requireType('Blockly.IDragTarget');
|
||||
const utils = goog.require('Blockly.utils');
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Bubble');
|
||||
goog.require('Blockly.ComponentManager');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.constants');
|
||||
goog.require('Blockly.Events');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.CommentMove');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
|
||||
goog.requireType('Blockly.BlockDragSurfaceSvg');
|
||||
goog.requireType('Blockly.IBubble');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a bubble dragger. It moves things on the bubble canvas around the
|
||||
* workspace when they are being dragged by a mouse or touch. These can be
|
||||
* block comments, mutators, warnings, or workspace comments.
|
||||
* @param {!Blockly.IBubble} bubble The item on the bubble canvas to drag.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace to drag on.
|
||||
* @param {!IBubble} bubble The item on the bubble canvas to drag.
|
||||
* @param {!WorkspaceSvg} workspace The workspace to drag on.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.BubbleDragger = function(bubble, workspace) {
|
||||
const BubbleDragger = function(bubble, workspace) {
|
||||
/**
|
||||
* The item on the bubble canvas that is being dragged.
|
||||
* @type {!Blockly.IBubble}
|
||||
* @type {!IBubble}
|
||||
* @private
|
||||
*/
|
||||
this.draggingBubble_ = bubble;
|
||||
|
||||
/**
|
||||
* The workspace on which the bubble is being dragged.
|
||||
* @type {!Blockly.WorkspaceSvg}
|
||||
* @type {!WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
this.workspace_ = workspace;
|
||||
|
||||
/**
|
||||
* Which drag target the mouse pointer is over, if any.
|
||||
* @type {?Blockly.IDragTarget}
|
||||
* @type {?IDragTarget}
|
||||
* @private
|
||||
*/
|
||||
this.dragTarget_ = null;
|
||||
@@ -68,7 +70,7 @@ Blockly.BubbleDragger = function(bubble, workspace) {
|
||||
/**
|
||||
* The location of the top left corner of the dragging bubble's body at the
|
||||
* beginning of the drag, in workspace coordinates.
|
||||
* @type {!Blockly.utils.Coordinate}
|
||||
* @type {!Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.startXY_ = this.draggingBubble_.getRelativeToSurfaceXY();
|
||||
@@ -76,11 +78,11 @@ Blockly.BubbleDragger = function(bubble, workspace) {
|
||||
/**
|
||||
* The drag surface to move bubbles to during a drag, or null if none should
|
||||
* be used. Block dragging and bubble dragging use the same surface.
|
||||
* @type {Blockly.BlockDragSurfaceSvg}
|
||||
* @type {BlockDragSurfaceSvg}
|
||||
* @private
|
||||
*/
|
||||
this.dragSurface_ =
|
||||
Blockly.utils.is3dSupported() && !!workspace.getBlockDragSurface() ?
|
||||
utils.is3dSupported() && !!workspace.getBlockDragSurface() ?
|
||||
workspace.getBlockDragSurface() :
|
||||
null;
|
||||
};
|
||||
@@ -90,7 +92,7 @@ Blockly.BubbleDragger = function(bubble, workspace) {
|
||||
* @package
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.dispose = function() {
|
||||
BubbleDragger.prototype.dispose = function() {
|
||||
this.draggingBubble_ = null;
|
||||
this.workspace_ = null;
|
||||
this.dragSurface_ = null;
|
||||
@@ -100,9 +102,9 @@ Blockly.BubbleDragger.prototype.dispose = function() {
|
||||
* Start dragging a bubble. This includes moving it to the drag surface.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.startBubbleDrag = function() {
|
||||
if (!Blockly.Events.getGroup()) {
|
||||
Blockly.Events.setGroup(true);
|
||||
BubbleDragger.prototype.startBubbleDrag = function() {
|
||||
if (!Events.getGroup()) {
|
||||
Events.setGroup(true);
|
||||
}
|
||||
|
||||
this.workspace_.setResizesEnabled(false);
|
||||
@@ -118,19 +120,19 @@ Blockly.BubbleDragger.prototype.startBubbleDrag = function() {
|
||||
* Execute a step of bubble dragging, based on the given event. Update the
|
||||
* display accordingly.
|
||||
* @param {!Event} e The most recent move event.
|
||||
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* @param {!Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* moved from the position at the start of the drag, in pixel units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) {
|
||||
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
|
||||
BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) {
|
||||
const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
const newLoc = Coordinate.sum(this.startXY_, delta);
|
||||
this.draggingBubble_.moveDuringDrag(this.dragSurface_, newLoc);
|
||||
|
||||
var oldDragTarget = this.dragTarget_;
|
||||
const oldDragTarget = this.dragTarget_;
|
||||
this.dragTarget_ = this.workspace_.getDragTarget(e);
|
||||
|
||||
var oldWouldDeleteBubble = this.wouldDeleteBubble_;
|
||||
const oldWouldDeleteBubble = this.wouldDeleteBubble_;
|
||||
this.wouldDeleteBubble_ = this.shouldDelete_(this.dragTarget_);
|
||||
if (oldWouldDeleteBubble != this.wouldDeleteBubble_) {
|
||||
// Prevent unnecessary add/remove class calls.
|
||||
@@ -147,19 +149,19 @@ Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) {
|
||||
|
||||
/**
|
||||
* Whether ending the drag would delete the bubble.
|
||||
* @param {?Blockly.IDragTarget} dragTarget The drag target that the bubblee is
|
||||
* @param {?IDragTarget} dragTarget The drag target that the bubblee is
|
||||
* currently over.
|
||||
* @return {boolean} Whether dropping the bubble immediately would delete the
|
||||
* block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.shouldDelete_ = function(dragTarget) {
|
||||
BubbleDragger.prototype.shouldDelete_ = function(dragTarget) {
|
||||
if (dragTarget) {
|
||||
var componentManager = this.workspace_.getComponentManager();
|
||||
var isDeleteArea = componentManager.hasCapability(dragTarget.id,
|
||||
Blockly.ComponentManager.Capability.DELETE_AREA);
|
||||
const componentManager = this.workspace_.getComponentManager();
|
||||
const isDeleteArea = componentManager.hasCapability(
|
||||
dragTarget.id, ComponentManager.Capability.DELETE_AREA);
|
||||
if (isDeleteArea) {
|
||||
return (/** @type {!Blockly.IDeleteArea} */ (dragTarget))
|
||||
return (/** @type {!IDeleteArea} */ (dragTarget))
|
||||
.wouldDelete(this.draggingBubble_, false);
|
||||
}
|
||||
}
|
||||
@@ -171,29 +173,29 @@ Blockly.BubbleDragger.prototype.shouldDelete_ = function(dragTarget) {
|
||||
* dragging bubble would be deleted if released immediately.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() {
|
||||
BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() {
|
||||
this.draggingBubble_.setDeleteStyle(this.wouldDeleteBubble_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Finish a bubble drag and put the bubble back on the workspace.
|
||||
* @param {!Event} e The mouseup/touchend event.
|
||||
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* @param {!Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* moved from the position at the start of the drag, in pixel units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.endBubbleDrag = function(
|
||||
e, currentDragDeltaXY) {
|
||||
BubbleDragger.prototype.endBubbleDrag = function(e, currentDragDeltaXY) {
|
||||
// Make sure internal state is fresh.
|
||||
this.dragBubble(e, currentDragDeltaXY);
|
||||
|
||||
var preventMove = this.dragTarget_ &&
|
||||
const preventMove = this.dragTarget_ &&
|
||||
this.dragTarget_.shouldPreventMove(this.draggingBubble_);
|
||||
let newLoc;
|
||||
if (preventMove) {
|
||||
var newLoc = this.startXY_;
|
||||
newLoc = this.startXY_;
|
||||
} else {
|
||||
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
|
||||
const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
newLoc = Coordinate.sum(this.startXY_, delta);
|
||||
}
|
||||
// Move the bubble to its final location.
|
||||
this.draggingBubble_.moveTo(newLoc.x, newLoc.y);
|
||||
@@ -218,20 +220,21 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function(
|
||||
}
|
||||
this.workspace_.setResizesEnabled(true);
|
||||
|
||||
Blockly.Events.setGroup(false);
|
||||
Events.setGroup(false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire a move event at the end of a bubble drag.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.fireMoveEvent_ = function() {
|
||||
BubbleDragger.prototype.fireMoveEvent_ = function() {
|
||||
if (this.draggingBubble_.isComment) {
|
||||
var event = new (Blockly.Events.get(Blockly.Events.COMMENT_MOVE))(
|
||||
// TODO (adodson): Resolve build errors when requiring WorkspaceCommentSvg.
|
||||
const event = new (Events.get(Events.COMMENT_MOVE))(
|
||||
/** @type {!Blockly.WorkspaceCommentSvg} */ (this.draggingBubble_));
|
||||
event.setOldCoordinate(this.startXY_);
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
Events.fire(event);
|
||||
}
|
||||
// TODO (fenichel): move events for comments.
|
||||
return;
|
||||
@@ -242,14 +245,14 @@ Blockly.BubbleDragger.prototype.fireMoveEvent_ = function() {
|
||||
* correction for mutator workspaces.
|
||||
* This function does not consider differing origins. It simply scales the
|
||||
* input's x and y values.
|
||||
* @param {!Blockly.utils.Coordinate} pixelCoord A coordinate with x and y
|
||||
* @param {!Coordinate} pixelCoord A coordinate with x and y
|
||||
* values in CSS pixel units.
|
||||
* @return {!Blockly.utils.Coordinate} The input coordinate divided by the
|
||||
* @return {!Coordinate} The input coordinate divided by the
|
||||
* workspace scale.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
|
||||
var result = new Blockly.utils.Coordinate(
|
||||
BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
|
||||
const result = new Coordinate(
|
||||
pixelCoord.x / this.workspace_.scale,
|
||||
pixelCoord.y / this.workspace_.scale);
|
||||
if (this.workspace_.isMutator) {
|
||||
@@ -257,7 +260,7 @@ Blockly.BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
|
||||
// oddities in our rendering optimizations. The actual scale is the same as
|
||||
// the scale on the parent workspace.
|
||||
// Fix that for dragging.
|
||||
var mainScale = this.workspace_.options.parentWorkspace.scale;
|
||||
const mainScale = this.workspace_.options.parentWorkspace.scale;
|
||||
result.scale(1 / mainScale);
|
||||
}
|
||||
return result;
|
||||
@@ -268,9 +271,11 @@ Blockly.BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
|
||||
* drag surface to preserve the apparent location of the bubble.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.moveToDragSurface_ = function() {
|
||||
BubbleDragger.prototype.moveToDragSurface_ = function() {
|
||||
this.draggingBubble_.moveTo(0, 0);
|
||||
this.dragSurface_.translateSurface(this.startXY_.x, this.startXY_.y);
|
||||
// Execute the move on the top-level SVG component.
|
||||
this.dragSurface_.setBlocksAndShow(this.draggingBubble_.getSvgRoot());
|
||||
};
|
||||
|
||||
exports = BubbleDragger;
|
||||
|
||||
206
core/comment.js
206
core/comment.js
@@ -10,43 +10,43 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Comment');
|
||||
goog.module('Blockly.Comment');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.browserEvents');
|
||||
goog.require('Blockly.Bubble');
|
||||
goog.require('Blockly.Css');
|
||||
goog.require('Blockly.Events');
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const Bubble = goog.require('Blockly.Bubble');
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
const Icon = goog.require('Blockly.Icon');
|
||||
const Size = goog.requireType('Blockly.utils.Size');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const userAgent = goog.require('Blockly.utils.userAgent');
|
||||
const {conditionalBind, Data, unbind} = goog.require('Blockly.browserEvents');
|
||||
const {createSvgElement, HTML_NS} = goog.require('Blockly.utils.dom');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
const {register} = goog.require('Blockly.Css');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.BlockChange');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.BubbleOpen');
|
||||
goog.require('Blockly.Icon');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
goog.require('Blockly.utils.userAgent');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Warning');
|
||||
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
goog.requireType('Blockly.utils.Size');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a comment.
|
||||
* @param {!Blockly.Block} block The block associated with this comment.
|
||||
* @extends {Blockly.Icon}
|
||||
* @param {!Block} block The block associated with this comment.
|
||||
* @extends {Icon}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Comment = function(block) {
|
||||
Blockly.Comment.superClass_.constructor.call(this, block);
|
||||
const Comment = function(block) {
|
||||
Comment.superClass_.constructor.call(this, block);
|
||||
|
||||
/**
|
||||
* The model for this comment.
|
||||
* @type {!Blockly.Block.CommentModel}
|
||||
* @type {!Block.CommentModel}
|
||||
* @private
|
||||
*/
|
||||
this.model_ = block.commentModel;
|
||||
@@ -64,62 +64,60 @@ Blockly.Comment = function(block) {
|
||||
|
||||
/**
|
||||
* Mouse up event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?Data}
|
||||
* @private
|
||||
*/
|
||||
this.onMouseUpWrapper_ = null;
|
||||
|
||||
/**
|
||||
* Wheel event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?Data}
|
||||
* @private
|
||||
*/
|
||||
this.onWheelWrapper_ = null;
|
||||
|
||||
/**
|
||||
* Change event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?Data}
|
||||
* @private
|
||||
*/
|
||||
this.onChangeWrapper_ = null;
|
||||
|
||||
/**
|
||||
* Input event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?Data}
|
||||
* @private
|
||||
*/
|
||||
this.onInputWrapper_ = null;
|
||||
|
||||
this.createIcon();
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.Comment, Blockly.Icon);
|
||||
inherits(Comment, Icon);
|
||||
|
||||
/**
|
||||
* Draw the comment icon.
|
||||
* @param {!Element} group The icon group.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Comment.prototype.drawIcon_ = function(group) {
|
||||
Comment.prototype.drawIcon_ = function(group) {
|
||||
// Circle.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.CIRCLE,
|
||||
{'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'},
|
||||
createSvgElement(
|
||||
Svg.CIRCLE, {'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'},
|
||||
group);
|
||||
// Can't use a real '?' text character since different browsers and operating
|
||||
// systems render it differently.
|
||||
// Body of question mark.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATH,
|
||||
{
|
||||
createSvgElement(
|
||||
Svg.PATH, {
|
||||
'class': 'blocklyIconSymbol',
|
||||
'd': 'm6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.405' +
|
||||
'0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25' +
|
||||
'-1.201,0.998 -1.201,1.528 -1.204,2.19z'},
|
||||
'0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25' +
|
||||
'-1.201,0.998 -1.201,1.528 -1.204,2.19z'
|
||||
},
|
||||
group);
|
||||
// Dot of question mark.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
createSvgElement(
|
||||
Svg.RECT, {
|
||||
'class': 'blocklyIconSymbol',
|
||||
'x': '6.8',
|
||||
'y': '10.78',
|
||||
@@ -134,7 +132,7 @@ Blockly.Comment.prototype.drawIcon_ = function(group) {
|
||||
* @return {!SVGElement} The top-level node of the editor.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Comment.prototype.createEditor_ = function() {
|
||||
Comment.prototype.createEditor_ = function() {
|
||||
/* Create the editor. Here's the markup that will be generated in
|
||||
* editable mode:
|
||||
<foreignObject x="8" y="8" width="164" height="164">
|
||||
@@ -147,18 +145,16 @@ Blockly.Comment.prototype.createEditor_ = function() {
|
||||
* For non-editable mode see Warning.textToDom_.
|
||||
*/
|
||||
|
||||
this.foreignObject_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FOREIGNOBJECT,
|
||||
{'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH},
|
||||
this.foreignObject_ = createSvgElement(
|
||||
Svg.FOREIGNOBJECT, {'x': Bubble.BORDER_WIDTH, 'y': Bubble.BORDER_WIDTH},
|
||||
null);
|
||||
|
||||
var body = document.createElementNS(Blockly.utils.dom.HTML_NS, 'body');
|
||||
body.setAttribute('xmlns', Blockly.utils.dom.HTML_NS);
|
||||
const body = document.createElementNS(HTML_NS, 'body');
|
||||
body.setAttribute('xmlns', HTML_NS);
|
||||
body.className = 'blocklyMinimalBody';
|
||||
|
||||
this.textarea_ = document.createElementNS(
|
||||
Blockly.utils.dom.HTML_NS, 'textarea');
|
||||
var textarea = this.textarea_;
|
||||
this.textarea_ = document.createElementNS(HTML_NS, 'textarea');
|
||||
const textarea = this.textarea_;
|
||||
textarea.className = 'blocklyCommentTextarea';
|
||||
textarea.setAttribute('dir', this.block_.RTL ? 'RTL' : 'LTR');
|
||||
textarea.value = this.model_.text;
|
||||
@@ -170,26 +166,23 @@ Blockly.Comment.prototype.createEditor_ = function() {
|
||||
// Ideally this would be hooked to the focus event for the comment.
|
||||
// However doing so in Firefox swallows the cursor for unknown reasons.
|
||||
// So this is hooked to mouseup instead. No big deal.
|
||||
this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
textarea, 'mouseup', this, this.startEdit_, true, true);
|
||||
this.onMouseUpWrapper_ =
|
||||
conditionalBind(textarea, 'mouseup', this, this.startEdit_, true, true);
|
||||
// Don't zoom with mousewheel.
|
||||
this.onWheelWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
textarea, 'wheel', this, function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
this.onChangeWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
textarea, 'change', this, function(_e) {
|
||||
this.onWheelWrapper_ = conditionalBind(textarea, 'wheel', this, function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
this.onChangeWrapper_ =
|
||||
conditionalBind(textarea, 'change', this, function(_e) {
|
||||
if (this.cachedText_ != this.model_.text) {
|
||||
Blockly.Events.fire(
|
||||
new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))(
|
||||
this.block_, 'comment', null, this.cachedText_,
|
||||
this.model_.text));
|
||||
Events.fire(new (Events.get(Events.BLOCK_CHANGE))(
|
||||
this.block_, 'comment', null, this.cachedText_,
|
||||
this.model_.text));
|
||||
}
|
||||
});
|
||||
this.onInputWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
textarea, 'input', this, function(_e) {
|
||||
this.model_.text = textarea.value;
|
||||
});
|
||||
this.onInputWrapper_ = conditionalBind(textarea, 'input', this, function(_e) {
|
||||
this.model_.text = textarea.value;
|
||||
});
|
||||
|
||||
setTimeout(textarea.focus.bind(textarea), 0);
|
||||
|
||||
@@ -200,8 +193,8 @@ Blockly.Comment.prototype.createEditor_ = function() {
|
||||
* Add or remove editability of the comment.
|
||||
* @override
|
||||
*/
|
||||
Blockly.Comment.prototype.updateEditable = function() {
|
||||
Blockly.Comment.superClass_.updateEditable.call(this);
|
||||
Comment.prototype.updateEditable = function() {
|
||||
Comment.superClass_.updateEditable.call(this);
|
||||
if (this.isVisible()) {
|
||||
// Recreate the bubble with the correct UI.
|
||||
this.disposeBubble_();
|
||||
@@ -214,7 +207,7 @@ Blockly.Comment.prototype.updateEditable = function() {
|
||||
* Resize the text area accordingly.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Comment.prototype.onBubbleResize_ = function() {
|
||||
Comment.prototype.onBubbleResize_ = function() {
|
||||
if (!this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
@@ -227,11 +220,11 @@ Blockly.Comment.prototype.onBubbleResize_ = function() {
|
||||
* the size of the bubble).
|
||||
* @private
|
||||
*/
|
||||
Blockly.Comment.prototype.resizeTextarea_ = function() {
|
||||
var size = this.model_.size;
|
||||
var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH;
|
||||
var widthMinusBorder = size.width - doubleBorderWidth;
|
||||
var heightMinusBorder = size.height - doubleBorderWidth;
|
||||
Comment.prototype.resizeTextarea_ = function() {
|
||||
const size = this.model_.size;
|
||||
const doubleBorderWidth = 2 * Bubble.BORDER_WIDTH;
|
||||
const widthMinusBorder = size.width - doubleBorderWidth;
|
||||
const heightMinusBorder = size.height - doubleBorderWidth;
|
||||
this.foreignObject_.setAttribute('width', widthMinusBorder);
|
||||
this.foreignObject_.setAttribute('height', heightMinusBorder);
|
||||
this.textarea_.style.width = (widthMinusBorder - 4) + 'px';
|
||||
@@ -242,12 +235,12 @@ Blockly.Comment.prototype.resizeTextarea_ = function() {
|
||||
* Show or hide the comment bubble.
|
||||
* @param {boolean} visible True if the bubble should be visible.
|
||||
*/
|
||||
Blockly.Comment.prototype.setVisible = function(visible) {
|
||||
Comment.prototype.setVisible = function(visible) {
|
||||
if (visible == this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BUBBLE_OPEN))(
|
||||
this.block_, visible, 'comment'));
|
||||
Events.fire(
|
||||
new (Events.get(Events.BUBBLE_OPEN))(this.block_, visible, 'comment'));
|
||||
this.model_.pinned = visible;
|
||||
if (visible) {
|
||||
this.createBubble_();
|
||||
@@ -260,8 +253,8 @@ Blockly.Comment.prototype.setVisible = function(visible) {
|
||||
* Show the bubble. Handles deciding if it should be editable or not.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Comment.prototype.createBubble_ = function() {
|
||||
if (!this.block_.isEditable() || Blockly.utils.userAgent.IE) {
|
||||
Comment.prototype.createBubble_ = function() {
|
||||
if (!this.block_.isEditable() || userAgent.IE) {
|
||||
// MSIE does not support foreignobject; textareas are impossible.
|
||||
// https://docs.microsoft.com/en-us/openspecs/ie_standards/ms-svg/56e6e04c-7c8c-44dd-8100-bd745ee42034
|
||||
// Always treat comments in IE as uneditable.
|
||||
@@ -275,12 +268,12 @@ Blockly.Comment.prototype.createBubble_ = function() {
|
||||
* Show an editable bubble.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Comment.prototype.createEditableBubble_ = function() {
|
||||
this.bubble_ = new Blockly.Bubble(
|
||||
/** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace),
|
||||
Comment.prototype.createEditableBubble_ = function() {
|
||||
this.bubble_ = new Bubble(
|
||||
/** @type {!WorkspaceSvg} */ (this.block_.workspace),
|
||||
this.createEditor_(), this.block_.pathObject.svgPath,
|
||||
/** @type {!Blockly.utils.Coordinate} */ (this.iconXY_),
|
||||
this.model_.size.width, this.model_.size.height);
|
||||
/** @type {!Coordinate} */ (this.iconXY_), this.model_.size.width,
|
||||
this.model_.size.height);
|
||||
// Expose this comment's block's ID on its top-level SVG group.
|
||||
this.bubble_.setSvgId(this.block_.id);
|
||||
this.bubble_.registerResizeEvent(this.onBubbleResize_.bind(this));
|
||||
@@ -292,12 +285,12 @@ Blockly.Comment.prototype.createEditableBubble_ = function() {
|
||||
* @private
|
||||
* @suppress {checkTypes} Suppress `this` type mismatch.
|
||||
*/
|
||||
Blockly.Comment.prototype.createNonEditableBubble_ = function() {
|
||||
Comment.prototype.createNonEditableBubble_ = function() {
|
||||
// TODO (#2917): It would be great if the comment could support line breaks.
|
||||
this.paragraphElement_ = Blockly.Bubble.textToDom(this.block_.getCommentText());
|
||||
this.bubble_ = Blockly.Bubble.createNonEditableBubble(
|
||||
this.paragraphElement_, /** @type {!Blockly.BlockSvg} */ (this.block_),
|
||||
/** @type {!Blockly.utils.Coordinate} */ (this.iconXY_));
|
||||
this.paragraphElement_ = Bubble.textToDom(this.block_.getCommentText());
|
||||
this.bubble_ = Bubble.createNonEditableBubble(
|
||||
this.paragraphElement_, /** @type {!BlockSvg} */ (this.block_),
|
||||
/** @type {!Coordinate} */ (this.iconXY_));
|
||||
this.applyColour();
|
||||
};
|
||||
|
||||
@@ -306,21 +299,21 @@ Blockly.Comment.prototype.createNonEditableBubble_ = function() {
|
||||
* @private
|
||||
* @suppress {checkTypes} Suppress `this` type mismatch.
|
||||
*/
|
||||
Blockly.Comment.prototype.disposeBubble_ = function() {
|
||||
Comment.prototype.disposeBubble_ = function() {
|
||||
if (this.onMouseUpWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onMouseUpWrapper_);
|
||||
unbind(this.onMouseUpWrapper_);
|
||||
this.onMouseUpWrapper_ = null;
|
||||
}
|
||||
if (this.onWheelWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onWheelWrapper_);
|
||||
unbind(this.onWheelWrapper_);
|
||||
this.onWheelWrapper_ = null;
|
||||
}
|
||||
if (this.onChangeWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onChangeWrapper_);
|
||||
unbind(this.onChangeWrapper_);
|
||||
this.onChangeWrapper_ = null;
|
||||
}
|
||||
if (this.onInputWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onInputWrapper_);
|
||||
unbind(this.onInputWrapper_);
|
||||
this.onInputWrapper_ = null;
|
||||
}
|
||||
this.bubble_.dispose();
|
||||
@@ -338,7 +331,7 @@ Blockly.Comment.prototype.disposeBubble_ = function() {
|
||||
* @param {!Event} _e Mouse up event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Comment.prototype.startEdit_ = function(_e) {
|
||||
Comment.prototype.startEdit_ = function(_e) {
|
||||
if (this.bubble_.promote()) {
|
||||
// Since the act of moving this node within the DOM causes a loss of focus,
|
||||
// we need to reapply the focus.
|
||||
@@ -350,9 +343,9 @@ Blockly.Comment.prototype.startEdit_ = function(_e) {
|
||||
|
||||
/**
|
||||
* Get the dimensions of this comment's bubble.
|
||||
* @return {Blockly.utils.Size} Object with width and height properties.
|
||||
* @return {Size} Object with width and height properties.
|
||||
*/
|
||||
Blockly.Comment.prototype.getBubbleSize = function() {
|
||||
Comment.prototype.getBubbleSize = function() {
|
||||
return this.model_.size;
|
||||
};
|
||||
|
||||
@@ -361,7 +354,7 @@ Blockly.Comment.prototype.getBubbleSize = function() {
|
||||
* @param {number} width Width of the bubble.
|
||||
* @param {number} height Height of the bubble.
|
||||
*/
|
||||
Blockly.Comment.prototype.setBubbleSize = function(width, height) {
|
||||
Comment.prototype.setBubbleSize = function(width, height) {
|
||||
if (this.bubble_) {
|
||||
this.bubble_.setBubbleSize(width, height);
|
||||
} else {
|
||||
@@ -374,7 +367,7 @@ Blockly.Comment.prototype.setBubbleSize = function(width, height) {
|
||||
* Update the comment's view to match the model.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Comment.prototype.updateText = function() {
|
||||
Comment.prototype.updateText = function() {
|
||||
if (this.textarea_) {
|
||||
this.textarea_.value = this.model_.text;
|
||||
} else if (this.paragraphElement_) {
|
||||
@@ -390,25 +383,20 @@ Blockly.Comment.prototype.updateText = function() {
|
||||
* If you want to receive a comment "delete" event (newValue: null), then this
|
||||
* should not be called directly. Instead call block.setCommentText(null);
|
||||
*/
|
||||
Blockly.Comment.prototype.dispose = function() {
|
||||
Comment.prototype.dispose = function() {
|
||||
this.block_.comment = null;
|
||||
Blockly.Icon.prototype.dispose.call(this);
|
||||
Icon.prototype.dispose.call(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* CSS for block comment. See css.js for use.
|
||||
*/
|
||||
Blockly.Css.register([
|
||||
register([
|
||||
/* eslint-disable indent */
|
||||
'.blocklyCommentTextarea {',
|
||||
'background-color: #fef49c;',
|
||||
'border: 0;',
|
||||
'outline: 0;',
|
||||
'margin: 0;',
|
||||
'padding: 3px;',
|
||||
'resize: none;',
|
||||
'display: block;',
|
||||
'text-overflow: hidden;',
|
||||
'}'
|
||||
'.blocklyCommentTextarea {', 'background-color: #fef49c;', 'border: 0;',
|
||||
'outline: 0;', 'margin: 0;', 'padding: 3px;', 'resize: none;',
|
||||
'display: block;', 'text-overflow: hidden;', '}'
|
||||
/* eslint-enable indent */
|
||||
]);
|
||||
|
||||
exports = Comment;
|
||||
|
||||
@@ -5,37 +5,36 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview An object that encapsulates logic for checking whether a potential
|
||||
* connection is safe and valid.
|
||||
* @fileoverview An object that encapsulates logic for checking whether a
|
||||
* potential connection is safe and valid.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ConnectionChecker');
|
||||
goog.module('Blockly.ConnectionChecker');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Connection');
|
||||
goog.require('Blockly.connectionTypes');
|
||||
const Connection = goog.require('Blockly.Connection');
|
||||
const IConnectionChecker = goog.require('Blockly.IConnectionChecker');
|
||||
const RenderedConnection = goog.requireType('Blockly.RenderedConnection');
|
||||
const connectionTypes = goog.require('Blockly.connectionTypes');
|
||||
const registry = goog.require('Blockly.registry');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.constants');
|
||||
goog.require('Blockly.IConnectionChecker');
|
||||
goog.require('Blockly.registry');
|
||||
|
||||
goog.requireType('Blockly.RenderedConnection');
|
||||
|
||||
|
||||
/**
|
||||
* Class for connection type checking logic.
|
||||
* @implements {Blockly.IConnectionChecker}
|
||||
* @implements {IConnectionChecker}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.ConnectionChecker = function() {
|
||||
};
|
||||
const ConnectionChecker = function() {};
|
||||
|
||||
/**
|
||||
* Check whether the current connection can connect with the target
|
||||
* connection.
|
||||
* @param {Blockly.Connection} a Connection to check compatibility with.
|
||||
* @param {Blockly.Connection} b Connection to check compatibility with.
|
||||
* @param {Connection} a Connection to check compatibility with.
|
||||
* @param {Connection} b Connection to check compatibility with.
|
||||
* @param {boolean} isDragging True if the connection is being made by dragging
|
||||
* a block.
|
||||
* @param {number=} opt_distance The max allowable distance between the
|
||||
@@ -43,80 +42,80 @@ Blockly.ConnectionChecker = function() {
|
||||
* @return {boolean} Whether the connection is legal.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ConnectionChecker.prototype.canConnect = function(a, b,
|
||||
isDragging, opt_distance) {
|
||||
ConnectionChecker.prototype.canConnect = function(
|
||||
a, b, isDragging, opt_distance) {
|
||||
return this.canConnectWithReason(a, b, isDragging, opt_distance) ==
|
||||
Blockly.Connection.CAN_CONNECT;
|
||||
Connection.CAN_CONNECT;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether the current connection can connect with the target
|
||||
* connection, and return an error code if there are problems.
|
||||
* @param {Blockly.Connection} a Connection to check compatibility with.
|
||||
* @param {Blockly.Connection} b Connection to check compatibility with.
|
||||
* @param {Connection} a Connection to check compatibility with.
|
||||
* @param {Connection} b Connection to check compatibility with.
|
||||
* @param {boolean} isDragging True if the connection is being made by dragging
|
||||
* a block.
|
||||
* @param {number=} opt_distance The max allowable distance between the
|
||||
* connections for drag checks.
|
||||
* @return {number} Blockly.Connection.CAN_CONNECT if the connection is legal,
|
||||
* @return {number} Connection.CAN_CONNECT if the connection is legal,
|
||||
* an error code otherwise.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ConnectionChecker.prototype.canConnectWithReason = function(
|
||||
ConnectionChecker.prototype.canConnectWithReason = function(
|
||||
a, b, isDragging, opt_distance) {
|
||||
var safety = this.doSafetyChecks(a, b);
|
||||
if (safety != Blockly.Connection.CAN_CONNECT) {
|
||||
const safety = this.doSafetyChecks(a, b);
|
||||
if (safety != Connection.CAN_CONNECT) {
|
||||
return safety;
|
||||
}
|
||||
|
||||
// If the safety checks passed, both connections are non-null.
|
||||
var connOne = /** @type {!Blockly.Connection} **/ (a);
|
||||
var connTwo = /** @type {!Blockly.Connection} **/ (b);
|
||||
const connOne = /** @type {!Connection} **/ (a);
|
||||
const connTwo = /** @type {!Connection} **/ (b);
|
||||
if (!this.doTypeChecks(connOne, connTwo)) {
|
||||
return Blockly.Connection.REASON_CHECKS_FAILED;
|
||||
return Connection.REASON_CHECKS_FAILED;
|
||||
}
|
||||
|
||||
if (isDragging &&
|
||||
!this.doDragChecks(
|
||||
/** @type {!Blockly.RenderedConnection} **/ (a),
|
||||
/** @type {!Blockly.RenderedConnection} **/ (b),
|
||||
opt_distance || 0)) {
|
||||
return Blockly.Connection.REASON_DRAG_CHECKS_FAILED;
|
||||
/** @type {!RenderedConnection} **/ (a),
|
||||
/** @type {!RenderedConnection} **/ (b), opt_distance || 0)) {
|
||||
return Connection.REASON_DRAG_CHECKS_FAILED;
|
||||
}
|
||||
|
||||
return Blockly.Connection.CAN_CONNECT;
|
||||
return Connection.CAN_CONNECT;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method that translates a connection error code into a string.
|
||||
* @param {number} errorCode The error code.
|
||||
* @param {Blockly.Connection} a One of the two connections being checked.
|
||||
* @param {Blockly.Connection} b The second of the two connections being
|
||||
* @param {Connection} a One of the two connections being checked.
|
||||
* @param {Connection} b The second of the two connections being
|
||||
* checked.
|
||||
* @return {string} A developer-readable error string.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ConnectionChecker.prototype.getErrorMessage = function(errorCode,
|
||||
a, b) {
|
||||
ConnectionChecker.prototype.getErrorMessage = function(errorCode, a, b) {
|
||||
switch (errorCode) {
|
||||
case Blockly.Connection.REASON_SELF_CONNECTION:
|
||||
case Connection.REASON_SELF_CONNECTION:
|
||||
return 'Attempted to connect a block to itself.';
|
||||
case Blockly.Connection.REASON_DIFFERENT_WORKSPACES:
|
||||
case Connection.REASON_DIFFERENT_WORKSPACES:
|
||||
// Usually this means one block has been deleted.
|
||||
return 'Blocks not on same workspace.';
|
||||
case Blockly.Connection.REASON_WRONG_TYPE:
|
||||
case Connection.REASON_WRONG_TYPE:
|
||||
return 'Attempt to connect incompatible types.';
|
||||
case Blockly.Connection.REASON_TARGET_NULL:
|
||||
case Connection.REASON_TARGET_NULL:
|
||||
return 'Target connection is null.';
|
||||
case Blockly.Connection.REASON_CHECKS_FAILED:
|
||||
var connOne = /** @type {!Blockly.Connection} **/ (a);
|
||||
var connTwo = /** @type {!Blockly.Connection} **/ (b);
|
||||
var msg = 'Connection checks failed. ';
|
||||
msg += connOne + ' expected ' + connOne.getCheck() + ', found ' + connTwo.getCheck();
|
||||
case Connection.REASON_CHECKS_FAILED: {
|
||||
const connOne = /** @type {!Connection} **/ (a);
|
||||
const connTwo = /** @type {!Connection} **/ (b);
|
||||
let msg = 'Connection checks failed. ';
|
||||
msg += connOne + ' expected ' + connOne.getCheck() + ', found ' +
|
||||
connTwo.getCheck();
|
||||
return msg;
|
||||
case Blockly.Connection.REASON_SHADOW_PARENT:
|
||||
}
|
||||
case Connection.REASON_SHADOW_PARENT:
|
||||
return 'Connecting non-shadow to shadow block.';
|
||||
case Blockly.Connection.REASON_DRAG_CHECKS_FAILED:
|
||||
case Connection.REASON_DRAG_CHECKS_FAILED:
|
||||
return 'Drag checks failed.';
|
||||
default:
|
||||
return 'Unknown connection failure: this should never happen!';
|
||||
@@ -126,53 +125,54 @@ Blockly.ConnectionChecker.prototype.getErrorMessage = function(errorCode,
|
||||
/**
|
||||
* Check that connecting the given connections is safe, meaning that it would
|
||||
* not break any of Blockly's basic assumptions (e.g. no self connections).
|
||||
* @param {Blockly.Connection} a The first of the connections to check.
|
||||
* @param {Blockly.Connection} b The second of the connections to check.
|
||||
* @param {Connection} a The first of the connections to check.
|
||||
* @param {Connection} b The second of the connections to check.
|
||||
* @return {number} An enum with the reason this connection is safe or unsafe.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ConnectionChecker.prototype.doSafetyChecks = function(a, b) {
|
||||
ConnectionChecker.prototype.doSafetyChecks = function(a, b) {
|
||||
if (!a || !b) {
|
||||
return Blockly.Connection.REASON_TARGET_NULL;
|
||||
return Connection.REASON_TARGET_NULL;
|
||||
}
|
||||
let blockA, blockB;
|
||||
if (a.isSuperior()) {
|
||||
var blockA = a.getSourceBlock();
|
||||
var blockB = b.getSourceBlock();
|
||||
blockA = a.getSourceBlock();
|
||||
blockB = b.getSourceBlock();
|
||||
} else {
|
||||
var blockB = a.getSourceBlock();
|
||||
var blockA = b.getSourceBlock();
|
||||
blockB = a.getSourceBlock();
|
||||
blockA = b.getSourceBlock();
|
||||
}
|
||||
if (blockA == blockB) {
|
||||
return Blockly.Connection.REASON_SELF_CONNECTION;
|
||||
return Connection.REASON_SELF_CONNECTION;
|
||||
} else if (b.type != Blockly.OPPOSITE_TYPE[a.type]) {
|
||||
return Blockly.Connection.REASON_WRONG_TYPE;
|
||||
return Connection.REASON_WRONG_TYPE;
|
||||
} else if (blockA.workspace !== blockB.workspace) {
|
||||
return Blockly.Connection.REASON_DIFFERENT_WORKSPACES;
|
||||
return Connection.REASON_DIFFERENT_WORKSPACES;
|
||||
} else if (blockA.isShadow() && !blockB.isShadow()) {
|
||||
return Blockly.Connection.REASON_SHADOW_PARENT;
|
||||
return Connection.REASON_SHADOW_PARENT;
|
||||
}
|
||||
return Blockly.Connection.CAN_CONNECT;
|
||||
return Connection.CAN_CONNECT;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether this connection is compatible with another connection with
|
||||
* respect to the value type system. E.g. square_root("Hello") is not
|
||||
* compatible.
|
||||
* @param {!Blockly.Connection} a Connection to compare.
|
||||
* @param {!Blockly.Connection} b Connection to compare against.
|
||||
* @param {!Connection} a Connection to compare.
|
||||
* @param {!Connection} b Connection to compare against.
|
||||
* @return {boolean} True if the connections share a type.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ConnectionChecker.prototype.doTypeChecks = function(a, b) {
|
||||
var checkArrayOne = a.getCheck();
|
||||
var checkArrayTwo = b.getCheck();
|
||||
ConnectionChecker.prototype.doTypeChecks = function(a, b) {
|
||||
const checkArrayOne = a.getCheck();
|
||||
const checkArrayTwo = b.getCheck();
|
||||
|
||||
if (!checkArrayOne || !checkArrayTwo) {
|
||||
// One or both sides are promiscuous enough that anything will fit.
|
||||
return true;
|
||||
}
|
||||
// Find any intersection in the check lists.
|
||||
for (var i = 0; i < checkArrayOne.length; i++) {
|
||||
for (let i = 0; i < checkArrayOne.length; i++) {
|
||||
if (checkArrayTwo.indexOf(checkArrayOne[i]) != -1) {
|
||||
return true;
|
||||
}
|
||||
@@ -183,13 +183,13 @@ Blockly.ConnectionChecker.prototype.doTypeChecks = function(a, b) {
|
||||
|
||||
/**
|
||||
* Check whether this connection can be made by dragging.
|
||||
* @param {!Blockly.RenderedConnection} a Connection to compare.
|
||||
* @param {!Blockly.RenderedConnection} b Connection to compare against.
|
||||
* @param {!RenderedConnection} a Connection to compare.
|
||||
* @param {!RenderedConnection} b Connection to compare against.
|
||||
* @param {number} distance The maximum allowable distance between connections.
|
||||
* @return {boolean} True if the connection is allowed during a drag.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
|
||||
ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
|
||||
if (a.distanceFrom(b) > distance) {
|
||||
return false;
|
||||
}
|
||||
@@ -200,38 +200,34 @@ Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
|
||||
}
|
||||
|
||||
switch (b.type) {
|
||||
case Blockly.connectionTypes.PREVIOUS_STATEMENT:
|
||||
case connectionTypes.PREVIOUS_STATEMENT:
|
||||
return this.canConnectToPrevious_(a, b);
|
||||
case Blockly.connectionTypes.OUTPUT_VALUE: {
|
||||
case connectionTypes.OUTPUT_VALUE: {
|
||||
// Don't offer to connect an already connected left (male) value plug to
|
||||
// an available right (female) value plug.
|
||||
if ((b.isConnected() &&
|
||||
!b.targetBlock().isInsertionMarker()) ||
|
||||
if ((b.isConnected() && !b.targetBlock().isInsertionMarker()) ||
|
||||
a.isConnected()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Blockly.connectionTypes.INPUT_VALUE: {
|
||||
case connectionTypes.INPUT_VALUE: {
|
||||
// Offering to connect the left (male) of a value block to an already
|
||||
// connected value pair is ok, we'll splice it in.
|
||||
// However, don't offer to splice into an immovable block.
|
||||
if (b.isConnected() &&
|
||||
!b.targetBlock().isMovable() &&
|
||||
if (b.isConnected() && !b.targetBlock().isMovable() &&
|
||||
!b.targetBlock().isShadow()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Blockly.connectionTypes.NEXT_STATEMENT: {
|
||||
case connectionTypes.NEXT_STATEMENT: {
|
||||
// Don't let a block with no next connection bump other blocks out of the
|
||||
// stack. But covering up a shadow block or stack of shadow blocks is
|
||||
// fine. Similarly, replacing a terminal statement with another terminal
|
||||
// statement is allowed.
|
||||
if (b.isConnected() &&
|
||||
!a.getSourceBlock().nextConnection &&
|
||||
!b.targetBlock().isShadow() &&
|
||||
b.targetBlock().nextConnection) {
|
||||
if (b.isConnected() && !a.getSourceBlock().nextConnection &&
|
||||
!b.targetBlock().isShadow() && b.targetBlock().nextConnection) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -251,14 +247,14 @@ Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
|
||||
|
||||
/**
|
||||
* Helper function for drag checking.
|
||||
* @param {!Blockly.Connection} a The connection to check, which must be a
|
||||
* @param {!Connection} a The connection to check, which must be a
|
||||
* statement input or next connection.
|
||||
* @param {!Blockly.Connection} b A nearby connection to check, which
|
||||
* @param {!Connection} b A nearby connection to check, which
|
||||
* must be a previous connection.
|
||||
* @return {boolean} True if the connection is allowed, false otherwise.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
|
||||
ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
|
||||
if (a.targetConnection) {
|
||||
// This connection is already occupied.
|
||||
// A next connection will never disconnect itself mid-drag.
|
||||
@@ -274,7 +270,7 @@ Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var targetBlock = b.targetBlock();
|
||||
const targetBlock = b.targetBlock();
|
||||
// If it is connected to a real block, game over.
|
||||
if (!targetBlock.isInsertionMarker()) {
|
||||
return false;
|
||||
@@ -285,5 +281,7 @@ Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
|
||||
return !targetBlock.getPreviousBlock();
|
||||
};
|
||||
|
||||
Blockly.registry.register(Blockly.registry.Type.CONNECTION_CHECKER,
|
||||
Blockly.registry.DEFAULT, Blockly.ConnectionChecker);
|
||||
registry.register(
|
||||
registry.Type.CONNECTION_CHECKER, registry.DEFAULT, ConnectionChecker);
|
||||
|
||||
exports = ConnectionChecker;
|
||||
|
||||
@@ -12,37 +12,37 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ConnectionDB');
|
||||
goog.module('Blockly.ConnectionDB');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.connectionTypes');
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const IConnectionChecker = goog.requireType('Blockly.IConnectionChecker');
|
||||
const RenderedConnection = goog.require('Blockly.RenderedConnection');
|
||||
const connectionTypes = goog.require('Blockly.connectionTypes');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.constants');
|
||||
goog.require('Blockly.RenderedConnection');
|
||||
|
||||
goog.requireType('Blockly.IConnectionChecker');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* Database of connections.
|
||||
* Connections are stored in order of their vertical component. This way
|
||||
* connections in an area may be looked up quickly using a binary search.
|
||||
* @param {!Blockly.IConnectionChecker} checker The workspace's
|
||||
* @param {!IConnectionChecker} checker The workspace's
|
||||
* connection type checker, used to decide if connections are valid during a
|
||||
* drag.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.ConnectionDB = function(checker) {
|
||||
const ConnectionDB = function(checker) {
|
||||
/**
|
||||
* Array of connections sorted by y position in workspace units.
|
||||
* @type {!Array<!Blockly.RenderedConnection>}
|
||||
* @type {!Array<!RenderedConnection>}
|
||||
* @private
|
||||
*/
|
||||
this.connections_ = [];
|
||||
/**
|
||||
* The workspace's connection type checker, used to decide if connections are
|
||||
* valid during a drag.
|
||||
* @type {!Blockly.IConnectionChecker}
|
||||
* @type {!IConnectionChecker}
|
||||
* @private
|
||||
*/
|
||||
this.connectionChecker_ = checker;
|
||||
@@ -50,13 +50,13 @@ Blockly.ConnectionDB = function(checker) {
|
||||
|
||||
/**
|
||||
* Add a connection to the database. Should not already exist in the database.
|
||||
* @param {!Blockly.RenderedConnection} connection The connection to be added.
|
||||
* @param {!RenderedConnection} connection The connection to be added.
|
||||
* @param {number} yPos The y position used to decide where to insert the
|
||||
* connection.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ConnectionDB.prototype.addConnection = function(connection, yPos) {
|
||||
var index = this.calculateIndexForYPos_(yPos);
|
||||
ConnectionDB.prototype.addConnection = function(connection, yPos) {
|
||||
const index = this.calculateIndexForYPos_(yPos);
|
||||
this.connections_.splice(index, 0, connection);
|
||||
};
|
||||
|
||||
@@ -65,18 +65,18 @@ Blockly.ConnectionDB.prototype.addConnection = function(connection, yPos) {
|
||||
*
|
||||
* Starts by doing a binary search to find the approximate location, then
|
||||
* linearly searches nearby for the exact connection.
|
||||
* @param {!Blockly.RenderedConnection} conn The connection to find.
|
||||
* @param {!RenderedConnection} conn The connection to find.
|
||||
* @param {number} yPos The y position used to find the index of the connection.
|
||||
* @return {number} The index of the connection, or -1 if the connection was
|
||||
* not found.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) {
|
||||
ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) {
|
||||
if (!this.connections_.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var bestGuess = this.calculateIndexForYPos_(yPos);
|
||||
const bestGuess = this.calculateIndexForYPos_(yPos);
|
||||
if (bestGuess >= this.connections_.length) {
|
||||
// Not in list
|
||||
return -1;
|
||||
@@ -84,7 +84,7 @@ Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) {
|
||||
|
||||
yPos = conn.y;
|
||||
// Walk forward and back on the y axis looking for the connection.
|
||||
var pointer = bestGuess;
|
||||
let pointer = bestGuess;
|
||||
while (pointer >= 0 && this.connections_[pointer].y == yPos) {
|
||||
if (this.connections_[pointer] == conn) {
|
||||
return pointer;
|
||||
@@ -110,14 +110,14 @@ Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) {
|
||||
* @return {number} The candidate index.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ConnectionDB.prototype.calculateIndexForYPos_ = function(yPos) {
|
||||
ConnectionDB.prototype.calculateIndexForYPos_ = function(yPos) {
|
||||
if (!this.connections_.length) {
|
||||
return 0;
|
||||
}
|
||||
var pointerMin = 0;
|
||||
var pointerMax = this.connections_.length;
|
||||
let pointerMin = 0;
|
||||
let pointerMax = this.connections_.length;
|
||||
while (pointerMin < pointerMax) {
|
||||
var pointerMid = Math.floor((pointerMin + pointerMax) / 2);
|
||||
const pointerMid = Math.floor((pointerMin + pointerMax) / 2);
|
||||
if (this.connections_[pointerMid].y < yPos) {
|
||||
pointerMin = pointerMid + 1;
|
||||
} else if (this.connections_[pointerMid].y > yPos) {
|
||||
@@ -132,12 +132,12 @@ Blockly.ConnectionDB.prototype.calculateIndexForYPos_ = function(yPos) {
|
||||
|
||||
/**
|
||||
* Remove a connection from the database. Must already exist in DB.
|
||||
* @param {!Blockly.RenderedConnection} connection The connection to be removed.
|
||||
* @param {!RenderedConnection} connection The connection to be removed.
|
||||
* @param {number} yPos The y position used to find the index of the connection.
|
||||
* @throws {Error} If the connection cannot be found in the database.
|
||||
*/
|
||||
Blockly.ConnectionDB.prototype.removeConnection = function(connection, yPos) {
|
||||
var index = this.findIndexOfConnection_(connection, yPos);
|
||||
ConnectionDB.prototype.removeConnection = function(connection, yPos) {
|
||||
const index = this.findIndexOfConnection_(connection, yPos);
|
||||
if (index == -1) {
|
||||
throw Error('Unable to find connection in connectionDB.');
|
||||
}
|
||||
@@ -147,20 +147,20 @@ Blockly.ConnectionDB.prototype.removeConnection = function(connection, yPos) {
|
||||
/**
|
||||
* Find all nearby connections to the given connection.
|
||||
* Type checking does not apply, since this function is used for bumping.
|
||||
* @param {!Blockly.RenderedConnection} connection The connection whose
|
||||
* @param {!RenderedConnection} connection The connection whose
|
||||
* neighbours should be returned.
|
||||
* @param {number} maxRadius The maximum radius to another connection.
|
||||
* @return {!Array<!Blockly.RenderedConnection>} List of connections.
|
||||
* @return {!Array<!RenderedConnection>} List of connections.
|
||||
*/
|
||||
Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
|
||||
var db = this.connections_;
|
||||
var currentX = connection.x;
|
||||
var currentY = connection.y;
|
||||
ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
|
||||
const db = this.connections_;
|
||||
const currentX = connection.x;
|
||||
const currentY = connection.y;
|
||||
|
||||
// Binary search to find the closest y location.
|
||||
var pointerMin = 0;
|
||||
var pointerMax = db.length - 2;
|
||||
var pointerMid = pointerMax;
|
||||
let pointerMin = 0;
|
||||
let pointerMax = db.length - 2;
|
||||
let pointerMid = pointerMax;
|
||||
while (pointerMin < pointerMid) {
|
||||
if (db[pointerMid].y < currentY) {
|
||||
pointerMin = pointerMid;
|
||||
@@ -170,7 +170,7 @@ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
|
||||
pointerMid = Math.floor((pointerMin + pointerMax) / 2);
|
||||
}
|
||||
|
||||
var neighbours = [];
|
||||
const neighbours = [];
|
||||
/**
|
||||
* Computes if the current connection is within the allowed radius of another
|
||||
* connection.
|
||||
@@ -180,9 +180,9 @@ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
|
||||
* the other connection is less than the allowed radius.
|
||||
*/
|
||||
function checkConnection_(yIndex) {
|
||||
var dx = currentX - db[yIndex].x;
|
||||
var dy = currentY - db[yIndex].y;
|
||||
var r = Math.sqrt(dx * dx + dy * dy);
|
||||
const dx = currentX - db[yIndex].x;
|
||||
const dy = currentY - db[yIndex].y;
|
||||
const r = Math.sqrt(dx * dx + dy * dy);
|
||||
if (r <= maxRadius) {
|
||||
neighbours.push(db[yIndex]);
|
||||
}
|
||||
@@ -213,32 +213,31 @@ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
|
||||
* @return {boolean} True if connection is in range.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) {
|
||||
ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) {
|
||||
return (Math.abs(this.connections_[index].y - baseY) <= maxRadius);
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the closest compatible connection to this connection.
|
||||
* @param {!Blockly.RenderedConnection} conn The connection searching for a compatible
|
||||
* @param {!RenderedConnection} conn The connection searching for a compatible
|
||||
* mate.
|
||||
* @param {number} maxRadius The maximum radius to another connection.
|
||||
* @param {!Blockly.utils.Coordinate} dxy Offset between this connection's
|
||||
* @param {!Coordinate} dxy Offset between this connection's
|
||||
* location in the database and the current location (as a result of
|
||||
* dragging).
|
||||
* @return {!{connection: Blockly.RenderedConnection, radius: number}}
|
||||
* @return {!{connection: RenderedConnection, radius: number}}
|
||||
* Contains two properties: 'connection' which is either another
|
||||
* connection or null, and 'radius' which is the distance.
|
||||
*/
|
||||
Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
|
||||
dxy) {
|
||||
ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, dxy) {
|
||||
if (!this.connections_.length) {
|
||||
// Don't bother.
|
||||
return {connection: null, radius: maxRadius};
|
||||
}
|
||||
|
||||
// Stash the values of x and y from before the drag.
|
||||
var baseY = conn.y;
|
||||
var baseX = conn.x;
|
||||
const baseY = conn.y;
|
||||
const baseX = conn.x;
|
||||
|
||||
conn.x = baseX + dxy.x;
|
||||
conn.y = baseY + dxy.y;
|
||||
@@ -246,14 +245,14 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
|
||||
// calculateIndexForYPos_ finds an index for insertion, which is always
|
||||
// after any block with the same y index. We want to search both forward
|
||||
// and back, so search on both sides of the index.
|
||||
var closestIndex = this.calculateIndexForYPos_(conn.y);
|
||||
const closestIndex = this.calculateIndexForYPos_(conn.y);
|
||||
|
||||
var bestConnection = null;
|
||||
var bestRadius = maxRadius;
|
||||
var temp;
|
||||
let bestConnection = null;
|
||||
let bestRadius = maxRadius;
|
||||
let temp;
|
||||
|
||||
// Walk forward and back on the y axis looking for the closest x,y point.
|
||||
var pointerMin = closestIndex - 1;
|
||||
let pointerMin = closestIndex - 1;
|
||||
while (pointerMin >= 0 && this.isInYRange_(pointerMin, conn.y, maxRadius)) {
|
||||
temp = this.connections_[pointerMin];
|
||||
if (this.connectionChecker_.canConnect(conn, temp, true, bestRadius)) {
|
||||
@@ -263,9 +262,9 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
|
||||
pointerMin--;
|
||||
}
|
||||
|
||||
var pointerMax = closestIndex;
|
||||
let pointerMax = closestIndex;
|
||||
while (pointerMax < this.connections_.length &&
|
||||
this.isInYRange_(pointerMax, conn.y, maxRadius)) {
|
||||
this.isInYRange_(pointerMax, conn.y, maxRadius)) {
|
||||
temp = this.connections_[pointerMax];
|
||||
if (this.connectionChecker_.canConnect(conn, temp, true, bestRadius)) {
|
||||
bestConnection = temp;
|
||||
@@ -284,20 +283,19 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
|
||||
|
||||
/**
|
||||
* Initialize a set of connection DBs for a workspace.
|
||||
* @param {!Blockly.IConnectionChecker} checker The workspace's
|
||||
* connection checker, used to decide if connections are valid during a drag.
|
||||
* @return {!Array<!Blockly.ConnectionDB>} Array of databases.
|
||||
* @param {!IConnectionChecker} checker The workspace's
|
||||
* connection checker, used to decide if connections are valid during a
|
||||
* drag.
|
||||
* @return {!Array<!ConnectionDB>} Array of databases.
|
||||
*/
|
||||
Blockly.ConnectionDB.init = function(checker) {
|
||||
ConnectionDB.init = function(checker) {
|
||||
// Create four databases, one for each connection type.
|
||||
var dbList = [];
|
||||
dbList[Blockly.connectionTypes.INPUT_VALUE] =
|
||||
new Blockly.ConnectionDB(checker);
|
||||
dbList[Blockly.connectionTypes.OUTPUT_VALUE] =
|
||||
new Blockly.ConnectionDB(checker);
|
||||
dbList[Blockly.connectionTypes.NEXT_STATEMENT] =
|
||||
new Blockly.ConnectionDB(checker);
|
||||
dbList[Blockly.connectionTypes.PREVIOUS_STATEMENT] =
|
||||
new Blockly.ConnectionDB(checker);
|
||||
const dbList = [];
|
||||
dbList[connectionTypes.INPUT_VALUE] = new ConnectionDB(checker);
|
||||
dbList[connectionTypes.OUTPUT_VALUE] = new ConnectionDB(checker);
|
||||
dbList[connectionTypes.NEXT_STATEMENT] = new ConnectionDB(checker);
|
||||
dbList[connectionTypes.PREVIOUS_STATEMENT] = new ConnectionDB(checker);
|
||||
return dbList;
|
||||
};
|
||||
|
||||
exports = ConnectionDB;
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview AST Node and keyboard navigation interfaces.
|
||||
* @author samelh@google.com (Sam El-Husseini)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IASTNodeLocation');
|
||||
goog.provide('Blockly.IASTNodeLocationSvg');
|
||||
goog.provide('Blockly.IASTNodeLocationWithBlock');
|
||||
goog.provide('Blockly.IKeyboardAccessible');
|
||||
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.ShortcutRegistry');
|
||||
|
||||
|
||||
/**
|
||||
* An AST node location interface.
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IASTNodeLocation = function() {};
|
||||
|
||||
/**
|
||||
* An AST node location SVG interface.
|
||||
* @interface
|
||||
* @extends {Blockly.IASTNodeLocation}
|
||||
*/
|
||||
Blockly.IASTNodeLocationSvg = function() {};
|
||||
|
||||
/**
|
||||
* Add the marker SVG to this node's SVG group.
|
||||
* @param {SVGElement} markerSvg The SVG root of the marker to be added to the
|
||||
* SVG group.
|
||||
*/
|
||||
Blockly.IASTNodeLocationSvg.prototype.setMarkerSvg;
|
||||
|
||||
/**
|
||||
* Add the cursor SVG to this node's SVG group.
|
||||
* @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the
|
||||
* SVG group.
|
||||
*/
|
||||
Blockly.IASTNodeLocationSvg.prototype.setCursorSvg;
|
||||
|
||||
/**
|
||||
* An AST node location that has an associated block.
|
||||
* @interface
|
||||
* @extends {Blockly.IASTNodeLocation}
|
||||
*/
|
||||
Blockly.IASTNodeLocationWithBlock = function() {};
|
||||
|
||||
/**
|
||||
* Get the source block associated with this node.
|
||||
* @return {Blockly.Block} The source block.
|
||||
*/
|
||||
Blockly.IASTNodeLocationWithBlock.prototype.getSourceBlock;
|
||||
|
||||
|
||||
/**
|
||||
* An interface for an object that handles keyboard shortcuts.
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IKeyboardAccessible = function() {};
|
||||
|
||||
/**
|
||||
* Handles the given keyboard shortcut.
|
||||
* @param {!Blockly.ShortcutRegistry.KeyboardShortcut} shortcut The shortcut to be handled.
|
||||
* @return {boolean} True if the shortcut has been handled, false otherwise.
|
||||
*/
|
||||
Blockly.IKeyboardAccessible.prototype.onShortcut;
|
||||
23
core/interfaces/i_ast_node_location.js
Normal file
23
core/interfaces/i_ast_node_location.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview The interface for an AST node location.
|
||||
* @author samelh@google.com (Sam El-Husseini)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.IASTNodeLocation');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/**
|
||||
* An AST node location interface.
|
||||
* @interface
|
||||
*/
|
||||
const IASTNodeLocation = function() {};
|
||||
|
||||
exports = IASTNodeLocation;
|
||||
41
core/interfaces/i_ast_node_location_svg.js
Normal file
41
core/interfaces/i_ast_node_location_svg.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview The interface for an AST node location SVG.
|
||||
* @author samelh@google.com (Sam El-Husseini)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.IASTNodeLocationSvg');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
const IASTNodeLocation = goog.require('Blockly.IASTNodeLocation');
|
||||
|
||||
|
||||
/**
|
||||
* An AST node location SVG interface.
|
||||
* @interface
|
||||
* @extends {IASTNodeLocation}
|
||||
*/
|
||||
const IASTNodeLocationSvg = function() {};
|
||||
|
||||
/**
|
||||
* Add the marker SVG to this node's SVG group.
|
||||
* @param {SVGElement} markerSvg The SVG root of the marker to be added to the
|
||||
* SVG group.
|
||||
*/
|
||||
IASTNodeLocationSvg.prototype.setMarkerSvg;
|
||||
|
||||
/**
|
||||
* Add the cursor SVG to this node's SVG group.
|
||||
* @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the
|
||||
* SVG group.
|
||||
*/
|
||||
IASTNodeLocationSvg.prototype.setCursorSvg;
|
||||
|
||||
exports = IASTNodeLocationSvg;
|
||||
35
core/interfaces/i_ast_node_location_with_block.js
Normal file
35
core/interfaces/i_ast_node_location_with_block.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview The interface for an AST node location that has an associated
|
||||
* block.
|
||||
* @author samelh@google.com (Sam El-Husseini)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.IASTNodeLocationWithBlock');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
const IASTNodeLocation = goog.require('Blockly.IASTNodeLocation');
|
||||
|
||||
|
||||
/**
|
||||
* An AST node location that has an associated block.
|
||||
* @interface
|
||||
* @extends {IASTNodeLocation}
|
||||
*/
|
||||
const IASTNodeLocationWithBlock = function() {};
|
||||
|
||||
/**
|
||||
* Get the source block associated with this node.
|
||||
* @return {Block} The source block.
|
||||
*/
|
||||
IASTNodeLocationWithBlock.prototype.getSourceBlock;
|
||||
|
||||
exports = IASTNodeLocationWithBlock;
|
||||
@@ -12,21 +12,24 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IAutoHideable');
|
||||
goog.module('Blockly.IAutoHideable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.IComponent');
|
||||
const IComponent = goog.require('Blockly.IComponent');
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a component that can be automatically hidden.
|
||||
* @extends {Blockly.IComponent}
|
||||
* @extends {IComponent}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IAutoHideable = function() {};
|
||||
const IAutoHideable = function() {};
|
||||
|
||||
/**
|
||||
* Hides the component. Called in Blockly.hideChaff.
|
||||
* @param {boolean} onlyClosePopups Whether only popups should be closed.
|
||||
* Flyouts should not be closed if this is true.
|
||||
*/
|
||||
Blockly.IAutoHideable.prototype.autoHide;
|
||||
IAutoHideable.prototype.autoHide;
|
||||
|
||||
exports = IAutoHideable;
|
||||
|
||||
@@ -11,35 +11,35 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IBubble');
|
||||
goog.module('Blockly.IBubble');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.IContextMenu');
|
||||
goog.require('Blockly.IDraggable');
|
||||
|
||||
goog.requireType('Blockly.BlockDragSurfaceSvg');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
const BlockDragSurfaceSvg = goog.requireType('Blockly.BlockDragSurfaceSvg');
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const IContextMenu = goog.require('Blockly.IContextMenu');
|
||||
const IDraggable = goog.require('Blockly.IDraggable');
|
||||
|
||||
|
||||
/**
|
||||
* A bubble interface.
|
||||
* @interface
|
||||
* @extends {Blockly.IDraggable}
|
||||
* @extends {Blockly.IContextMenu}
|
||||
* @extends {IDraggable}
|
||||
* @extends {IContextMenu}
|
||||
*/
|
||||
Blockly.IBubble = function() {};
|
||||
const IBubble = function() {};
|
||||
|
||||
/**
|
||||
* Return the coordinates of the top-left corner of this bubble's body relative
|
||||
* to the drawing surface's origin (0,0), in workspace units.
|
||||
* @return {!Blockly.utils.Coordinate} Object with .x and .y properties.
|
||||
* @return {!Coordinate} Object with .x and .y properties.
|
||||
*/
|
||||
Blockly.IBubble.prototype.getRelativeToSurfaceXY;
|
||||
IBubble.prototype.getRelativeToSurfaceXY;
|
||||
|
||||
/**
|
||||
* Return the root node of the bubble's SVG group.
|
||||
* @return {!SVGElement} The root SVG node of the bubble's group.
|
||||
*/
|
||||
Blockly.IBubble.prototype.getSvgRoot;
|
||||
IBubble.prototype.getSvgRoot;
|
||||
|
||||
/**
|
||||
* Set whether auto-layout of this bubble is enabled. The first time a bubble
|
||||
@@ -48,39 +48,41 @@ Blockly.IBubble.prototype.getSvgRoot;
|
||||
* @param {boolean} enable True if auto-layout should be enabled, false
|
||||
* otherwise.
|
||||
*/
|
||||
Blockly.IBubble.prototype.setAutoLayout;
|
||||
IBubble.prototype.setAutoLayout;
|
||||
|
||||
/**
|
||||
* Triggers a move callback if one exists at the end of a drag.
|
||||
* @param {boolean} adding True if adding, false if removing.
|
||||
*/
|
||||
Blockly.IBubble.prototype.setDragging;
|
||||
IBubble.prototype.setDragging;
|
||||
|
||||
/**
|
||||
* Move this bubble during a drag, taking into account whether or not there is
|
||||
* a drag surface.
|
||||
* @param {Blockly.BlockDragSurfaceSvg} dragSurface The surface that carries
|
||||
* @param {?BlockDragSurfaceSvg} dragSurface The surface that carries
|
||||
* rendered items during a drag, or null if no drag surface is in use.
|
||||
* @param {!Blockly.utils.Coordinate} newLoc The location to translate to, in
|
||||
* @param {!Coordinate} newLoc The location to translate to, in
|
||||
* workspace coordinates.
|
||||
*/
|
||||
Blockly.IBubble.prototype.moveDuringDrag;
|
||||
IBubble.prototype.moveDuringDrag;
|
||||
|
||||
/**
|
||||
* Move the bubble to the specified location in workspace coordinates.
|
||||
* @param {number} x The x position to move to.
|
||||
* @param {number} y The y position to move to.
|
||||
*/
|
||||
Blockly.IBubble.prototype.moveTo;
|
||||
IBubble.prototype.moveTo;
|
||||
|
||||
/**
|
||||
* Update the style of this bubble when it is dragged over a delete area.
|
||||
* @param {boolean} enable True if the bubble is about to be deleted, false
|
||||
* otherwise.
|
||||
*/
|
||||
Blockly.IBubble.prototype.setDeleteStyle;
|
||||
IBubble.prototype.setDeleteStyle;
|
||||
|
||||
/**
|
||||
* Dispose of this bubble.
|
||||
*/
|
||||
Blockly.IBubble.prototype.dispose;
|
||||
IBubble.prototype.dispose;
|
||||
|
||||
exports = IBubble;
|
||||
|
||||
@@ -11,16 +11,19 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IContextMenu');
|
||||
goog.module('Blockly.IContextMenu');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IContextMenu = function() {};
|
||||
const IContextMenu = function() {};
|
||||
|
||||
/**
|
||||
* Show the context menu for this object.
|
||||
* @param {!Event} e Mouse event.
|
||||
*/
|
||||
Blockly.IContextMenu.prototype.showContextMenu;
|
||||
IContextMenu.prototype.showContextMenu;
|
||||
|
||||
exports = IContextMenu;
|
||||
|
||||
@@ -11,30 +11,33 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ICopyable');
|
||||
goog.module('Blockly.ICopyable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.requireType('Blockly.ISelectable');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
const ISelectable = goog.requireType('Blockly.ISelectable');
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
* @extends {Blockly.ISelectable}
|
||||
* @extends {ISelectable}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.ICopyable = function() {};
|
||||
const ICopyable = function() {};
|
||||
|
||||
/**
|
||||
* Encode for copying.
|
||||
* @return {?Blockly.ICopyable.CopyData} Copy metadata.
|
||||
* @return {?ICopyable.CopyData} Copy metadata.
|
||||
*/
|
||||
Blockly.ICopyable.prototype.toCopyData;
|
||||
ICopyable.prototype.toCopyData;
|
||||
|
||||
/**
|
||||
* Copy Metadata.
|
||||
* @typedef {{
|
||||
* xml:!Element,
|
||||
* source:Blockly.WorkspaceSvg,
|
||||
* source:WorkspaceSvg,
|
||||
* typeCounts:?Object
|
||||
* }}
|
||||
*/
|
||||
Blockly.ICopyable.CopyData;
|
||||
ICopyable.CopyData;
|
||||
|
||||
exports = ICopyable;
|
||||
|
||||
@@ -11,17 +11,20 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IDeletable');
|
||||
goog.module('Blockly.IDeletable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
|
||||
/**
|
||||
* The interface for an object that can be deleted.
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IDeletable = function() {};
|
||||
const IDeletable = function() {};
|
||||
|
||||
/**
|
||||
* Get whether this object is deletable or not.
|
||||
* @return {boolean} True if deletable.
|
||||
*/
|
||||
Blockly.IDeletable.prototype.isDeletable;
|
||||
IDeletable.prototype.isDeletable;
|
||||
|
||||
exports = IDeletable;
|
||||
|
||||
@@ -12,31 +12,33 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IDeleteArea');
|
||||
goog.module('Blockly.IDeleteArea');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.IDragTarget');
|
||||
|
||||
goog.requireType('Blockly.IDraggable');
|
||||
const IDraggable = goog.requireType('Blockly.IDraggable');
|
||||
const IDragTarget = goog.require('Blockly.IDragTarget');
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a component that can delete a block or bubble that is dropped
|
||||
* on top of it.
|
||||
* @extends {Blockly.IDragTarget}
|
||||
* @extends {IDragTarget}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IDeleteArea = function() {};
|
||||
const IDeleteArea = function() {};
|
||||
|
||||
/**
|
||||
* Returns whether the provided block or bubble would be deleted if dropped on
|
||||
* this area.
|
||||
* This method should check if the element is deletable and is always called
|
||||
* before onDragEnter/onDragOver/onDragExit.
|
||||
* @param {!Blockly.IDraggable} element The block or bubble currently being
|
||||
* @param {!IDraggable} element The block or bubble currently being
|
||||
* dragged.
|
||||
* @param {boolean} couldConnect Whether the element could could connect to
|
||||
* another.
|
||||
* @return {boolean} Whether the element provided would be deleted if dropped on
|
||||
* this area.
|
||||
*/
|
||||
Blockly.IDeleteArea.prototype.wouldDelete;
|
||||
IDeleteArea.prototype.wouldDelete;
|
||||
|
||||
exports = IDeleteArea;
|
||||
|
||||
@@ -12,67 +12,70 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IDragTarget');
|
||||
goog.module('Blockly.IDragTarget');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.IComponent');
|
||||
const IComponent = goog.require('Blockly.IComponent');
|
||||
const IDraggable = goog.requireType('Blockly.IDraggable');
|
||||
const Rect = goog.requireType('Blockly.utils.Rect');
|
||||
|
||||
goog.requireType('Blockly.IDraggable');
|
||||
goog.requireType('Blockly.utils.Rect');
|
||||
|
||||
/**
|
||||
* Interface for a component with custom behaviour when a block or bubble is
|
||||
* dragged over or dropped on top of it.
|
||||
* @extends {Blockly.IComponent}
|
||||
* @extends {IComponent}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IDragTarget = function() {};
|
||||
const IDragTarget = function() {};
|
||||
|
||||
/**
|
||||
* Returns the bounding rectangle of the drag target area in pixel units
|
||||
* relative to viewport.
|
||||
* @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
|
||||
* @return {?Rect} The component's bounding box. Null if drag
|
||||
* target area should be ignored.
|
||||
*/
|
||||
Blockly.IDragTarget.prototype.getClientRect;
|
||||
IDragTarget.prototype.getClientRect;
|
||||
|
||||
/**
|
||||
* Handles when a cursor with a block or bubble enters this drag target.
|
||||
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
|
||||
* @param {!IDraggable} dragElement The block or bubble currently being
|
||||
* dragged.
|
||||
*/
|
||||
Blockly.IDragTarget.prototype.onDragEnter;
|
||||
IDragTarget.prototype.onDragEnter;
|
||||
|
||||
/**
|
||||
* Handles when a cursor with a block or bubble is dragged over this drag
|
||||
* target.
|
||||
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
|
||||
* @param {!IDraggable} dragElement The block or bubble currently being
|
||||
* dragged.
|
||||
*/
|
||||
Blockly.IDragTarget.prototype.onDragOver;
|
||||
IDragTarget.prototype.onDragOver;
|
||||
|
||||
|
||||
/**
|
||||
* Handles when a cursor with a block or bubble exits this drag target.
|
||||
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
|
||||
* @param {!IDraggable} dragElement The block or bubble currently being
|
||||
* dragged.
|
||||
*/
|
||||
Blockly.IDragTarget.prototype.onDragExit;
|
||||
IDragTarget.prototype.onDragExit;
|
||||
|
||||
/**
|
||||
* Handles when a block or bubble is dropped on this component.
|
||||
* Should not handle delete here.
|
||||
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
|
||||
* @param {!IDraggable} dragElement The block or bubble currently being
|
||||
* dragged.
|
||||
*/
|
||||
Blockly.IDragTarget.prototype.onDrop;
|
||||
IDragTarget.prototype.onDrop;
|
||||
|
||||
/**
|
||||
* Returns whether the provided block or bubble should not be moved after being
|
||||
* dropped on this component. If true, the element will return to where it was
|
||||
* when the drag started.
|
||||
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
|
||||
* @param {!IDraggable} dragElement The block or bubble currently being
|
||||
* dragged.
|
||||
* @return {boolean} Whether the block or bubble provided should be returned to
|
||||
* drag start.
|
||||
*/
|
||||
Blockly.IDragTarget.prototype.shouldPreventMove;
|
||||
IDragTarget.prototype.shouldPreventMove;
|
||||
|
||||
exports = IDragTarget;
|
||||
|
||||
@@ -11,14 +11,17 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IDraggable');
|
||||
goog.module('Blockly.IDraggable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.IDeletable');
|
||||
const IDeletable = goog.require('Blockly.IDeletable');
|
||||
|
||||
|
||||
/**
|
||||
* The interface for an object that can be dragged.
|
||||
* @extends {Blockly.IDeletable}
|
||||
* @extends {IDeletable}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IDraggable = function() {};
|
||||
const IDraggable = function() {};
|
||||
|
||||
exports = IDraggable;
|
||||
|
||||
@@ -11,179 +11,182 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IFlyout');
|
||||
goog.module('Blockly.IFlyout');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.IRegistrable');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
goog.requireType('Blockly.utils.Svg');
|
||||
goog.requireType('Blockly.utils.toolbox');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const IRegistrable = goog.require('Blockly.IRegistrable');
|
||||
const Svg = goog.requireType('Blockly.utils.Svg');
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const {FlyoutDefinition} = goog.requireType('Blockly.utils.toolbox');
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a flyout.
|
||||
* @extends {Blockly.IRegistrable}
|
||||
* @extends {IRegistrable}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IFlyout = function() {};
|
||||
const IFlyout = function() {};
|
||||
|
||||
/**
|
||||
* Whether the flyout is laid out horizontally or not.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.IFlyout.prototype.horizontalLayout;
|
||||
IFlyout.prototype.horizontalLayout;
|
||||
|
||||
/**
|
||||
* Is RTL vs LTR.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.IFlyout.prototype.RTL;
|
||||
IFlyout.prototype.RTL;
|
||||
|
||||
/**
|
||||
* The target workspace
|
||||
* @type {?Blockly.WorkspaceSvg}
|
||||
* @type {?WorkspaceSvg}
|
||||
*/
|
||||
Blockly.IFlyout.prototype.targetWorkspace;
|
||||
IFlyout.prototype.targetWorkspace;
|
||||
|
||||
/**
|
||||
* Margin around the edges of the blocks in the flyout.
|
||||
* @type {number}
|
||||
* @const
|
||||
*/
|
||||
Blockly.IFlyout.prototype.MARGIN;
|
||||
IFlyout.prototype.MARGIN;
|
||||
|
||||
/**
|
||||
* Does the flyout automatically close when a block is created?
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.IFlyout.prototype.autoClose;
|
||||
IFlyout.prototype.autoClose;
|
||||
|
||||
/**
|
||||
* Corner radius of the flyout background.
|
||||
* @type {number}
|
||||
* @const
|
||||
*/
|
||||
Blockly.IFlyout.prototype.CORNER_RADIUS;
|
||||
IFlyout.prototype.CORNER_RADIUS;
|
||||
|
||||
/**
|
||||
* Creates the flyout's DOM. Only needs to be called once. The flyout can
|
||||
* either exist as its own svg element or be a g element nested inside a
|
||||
* separate svg element.
|
||||
* @param {string|
|
||||
* !Blockly.utils.Svg<!SVGSVGElement>|
|
||||
* !Blockly.utils.Svg<!SVGGElement>} tagName The type of tag to
|
||||
* !Svg<!SVGSVGElement>|
|
||||
* !Svg<!SVGGElement>} tagName The type of tag to
|
||||
* put the flyout in. This should be <svg> or <g>.
|
||||
* @return {!SVGElement} The flyout's SVG group.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.createDom;
|
||||
IFlyout.prototype.createDom;
|
||||
|
||||
/**
|
||||
* Initializes the flyout.
|
||||
* @param {!Blockly.WorkspaceSvg} targetWorkspace The workspace in which to
|
||||
* @param {!WorkspaceSvg} targetWorkspace The workspace in which to
|
||||
* create new blocks.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.init;
|
||||
IFlyout.prototype.init;
|
||||
|
||||
/**
|
||||
* Dispose of this flyout.
|
||||
* Unlink from all DOM elements to prevent memory leaks.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.dispose;
|
||||
IFlyout.prototype.dispose;
|
||||
|
||||
/**
|
||||
* Get the width of the flyout.
|
||||
* @return {number} The width of the flyout.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.getWidth;
|
||||
IFlyout.prototype.getWidth;
|
||||
|
||||
/**
|
||||
* Get the height of the flyout.
|
||||
* @return {number} The width of the flyout.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.getHeight;
|
||||
IFlyout.prototype.getHeight;
|
||||
|
||||
/**
|
||||
* Get the workspace inside the flyout.
|
||||
* @return {!Blockly.WorkspaceSvg} The workspace inside the flyout.
|
||||
* @return {!WorkspaceSvg} The workspace inside the flyout.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.getWorkspace;
|
||||
IFlyout.prototype.getWorkspace;
|
||||
|
||||
/**
|
||||
* Is the flyout visible?
|
||||
* @return {boolean} True if visible.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.isVisible;
|
||||
IFlyout.prototype.isVisible;
|
||||
|
||||
/**
|
||||
* Set whether the flyout is visible. A value of true does not necessarily mean
|
||||
* that the flyout is shown. It could be hidden because its container is hidden.
|
||||
* @param {boolean} visible True if visible.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.setVisible;
|
||||
IFlyout.prototype.setVisible;
|
||||
|
||||
/**
|
||||
* Set whether this flyout's container is visible.
|
||||
* @param {boolean} visible Whether the container is visible.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.setContainerVisible;
|
||||
IFlyout.prototype.setContainerVisible;
|
||||
|
||||
/**
|
||||
* Hide and empty the flyout.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.hide;
|
||||
IFlyout.prototype.hide;
|
||||
|
||||
/**
|
||||
* Show and populate the flyout.
|
||||
* @param {!Blockly.utils.toolbox.FlyoutDefinition|string} flyoutDef Contents to
|
||||
* @param {!FlyoutDefinition|string} flyoutDef Contents to
|
||||
* display in the flyout. This is either an array of Nodes, a NodeList, a
|
||||
* toolbox definition, or a string with the name of the dynamic category.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.show;
|
||||
IFlyout.prototype.show;
|
||||
|
||||
/**
|
||||
* Create a copy of this block on the workspace.
|
||||
* @param {!Blockly.BlockSvg} originalBlock The block to copy from the flyout.
|
||||
* @return {!Blockly.BlockSvg} The newly created block.
|
||||
* @param {!BlockSvg} originalBlock The block to copy from the flyout.
|
||||
* @return {!BlockSvg} The newly created block.
|
||||
* @throws {Error} if something went wrong with deserialization.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.createBlock;
|
||||
IFlyout.prototype.createBlock;
|
||||
|
||||
/**
|
||||
* Reflow blocks and their mats.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.reflow;
|
||||
IFlyout.prototype.reflow;
|
||||
|
||||
/**
|
||||
* @return {boolean} True if this flyout may be scrolled with a scrollbar or by
|
||||
* dragging.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.isScrollable;
|
||||
IFlyout.prototype.isScrollable;
|
||||
|
||||
/**
|
||||
* Calculates the x coordinate for the flyout position.
|
||||
* @return {number} X coordinate.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.getX;
|
||||
IFlyout.prototype.getX;
|
||||
|
||||
/**
|
||||
* Calculates the y coordinate for the flyout position.
|
||||
* @return {number} Y coordinate.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.getY;
|
||||
IFlyout.prototype.getY;
|
||||
|
||||
/**
|
||||
* Position the flyout.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IFlyout.prototype.position;
|
||||
IFlyout.prototype.position;
|
||||
|
||||
/**
|
||||
* Determine if a drag delta is toward the workspace, based on the position
|
||||
* and orientation of the flyout. This is used in determineDragIntention_ to
|
||||
* determine if a new block should be created or if the flyout should scroll.
|
||||
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* @param {!Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* moved from the position at mouse down, in pixel units.
|
||||
* @return {boolean} True if the drag is toward the workspace.
|
||||
*/
|
||||
Blockly.IFlyout.prototype.isDragTowardWorkspace;
|
||||
IFlyout.prototype.isDragTowardWorkspace;
|
||||
|
||||
exports = IFlyout;
|
||||
|
||||
33
core/interfaces/i_keyboard_accessible.js
Normal file
33
core/interfaces/i_keyboard_accessible.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview The interface for objects that handle keyboard shortcuts.
|
||||
* @author samelh@google.com (Sam El-Husseini)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.IKeyboardAccessible');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
const {KeyboardShortcut} = goog.requireType('Blockly.ShortcutRegistry');
|
||||
|
||||
|
||||
/**
|
||||
* An interface for an object that handles keyboard shortcuts.
|
||||
* @interface
|
||||
*/
|
||||
const IKeyboardAccessible = function() {};
|
||||
|
||||
/**
|
||||
* Handles the given keyboard shortcut.
|
||||
* @param {!KeyboardShortcut} shortcut The shortcut to be handled.
|
||||
* @return {boolean} True if the shortcut has been handled, false otherwise.
|
||||
*/
|
||||
IKeyboardAccessible.prototype.onShortcut;
|
||||
|
||||
exports = IKeyboardAccessible;
|
||||
@@ -11,17 +11,20 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IMovable');
|
||||
goog.module('Blockly.IMovable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
|
||||
/**
|
||||
* The interface for an object that is movable.
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IMovable = function() {};
|
||||
const IMovable = function() {};
|
||||
|
||||
/**
|
||||
* Get whether this is movable or not.
|
||||
* @return {boolean} True if movable.
|
||||
*/
|
||||
Blockly.IMovable.prototype.isMovable;
|
||||
IMovable.prototype.isMovable;
|
||||
|
||||
exports = IMovable;
|
||||
|
||||
@@ -11,33 +11,35 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IPositionable');
|
||||
goog.module('Blockly.IPositionable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.IComponent');
|
||||
|
||||
goog.requireType('Blockly.MetricsManager');
|
||||
goog.requireType('Blockly.utils.Rect');
|
||||
const IComponent = goog.require('Blockly.IComponent');
|
||||
const Rect = goog.requireType('Blockly.utils.Rect');
|
||||
const {UiMetrics} = goog.requireType('Blockly.MetricsManager');
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a component that is positioned on top of the workspace.
|
||||
* @extends {Blockly.IComponent}
|
||||
* @extends {IComponent}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IPositionable = function() {};
|
||||
const IPositionable = function() {};
|
||||
|
||||
/**
|
||||
* Positions the element. Called when the window is resized.
|
||||
* @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace metrics.
|
||||
* @param {!Array<!Blockly.utils.Rect>} savedPositions List of rectangles that
|
||||
* @param {!UiMetrics} metrics The workspace metrics.
|
||||
* @param {!Array<!Rect>} savedPositions List of rectangles that
|
||||
* are already on the workspace.
|
||||
*/
|
||||
Blockly.IPositionable.prototype.position;
|
||||
IPositionable.prototype.position;
|
||||
|
||||
/**
|
||||
* Returns the bounding rectangle of the UI element in pixel units relative to
|
||||
* the Blockly injection div.
|
||||
* @return {?Blockly.utils.Rect} The UI elements’s bounding box. Null if
|
||||
* @return {?Rect} The UI elements’s bounding box. Null if
|
||||
* bounding box should be ignored by other UI elements.
|
||||
*/
|
||||
Blockly.IPositionable.prototype.getBoundingRectangle;
|
||||
IPositionable.prototype.getBoundingRectangle;
|
||||
|
||||
exports = IPositionable;
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ISelectable');
|
||||
goog.module('Blockly.ISelectable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.requireType('Blockly.IDeletable');
|
||||
goog.requireType('Blockly.IMovable');
|
||||
@@ -23,21 +24,23 @@ goog.requireType('Blockly.IMovable');
|
||||
* @extends {Blockly.IMovable}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.ISelectable = function() {};
|
||||
const ISelectable = function() {};
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.ISelectable.prototype.id;
|
||||
ISelectable.prototype.id;
|
||||
|
||||
/**
|
||||
* Select this. Highlight it visually.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.ISelectable.prototype.select;
|
||||
ISelectable.prototype.select;
|
||||
|
||||
/**
|
||||
* Unselect this. Unhighlight it visually.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.ISelectable.prototype.unselect;
|
||||
ISelectable.prototype.unselect;
|
||||
|
||||
exports = ISelectable;
|
||||
|
||||
@@ -11,23 +11,26 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IStyleable');
|
||||
goog.module('Blockly.IStyleable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
|
||||
/**
|
||||
* Interface for an object that a style can be added to.
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IStyleable = function() {};
|
||||
const IStyleable = function() {};
|
||||
|
||||
/**
|
||||
* Adds a style on the toolbox. Usually used to change the cursor.
|
||||
* @param {string} style The name of the class to add.
|
||||
*/
|
||||
Blockly.IStyleable.prototype.addStyle;
|
||||
IStyleable.prototype.addStyle;
|
||||
|
||||
/**
|
||||
* Removes a style from the toolbox. Usually used to change the cursor.
|
||||
* @param {string} style The name of the class to remove.
|
||||
*/
|
||||
Blockly.IStyleable.prototype.removeStyle;
|
||||
IStyleable.prototype.removeStyle;
|
||||
|
||||
exports = IStyleable;
|
||||
|
||||
@@ -11,90 +11,91 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IToolbox');
|
||||
goog.module('Blockly.IToolbox');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.requireType('Blockly.IFlyout');
|
||||
goog.requireType('Blockly.IRegistrable');
|
||||
goog.requireType('Blockly.IToolboxItem');
|
||||
goog.requireType('Blockly.utils.toolbox');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
const IFlyout = goog.requireType('Blockly.IFlyout');
|
||||
const IRegistrable = goog.require('Blockly.IRegistrable');
|
||||
const IToolboxItem = goog.requireType('Blockly.IToolboxItem');
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const {ToolboxInfo} = goog.requireType('Blockly.utils.toolbox');
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a toolbox.
|
||||
* @extends {Blockly.IRegistrable}
|
||||
* @extends {IRegistrable}
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IToolbox = function() {};
|
||||
const IToolbox = function() {};
|
||||
|
||||
/**
|
||||
* Initializes the toolbox.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.init;
|
||||
IToolbox.prototype.init;
|
||||
|
||||
/**
|
||||
* Fills the toolbox with new toolbox items and removes any old contents.
|
||||
* @param {!Blockly.utils.toolbox.ToolboxInfo} toolboxDef Object holding information
|
||||
* @param {!ToolboxInfo} toolboxDef Object holding information
|
||||
* for creating a toolbox.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.render;
|
||||
IToolbox.prototype.render;
|
||||
|
||||
/**
|
||||
* Gets the width of the toolbox.
|
||||
* @return {number} The width of the toolbox.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.getWidth;
|
||||
IToolbox.prototype.getWidth;
|
||||
|
||||
/**
|
||||
* Gets the height of the toolbox.
|
||||
* @return {number} The width of the toolbox.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.getHeight;
|
||||
IToolbox.prototype.getHeight;
|
||||
|
||||
/**
|
||||
* Gets the toolbox flyout.
|
||||
* @return {?Blockly.IFlyout} The toolbox flyout.
|
||||
* @return {?IFlyout} The toolbox flyout.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.getFlyout;
|
||||
IToolbox.prototype.getFlyout;
|
||||
|
||||
/**
|
||||
* Gets the workspace for the toolbox.
|
||||
* @return {!Blockly.WorkspaceSvg} The parent workspace for the toolbox.
|
||||
* @return {!WorkspaceSvg} The parent workspace for the toolbox.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.getWorkspace;
|
||||
IToolbox.prototype.getWorkspace;
|
||||
|
||||
/**
|
||||
* Gets whether or not the toolbox is horizontal.
|
||||
* @return {boolean} True if the toolbox is horizontal, false if the toolbox is
|
||||
* vertical.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.isHorizontal;
|
||||
IToolbox.prototype.isHorizontal;
|
||||
|
||||
/**
|
||||
* Positions the toolbox based on whether it is a horizontal toolbox and whether
|
||||
* the workspace is in rtl.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.position;
|
||||
IToolbox.prototype.position;
|
||||
|
||||
/**
|
||||
* Handles resizing the toolbox when a toolbox item resizes.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.handleToolboxItemResize;
|
||||
IToolbox.prototype.handleToolboxItemResize;
|
||||
|
||||
/**
|
||||
* Unhighlights any previously selected item.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.clearSelection;
|
||||
IToolbox.prototype.clearSelection;
|
||||
|
||||
/**
|
||||
* Updates the category colours and background colour of selected categories.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.refreshTheme;
|
||||
IToolbox.prototype.refreshTheme;
|
||||
|
||||
/**
|
||||
* Updates the flyout's content without closing it. Should be used in response
|
||||
@@ -102,30 +103,32 @@ Blockly.IToolbox.prototype.refreshTheme;
|
||||
* procedures.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.refreshSelection;
|
||||
IToolbox.prototype.refreshSelection;
|
||||
|
||||
/**
|
||||
* Sets the visibility of the toolbox.
|
||||
* @param {boolean} isVisible True if toolbox should be visible.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.setVisible;
|
||||
IToolbox.prototype.setVisible;
|
||||
|
||||
/**
|
||||
* Selects the toolbox item by it's position in the list of toolbox items.
|
||||
* @param {number} position The position of the item to select.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.selectItemByPosition;
|
||||
IToolbox.prototype.selectItemByPosition;
|
||||
|
||||
/**
|
||||
* Gets the selected item.
|
||||
* @return {?Blockly.IToolboxItem} The selected item, or null if no item is
|
||||
* @return {?IToolboxItem} The selected item, or null if no item is
|
||||
* currently selected.
|
||||
*/
|
||||
Blockly.IToolbox.prototype.getSelectedItem;
|
||||
IToolbox.prototype.getSelectedItem;
|
||||
|
||||
/**
|
||||
* Disposes of this toolbox.
|
||||
* @return {void}
|
||||
*/
|
||||
Blockly.IToolbox.prototype.dispose;
|
||||
IToolbox.prototype.dispose;
|
||||
|
||||
exports = IToolbox;
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.BasicCursor');
|
||||
goog.module('Blockly.BasicCursor');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.ASTNode');
|
||||
goog.require('Blockly.Cursor');
|
||||
goog.require('Blockly.registry');
|
||||
const ASTNode = goog.require('Blockly.ASTNode');
|
||||
const Cursor = goog.require('Blockly.Cursor');
|
||||
const {register, Type} = goog.require('Blockly.registry');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
|
||||
|
||||
/**
|
||||
@@ -23,31 +25,31 @@ goog.require('Blockly.registry');
|
||||
* This will allow the user to get to all nodes in the AST by hitting next or
|
||||
* previous.
|
||||
* @constructor
|
||||
* @extends {Blockly.Cursor}
|
||||
* @extends {Cursor}
|
||||
*/
|
||||
Blockly.BasicCursor = function() {
|
||||
Blockly.BasicCursor.superClass_.constructor.call(this);
|
||||
const BasicCursor = function() {
|
||||
BasicCursor.superClass_.constructor.call(this);
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.BasicCursor, Blockly.Cursor);
|
||||
inherits(BasicCursor, Cursor);
|
||||
|
||||
/**
|
||||
* Name used for registering a basic cursor.
|
||||
* @const {string}
|
||||
*/
|
||||
Blockly.BasicCursor.registrationName = 'basicCursor';
|
||||
BasicCursor.registrationName = 'basicCursor';
|
||||
|
||||
/**
|
||||
* Find the next node in the pre order traversal.
|
||||
* @return {Blockly.ASTNode} The next node, or null if the current node is
|
||||
* @return {?ASTNode} The next node, or null if the current node is
|
||||
* not set or there is no next value.
|
||||
* @override
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.next = function() {
|
||||
var curNode = this.getCurNode();
|
||||
BasicCursor.prototype.next = function() {
|
||||
const curNode = this.getCurNode();
|
||||
if (!curNode) {
|
||||
return null;
|
||||
}
|
||||
var newNode = this.getNextNode_(curNode, this.validNode_);
|
||||
const newNode = this.getNextNode_(curNode, this.validNode_);
|
||||
|
||||
if (newNode) {
|
||||
this.setCurNode(newNode);
|
||||
@@ -59,26 +61,26 @@ Blockly.BasicCursor.prototype.next = function() {
|
||||
* For a basic cursor we only have the ability to go next and previous, so
|
||||
* in will also allow the user to get to the next node in the pre order
|
||||
* traversal.
|
||||
* @return {Blockly.ASTNode} The next node, or null if the current node is
|
||||
* @return {?ASTNode} The next node, or null if the current node is
|
||||
* not set or there is no next value.
|
||||
* @override
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.in = function() {
|
||||
BasicCursor.prototype.in = function() {
|
||||
return this.next();
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the previous node in the pre order traversal.
|
||||
* @return {Blockly.ASTNode} The previous node, or null if the current node
|
||||
* @return {?ASTNode} The previous node, or null if the current node
|
||||
* is not set or there is no previous value.
|
||||
* @override
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.prev = function() {
|
||||
var curNode = this.getCurNode();
|
||||
BasicCursor.prototype.prev = function() {
|
||||
const curNode = this.getCurNode();
|
||||
if (!curNode) {
|
||||
return null;
|
||||
}
|
||||
var newNode = this.getPreviousNode_(curNode, this.validNode_);
|
||||
const newNode = this.getPreviousNode_(curNode, this.validNode_);
|
||||
|
||||
if (newNode) {
|
||||
this.setCurNode(newNode);
|
||||
@@ -90,11 +92,11 @@ Blockly.BasicCursor.prototype.prev = function() {
|
||||
* For a basic cursor we only have the ability to go next and previous, so
|
||||
* out will allow the user to get to the previous node in the pre order
|
||||
* traversal.
|
||||
* @return {Blockly.ASTNode} The previous node, or null if the current node is
|
||||
* @return {?ASTNode} The previous node, or null if the current node is
|
||||
* not set or there is no previous value.
|
||||
* @override
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.out = function() {
|
||||
BasicCursor.prototype.out = function() {
|
||||
return this.prev();
|
||||
};
|
||||
|
||||
@@ -102,23 +104,23 @@ Blockly.BasicCursor.prototype.out = function() {
|
||||
* Uses pre order traversal to navigate the Blockly AST. This will allow
|
||||
* a user to easily navigate the entire Blockly AST without having to go in
|
||||
* and out levels on the tree.
|
||||
* @param {Blockly.ASTNode} node The current position in the AST.
|
||||
* @param {!function(Blockly.ASTNode) : boolean} isValid A function true/false
|
||||
* @param {?ASTNode} node The current position in the AST.
|
||||
* @param {!function(ASTNode) : boolean} isValid A function true/false
|
||||
* depending on whether the given node should be traversed.
|
||||
* @return {Blockly.ASTNode} The next node in the traversal.
|
||||
* @return {?ASTNode} The next node in the traversal.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.getNextNode_ = function(node, isValid) {
|
||||
BasicCursor.prototype.getNextNode_ = function(node, isValid) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
var newNode = node.in() || node.next();
|
||||
const newNode = node.in() || node.next();
|
||||
if (isValid(newNode)) {
|
||||
return newNode;
|
||||
} else if (newNode) {
|
||||
return this.getNextNode_(newNode, isValid);
|
||||
}
|
||||
var siblingOrParent = this.findSiblingOrParent_(node.out());
|
||||
const siblingOrParent = this.findSiblingOrParent_(node.out());
|
||||
if (isValid(siblingOrParent)) {
|
||||
return siblingOrParent;
|
||||
} else if (siblingOrParent) {
|
||||
@@ -131,18 +133,18 @@ Blockly.BasicCursor.prototype.getNextNode_ = function(node, isValid) {
|
||||
* Reverses the pre order traversal in order to find the previous node. This
|
||||
* will allow a user to easily navigate the entire Blockly AST without having to
|
||||
* go in and out levels on the tree.
|
||||
* @param {Blockly.ASTNode} node The current position in the AST.
|
||||
* @param {!function(Blockly.ASTNode) : boolean} isValid A function true/false
|
||||
* @param {?ASTNode} node The current position in the AST.
|
||||
* @param {!function(ASTNode) : boolean} isValid A function true/false
|
||||
* depending on whether the given node should be traversed.
|
||||
* @return {Blockly.ASTNode} The previous node in the traversal or null if no
|
||||
* @return {?ASTNode} The previous node in the traversal or null if no
|
||||
* previous node exists.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.getPreviousNode_ = function(node, isValid) {
|
||||
BasicCursor.prototype.getPreviousNode_ = function(node, isValid) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
var newNode = node.prev();
|
||||
let newNode = node.prev();
|
||||
|
||||
if (newNode) {
|
||||
newNode = this.getRightMostChild_(newNode);
|
||||
@@ -160,19 +162,16 @@ Blockly.BasicCursor.prototype.getPreviousNode_ = function(node, isValid) {
|
||||
/**
|
||||
* Decides what nodes to traverse and which ones to skip. Currently, it
|
||||
* skips output, stack and workspace nodes.
|
||||
* @param {Blockly.ASTNode} node The AST node to check whether it is valid.
|
||||
* @param {?ASTNode} node The AST node to check whether it is valid.
|
||||
* @return {boolean} True if the node should be visited, false otherwise.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.validNode_ = function(node) {
|
||||
var isValid = false;
|
||||
var type = node && node.getType();
|
||||
if (type == Blockly.ASTNode.types.OUTPUT ||
|
||||
type == Blockly.ASTNode.types.INPUT ||
|
||||
type == Blockly.ASTNode.types.FIELD ||
|
||||
type == Blockly.ASTNode.types.NEXT ||
|
||||
type == Blockly.ASTNode.types.PREVIOUS ||
|
||||
type == Blockly.ASTNode.types.WORKSPACE) {
|
||||
BasicCursor.prototype.validNode_ = function(node) {
|
||||
let isValid = false;
|
||||
const type = node && node.getType();
|
||||
if (type == ASTNode.types.OUTPUT || type == ASTNode.types.INPUT ||
|
||||
type == ASTNode.types.FIELD || type == ASTNode.types.NEXT ||
|
||||
type == ASTNode.types.PREVIOUS || type == ASTNode.types.WORKSPACE) {
|
||||
isValid = true;
|
||||
}
|
||||
return isValid;
|
||||
@@ -180,16 +179,16 @@ Blockly.BasicCursor.prototype.validNode_ = function(node) {
|
||||
|
||||
/**
|
||||
* From the given node find either the next valid sibling or parent.
|
||||
* @param {Blockly.ASTNode} node The current position in the AST.
|
||||
* @return {Blockly.ASTNode} The parent AST node or null if there are no
|
||||
* @param {?ASTNode} node The current position in the AST.
|
||||
* @return {?ASTNode} The parent AST node or null if there are no
|
||||
* valid parents.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.findSiblingOrParent_ = function(node) {
|
||||
BasicCursor.prototype.findSiblingOrParent_ = function(node) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
var nextNode = node.next();
|
||||
const nextNode = node.next();
|
||||
if (nextNode) {
|
||||
return nextNode;
|
||||
}
|
||||
@@ -199,22 +198,22 @@ Blockly.BasicCursor.prototype.findSiblingOrParent_ = function(node) {
|
||||
|
||||
/**
|
||||
* Get the right most child of a node.
|
||||
* @param {Blockly.ASTNode} node The node to find the right most child of.
|
||||
* @return {Blockly.ASTNode} The right most child of the given node, or the node
|
||||
* @param {?ASTNode} node The node to find the right most child of.
|
||||
* @return {?ASTNode} The right most child of the given node, or the node
|
||||
* if no child exists.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BasicCursor.prototype.getRightMostChild_ = function(node) {
|
||||
BasicCursor.prototype.getRightMostChild_ = function(node) {
|
||||
if (!node.in()) {
|
||||
return node;
|
||||
}
|
||||
var newNode = node.in();
|
||||
let newNode = node.in();
|
||||
while (newNode.next()) {
|
||||
newNode = newNode.next();
|
||||
}
|
||||
return this.getRightMostChild_(newNode);
|
||||
};
|
||||
|
||||
Blockly.registry.register(
|
||||
Blockly.registry.Type.CURSOR, Blockly.BasicCursor.registrationName,
|
||||
Blockly.BasicCursor);
|
||||
register(Type.CURSOR, BasicCursor.registrationName, BasicCursor);
|
||||
|
||||
exports = BasicCursor;
|
||||
|
||||
@@ -10,29 +10,29 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.blockRendering.Drawer');
|
||||
goog.module('Blockly.blockRendering.Drawer');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.blockRendering.RenderInfo');
|
||||
goog.require('Blockly.blockRendering.Row');
|
||||
goog.require('Blockly.blockRendering.Types');
|
||||
goog.require('Blockly.utils.svgPaths');
|
||||
|
||||
goog.requireType('Blockly.blockRendering.ConstantProvider');
|
||||
goog.requireType('Blockly.blockRendering.Field');
|
||||
goog.requireType('Blockly.blockRendering.Icon');
|
||||
goog.requireType('Blockly.blockRendering.InlineInput');
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const ConstantProvider = goog.requireType('Blockly.blockRendering.ConstantProvider');
|
||||
const Field = goog.requireType('Blockly.blockRendering.Field');
|
||||
const Icon = goog.requireType('Blockly.blockRendering.Icon');
|
||||
const InlineInput = goog.requireType('Blockly.blockRendering.InlineInput');
|
||||
const RenderInfo = goog.requireType('Blockly.blockRendering.RenderInfo');
|
||||
const Row = goog.require('Blockly.blockRendering.Row');
|
||||
const svgPaths = goog.require('Blockly.utils.svgPaths');
|
||||
const Types = goog.require('Blockly.blockRendering.Types');
|
||||
|
||||
|
||||
/**
|
||||
* An object that draws a block based on the given rendering information.
|
||||
* @param {!Blockly.BlockSvg} block The block to render.
|
||||
* @param {!Blockly.blockRendering.RenderInfo} info An object containing all
|
||||
* @param {!BlockSvg} block The block to render.
|
||||
* @param {!RenderInfo} info An object containing all
|
||||
* information needed to render this block.
|
||||
* @package
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.blockRendering.Drawer = function(block, info) {
|
||||
const Drawer = function(block, info) {
|
||||
this.block_ = block;
|
||||
this.info_ = info;
|
||||
this.topLeft_ = block.getRelativeToSurfaceXY();
|
||||
@@ -41,7 +41,7 @@ Blockly.blockRendering.Drawer = function(block, info) {
|
||||
|
||||
/**
|
||||
* The renderer's constant provider.
|
||||
* @type {!Blockly.blockRendering.ConstantProvider}
|
||||
* @type {!ConstantProvider}
|
||||
* @protected
|
||||
*/
|
||||
this.constants_ = info.getRenderer().getConstants();
|
||||
@@ -57,7 +57,7 @@ Blockly.blockRendering.Drawer = function(block, info) {
|
||||
* required.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.draw = function() {
|
||||
Drawer.prototype.draw = function() {
|
||||
this.hideHiddenIcons_();
|
||||
this.drawOutline_();
|
||||
this.drawInternals_();
|
||||
@@ -78,7 +78,7 @@ Blockly.blockRendering.Drawer.prototype.draw = function() {
|
||||
* render. Anything that needs to be kept around should be set in this function.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.recordSizeOnBlock_ = function() {
|
||||
Drawer.prototype.recordSizeOnBlock_ = function() {
|
||||
// This is used when the block is reporting its size to anyone else.
|
||||
// The dark path adds to the size of the block in both X and Y.
|
||||
this.block_.height = this.info_.height;
|
||||
@@ -89,8 +89,8 @@ Blockly.blockRendering.Drawer.prototype.recordSizeOnBlock_ = function() {
|
||||
* Hide icons that were marked as hidden.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.hideHiddenIcons_ = function() {
|
||||
for (var i = 0, iconInfo; (iconInfo = this.info_.hiddenIcons[i]); i++) {
|
||||
Drawer.prototype.hideHiddenIcons_ = function() {
|
||||
for (let i = 0, iconInfo; (iconInfo = this.info_.hiddenIcons[i]); i++) {
|
||||
iconInfo.icon.iconGroup_.setAttribute('display', 'none');
|
||||
}
|
||||
};
|
||||
@@ -99,10 +99,10 @@ Blockly.blockRendering.Drawer.prototype.hideHiddenIcons_ = function() {
|
||||
* Create the outline of the block. This is a single continuous path.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawOutline_ = function() {
|
||||
Drawer.prototype.drawOutline_ = function() {
|
||||
this.drawTop_();
|
||||
for (var r = 1; r < this.info_.rows.length - 1; r++) {
|
||||
var row = this.info_.rows[r];
|
||||
for (let r = 1; r < this.info_.rows.length - 1; r++) {
|
||||
const row = this.info_.rows[r];
|
||||
if (row.hasJaggedEdge) {
|
||||
this.drawJaggedEdge_(row);
|
||||
} else if (row.hasStatement) {
|
||||
@@ -123,91 +123,80 @@ Blockly.blockRendering.Drawer.prototype.drawOutline_ = function() {
|
||||
* details such as hats and rounded corners.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawTop_ = function() {
|
||||
var topRow = this.info_.topRow;
|
||||
var elements = topRow.elements;
|
||||
Drawer.prototype.drawTop_ = function() {
|
||||
const topRow = this.info_.topRow;
|
||||
const elements = topRow.elements;
|
||||
|
||||
this.positionPreviousConnection_();
|
||||
this.outlinePath_ +=
|
||||
Blockly.utils.svgPaths.moveBy(topRow.xPos, this.info_.startY);
|
||||
for (var i = 0, elem; (elem = elements[i]); i++) {
|
||||
if (Blockly.blockRendering.Types.isLeftRoundedCorner(elem)) {
|
||||
this.outlinePath_ +=
|
||||
this.constants_.OUTSIDE_CORNERS.topLeft;
|
||||
} else if (Blockly.blockRendering.Types.isRightRoundedCorner(elem)) {
|
||||
this.outlinePath_ +=
|
||||
this.constants_.OUTSIDE_CORNERS.topRight;
|
||||
} else if (Blockly.blockRendering.Types.isPreviousConnection(elem)) {
|
||||
this.outlinePath_ += svgPaths.moveBy(topRow.xPos, this.info_.startY);
|
||||
for (let i = 0, elem; (elem = elements[i]); i++) {
|
||||
if (Types.isLeftRoundedCorner(elem)) {
|
||||
this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topLeft;
|
||||
} else if (Types.isRightRoundedCorner(elem)) {
|
||||
this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topRight;
|
||||
} else if (Types.isPreviousConnection(elem)) {
|
||||
this.outlinePath_ += elem.shape.pathLeft;
|
||||
} else if (Blockly.blockRendering.Types.isHat(elem)) {
|
||||
} else if (Types.isHat(elem)) {
|
||||
this.outlinePath_ += this.constants_.START_HAT.path;
|
||||
} else if (Blockly.blockRendering.Types.isSpacer(elem)) {
|
||||
this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('h', elem.width);
|
||||
} else if (Types.isSpacer(elem)) {
|
||||
this.outlinePath_ += svgPaths.lineOnAxis('h', elem.width);
|
||||
}
|
||||
// No branch for a square corner, because it's a no-op.
|
||||
}
|
||||
this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('v', topRow.height);
|
||||
this.outlinePath_ += svgPaths.lineOnAxis('v', topRow.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add steps for the jagged edge of a row on a collapsed block.
|
||||
* @param {!Blockly.blockRendering.Row} row The row to draw the side of.
|
||||
* @param {!Row} row The row to draw the side of.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawJaggedEdge_ = function(row) {
|
||||
var remainder =
|
||||
row.height - this.constants_.JAGGED_TEETH.height;
|
||||
this.outlinePath_ += this.constants_.JAGGED_TEETH.path +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', remainder);
|
||||
Drawer.prototype.drawJaggedEdge_ = function(row) {
|
||||
const remainder = row.height - this.constants_.JAGGED_TEETH.height;
|
||||
this.outlinePath_ +=
|
||||
this.constants_.JAGGED_TEETH.path + svgPaths.lineOnAxis('v', remainder);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add steps for an external value input, rendered as a notch in the side
|
||||
* of the block.
|
||||
* @param {!Blockly.blockRendering.Row} row The row that this input
|
||||
* belongs to.
|
||||
* @param {!Row} row The row that this input belongs to.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawValueInput_ = function(row) {
|
||||
var input = row.getLastInput();
|
||||
Drawer.prototype.drawValueInput_ = function(row) {
|
||||
const input = row.getLastInput();
|
||||
this.positionExternalValueConnection_(row);
|
||||
|
||||
var pathDown = (typeof input.shape.pathDown == "function") ?
|
||||
const pathDown = (typeof input.shape.pathDown == 'function') ?
|
||||
input.shape.pathDown(input.height) :
|
||||
input.shape.pathDown;
|
||||
|
||||
this.outlinePath_ +=
|
||||
Blockly.utils.svgPaths.lineOnAxis('H', input.xPos + input.width) +
|
||||
pathDown +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', row.height - input.connectionHeight);
|
||||
this.outlinePath_ += svgPaths.lineOnAxis('H', input.xPos + input.width) +
|
||||
pathDown + svgPaths.lineOnAxis('v', row.height - input.connectionHeight);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add steps for a statement input.
|
||||
* @param {!Blockly.blockRendering.Row} row The row that this input
|
||||
* belongs to.
|
||||
* @param {!Row} row The row that this input belongs to.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawStatementInput_ = function(row) {
|
||||
var input = row.getLastInput();
|
||||
Drawer.prototype.drawStatementInput_ = function(row) {
|
||||
const input = row.getLastInput();
|
||||
// Where to start drawing the notch, which is on the right side in LTR.
|
||||
var x = input.xPos + input.notchOffset + input.shape.width;
|
||||
const x = input.xPos + input.notchOffset + input.shape.width;
|
||||
|
||||
var innerTopLeftCorner =
|
||||
input.shape.pathRight +
|
||||
Blockly.utils.svgPaths.lineOnAxis('h',
|
||||
-(input.notchOffset - this.constants_.INSIDE_CORNERS.width)) +
|
||||
const innerTopLeftCorner = input.shape.pathRight +
|
||||
svgPaths.lineOnAxis(
|
||||
'h', -(input.notchOffset - this.constants_.INSIDE_CORNERS.width)) +
|
||||
this.constants_.INSIDE_CORNERS.pathTop;
|
||||
|
||||
var innerHeight =
|
||||
row.height - (2 * this.constants_.INSIDE_CORNERS.height);
|
||||
const innerHeight = row.height - (2 * this.constants_.INSIDE_CORNERS.height);
|
||||
|
||||
this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('H', x) +
|
||||
innerTopLeftCorner +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', innerHeight) +
|
||||
this.outlinePath_ += svgPaths.lineOnAxis('H', x) + innerTopLeftCorner +
|
||||
svgPaths.lineOnAxis('v', innerHeight) +
|
||||
this.constants_.INSIDE_CORNERS.pathBottom +
|
||||
Blockly.utils.svgPaths.lineOnAxis('H', row.xPos + row.width);
|
||||
svgPaths.lineOnAxis('H', row.xPos + row.width);
|
||||
|
||||
this.positionStatementInputConnection_(row);
|
||||
};
|
||||
@@ -215,13 +204,11 @@ Blockly.blockRendering.Drawer.prototype.drawStatementInput_ = function(row) {
|
||||
/**
|
||||
* Add steps for the right side of a row that does not have value or
|
||||
* statement input connections.
|
||||
* @param {!Blockly.blockRendering.Row} row The row to draw the
|
||||
* side of.
|
||||
* @param {!Row} row The row to draw the side of.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawRightSideRow_ = function(row) {
|
||||
this.outlinePath_ +=
|
||||
Blockly.utils.svgPaths.lineOnAxis('V', row.yPos + row.height);
|
||||
Drawer.prototype.drawRightSideRow_ = function(row) {
|
||||
this.outlinePath_ += svgPaths.lineOnAxis('V', row.yPos + row.height);
|
||||
};
|
||||
|
||||
|
||||
@@ -230,30 +217,30 @@ Blockly.blockRendering.Drawer.prototype.drawRightSideRow_ = function(row) {
|
||||
* for the next connection.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawBottom_ = function() {
|
||||
var bottomRow = this.info_.bottomRow;
|
||||
var elems = bottomRow.elements;
|
||||
Drawer.prototype.drawBottom_ = function() {
|
||||
const bottomRow = this.info_.bottomRow;
|
||||
const elems = bottomRow.elements;
|
||||
this.positionNextConnection_();
|
||||
|
||||
var rightCornerYOffset = 0;
|
||||
var outlinePath = '';
|
||||
for (var i = elems.length - 1, elem; (elem = elems[i]); i--) {
|
||||
if (Blockly.blockRendering.Types.isNextConnection(elem)) {
|
||||
let rightCornerYOffset = 0;
|
||||
let outlinePath = '';
|
||||
for (let i = elems.length - 1, elem; (elem = elems[i]); i--) {
|
||||
if (Types.isNextConnection(elem)) {
|
||||
outlinePath += elem.shape.pathRight;
|
||||
} else if (Blockly.blockRendering.Types.isLeftSquareCorner(elem)) {
|
||||
outlinePath += Blockly.utils.svgPaths.lineOnAxis('H', bottomRow.xPos);
|
||||
} else if (Blockly.blockRendering.Types.isLeftRoundedCorner(elem)) {
|
||||
} else if (Types.isLeftSquareCorner(elem)) {
|
||||
outlinePath += svgPaths.lineOnAxis('H', bottomRow.xPos);
|
||||
} else if (Types.isLeftRoundedCorner(elem)) {
|
||||
outlinePath += this.constants_.OUTSIDE_CORNERS.bottomLeft;
|
||||
} else if (Blockly.blockRendering.Types.isRightRoundedCorner(elem)) {
|
||||
} else if (Types.isRightRoundedCorner(elem)) {
|
||||
outlinePath += this.constants_.OUTSIDE_CORNERS.bottomRight;
|
||||
rightCornerYOffset = this.constants_.OUTSIDE_CORNERS.rightHeight;
|
||||
} else if (Blockly.blockRendering.Types.isSpacer(elem)) {
|
||||
outlinePath += Blockly.utils.svgPaths.lineOnAxis('h', elem.width * -1);
|
||||
} else if (Types.isSpacer(elem)) {
|
||||
outlinePath += svgPaths.lineOnAxis('h', elem.width * -1);
|
||||
}
|
||||
}
|
||||
|
||||
this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('V',
|
||||
bottomRow.baseline - rightCornerYOffset);
|
||||
this.outlinePath_ +=
|
||||
svgPaths.lineOnAxis('V', bottomRow.baseline - rightCornerYOffset);
|
||||
this.outlinePath_ += outlinePath;
|
||||
};
|
||||
|
||||
@@ -262,21 +249,19 @@ Blockly.blockRendering.Drawer.prototype.drawBottom_ = function() {
|
||||
* connection
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawLeft_ = function() {
|
||||
var outputConnection = this.info_.outputConnection;
|
||||
Drawer.prototype.drawLeft_ = function() {
|
||||
const outputConnection = this.info_.outputConnection;
|
||||
this.positionOutputConnection_();
|
||||
|
||||
if (outputConnection) {
|
||||
var tabBottom = outputConnection.connectionOffsetY +
|
||||
outputConnection.height;
|
||||
var pathUp = (typeof outputConnection.shape.pathUp == "function") ?
|
||||
const tabBottom =
|
||||
outputConnection.connectionOffsetY + outputConnection.height;
|
||||
const pathUp = (typeof outputConnection.shape.pathUp == 'function') ?
|
||||
outputConnection.shape.pathUp(outputConnection.height) :
|
||||
outputConnection.shape.pathUp;
|
||||
|
||||
// Draw a line up to the bottom of the tab.
|
||||
this.outlinePath_ +=
|
||||
Blockly.utils.svgPaths.lineOnAxis('V', tabBottom) +
|
||||
pathUp;
|
||||
this.outlinePath_ += svgPaths.lineOnAxis('V', tabBottom) + pathUp;
|
||||
}
|
||||
// Close off the path. This draws a vertical line up to the start of the
|
||||
// block's path, which may be either a rounded or a sharp corner.
|
||||
@@ -288,16 +273,15 @@ Blockly.blockRendering.Drawer.prototype.drawLeft_ = function() {
|
||||
* not depend on the outer path for placement.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawInternals_ = function() {
|
||||
for (var i = 0, row; (row = this.info_.rows[i]); i++) {
|
||||
for (var j = 0, elem; (elem = row.elements[j]); j++) {
|
||||
if (Blockly.blockRendering.Types.isInlineInput(elem)) {
|
||||
Drawer.prototype.drawInternals_ = function() {
|
||||
for (let i = 0, row; (row = this.info_.rows[i]); i++) {
|
||||
for (let j = 0, elem; (elem = row.elements[j]); j++) {
|
||||
if (Types.isInlineInput(elem)) {
|
||||
this.drawInlineInput_(
|
||||
/** @type {!Blockly.blockRendering.InlineInput} */ (elem));
|
||||
} else if (Blockly.blockRendering.Types.isIcon(elem) ||
|
||||
Blockly.blockRendering.Types.isField(elem)) {
|
||||
/** @type {!InlineInput} */ (elem));
|
||||
} else if (Types.isIcon(elem) || Types.isField(elem)) {
|
||||
this.layoutField_(
|
||||
/** @type {!Blockly.blockRendering.Field|!Blockly.blockRendering.Icon} */
|
||||
/** @type {!Field|!Icon} */
|
||||
(elem));
|
||||
}
|
||||
}
|
||||
@@ -306,20 +290,21 @@ Blockly.blockRendering.Drawer.prototype.drawInternals_ = function() {
|
||||
|
||||
/**
|
||||
* Push a field or icon's new position to its SVG root.
|
||||
* @param {!Blockly.blockRendering.Icon|!Blockly.blockRendering.Field} fieldInfo
|
||||
* @param {!Icon|!Field} fieldInfo
|
||||
* The rendering information for the field or icon.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.layoutField_ = function(fieldInfo) {
|
||||
if (Blockly.blockRendering.Types.isField(fieldInfo)) {
|
||||
var svgGroup = fieldInfo.field.getSvgRoot();
|
||||
} else if (Blockly.blockRendering.Types.isIcon(fieldInfo)) {
|
||||
var svgGroup = fieldInfo.icon.iconGroup_;
|
||||
Drawer.prototype.layoutField_ = function(fieldInfo) {
|
||||
let svgGroup;
|
||||
if (Types.isField(fieldInfo)) {
|
||||
svgGroup = fieldInfo.field.getSvgRoot();
|
||||
} else if (Types.isIcon(fieldInfo)) {
|
||||
svgGroup = fieldInfo.icon.iconGroup_;
|
||||
}
|
||||
|
||||
var yPos = fieldInfo.centerline - fieldInfo.height / 2;
|
||||
var xPos = fieldInfo.xPos;
|
||||
var scale = '';
|
||||
const yPos = fieldInfo.centerline - fieldInfo.height / 2;
|
||||
let xPos = fieldInfo.xPos;
|
||||
let scale = '';
|
||||
if (this.info_.RTL) {
|
||||
xPos = -(xPos + fieldInfo.width);
|
||||
if (fieldInfo.flipRtl) {
|
||||
@@ -327,7 +312,7 @@ Blockly.blockRendering.Drawer.prototype.layoutField_ = function(fieldInfo) {
|
||||
scale = 'scale(-1 1)';
|
||||
}
|
||||
}
|
||||
if (Blockly.blockRendering.Types.isIcon(fieldInfo)) {
|
||||
if (Types.isIcon(fieldInfo)) {
|
||||
svgGroup.setAttribute('display', 'block');
|
||||
svgGroup.setAttribute('transform', 'translate(' + xPos + ',' + yPos + ')');
|
||||
fieldInfo.icon.computeIconLocation();
|
||||
@@ -345,26 +330,24 @@ Blockly.blockRendering.Drawer.prototype.layoutField_ = function(fieldInfo) {
|
||||
|
||||
/**
|
||||
* Add steps for an inline input.
|
||||
* @param {!Blockly.blockRendering.InlineInput} input The information about the
|
||||
* @param {!InlineInput} input The information about the
|
||||
* input to render.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.drawInlineInput_ = function(input) {
|
||||
var width = input.width;
|
||||
var height = input.height;
|
||||
var yPos = input.centerline - height / 2;
|
||||
Drawer.prototype.drawInlineInput_ = function(input) {
|
||||
const width = input.width;
|
||||
const height = input.height;
|
||||
const yPos = input.centerline - height / 2;
|
||||
|
||||
var connectionTop = input.connectionOffsetY;
|
||||
var connectionBottom = input.connectionHeight + connectionTop;
|
||||
var connectionRight = input.xPos + input.connectionWidth;
|
||||
const connectionTop = input.connectionOffsetY;
|
||||
const connectionBottom = input.connectionHeight + connectionTop;
|
||||
const connectionRight = input.xPos + input.connectionWidth;
|
||||
|
||||
this.inlinePath_ += Blockly.utils.svgPaths.moveTo(connectionRight, yPos) +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', connectionTop) +
|
||||
input.shape.pathDown +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', height - connectionBottom) +
|
||||
Blockly.utils.svgPaths.lineOnAxis('h', width - input.connectionWidth) +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', -height) +
|
||||
'z';
|
||||
this.inlinePath_ += svgPaths.moveTo(connectionRight, yPos) +
|
||||
svgPaths.lineOnAxis('v', connectionTop) + input.shape.pathDown +
|
||||
svgPaths.lineOnAxis('v', height - connectionBottom) +
|
||||
svgPaths.lineOnAxis('h', width - input.connectionWidth) +
|
||||
svgPaths.lineOnAxis('v', -height) + 'z';
|
||||
|
||||
this.positionInlineInputConnection_(input);
|
||||
};
|
||||
@@ -373,21 +356,21 @@ Blockly.blockRendering.Drawer.prototype.drawInlineInput_ = function(input) {
|
||||
* Position the connection on an inline value input, taking into account
|
||||
* RTL and the small gap between the parent block and child block which lets the
|
||||
* parent block's dark path show through.
|
||||
* @param {Blockly.blockRendering.InlineInput} input The information about
|
||||
* @param {InlineInput} input The information about
|
||||
* the input that the connection is on.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.positionInlineInputConnection_ = function(input) {
|
||||
var yPos = input.centerline - input.height / 2;
|
||||
Drawer.prototype.positionInlineInputConnection_ = function(input) {
|
||||
const yPos = input.centerline - input.height / 2;
|
||||
// Move the connection.
|
||||
if (input.connectionModel) {
|
||||
// xPos already contains info about startX
|
||||
var connX = input.xPos + input.connectionWidth + input.connectionOffsetX;
|
||||
let connX = input.xPos + input.connectionWidth + input.connectionOffsetX;
|
||||
if (this.info_.RTL) {
|
||||
connX *= -1;
|
||||
}
|
||||
input.connectionModel.setOffsetInBlock(connX,
|
||||
yPos + input.connectionOffsetY);
|
||||
input.connectionModel.setOffsetInBlock(
|
||||
connX, yPos + input.connectionOffsetY);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -395,13 +378,13 @@ Blockly.blockRendering.Drawer.prototype.positionInlineInputConnection_ = functio
|
||||
* Position the connection on a statement input, taking into account
|
||||
* RTL and the small gap between the parent block and child block which lets the
|
||||
* parent block's dark path show through.
|
||||
* @param {!Blockly.blockRendering.Row} row The row that the connection is on.
|
||||
* @param {!Row} row The row that the connection is on.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.positionStatementInputConnection_ = function(row) {
|
||||
var input = row.getLastInput();
|
||||
Drawer.prototype.positionStatementInputConnection_ = function(row) {
|
||||
const input = row.getLastInput();
|
||||
if (input.connectionModel) {
|
||||
var connX = row.xPos + row.statementEdge + input.notchOffset;
|
||||
let connX = row.xPos + row.statementEdge + input.notchOffset;
|
||||
if (this.info_.RTL) {
|
||||
connX *= -1;
|
||||
}
|
||||
@@ -413,13 +396,13 @@ Blockly.blockRendering.Drawer.prototype.positionStatementInputConnection_ = func
|
||||
* Position the connection on an external value input, taking into account
|
||||
* RTL and the small gap between the parent block and child block which lets the
|
||||
* parent block's dark path show through.
|
||||
* @param {!Blockly.blockRendering.Row} row The row that the connection is on.
|
||||
* @param {!Row} row The row that the connection is on.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.positionExternalValueConnection_ = function(row) {
|
||||
var input = row.getLastInput();
|
||||
Drawer.prototype.positionExternalValueConnection_ = function(row) {
|
||||
const input = row.getLastInput();
|
||||
if (input.connectionModel) {
|
||||
var connX = row.xPos + row.width;
|
||||
let connX = row.xPos + row.width;
|
||||
if (this.info_.RTL) {
|
||||
connX *= -1;
|
||||
}
|
||||
@@ -431,11 +414,11 @@ Blockly.blockRendering.Drawer.prototype.positionExternalValueConnection_ = funct
|
||||
* Position the previous connection on a block.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.positionPreviousConnection_ = function() {
|
||||
var topRow = this.info_.topRow;
|
||||
Drawer.prototype.positionPreviousConnection_ = function() {
|
||||
const topRow = this.info_.topRow;
|
||||
if (topRow.connection) {
|
||||
var x = topRow.xPos + topRow.notchOffset;
|
||||
var connX = (this.info_.RTL ? -x : x);
|
||||
const x = topRow.xPos + topRow.notchOffset;
|
||||
const connX = (this.info_.RTL ? -x : x);
|
||||
topRow.connection.connectionModel.setOffsetInBlock(connX, 0);
|
||||
}
|
||||
};
|
||||
@@ -444,13 +427,13 @@ Blockly.blockRendering.Drawer.prototype.positionPreviousConnection_ = function()
|
||||
* Position the next connection on a block.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.positionNextConnection_ = function() {
|
||||
var bottomRow = this.info_.bottomRow;
|
||||
Drawer.prototype.positionNextConnection_ = function() {
|
||||
const bottomRow = this.info_.bottomRow;
|
||||
|
||||
if (bottomRow.connection) {
|
||||
var connInfo = bottomRow.connection;
|
||||
var x = connInfo.xPos; // Already contains info about startX.
|
||||
var connX = (this.info_.RTL ? -x : x);
|
||||
const connInfo = bottomRow.connection;
|
||||
const x = connInfo.xPos; // Already contains info about startX.
|
||||
const connX = (this.info_.RTL ? -x : x);
|
||||
connInfo.connectionModel.setOffsetInBlock(connX, bottomRow.baseline);
|
||||
}
|
||||
};
|
||||
@@ -459,11 +442,13 @@ Blockly.blockRendering.Drawer.prototype.positionNextConnection_ = function() {
|
||||
* Position the output connection on a block.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.Drawer.prototype.positionOutputConnection_ = function() {
|
||||
Drawer.prototype.positionOutputConnection_ = function() {
|
||||
if (this.info_.outputConnection) {
|
||||
var x = this.info_.startX + this.info_.outputConnection.connectionOffsetX;
|
||||
var connX = this.info_.RTL ? -x : x;
|
||||
this.block_.outputConnection.setOffsetInBlock(connX,
|
||||
this.info_.outputConnection.connectionOffsetY);
|
||||
const x = this.info_.startX + this.info_.outputConnection.connectionOffsetX;
|
||||
const connX = this.info_.RTL ? -x : x;
|
||||
this.block_.outputConnection.setOffsetInBlock(
|
||||
connX, this.info_.outputConnection.connectionOffsetY);
|
||||
}
|
||||
};
|
||||
|
||||
exports = Drawer;
|
||||
|
||||
@@ -16,54 +16,55 @@
|
||||
* @name Blockly.utils.style
|
||||
* @namespace
|
||||
*/
|
||||
goog.provide('Blockly.utils.style');
|
||||
goog.module('Blockly.utils.style');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.Size');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
const Size = goog.require('Blockly.utils.Size');
|
||||
|
||||
|
||||
/**
|
||||
* Gets the height and width of an element.
|
||||
* Similar to Closure's goog.style.getSize
|
||||
* @param {!Element} element Element to get size of.
|
||||
* @return {!Blockly.utils.Size} Object with width/height properties.
|
||||
* @return {!Size} Object with width/height properties.
|
||||
*/
|
||||
Blockly.utils.style.getSize = function(element) {
|
||||
if (Blockly.utils.style.getStyle_(element, 'display') != 'none') {
|
||||
return Blockly.utils.style.getSizeWithDisplay_(element);
|
||||
function getSize(element) {
|
||||
if (getStyle(element, 'display') != 'none') {
|
||||
return getSizeWithDisplay(element);
|
||||
}
|
||||
|
||||
// Evaluate size with a temporary element.
|
||||
var style = element.style;
|
||||
var originalDisplay = style.display;
|
||||
var originalVisibility = style.visibility;
|
||||
var originalPosition = style.position;
|
||||
const style = element.style;
|
||||
const originalDisplay = style.display;
|
||||
const originalVisibility = style.visibility;
|
||||
const originalPosition = style.position;
|
||||
|
||||
style.visibility = 'hidden';
|
||||
style.position = 'absolute';
|
||||
style.display = 'inline';
|
||||
|
||||
var offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth;
|
||||
var offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight;
|
||||
const offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth;
|
||||
const offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight;
|
||||
|
||||
style.display = originalDisplay;
|
||||
style.position = originalPosition;
|
||||
style.visibility = originalVisibility;
|
||||
|
||||
return new Blockly.utils.Size(offsetWidth, offsetHeight);
|
||||
};
|
||||
return new Size(offsetWidth, offsetHeight);
|
||||
}
|
||||
exports.getSize = getSize;
|
||||
|
||||
/**
|
||||
* Gets the height and width of an element when the display is not none.
|
||||
* @param {!Element} element Element to get size of.
|
||||
* @return {!Blockly.utils.Size} Object with width/height properties.
|
||||
* @private
|
||||
* @return {!Size} Object with width/height properties.
|
||||
*/
|
||||
Blockly.utils.style.getSizeWithDisplay_ = function(element) {
|
||||
var offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth;
|
||||
var offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight;
|
||||
return new Blockly.utils.Size(offsetWidth, offsetHeight);
|
||||
};
|
||||
function getSizeWithDisplay(element) {
|
||||
const offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth;
|
||||
const offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight;
|
||||
return new Size(offsetWidth, offsetHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-browser pseudo get computed style. It returns the computed style where
|
||||
@@ -77,13 +78,11 @@ Blockly.utils.style.getSizeWithDisplay_ = function(element) {
|
||||
* @param {!Element} element Element to get style of.
|
||||
* @param {string} style Property to get (must be camelCase, not CSS-style).
|
||||
* @return {string} Style value.
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.style.getStyle_ = function(element, style) {
|
||||
return Blockly.utils.style.getComputedStyle(element, style) ||
|
||||
Blockly.utils.style.getCascadedStyle(element, style) ||
|
||||
function getStyle(element, style) {
|
||||
return getComputedStyle(element, style) || getCascadedStyle(element, style) ||
|
||||
(element.style && element.style[style]);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a computed style value of a node. It returns empty string if the
|
||||
@@ -97,9 +96,9 @@ Blockly.utils.style.getStyle_ = function(element, style) {
|
||||
* @param {string} property Property to get (camel-case).
|
||||
* @return {string} Style value.
|
||||
*/
|
||||
Blockly.utils.style.getComputedStyle = function(element, property) {
|
||||
function getComputedStyle(element, property) {
|
||||
if (document.defaultView && document.defaultView.getComputedStyle) {
|
||||
var styles = document.defaultView.getComputedStyle(element, null);
|
||||
const styles = document.defaultView.getComputedStyle(element, null);
|
||||
if (styles) {
|
||||
// element.style[..] is undefined for browser specific styles
|
||||
// as 'filter'.
|
||||
@@ -108,7 +107,8 @@ Blockly.utils.style.getComputedStyle = function(element, property) {
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
}
|
||||
exports.getComputedStyle = getComputedStyle;
|
||||
|
||||
/**
|
||||
* Gets the cascaded style value of a node, or null if the value cannot be
|
||||
@@ -120,45 +120,48 @@ Blockly.utils.style.getComputedStyle = function(element, property) {
|
||||
* @param {string} style Property to get (camel-case).
|
||||
* @return {string} Style value.
|
||||
*/
|
||||
Blockly.utils.style.getCascadedStyle = function(element, style) {
|
||||
function getCascadedStyle(element, style) {
|
||||
return /** @type {string} */ (
|
||||
element.currentStyle ? element.currentStyle[style] : null);
|
||||
};
|
||||
}
|
||||
exports.getCascadedStyle = getCascadedStyle;
|
||||
|
||||
/**
|
||||
* Returns a Coordinate object relative to the top-left of the HTML document.
|
||||
* Similar to Closure's goog.style.getPageOffset
|
||||
* @param {!Element} el Element to get the page offset for.
|
||||
* @return {!Blockly.utils.Coordinate} The page offset.
|
||||
* @return {!Coordinate} The page offset.
|
||||
*/
|
||||
Blockly.utils.style.getPageOffset = function(el) {
|
||||
var pos = new Blockly.utils.Coordinate(0, 0);
|
||||
var box = el.getBoundingClientRect();
|
||||
var documentElement = document.documentElement;
|
||||
function getPageOffset(el) {
|
||||
const pos = new Coordinate(0, 0);
|
||||
const box = el.getBoundingClientRect();
|
||||
const documentElement = document.documentElement;
|
||||
// Must add the scroll coordinates in to get the absolute page offset
|
||||
// of element since getBoundingClientRect returns relative coordinates to
|
||||
// the viewport.
|
||||
var scrollCoord = new Blockly.utils.Coordinate(
|
||||
const scrollCoord = new Coordinate(
|
||||
window.pageXOffset || documentElement.scrollLeft,
|
||||
window.pageYOffset || documentElement.scrollTop);
|
||||
pos.x = box.left + scrollCoord.x;
|
||||
pos.y = box.top + scrollCoord.y;
|
||||
|
||||
return pos;
|
||||
};
|
||||
}
|
||||
exports.getPageOffset = getPageOffset;
|
||||
|
||||
/**
|
||||
* Calculates the viewport coordinates relative to the document.
|
||||
* Similar to Closure's goog.style.getViewportPageOffset
|
||||
* @return {!Blockly.utils.Coordinate} The page offset of the viewport.
|
||||
* @return {!Coordinate} The page offset of the viewport.
|
||||
*/
|
||||
Blockly.utils.style.getViewportPageOffset = function() {
|
||||
var body = document.body;
|
||||
var documentElement = document.documentElement;
|
||||
var scrollLeft = body.scrollLeft || documentElement.scrollLeft;
|
||||
var scrollTop = body.scrollTop || documentElement.scrollTop;
|
||||
return new Blockly.utils.Coordinate(scrollLeft, scrollTop);
|
||||
};
|
||||
function getViewportPageOffset() {
|
||||
const body = document.body;
|
||||
const documentElement = document.documentElement;
|
||||
const scrollLeft = body.scrollLeft || documentElement.scrollLeft;
|
||||
const scrollTop = body.scrollTop || documentElement.scrollTop;
|
||||
return new Coordinate(scrollLeft, scrollTop);
|
||||
}
|
||||
exports.getViewportPageOffset = getViewportPageOffset;
|
||||
|
||||
/**
|
||||
* Shows or hides an element from the page. Hiding the element is done by
|
||||
@@ -172,9 +175,10 @@ Blockly.utils.style.getViewportPageOffset = function() {
|
||||
* @param {*} isShown True to render the element in its default style,
|
||||
* false to disable rendering the element.
|
||||
*/
|
||||
Blockly.utils.style.setElementShown = function(el, isShown) {
|
||||
function setElementShown(el, isShown) {
|
||||
el.style.display = isShown ? '' : 'none';
|
||||
};
|
||||
}
|
||||
exports.setElementShown = setElementShown;
|
||||
|
||||
/**
|
||||
* Returns true if the element is using right to left (RTL) direction.
|
||||
@@ -183,9 +187,10 @@ Blockly.utils.style.setElementShown = function(el, isShown) {
|
||||
* @param {!Element} el The element to test.
|
||||
* @return {boolean} True for right to left, false for left to right.
|
||||
*/
|
||||
Blockly.utils.style.isRightToLeft = function(el) {
|
||||
return 'rtl' == Blockly.utils.style.getStyle_(el, 'direction');
|
||||
};
|
||||
function isRightToLeft(el) {
|
||||
return 'rtl' == getStyle(el, 'direction');
|
||||
}
|
||||
exports.isRightToLeft = isRightToLeft;
|
||||
|
||||
/**
|
||||
* Gets the computed border widths (on all sides) in pixels
|
||||
@@ -193,11 +198,11 @@ Blockly.utils.style.isRightToLeft = function(el) {
|
||||
* @param {!Element} element The element to get the border widths for.
|
||||
* @return {!Object} The computed border widths.
|
||||
*/
|
||||
Blockly.utils.style.getBorderBox = function(element) {
|
||||
var left = Blockly.utils.style.getComputedStyle(element, 'borderLeftWidth');
|
||||
var right = Blockly.utils.style.getComputedStyle(element, 'borderRightWidth');
|
||||
var top = Blockly.utils.style.getComputedStyle(element, 'borderTopWidth');
|
||||
var bottom = Blockly.utils.style.getComputedStyle(element, 'borderBottomWidth');
|
||||
function getBorderBox(element) {
|
||||
const left = getComputedStyle(element, 'borderLeftWidth');
|
||||
const right = getComputedStyle(element, 'borderRightWidth');
|
||||
const top = getComputedStyle(element, 'borderTopWidth');
|
||||
const bottom = getComputedStyle(element, 'borderBottomWidth');
|
||||
|
||||
return {
|
||||
top: parseFloat(top),
|
||||
@@ -205,7 +210,8 @@ Blockly.utils.style.getBorderBox = function(element) {
|
||||
bottom: parseFloat(bottom),
|
||||
left: parseFloat(left)
|
||||
};
|
||||
};
|
||||
}
|
||||
exports.getBorderBox = getBorderBox;
|
||||
|
||||
/**
|
||||
* Changes the scroll position of `container` with the minimum amount so
|
||||
@@ -220,14 +226,12 @@ Blockly.utils.style.getBorderBox = function(element) {
|
||||
* @param {boolean=} opt_center Whether to center the element in the container.
|
||||
* Defaults to false.
|
||||
*/
|
||||
Blockly.utils.style.scrollIntoContainerView = function(
|
||||
element, container, opt_center) {
|
||||
var offset =
|
||||
Blockly.utils.style.getContainerOffsetToScrollInto(element,
|
||||
container, opt_center);
|
||||
function scrollIntoContainerView(element, container, opt_center) {
|
||||
const offset = getContainerOffsetToScrollInto(element, container, opt_center);
|
||||
container.scrollLeft = offset.x;
|
||||
container.scrollTop = offset.y;
|
||||
};
|
||||
}
|
||||
exports.scrollIntoContainerView = scrollIntoContainerView;
|
||||
|
||||
/**
|
||||
* Calculate the scroll position of `container` with the minimum amount so
|
||||
@@ -241,27 +245,26 @@ Blockly.utils.style.scrollIntoContainerView = function(
|
||||
* document scroll element will be used.
|
||||
* @param {boolean=} opt_center Whether to center the element in the container.
|
||||
* Defaults to false.
|
||||
* @return {!Blockly.utils.Coordinate} The new scroll position of the container,
|
||||
* @return {!Coordinate} The new scroll position of the container,
|
||||
* in form of goog.math.Coordinate(scrollLeft, scrollTop).
|
||||
*/
|
||||
Blockly.utils.style.getContainerOffsetToScrollInto = function(
|
||||
element, container, opt_center) {
|
||||
function getContainerOffsetToScrollInto(element, container, opt_center) {
|
||||
// Absolute position of the element's border's top left corner.
|
||||
var elementPos = Blockly.utils.style.getPageOffset(element);
|
||||
const elementPos = getPageOffset(element);
|
||||
// Absolute position of the container's border's top left corner.
|
||||
var containerPos = Blockly.utils.style.getPageOffset(container);
|
||||
var containerBorder = Blockly.utils.style.getBorderBox(container);
|
||||
const containerPos = getPageOffset(container);
|
||||
const containerBorder = getBorderBox(container);
|
||||
// Relative pos. of the element's border box to the container's content box.
|
||||
var relX = elementPos.x - containerPos.x - containerBorder.left;
|
||||
var relY = elementPos.y - containerPos.y - containerBorder.top;
|
||||
const relX = elementPos.x - containerPos.x - containerBorder.left;
|
||||
const relY = elementPos.y - containerPos.y - containerBorder.top;
|
||||
// How much the element can move in the container, i.e. the difference between
|
||||
// the element's bottom-right-most and top-left-most position where it's
|
||||
// fully visible.
|
||||
var elementSize = Blockly.utils.style.getSizeWithDisplay_(element);
|
||||
var spaceX = container.clientWidth - elementSize.width;
|
||||
var spaceY = container.clientHeight - elementSize.height;
|
||||
var scrollLeft = container.scrollLeft;
|
||||
var scrollTop = container.scrollTop;
|
||||
const elementSize = getSizeWithDisplay(element);
|
||||
const spaceX = container.clientWidth - elementSize.width;
|
||||
const spaceY = container.clientHeight - elementSize.height;
|
||||
let scrollLeft = container.scrollLeft;
|
||||
let scrollTop = container.scrollTop;
|
||||
if (opt_center) {
|
||||
// All browsers round non-integer scroll positions down.
|
||||
scrollLeft += relX - spaceX / 2;
|
||||
@@ -277,5 +280,6 @@ Blockly.utils.style.getContainerOffsetToScrollInto = function(
|
||||
scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0));
|
||||
scrollTop += Math.min(relY, Math.max(relY - spaceY, 0));
|
||||
}
|
||||
return new Blockly.utils.Coordinate(scrollLeft, scrollTop);
|
||||
};
|
||||
return new Coordinate(scrollLeft, scrollTop);
|
||||
}
|
||||
exports.getContainerOffsetToScrollInto = getContainerOffsetToScrollInto;
|
||||
|
||||
@@ -16,12 +16,12 @@ goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentMana
|
||||
goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.utils.global']);
|
||||
goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.IBubble', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']);
|
||||
goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry']);
|
||||
goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants']);
|
||||
goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes']);
|
||||
goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']);
|
||||
@@ -73,31 +73,34 @@ goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDr
|
||||
goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes']);
|
||||
goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.ComponentManager', 'Blockly.Events', 'Blockly.blockAnimations', 'Blockly.connectionTypes', 'Blockly.constants'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/interfaces/i_accessibility.js', ['Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible'], []);
|
||||
goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], ['Blockly.IComponent']);
|
||||
goog.addDependency('../../core/interfaces/i_ast_node_location.js', ['Blockly.IASTNodeLocation'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_ast_node_location_svg.js', ['Blockly.IASTNodeLocationSvg'], ['Blockly.IASTNodeLocation'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_ast_node_location_with_block.js', ['Blockly.IASTNodeLocationWithBlock'], ['Blockly.IASTNodeLocation'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], ['Blockly.IComponent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], ['Blockly.IContextMenu', 'Blockly.IDraggable']);
|
||||
goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], ['Blockly.IContextMenu', 'Blockly.IDraggable'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], []);
|
||||
goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], []);
|
||||
goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], []);
|
||||
goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], []);
|
||||
goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget']);
|
||||
goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent']);
|
||||
goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], ['Blockly.IDeletable']);
|
||||
goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], []);
|
||||
goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], ['Blockly.IDeletable'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], ['Blockly.IRegistrable'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_keyboard_accessible.js', ['Blockly.IKeyboardAccessible'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], []);
|
||||
goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], []);
|
||||
goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IComponent']);
|
||||
goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IComponent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], []);
|
||||
goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], []);
|
||||
goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], []);
|
||||
goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], []);
|
||||
goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], []);
|
||||
goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], ['Blockly.IRegistrable'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem', 'Blockly.ISelectableToolboxItem', 'Blockly.IToolboxItem'], []);
|
||||
goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Coordinate'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode']);
|
||||
goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object']);
|
||||
@@ -116,7 +119,7 @@ goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnec
|
||||
goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry']);
|
||||
goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/renderers/common/debugger.js', ['Blockly.blockRendering.Debug'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']);
|
||||
goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], []);
|
||||
goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes']);
|
||||
goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
@@ -183,7 +186,7 @@ goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], [], {
|
||||
goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], []);
|
||||
goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], []);
|
||||
goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size']);
|
||||
goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], []);
|
||||
goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.constants']);
|
||||
|
||||
Reference in New Issue
Block a user