mirror of
https://github.com/google/blockly.git
synced 2026-01-09 10:00:09 +01:00
Merge branch 'goog_module' into flyout_button
This commit is contained in:
@@ -10,61 +10,63 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.BlockDragger');
|
||||
goog.module('Blockly.BlockDragger');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.blockAnimations');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.constants');
|
||||
goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IBlockDragger = goog.require('Blockly.IBlockDragger');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IDragTarget = goog.requireType('Blockly.IDragTarget');
|
||||
const InsertionMarkerManager = goog.require('Blockly.InsertionMarkerManager');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const blockAnimation = goog.require('Blockly.blockAnimations');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const events = goog.require('Blockly.Events');
|
||||
const registry = goog.require('Blockly.registry');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.BlockDrag');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.BlockMove');
|
||||
goog.require('Blockly.IBlockDragger');
|
||||
goog.require('Blockly.InsertionMarkerManager');
|
||||
goog.require('Blockly.registry');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.dom');
|
||||
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.IDragTarget');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a block dragger. It moves blocks around the workspace when they
|
||||
* are being dragged by a mouse or touch.
|
||||
* @param {!Blockly.BlockSvg} block The block to drag.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace to drag on.
|
||||
* @param {!BlockSvg} block The block to drag.
|
||||
* @param {!WorkspaceSvg} workspace The workspace to drag on.
|
||||
* @constructor
|
||||
* @implements {Blockly.IBlockDragger}
|
||||
* @implements {IBlockDragger}
|
||||
*/
|
||||
Blockly.BlockDragger = function(block, workspace) {
|
||||
const BlockDragger = function(block, workspace) {
|
||||
/**
|
||||
* The top block in the stack that is being dragged.
|
||||
* @type {!Blockly.BlockSvg}
|
||||
* @type {!BlockSvg}
|
||||
* @protected
|
||||
*/
|
||||
this.draggingBlock_ = block;
|
||||
|
||||
/**
|
||||
* The workspace on which the block is being dragged.
|
||||
* @type {!Blockly.WorkspaceSvg}
|
||||
* @type {!WorkspaceSvg}
|
||||
* @protected
|
||||
*/
|
||||
this.workspace_ = workspace;
|
||||
|
||||
/**
|
||||
* Object that keeps track of connections on dragged blocks.
|
||||
* @type {!Blockly.InsertionMarkerManager}
|
||||
* @type {!InsertionMarkerManager}
|
||||
* @protected
|
||||
*/
|
||||
this.draggedConnectionManager_ =
|
||||
new Blockly.InsertionMarkerManager(this.draggingBlock_);
|
||||
new InsertionMarkerManager(this.draggingBlock_);
|
||||
|
||||
/**
|
||||
* Which drag area the mouse pointer is over, if any.
|
||||
* @type {?Blockly.IDragTarget}
|
||||
* @type {?IDragTarget}
|
||||
* @private
|
||||
*/
|
||||
this.dragTarget_ = null;
|
||||
@@ -79,7 +81,7 @@ Blockly.BlockDragger = function(block, workspace) {
|
||||
/**
|
||||
* The location of the top left corner of the dragging block at the beginning
|
||||
* of the drag in workspace coordinates.
|
||||
* @type {!Blockly.utils.Coordinate}
|
||||
* @type {!Coordinate}
|
||||
* @protected
|
||||
*/
|
||||
this.startXY_ = this.draggingBlock_.getRelativeToSurfaceXY();
|
||||
@@ -91,14 +93,14 @@ Blockly.BlockDragger = function(block, workspace) {
|
||||
* @type {Array<!Object>}
|
||||
* @protected
|
||||
*/
|
||||
this.dragIconData_ = Blockly.BlockDragger.initIconData_(block);
|
||||
this.dragIconData_ = initIconData(block);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sever all links from this object.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.dispose = function() {
|
||||
BlockDragger.prototype.dispose = function() {
|
||||
this.dragIconData_.length = 0;
|
||||
|
||||
if (this.draggedConnectionManager_) {
|
||||
@@ -110,19 +112,19 @@ Blockly.BlockDragger.prototype.dispose = function() {
|
||||
* Make a list of all of the icons (comment, warning, and mutator) that are
|
||||
* on this block and its descendants. Moving an icon moves the bubble that
|
||||
* extends from it if that bubble is open.
|
||||
* @param {!Blockly.BlockSvg} block The root block that is being dragged.
|
||||
* @param {!BlockSvg} block The root block that is being dragged.
|
||||
* @return {!Array<!Object>} The list of all icons and their locations.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockDragger.initIconData_ = function(block) {
|
||||
const initIconData = function(block) {
|
||||
// Build a list of icons that need to be moved and where they started.
|
||||
var dragIconData = [];
|
||||
var descendants = block.getDescendants(false);
|
||||
for (var i = 0, descendant; (descendant = descendants[i]); i++) {
|
||||
var icons = descendant.getIcons();
|
||||
for (var j = 0; j < icons.length; j++) {
|
||||
var data = {
|
||||
// Blockly.utils.Coordinate with x and y properties (workspace
|
||||
const dragIconData = [];
|
||||
const descendants = block.getDescendants(false);
|
||||
|
||||
for (let i = 0, descendant; (descendant = descendants[i]); i++) {
|
||||
const icons = descendant.getIcons();
|
||||
for (let j = 0; j < icons.length; j++) {
|
||||
const data = {
|
||||
// Coordinate with x and y properties (workspace
|
||||
// coordinates).
|
||||
location: icons[j].getIconLocation(),
|
||||
// Blockly.Icon
|
||||
@@ -136,16 +138,15 @@ Blockly.BlockDragger.initIconData_ = function(block) {
|
||||
|
||||
/**
|
||||
* Start dragging a block. This includes moving it to the drag surface.
|
||||
* @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.
|
||||
* @param {boolean} healStack Whether or not to heal the stack after
|
||||
* disconnecting.
|
||||
* @public
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.startDrag = function(
|
||||
currentDragDeltaXY, healStack) {
|
||||
if (!Blockly.Events.getGroup()) {
|
||||
Blockly.Events.setGroup(true);
|
||||
BlockDragger.prototype.startDrag = function(currentDragDeltaXY, healStack) {
|
||||
if (!events.getGroup()) {
|
||||
events.setGroup(true);
|
||||
}
|
||||
this.fireDragStartEvent_();
|
||||
|
||||
@@ -159,9 +160,9 @@ Blockly.BlockDragger.prototype.startDrag = function(
|
||||
|
||||
// During a drag there may be a lot of rerenders, but not field changes.
|
||||
// Turn the cache on so we don't do spurious remeasures during the drag.
|
||||
Blockly.utils.dom.startTextWidthCache();
|
||||
dom.startTextWidthCache();
|
||||
this.workspace_.setResizesEnabled(false);
|
||||
Blockly.blockAnimations.disconnectUiStop();
|
||||
blockAnimation.disconnectUiStop();
|
||||
|
||||
if (this.shouldDisconnect_(healStack)) {
|
||||
this.disconnectBlock_(healStack, currentDragDeltaXY);
|
||||
@@ -180,9 +181,9 @@ Blockly.BlockDragger.prototype.startDrag = function(
|
||||
* @return {boolean} True to disconnect the block, false otherwise.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.shouldDisconnect_ = function(healStack) {
|
||||
BlockDragger.prototype.shouldDisconnect_ = function(healStack) {
|
||||
return !!(
|
||||
this.draggingBlock_.getParent() ||
|
||||
this.draggingBlock_.getParent() ||
|
||||
(healStack && this.draggingBlock_.nextConnection &&
|
||||
this.draggingBlock_.nextConnection.targetBlock()));
|
||||
};
|
||||
@@ -191,18 +192,18 @@ Blockly.BlockDragger.prototype.shouldDisconnect_ = function(healStack) {
|
||||
* Disconnects the block and moves it to a new location.
|
||||
* @param {boolean} healStack Whether or not to heal the stack after
|
||||
* disconnecting.
|
||||
* @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.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.disconnectBlock_ = function(
|
||||
BlockDragger.prototype.disconnectBlock_ = function(
|
||||
healStack, currentDragDeltaXY) {
|
||||
this.draggingBlock_.unplug(healStack);
|
||||
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
|
||||
const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
const newLoc = Coordinate.sum(this.startXY_, delta);
|
||||
|
||||
this.draggingBlock_.translate(newLoc.x, newLoc.y);
|
||||
Blockly.blockAnimations.disconnectUiEffect(this.draggingBlock_);
|
||||
blockAnimation.disconnectUiEffect(this.draggingBlock_);
|
||||
this.draggedConnectionManager_.updateAvailableConnections();
|
||||
};
|
||||
|
||||
@@ -210,31 +211,31 @@ Blockly.BlockDragger.prototype.disconnectBlock_ = function(
|
||||
* Fire a UI event at the start of a block drag.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.fireDragStartEvent_ = function() {
|
||||
var event = new (Blockly.Events.get(Blockly.Events.BLOCK_DRAG))(
|
||||
BlockDragger.prototype.fireDragStartEvent_ = function() {
|
||||
const event = new (events.get(events.BLOCK_DRAG))(
|
||||
this.draggingBlock_, true, this.draggingBlock_.getDescendants(false));
|
||||
Blockly.Events.fire(event);
|
||||
events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a step of block 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.
|
||||
* @public
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.drag = function(e, currentDragDeltaXY) {
|
||||
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
|
||||
BlockDragger.prototype.drag = function(e, currentDragDeltaXY) {
|
||||
const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
const newLoc = Coordinate.sum(this.startXY_, delta);
|
||||
this.draggingBlock_.moveDuringDrag(newLoc);
|
||||
this.dragIcons_(delta);
|
||||
|
||||
var oldDragTarget = this.dragTarget_;
|
||||
const oldDragTarget = this.dragTarget_;
|
||||
this.dragTarget_ = this.workspace_.getDragTarget(e);
|
||||
|
||||
this.draggedConnectionManager_.update(delta, this.dragTarget_);
|
||||
var oldWouldDeleteBlock = this.wouldDeleteBlock_;
|
||||
const oldWouldDeleteBlock = this.wouldDeleteBlock_;
|
||||
this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock();
|
||||
if (oldWouldDeleteBlock != this.wouldDeleteBlock_) {
|
||||
// Prevent unnecessary add/remove class calls.
|
||||
@@ -253,26 +254,26 @@ Blockly.BlockDragger.prototype.drag = function(e, currentDragDeltaXY) {
|
||||
/**
|
||||
* Finish a block drag and put the block 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.
|
||||
* @public
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) {
|
||||
BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) {
|
||||
// Make sure internal state is fresh.
|
||||
this.drag(e, currentDragDeltaXY);
|
||||
this.dragIconData_ = [];
|
||||
this.fireDragEndEvent_();
|
||||
|
||||
Blockly.utils.dom.stopTextWidthCache();
|
||||
dom.stopTextWidthCache();
|
||||
|
||||
Blockly.blockAnimations.disconnectUiStop();
|
||||
blockAnimation.disconnectUiStop();
|
||||
|
||||
var preventMove = !!this.dragTarget_ &&
|
||||
const preventMove = !!this.dragTarget_ &&
|
||||
this.dragTarget_.shouldPreventMove(this.draggingBlock_);
|
||||
if (preventMove) {
|
||||
var newLoc = this.startXY_;
|
||||
} else {
|
||||
var newValues = this.getNewLocationAfterDrag_(currentDragDeltaXY);
|
||||
const newValues = this.getNewLocationAfterDrag_(currentDragDeltaXY);
|
||||
var delta = newValues.delta;
|
||||
var newLoc = newValues.newLocation;
|
||||
}
|
||||
@@ -282,7 +283,7 @@ Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) {
|
||||
this.dragTarget_.onDrop(this.draggingBlock_);
|
||||
}
|
||||
|
||||
var deleted = this.maybeDeleteBlock_();
|
||||
const deleted = this.maybeDeleteBlock_();
|
||||
if (!deleted) {
|
||||
// These are expensive and don't need to be done if we're deleting.
|
||||
this.draggingBlock_.setDragging(false);
|
||||
@@ -299,25 +300,23 @@ Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) {
|
||||
}
|
||||
this.workspace_.setResizesEnabled(true);
|
||||
|
||||
Blockly.Events.setGroup(false);
|
||||
events.setGroup(false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the drag delta and new location values after a block is dragged.
|
||||
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* @param {!Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* moved from the start of the drag, in pixel units.
|
||||
* @return {{delta: !Blockly.utils.Coordinate, newLocation:
|
||||
* !Blockly.utils.Coordinate}} New location after drag. delta is in
|
||||
* @return {{delta: !Coordinate, newLocation:
|
||||
* !Coordinate}} New location after drag. delta is in
|
||||
* workspace units. newLocation is the new coordinate where the block should
|
||||
* end up.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.getNewLocationAfterDrag_ = function(
|
||||
currentDragDeltaXY) {
|
||||
var newValues = {};
|
||||
BlockDragger.prototype.getNewLocationAfterDrag_ = function(currentDragDeltaXY) {
|
||||
const newValues = {};
|
||||
newValues.delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
newValues.newLocation =
|
||||
Blockly.utils.Coordinate.sum(this.startXY_, newValues.delta);
|
||||
newValues.newLocation = Coordinate.sum(this.startXY_, newValues.delta);
|
||||
return newValues;
|
||||
};
|
||||
|
||||
@@ -328,7 +327,7 @@ Blockly.BlockDragger.prototype.getNewLocationAfterDrag_ = function(
|
||||
* @return {boolean} True if the block was deleted.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() {
|
||||
BlockDragger.prototype.maybeDeleteBlock_ = function() {
|
||||
if (this.wouldDeleteBlock_) {
|
||||
// Fire a move event, so we know where to go back to for an undo.
|
||||
this.fireMoveEvent_();
|
||||
@@ -341,11 +340,11 @@ Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() {
|
||||
|
||||
/**
|
||||
* Updates the necessary information to place a block at a certain location.
|
||||
* @param {!Blockly.utils.Coordinate} delta The change in location from where
|
||||
* @param {!Coordinate} delta The change in location from where
|
||||
* the block started the drag to where it ended the drag.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.updateBlockAfterMove_ = function(delta) {
|
||||
BlockDragger.prototype.updateBlockAfterMove_ = function(delta) {
|
||||
this.draggingBlock_.moveConnections(delta.x, delta.y);
|
||||
this.fireMoveEvent_();
|
||||
if (this.draggedConnectionManager_.wouldConnectBlock()) {
|
||||
@@ -361,10 +360,10 @@ Blockly.BlockDragger.prototype.updateBlockAfterMove_ = function(delta) {
|
||||
* Fire a UI event at the end of a block drag.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.fireDragEndEvent_ = function() {
|
||||
var event = new (Blockly.Events.get(Blockly.Events.BLOCK_DRAG))(
|
||||
BlockDragger.prototype.fireDragEndEvent_ = function() {
|
||||
const event = new (events.get(events.BLOCK_DRAG))(
|
||||
this.draggingBlock_, false, this.draggingBlock_.getDescendants(false));
|
||||
Blockly.Events.fire(event);
|
||||
events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -374,12 +373,12 @@ Blockly.BlockDragger.prototype.fireDragEndEvent_ = function() {
|
||||
* @param {boolean} isEnd True if we are at the end of a drag, false otherwise.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.updateToolboxStyle_ = function(isEnd) {
|
||||
var toolbox = this.workspace_.getToolbox();
|
||||
BlockDragger.prototype.updateToolboxStyle_ = function(isEnd) {
|
||||
const toolbox = this.workspace_.getToolbox();
|
||||
|
||||
if (toolbox) {
|
||||
var style = this.draggingBlock_.isDeletable() ? 'blocklyToolboxDelete' :
|
||||
'blocklyToolboxGrab';
|
||||
const style = this.draggingBlock_.isDeletable() ? 'blocklyToolboxDelete' :
|
||||
'blocklyToolboxGrab';
|
||||
|
||||
if (isEnd && typeof toolbox.removeStyle == 'function') {
|
||||
toolbox.removeStyle(style);
|
||||
@@ -394,12 +393,11 @@ Blockly.BlockDragger.prototype.updateToolboxStyle_ = function(isEnd) {
|
||||
* Fire a move event at the end of a block drag.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.fireMoveEvent_ = function() {
|
||||
var event =
|
||||
new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(this.draggingBlock_);
|
||||
BlockDragger.prototype.fireMoveEvent_ = function() {
|
||||
const event = new (events.get(events.BLOCK_MOVE))(this.draggingBlock_);
|
||||
event.oldCoordinate = this.startXY_;
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -407,7 +405,7 @@ Blockly.BlockDragger.prototype.fireMoveEvent_ = function() {
|
||||
* dragging block would be deleted if released immediately.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() {
|
||||
BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() {
|
||||
this.draggingBlock_.setDeleteStyle(this.wouldDeleteBlock_);
|
||||
};
|
||||
|
||||
@@ -416,14 +414,14 @@ Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = 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.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
|
||||
var result = new Blockly.utils.Coordinate(
|
||||
BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
|
||||
const result = new Coordinate(
|
||||
pixelCoord.x / this.workspace_.scale,
|
||||
pixelCoord.y / this.workspace_.scale);
|
||||
if (this.workspace_.isMutator) {
|
||||
@@ -431,7 +429,7 @@ Blockly.BlockDragger.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;
|
||||
@@ -439,26 +437,26 @@ Blockly.BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
|
||||
|
||||
/**
|
||||
* Move all of the icons connected to this drag.
|
||||
* @param {!Blockly.utils.Coordinate} dxy How far to move the icons from their
|
||||
* @param {!Coordinate} dxy How far to move the icons from their
|
||||
* original positions, in workspace units.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.dragIcons_ = function(dxy) {
|
||||
BlockDragger.prototype.dragIcons_ = function(dxy) {
|
||||
// Moving icons moves their associated bubbles.
|
||||
for (var i = 0; i < this.dragIconData_.length; i++) {
|
||||
var data = this.dragIconData_[i];
|
||||
data.icon.setIconLocation(Blockly.utils.Coordinate.sum(data.location, dxy));
|
||||
for (let i = 0; i < this.dragIconData_.length; i++) {
|
||||
const data = this.dragIconData_[i];
|
||||
data.icon.setIconLocation(Coordinate.sum(data.location, dxy));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a list of the insertion markers that currently exist. Drags have 0, 1,
|
||||
* or 2 insertion markers.
|
||||
* @return {!Array<!Blockly.BlockSvg>} A possibly empty list of insertion
|
||||
* @return {!Array<!BlockSvg>} A possibly empty list of insertion
|
||||
* marker blocks.
|
||||
* @public
|
||||
*/
|
||||
Blockly.BlockDragger.prototype.getInsertionMarkers = function() {
|
||||
BlockDragger.prototype.getInsertionMarkers = function() {
|
||||
// No insertion markers with the old style of dragged connection managers.
|
||||
if (this.draggedConnectionManager_ &&
|
||||
this.draggedConnectionManager_.getInsertionMarkers) {
|
||||
@@ -467,6 +465,6 @@ Blockly.BlockDragger.prototype.getInsertionMarkers = function() {
|
||||
return [];
|
||||
};
|
||||
|
||||
Blockly.registry.register(
|
||||
Blockly.registry.Type.BLOCK_DRAGGER, Blockly.registry.DEFAULT,
|
||||
Blockly.BlockDragger);
|
||||
registry.register(registry.Type.BLOCK_DRAGGER, registry.DEFAULT, BlockDragger);
|
||||
|
||||
exports = BlockDragger;
|
||||
|
||||
@@ -10,15 +10,16 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldImage');
|
||||
goog.module('Blockly.FieldImage');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Field');
|
||||
goog.require('Blockly.fieldRegistry');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.Size');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
const Field = goog.require('Blockly.Field');
|
||||
const Size = goog.require('Blockly.utils.Size');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const fieldRegistry = goog.require('Blockly.fieldRegistry');
|
||||
const {createSvgElement, XLINK_NS} = goog.require('Blockly.utils.dom');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
const {replaceMessageReferences} = goog.require('Blockly.utils');
|
||||
|
||||
|
||||
/**
|
||||
@@ -27,32 +28,35 @@ goog.require('Blockly.utils.Svg');
|
||||
* @param {!(string|number)} width Width of the image.
|
||||
* @param {!(string|number)} height Height of the image.
|
||||
* @param {string=} opt_alt Optional alt text for when block is collapsed.
|
||||
* @param {function(!Blockly.FieldImage)=} opt_onClick Optional function to be
|
||||
* @param {function(!FieldImage)=} opt_onClick Optional function to be
|
||||
* called when the image is clicked. If opt_onClick is defined, opt_alt must
|
||||
* also be defined.
|
||||
* @param {boolean=} opt_flipRtl Whether to flip the icon in RTL.
|
||||
* @param {Object=} opt_config A map of options used to configure the field.
|
||||
* See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/image#creation}
|
||||
* See the [field creation documentation]{@link
|
||||
* https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/image#creation}
|
||||
* for a list of properties this parameter supports.
|
||||
* @extends {Blockly.Field}
|
||||
* @extends {Field}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldImage = function(src, width, height,
|
||||
opt_alt, opt_onClick, opt_flipRtl, opt_config) {
|
||||
const FieldImage = function(
|
||||
src, width, height, opt_alt, opt_onClick, opt_flipRtl, opt_config) {
|
||||
// Return early.
|
||||
if (!src) {
|
||||
throw Error('Src value of an image field is required');
|
||||
}
|
||||
src = Blockly.utils.replaceMessageReferences(src);
|
||||
var imageHeight = Number(Blockly.utils.replaceMessageReferences(height));
|
||||
var imageWidth = Number(Blockly.utils.replaceMessageReferences(width));
|
||||
src = replaceMessageReferences(src);
|
||||
const imageHeight = Number(replaceMessageReferences(height));
|
||||
const imageWidth = Number(replaceMessageReferences(width));
|
||||
if (isNaN(imageHeight) || isNaN(imageWidth)) {
|
||||
throw Error('Height and width values of an image field must cast to' +
|
||||
' numbers.');
|
||||
throw Error(
|
||||
'Height and width values of an image field must cast to' +
|
||||
' numbers.');
|
||||
}
|
||||
if (imageHeight <= 0 || imageWidth <= 0) {
|
||||
throw Error('Height and width values of an image field must be greater' +
|
||||
' than 0.');
|
||||
throw Error(
|
||||
'Height and width values of an image field must be greater' +
|
||||
' than 0.');
|
||||
}
|
||||
|
||||
// Initialize configurable properties.
|
||||
@@ -70,23 +74,21 @@ Blockly.FieldImage = function(src, width, height,
|
||||
*/
|
||||
this.altText_ = '';
|
||||
|
||||
Blockly.FieldImage.superClass_.constructor.call(
|
||||
this, src, null, opt_config);
|
||||
FieldImage.superClass_.constructor.call(this, src, null, opt_config);
|
||||
|
||||
if (!opt_config) { // If the config wasn't passed, do old configuration.
|
||||
this.flipRtl_ = !!opt_flipRtl;
|
||||
this.altText_ = Blockly.utils.replaceMessageReferences(opt_alt) || '';
|
||||
this.altText_ = replaceMessageReferences(opt_alt) || '';
|
||||
}
|
||||
|
||||
// Initialize other properties.
|
||||
/**
|
||||
* The size of the area rendered by the field.
|
||||
* @type {Blockly.utils.Size}
|
||||
* @type {Size}
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
this.size_ = new Blockly.utils.Size(imageWidth,
|
||||
imageHeight + Blockly.FieldImage.Y_PADDING);
|
||||
this.size_ = new Size(imageWidth, imageHeight + FieldImage.Y_PADDING);
|
||||
|
||||
/**
|
||||
* Store the image height, since it is different from the field height.
|
||||
@@ -97,7 +99,7 @@ Blockly.FieldImage = function(src, width, height,
|
||||
|
||||
/**
|
||||
* The function to be called when this field is clicked.
|
||||
* @type {?function(!Blockly.FieldImage)}
|
||||
* @type {?function(!FieldImage)}
|
||||
* @private
|
||||
*/
|
||||
this.clickHandler_ = null;
|
||||
@@ -113,29 +115,30 @@ Blockly.FieldImage = function(src, width, height,
|
||||
*/
|
||||
this.imageElement_ = null;
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.FieldImage, Blockly.Field);
|
||||
inherits(FieldImage, Field);
|
||||
|
||||
/**
|
||||
* The default value for this field.
|
||||
* @type {*}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldImage.prototype.DEFAULT_VALUE = '';
|
||||
FieldImage.prototype.DEFAULT_VALUE = '';
|
||||
|
||||
/**
|
||||
* Construct a FieldImage from a JSON arg object,
|
||||
* dereferencing any string table references.
|
||||
* @param {!Object} options A JSON object with options (src, width, height,
|
||||
* alt, and flipRtl).
|
||||
* @return {!Blockly.FieldImage} The new field instance.
|
||||
* @return {!FieldImage} The new field instance.
|
||||
* @package
|
||||
* @nocollapse
|
||||
*/
|
||||
Blockly.FieldImage.fromJson = function(options) {
|
||||
FieldImage.fromJson = function(options) {
|
||||
// `this` might be a subclass of FieldImage if that class doesn't override
|
||||
// the static fromJson method.
|
||||
return new this(options['src'], options['width'], options['height'],
|
||||
undefined, undefined, undefined, options);
|
||||
return new this(
|
||||
options['src'], options['width'], options['height'], undefined, undefined,
|
||||
undefined, options);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -144,14 +147,14 @@ Blockly.FieldImage.fromJson = function(options) {
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldImage.Y_PADDING = 1;
|
||||
FieldImage.Y_PADDING = 1;
|
||||
|
||||
/**
|
||||
* Editable fields usually show some sort of UI indicating they are
|
||||
* editable. This field should not.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.FieldImage.prototype.EDITABLE = false;
|
||||
FieldImage.prototype.EDITABLE = false;
|
||||
|
||||
/**
|
||||
* Used to tell if the field needs to be rendered the next time the block is
|
||||
@@ -160,7 +163,7 @@ Blockly.FieldImage.prototype.EDITABLE = false;
|
||||
* @type {boolean}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldImage.prototype.isDirty_ = false;
|
||||
FieldImage.prototype.isDirty_ = false;
|
||||
|
||||
/**
|
||||
* Configure the field based on the given map of options.
|
||||
@@ -168,27 +171,26 @@ Blockly.FieldImage.prototype.isDirty_ = false;
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldImage.prototype.configure_ = function(config) {
|
||||
Blockly.FieldImage.superClass_.configure_.call(this, config);
|
||||
FieldImage.prototype.configure_ = function(config) {
|
||||
FieldImage.superClass_.configure_.call(this, config);
|
||||
this.flipRtl_ = !!config['flipRtl'];
|
||||
this.altText_ = Blockly.utils.replaceMessageReferences(config['alt']) || '';
|
||||
this.altText_ = replaceMessageReferences(config['alt']) || '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the block UI for this image.
|
||||
* @package
|
||||
*/
|
||||
Blockly.FieldImage.prototype.initView = function() {
|
||||
this.imageElement_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.IMAGE,
|
||||
{
|
||||
FieldImage.prototype.initView = function() {
|
||||
this.imageElement_ = createSvgElement(
|
||||
Svg.IMAGE, {
|
||||
'height': this.imageHeight_ + 'px',
|
||||
'width': this.size_.width + 'px',
|
||||
'alt': this.altText_
|
||||
},
|
||||
this.fieldGroup_);
|
||||
this.imageElement_.setAttributeNS(Blockly.utils.dom.XLINK_NS,
|
||||
'xlink:href', /** @type {string} */ (this.value_));
|
||||
this.imageElement_.setAttributeNS(
|
||||
XLINK_NS, 'xlink:href', /** @type {string} */ (this.value_));
|
||||
|
||||
if (this.clickHandler_) {
|
||||
this.imageElement_.style.cursor = 'pointer';
|
||||
@@ -198,7 +200,7 @@ Blockly.FieldImage.prototype.initView = function() {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldImage.prototype.updateSize_ = function() {
|
||||
FieldImage.prototype.updateSize_ = function() {
|
||||
// NOP
|
||||
};
|
||||
|
||||
@@ -208,7 +210,7 @@ Blockly.FieldImage.prototype.updateSize_ = function() {
|
||||
* @return {?string} A string, or null if invalid.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldImage.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
FieldImage.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
if (typeof opt_newValue != 'string') {
|
||||
return null;
|
||||
}
|
||||
@@ -221,11 +223,11 @@ Blockly.FieldImage.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
* that this is a string.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldImage.prototype.doValueUpdate_ = function(newValue) {
|
||||
FieldImage.prototype.doValueUpdate_ = function(newValue) {
|
||||
this.value_ = newValue;
|
||||
if (this.imageElement_) {
|
||||
this.imageElement_.setAttributeNS(Blockly.utils.dom.XLINK_NS,
|
||||
'xlink:href', String(this.value_));
|
||||
this.imageElement_.setAttributeNS(
|
||||
XLINK_NS, 'xlink:href', String(this.value_));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -234,7 +236,7 @@ Blockly.FieldImage.prototype.doValueUpdate_ = function(newValue) {
|
||||
* @return {boolean} True if we should flip in RTL.
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldImage.prototype.getFlipRtl = function() {
|
||||
FieldImage.prototype.getFlipRtl = function() {
|
||||
return this.flipRtl_;
|
||||
};
|
||||
|
||||
@@ -243,7 +245,7 @@ Blockly.FieldImage.prototype.getFlipRtl = function() {
|
||||
* @param {?string} alt New alt text.
|
||||
* @public
|
||||
*/
|
||||
Blockly.FieldImage.prototype.setAlt = function(alt) {
|
||||
FieldImage.prototype.setAlt = function(alt) {
|
||||
if (alt == this.altText_) {
|
||||
return;
|
||||
}
|
||||
@@ -258,7 +260,7 @@ Blockly.FieldImage.prototype.setAlt = function(alt) {
|
||||
* call the handler.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldImage.prototype.showEditor_ = function() {
|
||||
FieldImage.prototype.showEditor_ = function() {
|
||||
if (this.clickHandler_) {
|
||||
this.clickHandler_(this);
|
||||
}
|
||||
@@ -266,10 +268,10 @@ Blockly.FieldImage.prototype.showEditor_ = function() {
|
||||
|
||||
/**
|
||||
* Set the function that is called when this image is clicked.
|
||||
* @param {?function(!Blockly.FieldImage)} func The function that is called
|
||||
* @param {?function(!FieldImage)} func The function that is called
|
||||
* when the image is clicked, or null to remove.
|
||||
*/
|
||||
Blockly.FieldImage.prototype.setOnClickHandler = function(func) {
|
||||
FieldImage.prototype.setOnClickHandler = function(func) {
|
||||
this.clickHandler_ = func;
|
||||
};
|
||||
|
||||
@@ -281,8 +283,10 @@ Blockly.FieldImage.prototype.setOnClickHandler = function(func) {
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldImage.prototype.getText_ = function() {
|
||||
FieldImage.prototype.getText_ = function() {
|
||||
return this.altText_;
|
||||
};
|
||||
|
||||
Blockly.fieldRegistry.register('field_image', Blockly.FieldImage);
|
||||
fieldRegistry.register('field_image', FieldImage);
|
||||
|
||||
exports = FieldImage;
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldLabel');
|
||||
goog.module('Blockly.FieldLabel');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Field');
|
||||
goog.require('Blockly.fieldRegistry');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.object');
|
||||
const Field = goog.require('Blockly.Field');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const fieldRegistry = goog.require('Blockly.fieldRegistry');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
const {replaceMessageReferences} = goog.require('Blockly.utils');
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,12 +27,13 @@ goog.require('Blockly.utils.object');
|
||||
* string. Defaults to an empty string if null or undefined.
|
||||
* @param {string=} opt_class Optional CSS class for the field's text.
|
||||
* @param {Object=} opt_config A map of options used to configure the field.
|
||||
* See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label#creation}
|
||||
* See the [field creation documentation]{@link
|
||||
* https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label#creation}
|
||||
* for a list of properties this parameter supports.
|
||||
* @extends {Blockly.Field}
|
||||
* @extends {Field}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldLabel = function(opt_value, opt_class, opt_config) {
|
||||
const FieldLabel = function(opt_value, opt_class, opt_config) {
|
||||
/**
|
||||
* The html class name to use for this field.
|
||||
* @type {?string}
|
||||
@@ -39,32 +41,31 @@ Blockly.FieldLabel = function(opt_value, opt_class, opt_config) {
|
||||
*/
|
||||
this.class_ = null;
|
||||
|
||||
Blockly.FieldLabel.superClass_.constructor.call(
|
||||
this, opt_value, null, opt_config);
|
||||
FieldLabel.superClass_.constructor.call(this, opt_value, null, opt_config);
|
||||
|
||||
if (!opt_config) { // If the config was not passed use old configuration.
|
||||
this.class_ = opt_class || null;
|
||||
}
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.FieldLabel, Blockly.Field);
|
||||
inherits(FieldLabel, Field);
|
||||
|
||||
/**
|
||||
* The default value for this field.
|
||||
* @type {*}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldLabel.prototype.DEFAULT_VALUE = '';
|
||||
FieldLabel.prototype.DEFAULT_VALUE = '';
|
||||
|
||||
/**
|
||||
* Construct a FieldLabel from a JSON arg object,
|
||||
* dereferencing any string table references.
|
||||
* @param {!Object} options A JSON object with options (text, and class).
|
||||
* @return {!Blockly.FieldLabel} The new field instance.
|
||||
* @return {!FieldLabel} The new field instance.
|
||||
* @package
|
||||
* @nocollapse
|
||||
*/
|
||||
Blockly.FieldLabel.fromJson = function(options) {
|
||||
var text = Blockly.utils.replaceMessageReferences(options['text']);
|
||||
FieldLabel.fromJson = function(options) {
|
||||
const text = replaceMessageReferences(options['text']);
|
||||
// `this` might be a subclass of FieldLabel if that class doesn't override
|
||||
// the static fromJson method.
|
||||
return new this(text, undefined, options);
|
||||
@@ -75,13 +76,13 @@ Blockly.FieldLabel.fromJson = function(options) {
|
||||
* editable. This field should not.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.FieldLabel.prototype.EDITABLE = false;
|
||||
FieldLabel.prototype.EDITABLE = false;
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldLabel.prototype.configure_ = function(config) {
|
||||
Blockly.FieldLabel.superClass_.configure_.call(this, config);
|
||||
FieldLabel.prototype.configure_ = function(config) {
|
||||
FieldLabel.superClass_.configure_.call(this, config);
|
||||
this.class_ = config['class'];
|
||||
};
|
||||
|
||||
@@ -89,10 +90,10 @@ Blockly.FieldLabel.prototype.configure_ = function(config) {
|
||||
* Create block UI for this label.
|
||||
* @package
|
||||
*/
|
||||
Blockly.FieldLabel.prototype.initView = function() {
|
||||
FieldLabel.prototype.initView = function() {
|
||||
this.createTextElement_();
|
||||
if (this.class_) {
|
||||
Blockly.utils.dom.addClass(
|
||||
dom.addClass(
|
||||
/** @type {!SVGTextElement} */ (this.textElement_), this.class_);
|
||||
}
|
||||
};
|
||||
@@ -103,7 +104,7 @@ Blockly.FieldLabel.prototype.initView = function() {
|
||||
* @return {?string} A valid string, or null if invalid.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldLabel.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
FieldLabel.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
if (opt_newValue === null || opt_newValue === undefined) {
|
||||
return null;
|
||||
}
|
||||
@@ -114,18 +115,20 @@ Blockly.FieldLabel.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
* Set the CSS class applied to the field's textElement_.
|
||||
* @param {?string} cssClass The new CSS class name, or null to remove.
|
||||
*/
|
||||
Blockly.FieldLabel.prototype.setClass = function(cssClass) {
|
||||
FieldLabel.prototype.setClass = function(cssClass) {
|
||||
if (this.textElement_) {
|
||||
// This check isn't necessary, but it's faster than letting removeClass
|
||||
// figure it out.
|
||||
if (this.class_) {
|
||||
Blockly.utils.dom.removeClass(this.textElement_, this.class_);
|
||||
dom.removeClass(this.textElement_, this.class_);
|
||||
}
|
||||
if (cssClass) {
|
||||
Blockly.utils.dom.addClass(this.textElement_, cssClass);
|
||||
dom.addClass(this.textElement_, cssClass);
|
||||
}
|
||||
}
|
||||
this.class_ = cssClass;
|
||||
};
|
||||
|
||||
Blockly.fieldRegistry.register('field_label', Blockly.FieldLabel);
|
||||
fieldRegistry.register('field_label', FieldLabel);
|
||||
|
||||
exports = FieldLabel;
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldLabelSerializable');
|
||||
goog.module('Blockly.FieldLabelSerializable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.FieldLabel');
|
||||
goog.require('Blockly.fieldRegistry');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.object');
|
||||
const FieldLabel = goog.require('Blockly.FieldLabel');
|
||||
const fieldRegistry = goog.require('Blockly.fieldRegistry');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
const {replaceMessageReferences} = goog.require('Blockly.utils');
|
||||
|
||||
|
||||
/**
|
||||
@@ -25,29 +26,29 @@ goog.require('Blockly.utils.object');
|
||||
* string. Defaults to an empty string if null or undefined.
|
||||
* @param {string=} opt_class Optional CSS class for the field's text.
|
||||
* @param {Object=} opt_config A map of options used to configure the field.
|
||||
* See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label-serializable#creation}
|
||||
* See the [field creation documentation]{@link
|
||||
* https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label-serializable#creation}
|
||||
* for a list of properties this parameter supports.
|
||||
* @extends {Blockly.FieldLabel}
|
||||
* @extends {FieldLabel}
|
||||
* @constructor
|
||||
*
|
||||
*/
|
||||
Blockly.FieldLabelSerializable = function(opt_value, opt_class, opt_config) {
|
||||
Blockly.FieldLabelSerializable.superClass_.constructor.call(
|
||||
const FieldLabelSerializable = function(opt_value, opt_class, opt_config) {
|
||||
FieldLabelSerializable.superClass_.constructor.call(
|
||||
this, opt_value, opt_class, opt_config);
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.FieldLabelSerializable,
|
||||
Blockly.FieldLabel);
|
||||
inherits(FieldLabelSerializable, FieldLabel);
|
||||
|
||||
/**
|
||||
* Construct a FieldLabelSerializable from a JSON arg object,
|
||||
* dereferencing any string table references.
|
||||
* @param {!Object} options A JSON object with options (text, and class).
|
||||
* @return {!Blockly.FieldLabelSerializable} The new field instance.
|
||||
* @return {!FieldLabelSerializable} The new field instance.
|
||||
* @package
|
||||
* @nocollapse
|
||||
*/
|
||||
Blockly.FieldLabelSerializable.fromJson = function(options) {
|
||||
var text = Blockly.utils.replaceMessageReferences(options['text']);
|
||||
FieldLabelSerializable.fromJson = function(options) {
|
||||
const text = replaceMessageReferences(options['text']);
|
||||
// `this` might be a subclass of FieldLabelSerializable if that class doesn't
|
||||
// override the static fromJson method.
|
||||
return new this(text, undefined, options);
|
||||
@@ -58,14 +59,15 @@ Blockly.FieldLabelSerializable.fromJson = function(options) {
|
||||
* editable. This field should not.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.FieldLabelSerializable.prototype.EDITABLE = false;
|
||||
FieldLabelSerializable.prototype.EDITABLE = false;
|
||||
|
||||
/**
|
||||
* Serializable fields are saved by the XML renderer, non-serializable fields
|
||||
* are not. This field should be serialized, but only edited programmatically.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.FieldLabelSerializable.prototype.SERIALIZABLE = true;
|
||||
FieldLabelSerializable.prototype.SERIALIZABLE = true;
|
||||
|
||||
Blockly.fieldRegistry.register(
|
||||
'field_label_serializable', Blockly.FieldLabelSerializable);
|
||||
fieldRegistry.register('field_label_serializable', FieldLabelSerializable);
|
||||
|
||||
exports = FieldLabelSerializable;
|
||||
|
||||
@@ -12,20 +12,21 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldMultilineInput');
|
||||
goog.module('Blockly.FieldMultilineInput');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Css');
|
||||
goog.require('Blockly.Field');
|
||||
goog.require('Blockly.fieldRegistry');
|
||||
goog.require('Blockly.FieldTextInput');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.aria');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.KeyCodes');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
goog.require('Blockly.utils.userAgent');
|
||||
goog.require('Blockly.WidgetDiv');
|
||||
const Css = goog.require('Blockly.Css');
|
||||
const Field = goog.require('Blockly.Field');
|
||||
const FieldTextInput = goog.require('Blockly.FieldTextInput');
|
||||
const KeyCodes = goog.require('Blockly.utils.KeyCodes');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const WidgetDiv = goog.require('Blockly.WidgetDiv');
|
||||
const aria = goog.require('Blockly.utils.aria');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const fieldRegistry = goog.require('Blockly.fieldRegistry');
|
||||
const userAgent = goog.require('Blockly.utils.userAgent');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
const {replaceMessageReferences} = goog.require('Blockly.utils');
|
||||
|
||||
|
||||
/**
|
||||
@@ -37,14 +38,15 @@ goog.require('Blockly.WidgetDiv');
|
||||
* text as an argument and returns either the accepted text, a replacement
|
||||
* text, or null to abort the change.
|
||||
* @param {Object=} opt_config A map of options used to configure the field.
|
||||
* See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/multiline-text-input#creation}
|
||||
* See the [field creation documentation]{@link
|
||||
* https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/multiline-text-input#creation}
|
||||
* for a list of properties this parameter supports.
|
||||
* @extends {Blockly.FieldTextInput}
|
||||
* @extends {FieldTextInput}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldMultilineInput = function(opt_value, opt_validator, opt_config) {
|
||||
Blockly.FieldMultilineInput.superClass_.constructor.call(this,
|
||||
opt_value, opt_validator, opt_config);
|
||||
const FieldMultilineInput = function(opt_value, opt_validator, opt_config) {
|
||||
FieldMultilineInput.superClass_.constructor.call(
|
||||
this, opt_value, opt_validator, opt_config);
|
||||
|
||||
/**
|
||||
* The SVG group element that will contain a text element for each text row
|
||||
@@ -68,14 +70,13 @@ Blockly.FieldMultilineInput = function(opt_value, opt_validator, opt_config) {
|
||||
*/
|
||||
this.isOverflowedY_ = false;
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.FieldMultilineInput,
|
||||
Blockly.FieldTextInput);
|
||||
inherits(FieldMultilineInput, FieldTextInput);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.configure_ = function(config) {
|
||||
Blockly.FieldMultilineInput.superClass_.configure_.call(this, config);
|
||||
FieldMultilineInput.prototype.configure_ = function(config) {
|
||||
FieldMultilineInput.superClass_.configure_.call(this, config);
|
||||
config.maxLines && this.setMaxLines(config.maxLines);
|
||||
};
|
||||
|
||||
@@ -83,12 +84,12 @@ Blockly.FieldMultilineInput.prototype.configure_ = function(config) {
|
||||
* Construct a FieldMultilineInput from a JSON arg object,
|
||||
* dereferencing any string table references.
|
||||
* @param {!Object} options A JSON object with options (text, and spellcheck).
|
||||
* @return {!Blockly.FieldMultilineInput} The new field instance.
|
||||
* @return {!FieldMultilineInput} The new field instance.
|
||||
* @package
|
||||
* @nocollapse
|
||||
*/
|
||||
Blockly.FieldMultilineInput.fromJson = function(options) {
|
||||
var text = Blockly.utils.replaceMessageReferences(options['text']);
|
||||
FieldMultilineInput.fromJson = function(options) {
|
||||
const text = replaceMessageReferences(options['text']);
|
||||
// `this` might be a subclass of FieldMultilineInput if that class doesn't
|
||||
// override the static fromJson method.
|
||||
return new this(text, undefined, options);
|
||||
@@ -101,7 +102,7 @@ Blockly.FieldMultilineInput.fromJson = function(options) {
|
||||
* @return {!Element} The element containing info about the field's state.
|
||||
* @package
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.toXml = function(fieldElement) {
|
||||
FieldMultilineInput.prototype.toXml = function(fieldElement) {
|
||||
// Replace '\n' characters with HTML-escaped equivalent '
'. This is
|
||||
// needed so the plain-text representation of the XML produced by
|
||||
// `Blockly.Xml.domToText` will appear on a single line (this is a limitation
|
||||
@@ -117,7 +118,7 @@ Blockly.FieldMultilineInput.prototype.toXml = function(fieldElement) {
|
||||
* field's state.
|
||||
* @package
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.fromXml = function(fieldElement) {
|
||||
FieldMultilineInput.prototype.fromXml = function(fieldElement) {
|
||||
this.setValue(fieldElement.textContent.replace(/ /g, '\n'));
|
||||
};
|
||||
|
||||
@@ -125,12 +126,13 @@ Blockly.FieldMultilineInput.prototype.fromXml = function(fieldElement) {
|
||||
* Create the block UI for this field.
|
||||
* @package
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.initView = function() {
|
||||
FieldMultilineInput.prototype.initView = function() {
|
||||
this.createBorderRect_();
|
||||
this.textGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G, {
|
||||
this.textGroup_ = dom.createSvgElement(
|
||||
Svg.G, {
|
||||
'class': 'blocklyEditableText',
|
||||
}, this.fieldGroup_);
|
||||
},
|
||||
this.fieldGroup_);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -140,17 +142,18 @@ Blockly.FieldMultilineInput.prototype.initView = function() {
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() {
|
||||
var textLines = this.getText();
|
||||
FieldMultilineInput.prototype.getDisplayText_ = function() {
|
||||
let textLines = this.getText();
|
||||
if (!textLines) {
|
||||
// Prevent the field from disappearing if empty.
|
||||
return Blockly.Field.NBSP;
|
||||
return Field.NBSP;
|
||||
}
|
||||
var lines = textLines.split('\n');
|
||||
const lines = textLines.split('\n');
|
||||
textLines = '';
|
||||
var displayLinesNumber = this.isOverflowedY_ ? this.maxLines_ : lines.length;
|
||||
for (var i = 0; i < displayLinesNumber; i++) {
|
||||
var text = lines[i];
|
||||
const displayLinesNumber =
|
||||
this.isOverflowedY_ ? this.maxLines_ : lines.length;
|
||||
for (let i = 0; i < displayLinesNumber; i++) {
|
||||
let text = lines[i];
|
||||
if (text.length > this.maxDisplayLength) {
|
||||
// Truncate displayed string and add an ellipsis ('...').
|
||||
text = text.substring(0, this.maxDisplayLength - 4) + '...';
|
||||
@@ -158,7 +161,7 @@ Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() {
|
||||
text = text.substring(0, text.length - 3) + '...';
|
||||
}
|
||||
// Replace whitespace with non-breaking spaces so the text doesn't collapse.
|
||||
text = text.replace(/\s/g, Blockly.Field.NBSP);
|
||||
text = text.replace(/\s/g, Field.NBSP);
|
||||
|
||||
textLines += text;
|
||||
if (i !== displayLinesNumber - 1) {
|
||||
@@ -181,8 +184,8 @@ Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() {
|
||||
* that this is a string.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.doValueUpdate_ = function(newValue) {
|
||||
Blockly.FieldMultilineInput.superClass_.doValueUpdate_.call(this, newValue);
|
||||
FieldMultilineInput.prototype.doValueUpdate_ = function(newValue) {
|
||||
FieldMultilineInput.superClass_.doValueUpdate_.call(this, newValue);
|
||||
this.isOverflowedY_ = this.value_.split('\n').length > this.maxLines_;
|
||||
};
|
||||
|
||||
@@ -190,36 +193,37 @@ Blockly.FieldMultilineInput.prototype.doValueUpdate_ = function(newValue) {
|
||||
* Updates the text of the textElement.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.render_ = function() {
|
||||
FieldMultilineInput.prototype.render_ = function() {
|
||||
// Remove all text group children.
|
||||
var currentChild;
|
||||
let currentChild;
|
||||
while ((currentChild = this.textGroup_.firstChild)) {
|
||||
this.textGroup_.removeChild(currentChild);
|
||||
}
|
||||
|
||||
// Add in text elements into the group.
|
||||
var lines = this.getDisplayText_().split('\n');
|
||||
var y = 0;
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var lineHeight = this.getConstants().FIELD_TEXT_HEIGHT +
|
||||
const lines = this.getDisplayText_().split('\n');
|
||||
let y = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const lineHeight = this.getConstants().FIELD_TEXT_HEIGHT +
|
||||
this.getConstants().FIELD_BORDER_RECT_Y_PADDING;
|
||||
var span = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.TEXT, {
|
||||
const span = dom.createSvgElement(
|
||||
Svg.TEXT, {
|
||||
'class': 'blocklyText blocklyMultilineText',
|
||||
x: this.getConstants().FIELD_BORDER_RECT_X_PADDING,
|
||||
y: y + this.getConstants().FIELD_BORDER_RECT_Y_PADDING,
|
||||
dy: this.getConstants().FIELD_TEXT_BASELINE
|
||||
}, this.textGroup_);
|
||||
},
|
||||
this.textGroup_);
|
||||
span.appendChild(document.createTextNode(lines[i]));
|
||||
y += lineHeight;
|
||||
}
|
||||
|
||||
if (this.isBeingEdited_) {
|
||||
var htmlInput = /** @type {!HTMLElement} */(this.htmlInput_);
|
||||
var htmlInput = /** @type {!HTMLElement} */ (this.htmlInput_);
|
||||
if (this.isOverflowedY_) {
|
||||
Blockly.utils.dom.addClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
|
||||
dom.addClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
|
||||
} else {
|
||||
Blockly.utils.dom.removeClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
|
||||
dom.removeClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,15 +238,13 @@ Blockly.FieldMultilineInput.prototype.render_ = function() {
|
||||
} else {
|
||||
this.resizeEditor_();
|
||||
}
|
||||
var htmlInput = /** @type {!HTMLElement} */(this.htmlInput_);
|
||||
var htmlInput = /** @type {!HTMLElement} */ (this.htmlInput_);
|
||||
if (!this.isTextValid_) {
|
||||
Blockly.utils.dom.addClass(htmlInput, 'blocklyInvalidInput');
|
||||
Blockly.utils.aria.setState(htmlInput,
|
||||
Blockly.utils.aria.State.INVALID, true);
|
||||
dom.addClass(htmlInput, 'blocklyInvalidInput');
|
||||
aria.setState(htmlInput, aria.State.INVALID, true);
|
||||
} else {
|
||||
Blockly.utils.dom.removeClass(htmlInput, 'blocklyInvalidInput');
|
||||
Blockly.utils.aria.setState(htmlInput,
|
||||
Blockly.utils.aria.State.INVALID, false);
|
||||
dom.removeClass(htmlInput, 'blocklyInvalidInput');
|
||||
aria.setState(htmlInput, aria.State.INVALID, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -251,13 +253,13 @@ Blockly.FieldMultilineInput.prototype.render_ = function() {
|
||||
* Updates the size of the field based on the text.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.updateSize_ = function() {
|
||||
var nodes = this.textGroup_.childNodes;
|
||||
var totalWidth = 0;
|
||||
var totalHeight = 0;
|
||||
FieldMultilineInput.prototype.updateSize_ = function() {
|
||||
const nodes = this.textGroup_.childNodes;
|
||||
let totalWidth = 0;
|
||||
let totalHeight = 0;
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var tspan = /** @type {!Element} */ (nodes[i]);
|
||||
var textWidth = Blockly.utils.dom.getTextWidth(tspan);
|
||||
const tspan = /** @type {!Element} */ (nodes[i]);
|
||||
const textWidth = dom.getTextWidth(tspan);
|
||||
if (textWidth > totalWidth) {
|
||||
totalWidth = textWidth;
|
||||
}
|
||||
@@ -270,26 +272,28 @@ Blockly.FieldMultilineInput.prototype.updateSize_ = function() {
|
||||
// absolute longest line, even if it would be truncated after editing.
|
||||
// Otherwise we would get wrong editor width when there are more
|
||||
// lines than this.maxLines_.
|
||||
var actualEditorLines = this.value_.split('\n');
|
||||
var dummyTextElement = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.TEXT,{'class': 'blocklyText blocklyMultilineText'});
|
||||
var fontSize = this.getConstants().FIELD_TEXT_FONTSIZE;
|
||||
var fontWeight = this.getConstants().FIELD_TEXT_FONTWEIGHT;
|
||||
var fontFamily = this.getConstants().FIELD_TEXT_FONTFAMILY;
|
||||
const actualEditorLines = this.value_.split('\n');
|
||||
const dummyTextElement = dom.createSvgElement(
|
||||
Svg.TEXT, {'class': 'blocklyText blocklyMultilineText'});
|
||||
const fontSize = this.getConstants().FIELD_TEXT_FONTSIZE;
|
||||
const fontWeight = this.getConstants().FIELD_TEXT_FONTWEIGHT;
|
||||
const fontFamily = this.getConstants().FIELD_TEXT_FONTFAMILY;
|
||||
|
||||
for (var i = 0; i < actualEditorLines.length; i++) {
|
||||
if (actualEditorLines[i].length > this.maxDisplayLength) {
|
||||
actualEditorLines[i] = actualEditorLines[i].substring(0, this.maxDisplayLength);
|
||||
actualEditorLines[i] =
|
||||
actualEditorLines[i].substring(0, this.maxDisplayLength);
|
||||
}
|
||||
dummyTextElement.textContent = actualEditorLines[i];
|
||||
var lineWidth = Blockly.utils.dom.getFastTextWidth(
|
||||
const lineWidth = dom.getFastTextWidth(
|
||||
dummyTextElement, fontSize, fontWeight, fontFamily);
|
||||
if (lineWidth > totalWidth) {
|
||||
totalWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
|
||||
var scrollbarWidth = this.htmlInput_.offsetWidth - this.htmlInput_.clientWidth;
|
||||
const scrollbarWidth =
|
||||
this.htmlInput_.offsetWidth - this.htmlInput_.clientWidth;
|
||||
totalWidth += scrollbarWidth;
|
||||
}
|
||||
if (this.borderRect_) {
|
||||
@@ -314,8 +318,9 @@ Blockly.FieldMultilineInput.prototype.updateSize_ = function() {
|
||||
* focus. Defaults to false.
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.showEditor_ = function(_opt_e, opt_quietInput) {
|
||||
Blockly.FieldMultilineInput.superClass_.showEditor_.call(this, _opt_e, opt_quietInput);
|
||||
FieldMultilineInput.prototype.showEditor_ = function(_opt_e, opt_quietInput) {
|
||||
FieldMultilineInput.superClass_.showEditor_.call(
|
||||
this, _opt_e, opt_quietInput);
|
||||
this.forceRerender();
|
||||
};
|
||||
|
||||
@@ -324,24 +329,24 @@ Blockly.FieldMultilineInput.prototype.showEditor_ = function(_opt_e, opt_quietIn
|
||||
* @return {!HTMLTextAreaElement} The newly created text input editor.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() {
|
||||
var div = Blockly.WidgetDiv.DIV;
|
||||
var scale = this.workspace_.getScale();
|
||||
FieldMultilineInput.prototype.widgetCreate_ = function() {
|
||||
const div = WidgetDiv.DIV;
|
||||
const scale = this.workspace_.getScale();
|
||||
|
||||
var htmlInput =
|
||||
/** @type {HTMLTextAreaElement} */ (document.createElement('textarea'));
|
||||
const htmlInput =
|
||||
/** @type {HTMLTextAreaElement} */ (document.createElement('textarea'));
|
||||
htmlInput.className = 'blocklyHtmlInput blocklyHtmlTextAreaInput';
|
||||
htmlInput.setAttribute('spellcheck', this.spellcheck_);
|
||||
var fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt';
|
||||
const fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt';
|
||||
div.style.fontSize = fontSize;
|
||||
htmlInput.style.fontSize = fontSize;
|
||||
var borderRadius = (Blockly.FieldTextInput.BORDERRADIUS * scale) + 'px';
|
||||
const borderRadius = (FieldTextInput.BORDERRADIUS * scale) + 'px';
|
||||
htmlInput.style.borderRadius = borderRadius;
|
||||
var paddingX = this.getConstants().FIELD_BORDER_RECT_X_PADDING * scale;
|
||||
var paddingY = this.getConstants().FIELD_BORDER_RECT_Y_PADDING * scale / 2;
|
||||
htmlInput.style.padding = paddingY + 'px ' + paddingX + 'px ' + paddingY +
|
||||
'px ' + paddingX + 'px';
|
||||
var lineHeight = this.getConstants().FIELD_TEXT_HEIGHT +
|
||||
const paddingX = this.getConstants().FIELD_BORDER_RECT_X_PADDING * scale;
|
||||
const paddingY = this.getConstants().FIELD_BORDER_RECT_Y_PADDING * scale / 2;
|
||||
htmlInput.style.padding =
|
||||
paddingY + 'px ' + paddingX + 'px ' + paddingY + 'px ' + paddingX + 'px';
|
||||
const lineHeight = this.getConstants().FIELD_TEXT_HEIGHT +
|
||||
this.getConstants().FIELD_BORDER_RECT_Y_PADDING;
|
||||
htmlInput.style.lineHeight = (lineHeight * scale) + 'px';
|
||||
|
||||
@@ -350,7 +355,7 @@ Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() {
|
||||
htmlInput.value = htmlInput.defaultValue = this.getEditorText_(this.value_);
|
||||
htmlInput.untypedDefaultValue_ = this.value_;
|
||||
htmlInput.oldValue_ = null;
|
||||
if (Blockly.utils.userAgent.GECKO) {
|
||||
if (userAgent.GECKO) {
|
||||
// In FF, ensure the browser reflows before resizing to avoid issue #2777.
|
||||
setTimeout(this.resizeEditor_.bind(this), 0);
|
||||
} else {
|
||||
@@ -367,8 +372,9 @@ Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() {
|
||||
* @param {number} maxLines Defines the maximum number of lines allowed,
|
||||
* before scrolling functionality is enabled.
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.setMaxLines = function(maxLines) {
|
||||
if (typeof maxLines === 'number' && maxLines > 0 && maxLines !== this.maxLines_) {
|
||||
FieldMultilineInput.prototype.setMaxLines = function(maxLines) {
|
||||
if (typeof maxLines === 'number' && maxLines > 0 &&
|
||||
maxLines !== this.maxLines_) {
|
||||
this.maxLines_ = maxLines;
|
||||
this.forceRerender();
|
||||
}
|
||||
@@ -378,7 +384,7 @@ Blockly.FieldMultilineInput.prototype.setMaxLines = function(maxLines) {
|
||||
* Returns the maxLines config of this field.
|
||||
* @return {number} The maxLines config value.
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.getMaxLines = function() {
|
||||
FieldMultilineInput.prototype.getMaxLines = function() {
|
||||
return this.maxLines_;
|
||||
};
|
||||
|
||||
@@ -388,29 +394,29 @@ Blockly.FieldMultilineInput.prototype.getMaxLines = function() {
|
||||
* @param {!Event} e Keyboard event.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldMultilineInput.prototype.onHtmlInputKeyDown_ = function(e) {
|
||||
if (e.keyCode !== Blockly.utils.KeyCodes.ENTER) {
|
||||
Blockly.FieldMultilineInput.superClass_.onHtmlInputKeyDown_.call(this, e);
|
||||
FieldMultilineInput.prototype.onHtmlInputKeyDown_ = function(e) {
|
||||
if (e.keyCode !== KeyCodes.ENTER) {
|
||||
FieldMultilineInput.superClass_.onHtmlInputKeyDown_.call(this, e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* CSS for multiline field. See css.js for use.
|
||||
*/
|
||||
Blockly.Css.register([
|
||||
/* eslint-disable indent */
|
||||
'.blocklyHtmlTextAreaInput {',
|
||||
'font-family: monospace;',
|
||||
'resize: none;',
|
||||
'overflow: hidden;',
|
||||
'height: 100%;',
|
||||
'text-align: left;',
|
||||
'}',
|
||||
'.blocklyHtmlTextAreaInputOverflowedY {',
|
||||
'overflow-y: scroll;',
|
||||
'}'
|
||||
/* eslint-enable indent */
|
||||
Css.register([
|
||||
`.blocklyHtmlTextAreaInput {
|
||||
font-family: monospace;
|
||||
resize: none;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
text-align: left;
|
||||
}`,
|
||||
`.blocklyHtmlTextAreaInputOverflowedY {
|
||||
overflow-y: scroll;
|
||||
}`
|
||||
]);
|
||||
|
||||
|
||||
Blockly.fieldRegistry.register('field_multilinetext', Blockly.FieldMultilineInput);
|
||||
fieldRegistry.register('field_multilinetext', FieldMultilineInput);
|
||||
|
||||
exports = FieldMultilineInput;
|
||||
|
||||
@@ -10,27 +10,30 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldTextInput');
|
||||
goog.module('Blockly.FieldTextInput');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.browserEvents');
|
||||
goog.require('Blockly.DropDownDiv');
|
||||
goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
const DropDownDiv = goog.require('Blockly.DropDownDiv');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
const Field = goog.require('Blockly.Field');
|
||||
const KeyCodes = goog.require('Blockly.utils.KeyCodes');
|
||||
const Msg = goog.require('Blockly.Msg');
|
||||
const WidgetDiv = goog.require('Blockly.WidgetDiv');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const aria = goog.require('Blockly.utils.aria');
|
||||
const browserEvents = goog.require('Blockly.browserEvents');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const fieldRegistry = goog.require('Blockly.fieldRegistry');
|
||||
const userAgent = goog.require('Blockly.utils.userAgent');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
const {prompt: blocklyPrompt} = goog.require('Blockly');
|
||||
const {replaceMessageReferences} = goog.require('Blockly.utils');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.BlockChange');
|
||||
goog.require('Blockly.Field');
|
||||
goog.require('Blockly.fieldRegistry');
|
||||
goog.require('Blockly.Msg');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.aria');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.KeyCodes');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.userAgent');
|
||||
goog.require('Blockly.WidgetDiv');
|
||||
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
@@ -41,12 +44,13 @@ goog.requireType('Blockly.WorkspaceSvg');
|
||||
* changes to the field's value. Takes in a string & returns a validated
|
||||
* string, or null to abort the change.
|
||||
* @param {Object=} opt_config A map of options used to configure the field.
|
||||
* See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/text-input#creation}
|
||||
* See the [field creation documentation]{@link
|
||||
* https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/text-input#creation}
|
||||
* for a list of properties this parameter supports.
|
||||
* @extends {Blockly.Field}
|
||||
* @extends {Field}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) {
|
||||
const FieldTextInput = function(opt_value, opt_validator, opt_config) {
|
||||
/**
|
||||
* Allow browser to spellcheck this field.
|
||||
* @type {boolean}
|
||||
@@ -54,8 +58,8 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) {
|
||||
*/
|
||||
this.spellcheck_ = true;
|
||||
|
||||
Blockly.FieldTextInput.superClass_.constructor.call(this,
|
||||
opt_value, opt_validator, opt_config);
|
||||
FieldTextInput.superClass_.constructor.call(
|
||||
this, opt_value, opt_validator, opt_config);
|
||||
|
||||
/**
|
||||
* The HTML input element.
|
||||
@@ -65,14 +69,14 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) {
|
||||
|
||||
/**
|
||||
* Key down event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.onKeyDownWrapper_ = null;
|
||||
|
||||
/**
|
||||
* Key input event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.onKeyInputWrapper_ = null;
|
||||
@@ -86,30 +90,30 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) {
|
||||
|
||||
/**
|
||||
* The workspace that this field belongs to.
|
||||
* @type {?Blockly.WorkspaceSvg}
|
||||
* @type {?WorkspaceSvg}
|
||||
* @protected
|
||||
*/
|
||||
this.workspace_ = null;
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.FieldTextInput, Blockly.Field);
|
||||
inherits(FieldTextInput, Field);
|
||||
|
||||
/**
|
||||
* The default value for this field.
|
||||
* @type {*}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.DEFAULT_VALUE = '';
|
||||
FieldTextInput.prototype.DEFAULT_VALUE = '';
|
||||
|
||||
/**
|
||||
* Construct a FieldTextInput from a JSON arg object,
|
||||
* dereferencing any string table references.
|
||||
* @param {!Object} options A JSON object with options (text, and spellcheck).
|
||||
* @return {!Blockly.FieldTextInput} The new field instance.
|
||||
* @return {!FieldTextInput} The new field instance.
|
||||
* @package
|
||||
* @nocollapse
|
||||
*/
|
||||
Blockly.FieldTextInput.fromJson = function(options) {
|
||||
var text = Blockly.utils.replaceMessageReferences(options['text']);
|
||||
FieldTextInput.fromJson = function(options) {
|
||||
const text = replaceMessageReferences(options['text']);
|
||||
// `this` might be a subclass of FieldTextInput if that class doesn't override
|
||||
// the static fromJson method.
|
||||
return new this(text, undefined, options);
|
||||
@@ -120,24 +124,24 @@ Blockly.FieldTextInput.fromJson = function(options) {
|
||||
* are not. Editable fields should also be serializable.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.SERIALIZABLE = true;
|
||||
FieldTextInput.prototype.SERIALIZABLE = true;
|
||||
|
||||
/**
|
||||
* Pixel size of input border radius.
|
||||
* Should match blocklyText's border-radius in CSS.
|
||||
*/
|
||||
Blockly.FieldTextInput.BORDERRADIUS = 4;
|
||||
FieldTextInput.BORDERRADIUS = 4;
|
||||
|
||||
/**
|
||||
* Mouse cursor style when over the hotspot that initiates the editor.
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.CURSOR = 'text';
|
||||
FieldTextInput.prototype.CURSOR = 'text';
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.configure_ = function(config) {
|
||||
Blockly.FieldTextInput.superClass_.configure_.call(this, config);
|
||||
FieldTextInput.prototype.configure_ = function(config) {
|
||||
FieldTextInput.superClass_.configure_.call(this, config);
|
||||
if (typeof config['spellcheck'] == 'boolean') {
|
||||
this.spellcheck_ = config['spellcheck'];
|
||||
}
|
||||
@@ -146,17 +150,17 @@ Blockly.FieldTextInput.prototype.configure_ = function(config) {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.initView = function() {
|
||||
FieldTextInput.prototype.initView = function() {
|
||||
if (this.getConstants().FULL_BLOCK_FIELDS) {
|
||||
// Step one: figure out if this is the only field on this block.
|
||||
// Rendering is quite different in that case.
|
||||
var nFields = 0;
|
||||
var nConnections = 0;
|
||||
let nFields = 0;
|
||||
let nConnections = 0;
|
||||
|
||||
// Count the number of fields, excluding text fields
|
||||
for (var i = 0, input; (input = this.sourceBlock_.inputList[i]); i++) {
|
||||
for (var j = 0; (input.fieldRow[j]); j++) {
|
||||
nFields ++;
|
||||
for (let i = 0, input; (input = this.sourceBlock_.inputList[i]); i++) {
|
||||
for (let j = 0; (input.fieldRow[j]); j++) {
|
||||
nFields++;
|
||||
}
|
||||
if (input.connection) {
|
||||
nConnections++;
|
||||
@@ -184,7 +188,7 @@ Blockly.FieldTextInput.prototype.initView = function() {
|
||||
* @return {*} A valid string, or null if invalid.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
FieldTextInput.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
if (opt_newValue === null || opt_newValue === undefined) {
|
||||
return null;
|
||||
}
|
||||
@@ -200,15 +204,16 @@ Blockly.FieldTextInput.prototype.doClassValidation_ = function(opt_newValue) {
|
||||
* the htmlInput_.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.doValueInvalid_ = function(_invalidValue) {
|
||||
FieldTextInput.prototype.doValueInvalid_ = function(_invalidValue) {
|
||||
if (this.isBeingEdited_) {
|
||||
this.isTextValid_ = false;
|
||||
var oldValue = this.value_;
|
||||
const oldValue = this.value_;
|
||||
// Revert value when the text becomes invalid.
|
||||
this.value_ = this.htmlInput_.untypedDefaultValue_;
|
||||
if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
|
||||
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))(
|
||||
this.sourceBlock_, 'field', this.name || null, oldValue, this.value_));
|
||||
if (this.sourceBlock_ && Events.isEnabled()) {
|
||||
Events.fire(new (Events.get(Events.BLOCK_CHANGE))(
|
||||
this.sourceBlock_, 'field', this.name || null, oldValue,
|
||||
this.value_));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -221,7 +226,7 @@ Blockly.FieldTextInput.prototype.doValueInvalid_ = function(_invalidValue) {
|
||||
* that this is a string.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.doValueUpdate_ = function(newValue) {
|
||||
FieldTextInput.prototype.doValueUpdate_ = function(newValue) {
|
||||
this.isTextValid_ = true;
|
||||
this.value_ = newValue;
|
||||
if (!this.isBeingEdited_) {
|
||||
@@ -234,14 +239,14 @@ Blockly.FieldTextInput.prototype.doValueUpdate_ = function(newValue) {
|
||||
* Updates text field to match the colour/style of the block.
|
||||
* @package
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.applyColour = function() {
|
||||
FieldTextInput.prototype.applyColour = function() {
|
||||
if (this.sourceBlock_ && this.getConstants().FULL_BLOCK_FIELDS) {
|
||||
if (this.borderRect_) {
|
||||
this.borderRect_.setAttribute('stroke',
|
||||
this.sourceBlock_.style.colourTertiary);
|
||||
this.borderRect_.setAttribute(
|
||||
'stroke', this.sourceBlock_.style.colourTertiary);
|
||||
} else {
|
||||
this.sourceBlock_.pathObject.svgPath.setAttribute('fill',
|
||||
this.getConstants().FIELD_BORDER_RECT_COLOUR);
|
||||
this.sourceBlock_.pathObject.svgPath.setAttribute(
|
||||
'fill', this.getConstants().FIELD_BORDER_RECT_COLOUR);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -251,21 +256,19 @@ Blockly.FieldTextInput.prototype.applyColour = function() {
|
||||
* field's value.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.render_ = function() {
|
||||
Blockly.FieldTextInput.superClass_.render_.call(this);
|
||||
FieldTextInput.prototype.render_ = function() {
|
||||
FieldTextInput.superClass_.render_.call(this);
|
||||
// This logic is done in render_ rather than doValueInvalid_ or
|
||||
// doValueUpdate_ so that the code is more centralized.
|
||||
if (this.isBeingEdited_) {
|
||||
this.resizeEditor_();
|
||||
var htmlInput = /** @type {!HTMLElement} */(this.htmlInput_);
|
||||
const htmlInput = /** @type {!HTMLElement} */ (this.htmlInput_);
|
||||
if (!this.isTextValid_) {
|
||||
Blockly.utils.dom.addClass(htmlInput, 'blocklyInvalidInput');
|
||||
Blockly.utils.aria.setState(htmlInput,
|
||||
Blockly.utils.aria.State.INVALID, true);
|
||||
dom.addClass(htmlInput, 'blocklyInvalidInput');
|
||||
aria.setState(htmlInput, aria.State.INVALID, true);
|
||||
} else {
|
||||
Blockly.utils.dom.removeClass(htmlInput, 'blocklyInvalidInput');
|
||||
Blockly.utils.aria.setState(htmlInput,
|
||||
Blockly.utils.aria.State.INVALID, false);
|
||||
dom.removeClass(htmlInput, 'blocklyInvalidInput');
|
||||
aria.setState(htmlInput, aria.State.INVALID, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -274,7 +277,7 @@ Blockly.FieldTextInput.prototype.render_ = function() {
|
||||
* Set whether this field is spellchecked by the browser.
|
||||
* @param {boolean} check True if checked.
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.setSpellcheck = function(check) {
|
||||
FieldTextInput.prototype.setSpellcheck = function(check) {
|
||||
if (check == this.spellcheck_) {
|
||||
return;
|
||||
}
|
||||
@@ -292,14 +295,11 @@ Blockly.FieldTextInput.prototype.setSpellcheck = function(check) {
|
||||
* focus. Defaults to false.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.showEditor_ = function(_opt_e,
|
||||
opt_quietInput) {
|
||||
this.workspace_ =
|
||||
(/** @type {!Blockly.BlockSvg} */ (this.sourceBlock_)).workspace;
|
||||
var quietInput = opt_quietInput || false;
|
||||
if (!quietInput && (Blockly.utils.userAgent.MOBILE ||
|
||||
Blockly.utils.userAgent.ANDROID ||
|
||||
Blockly.utils.userAgent.IPAD)) {
|
||||
FieldTextInput.prototype.showEditor_ = function(_opt_e, opt_quietInput) {
|
||||
this.workspace_ = (/** @type {!BlockSvg} */ (this.sourceBlock_)).workspace;
|
||||
const quietInput = opt_quietInput || false;
|
||||
if (!quietInput &&
|
||||
(userAgent.MOBILE || userAgent.ANDROID || userAgent.IPAD)) {
|
||||
this.showPromptEditor_();
|
||||
} else {
|
||||
this.showInlineEditor_(quietInput);
|
||||
@@ -311,11 +311,10 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(_opt_e,
|
||||
* Mobile browsers have issues with in-line textareas (focus and keyboards).
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.showPromptEditor_ = function() {
|
||||
Blockly.prompt(Blockly.Msg['CHANGE_VALUE_TITLE'], this.getText(),
|
||||
function(text) {
|
||||
this.setValue(this.getValueFromEditorText_(text));
|
||||
}.bind(this));
|
||||
FieldTextInput.prototype.showPromptEditor_ = function() {
|
||||
blocklyPrompt(Msg['CHANGE_VALUE_TITLE'], this.getText(), function(text) {
|
||||
this.setValue(this.getValueFromEditorText_(text));
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -324,14 +323,13 @@ Blockly.FieldTextInput.prototype.showPromptEditor_ = function() {
|
||||
* focus.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) {
|
||||
Blockly.WidgetDiv.show(
|
||||
this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));
|
||||
FieldTextInput.prototype.showInlineEditor_ = function(quietInput) {
|
||||
WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));
|
||||
this.htmlInput_ = this.widgetCreate_();
|
||||
this.isBeingEdited_ = true;
|
||||
|
||||
if (!quietInput) {
|
||||
this.htmlInput_.focus({preventScroll:true});
|
||||
this.htmlInput_.focus({preventScroll: true});
|
||||
this.htmlInput_.select();
|
||||
}
|
||||
};
|
||||
@@ -341,38 +339,37 @@ Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) {
|
||||
* @return {!HTMLElement} The newly created text input editor.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.widgetCreate_ = function() {
|
||||
Blockly.Events.setGroup(true);
|
||||
var div = Blockly.WidgetDiv.DIV;
|
||||
FieldTextInput.prototype.widgetCreate_ = function() {
|
||||
Events.setGroup(true);
|
||||
const div = WidgetDiv.DIV;
|
||||
|
||||
Blockly.utils.dom.addClass(this.getClickTarget_(), 'editing');
|
||||
dom.addClass(this.getClickTarget_(), 'editing');
|
||||
|
||||
var htmlInput = /** @type {HTMLInputElement} */ (document.createElement('input'));
|
||||
const htmlInput =
|
||||
/** @type {HTMLInputElement} */ (document.createElement('input'));
|
||||
htmlInput.className = 'blocklyHtmlInput';
|
||||
htmlInput.setAttribute('spellcheck', this.spellcheck_);
|
||||
var scale = this.workspace_.getScale();
|
||||
var fontSize =
|
||||
(this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt';
|
||||
const scale = this.workspace_.getScale();
|
||||
const fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt';
|
||||
div.style.fontSize = fontSize;
|
||||
htmlInput.style.fontSize = fontSize;
|
||||
var borderRadius =
|
||||
(Blockly.FieldTextInput.BORDERRADIUS * scale) + 'px';
|
||||
let borderRadius = (FieldTextInput.BORDERRADIUS * scale) + 'px';
|
||||
|
||||
if (this.fullBlockClickTarget_) {
|
||||
var bBox = this.getScaledBBox();
|
||||
const bBox = this.getScaledBBox();
|
||||
|
||||
// Override border radius.
|
||||
borderRadius = (bBox.bottom - bBox.top) / 2 + 'px';
|
||||
// Pull stroke colour from the existing shadow block
|
||||
var strokeColour = this.sourceBlock_.getParent() ?
|
||||
this.sourceBlock_.getParent().style.colourTertiary :
|
||||
this.sourceBlock_.style.colourTertiary;
|
||||
const strokeColour = this.sourceBlock_.getParent() ?
|
||||
this.sourceBlock_.getParent().style.colourTertiary :
|
||||
this.sourceBlock_.style.colourTertiary;
|
||||
htmlInput.style.border = (1 * scale) + 'px solid ' + strokeColour;
|
||||
div.style.borderRadius = borderRadius;
|
||||
div.style.transition = 'box-shadow 0.25s ease 0s';
|
||||
if (this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW) {
|
||||
div.style.boxShadow = 'rgba(255, 255, 255, 0.3) 0 0 0 ' +
|
||||
(4 * scale) + 'px';
|
||||
div.style.boxShadow =
|
||||
'rgba(255, 255, 255, 0.3) 0 0 0 ' + (4 * scale) + 'px';
|
||||
}
|
||||
}
|
||||
htmlInput.style.borderRadius = borderRadius;
|
||||
@@ -395,7 +392,7 @@ Blockly.FieldTextInput.prototype.widgetCreate_ = function() {
|
||||
* DOM-references belonging to the editor.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
|
||||
FieldTextInput.prototype.widgetDispose_ = function() {
|
||||
// Non-disposal related things that we do when the editor closes.
|
||||
this.isBeingEdited_ = false;
|
||||
this.isTextValid_ = true;
|
||||
@@ -405,11 +402,11 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
|
||||
if (this.onFinishEditing_) {
|
||||
this.onFinishEditing_(this.value_);
|
||||
}
|
||||
Blockly.Events.setGroup(false);
|
||||
Events.setGroup(false);
|
||||
|
||||
// Actual disposal.
|
||||
this.unbindInputEvents_();
|
||||
var style = Blockly.WidgetDiv.DIV.style;
|
||||
const style = WidgetDiv.DIV.style;
|
||||
style.width = 'auto';
|
||||
style.height = 'auto';
|
||||
style.fontSize = '';
|
||||
@@ -417,7 +414,7 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
|
||||
style.boxShadow = '';
|
||||
this.htmlInput_ = null;
|
||||
|
||||
Blockly.utils.dom.removeClass(this.getClickTarget_(), 'editing');
|
||||
dom.removeClass(this.getClickTarget_(), 'editing');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -426,12 +423,12 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
|
||||
* handlers will be bound.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) {
|
||||
FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) {
|
||||
// Trap Enter without IME and Esc to hide.
|
||||
this.onKeyDownWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
this.onKeyDownWrapper_ = browserEvents.conditionalBind(
|
||||
htmlInput, 'keydown', this, this.onHtmlInputKeyDown_);
|
||||
// Resize after every input change.
|
||||
this.onKeyInputWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
this.onKeyInputWrapper_ = browserEvents.conditionalBind(
|
||||
htmlInput, 'input', this, this.onHtmlInputChange_);
|
||||
};
|
||||
|
||||
@@ -439,13 +436,13 @@ Blockly.FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) {
|
||||
* Unbind handlers for user input and workspace size changes.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.unbindInputEvents_ = function() {
|
||||
FieldTextInput.prototype.unbindInputEvents_ = function() {
|
||||
if (this.onKeyDownWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onKeyDownWrapper_);
|
||||
browserEvents.unbind(this.onKeyDownWrapper_);
|
||||
this.onKeyDownWrapper_ = null;
|
||||
}
|
||||
if (this.onKeyInputWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onKeyInputWrapper_);
|
||||
browserEvents.unbind(this.onKeyInputWrapper_);
|
||||
this.onKeyInputWrapper_ = null;
|
||||
}
|
||||
};
|
||||
@@ -455,17 +452,17 @@ Blockly.FieldTextInput.prototype.unbindInputEvents_ = function() {
|
||||
* @param {!Event} e Keyboard event.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) {
|
||||
if (e.keyCode == Blockly.utils.KeyCodes.ENTER) {
|
||||
Blockly.WidgetDiv.hide();
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
} else if (e.keyCode == Blockly.utils.KeyCodes.ESC) {
|
||||
FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) {
|
||||
if (e.keyCode == KeyCodes.ENTER) {
|
||||
WidgetDiv.hide();
|
||||
DropDownDiv.hideWithoutAnimation();
|
||||
} else if (e.keyCode == KeyCodes.ESC) {
|
||||
this.setValue(this.htmlInput_.untypedDefaultValue_);
|
||||
Blockly.WidgetDiv.hide();
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
} else if (e.keyCode == Blockly.utils.KeyCodes.TAB) {
|
||||
Blockly.WidgetDiv.hide();
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
WidgetDiv.hide();
|
||||
DropDownDiv.hideWithoutAnimation();
|
||||
} else if (e.keyCode == KeyCodes.TAB) {
|
||||
WidgetDiv.hide();
|
||||
DropDownDiv.hideWithoutAnimation();
|
||||
this.sourceBlock_.tab(this, !e.shiftKey);
|
||||
e.preventDefault();
|
||||
}
|
||||
@@ -476,12 +473,12 @@ Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) {
|
||||
* @param {!Event} _e Keyboard event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(_e) {
|
||||
var text = this.htmlInput_.value;
|
||||
FieldTextInput.prototype.onHtmlInputChange_ = function(_e) {
|
||||
const text = this.htmlInput_.value;
|
||||
if (text !== this.htmlInput_.oldValue_) {
|
||||
this.htmlInput_.oldValue_ = text;
|
||||
|
||||
var value = this.getValueFromEditorText_(text);
|
||||
const value = this.getValueFromEditorText_(text);
|
||||
this.setValue(value);
|
||||
this.forceRerender();
|
||||
this.resizeEditor_();
|
||||
@@ -495,7 +492,7 @@ Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(_e) {
|
||||
* @param {*} newValue New value.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.setEditorValue_ = function(newValue) {
|
||||
FieldTextInput.prototype.setEditorValue_ = function(newValue) {
|
||||
this.isDirty_ = true;
|
||||
if (this.isBeingEdited_) {
|
||||
// In the case this method is passed an invalid value, we still
|
||||
@@ -511,16 +508,16 @@ Blockly.FieldTextInput.prototype.setEditorValue_ = function(newValue) {
|
||||
* Resize the editor to fit the text.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
|
||||
var div = Blockly.WidgetDiv.DIV;
|
||||
var bBox = this.getScaledBBox();
|
||||
FieldTextInput.prototype.resizeEditor_ = function() {
|
||||
const div = WidgetDiv.DIV;
|
||||
const bBox = this.getScaledBBox();
|
||||
div.style.width = bBox.right - bBox.left + 'px';
|
||||
div.style.height = bBox.bottom - bBox.top + 'px';
|
||||
|
||||
// In RTL mode block fields and LTR input fields the left edge moves,
|
||||
// whereas the right edge is fixed. Reposition the editor.
|
||||
var x = this.sourceBlock_.RTL ? bBox.right - div.offsetWidth : bBox.left;
|
||||
var xy = new Blockly.utils.Coordinate(x, bBox.top);
|
||||
const x = this.sourceBlock_.RTL ? bBox.right - div.offsetWidth : bBox.left;
|
||||
const xy = new Coordinate(x, bBox.top);
|
||||
|
||||
div.style.left = xy.x + 'px';
|
||||
div.style.top = xy.y + 'px';
|
||||
@@ -531,20 +528,20 @@ Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
|
||||
* @return {boolean} True if the field is tab navigable.
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.isTabNavigable = function() {
|
||||
FieldTextInput.prototype.isTabNavigable = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Use the `getText_` developer hook to override the field's text representation.
|
||||
* When we're currently editing, return the current HTML value instead.
|
||||
* Otherwise, return null which tells the field to use the default behaviour
|
||||
* (which is a string cast of the field's value).
|
||||
* Use the `getText_` developer hook to override the field's text
|
||||
* representation. When we're currently editing, return the current HTML value
|
||||
* instead. Otherwise, return null which tells the field to use the default
|
||||
* behaviour (which is a string cast of the field's value).
|
||||
* @return {?string} The HTML value if we're editing, otherwise null.
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.getText_ = function() {
|
||||
FieldTextInput.prototype.getText_ = function() {
|
||||
if (this.isBeingEdited_ && this.htmlInput_) {
|
||||
// We are currently editing, return the HTML input value instead.
|
||||
return this.htmlInput_.value;
|
||||
@@ -561,7 +558,7 @@ Blockly.FieldTextInput.prototype.getText_ = function() {
|
||||
* @return {string} The text to show on the HTML input.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.getEditorText_ = function(value) {
|
||||
FieldTextInput.prototype.getEditorText_ = function(value) {
|
||||
return String(value);
|
||||
};
|
||||
|
||||
@@ -575,8 +572,10 @@ Blockly.FieldTextInput.prototype.getEditorText_ = function(value) {
|
||||
* @return {*} The value to store.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.getValueFromEditorText_ = function(text) {
|
||||
FieldTextInput.prototype.getValueFromEditorText_ = function(text) {
|
||||
return text;
|
||||
};
|
||||
|
||||
Blockly.fieldRegistry.register('field_input', Blockly.FieldTextInput);
|
||||
fieldRegistry.register('field_input', FieldTextInput);
|
||||
|
||||
exports = FieldTextInput;
|
||||
|
||||
@@ -13,9 +13,12 @@
|
||||
goog.module('Blockly.FieldVariable');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
const FieldDropdown = goog.require('Blockly.FieldDropdown');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Menu = goog.requireType('Blockly.Menu');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const MenuItem = goog.requireType('Blockly.MenuItem');
|
||||
const Msg = goog.require('Blockly.Msg');
|
||||
const Size = goog.require('Blockly.utils.Size');
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,36 +10,36 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.HorizontalFlyout');
|
||||
goog.module('Blockly.HorizontalFlyout');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Block');
|
||||
goog.require('Blockly.DropDownDiv');
|
||||
goog.require('Blockly.Flyout');
|
||||
goog.require('Blockly.registry');
|
||||
goog.require('Blockly.Scrollbar');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.Rect');
|
||||
goog.require('Blockly.utils.toolbox');
|
||||
goog.require('Blockly.WidgetDiv');
|
||||
|
||||
goog.requireType('Blockly.Options');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const DropDownDiv = goog.require('Blockly.DropDownDiv');
|
||||
const Flyout = goog.require('Blockly.Flyout');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Options = goog.requireType('Blockly.Options');
|
||||
const Rect = goog.require('Blockly.utils.Rect');
|
||||
const Scrollbar = goog.require('Blockly.Scrollbar');
|
||||
const WidgetDiv = goog.require('Blockly.WidgetDiv');
|
||||
const registry = goog.require('Blockly.registry');
|
||||
const {Position} = goog.require('Blockly.utils.toolbox');
|
||||
const {getScrollDeltaPixels} = goog.require('Blockly.utils');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a flyout.
|
||||
* @param {!Blockly.Options} workspaceOptions Dictionary of options for the
|
||||
* @param {!Options} workspaceOptions Dictionary of options for the
|
||||
* workspace.
|
||||
* @extends {Blockly.Flyout}
|
||||
* @extends {Flyout}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.HorizontalFlyout = function(workspaceOptions) {
|
||||
Blockly.HorizontalFlyout.superClass_.constructor.call(this, workspaceOptions);
|
||||
const HorizontalFlyout = function(workspaceOptions) {
|
||||
HorizontalFlyout.superClass_.constructor.call(this, workspaceOptions);
|
||||
this.horizontalLayout = true;
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout);
|
||||
inherits(HorizontalFlyout, Flyout);
|
||||
|
||||
/**
|
||||
* Sets the translation of the flyout to match the scrollbars.
|
||||
@@ -48,23 +48,24 @@ Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout);
|
||||
* similar x property.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
if (!this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
const metricsManager = this.workspace_.getMetricsManager();
|
||||
const scrollMetrics = metricsManager.getScrollMetrics();
|
||||
const viewMetrics = metricsManager.getViewMetrics();
|
||||
const absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
|
||||
if (typeof xyRatio.x == 'number') {
|
||||
this.workspace_.scrollX =
|
||||
-(scrollMetrics.left +
|
||||
(scrollMetrics.width - viewMetrics.width) * xyRatio.x);
|
||||
(scrollMetrics.width - viewMetrics.width) * xyRatio.x);
|
||||
}
|
||||
|
||||
this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left,
|
||||
this.workspace_.translate(
|
||||
this.workspace_.scrollX + absoluteMetrics.left,
|
||||
this.workspace_.scrollY + absoluteMetrics.top);
|
||||
};
|
||||
|
||||
@@ -72,7 +73,7 @@ Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
* Calculates the x coordinate for the flyout position.
|
||||
* @return {number} X coordinate.
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.getX = function() {
|
||||
HorizontalFlyout.prototype.getX = function() {
|
||||
// X is always 0 since this is a horizontal flyout.
|
||||
return 0;
|
||||
};
|
||||
@@ -81,17 +82,17 @@ Blockly.HorizontalFlyout.prototype.getX = function() {
|
||||
* Calculates the y coordinate for the flyout position.
|
||||
* @return {number} Y coordinate.
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.getY = function() {
|
||||
HorizontalFlyout.prototype.getY = function() {
|
||||
if (!this.isVisible()) {
|
||||
return 0;
|
||||
}
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var toolboxMetrics = metricsManager.getToolboxMetrics();
|
||||
const metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
const absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
const viewMetrics = metricsManager.getViewMetrics();
|
||||
const toolboxMetrics = metricsManager.getToolboxMetrics();
|
||||
|
||||
var y = 0;
|
||||
var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP;
|
||||
let y = 0;
|
||||
const atTop = this.toolboxPosition_ == Position.TOP;
|
||||
// If this flyout is not the trashcan flyout (e.g. toolbox or mutator).
|
||||
if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_) {
|
||||
// If there is a category toolbox.
|
||||
@@ -129,22 +130,22 @@ Blockly.HorizontalFlyout.prototype.getY = function() {
|
||||
/**
|
||||
* Move the flyout to the edge of the workspace.
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.position = function() {
|
||||
HorizontalFlyout.prototype.position = function() {
|
||||
if (!this.isVisible() || !this.targetWorkspace.isVisible()) {
|
||||
return;
|
||||
}
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var targetWorkspaceViewMetrics = metricsManager.getViewMetrics();
|
||||
const metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
const targetWorkspaceViewMetrics = metricsManager.getViewMetrics();
|
||||
|
||||
// Record the width for workspace metrics.
|
||||
this.width_ = targetWorkspaceViewMetrics.width;
|
||||
|
||||
var edgeWidth = targetWorkspaceViewMetrics.width - 2 * this.CORNER_RADIUS;
|
||||
var edgeHeight = this.height_ - this.CORNER_RADIUS;
|
||||
const edgeWidth = targetWorkspaceViewMetrics.width - 2 * this.CORNER_RADIUS;
|
||||
const edgeHeight = this.height_ - this.CORNER_RADIUS;
|
||||
this.setBackgroundPath_(edgeWidth, edgeHeight);
|
||||
|
||||
var x = this.getX();
|
||||
var y = this.getY();
|
||||
const x = this.getX();
|
||||
const y = this.getY();
|
||||
|
||||
this.positionAt_(this.width_, this.height_, x, y);
|
||||
};
|
||||
@@ -157,11 +158,10 @@ Blockly.HorizontalFlyout.prototype.position = function() {
|
||||
* rounded corners.
|
||||
* @private
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function(
|
||||
width, height) {
|
||||
var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP;
|
||||
HorizontalFlyout.prototype.setBackgroundPath_ = function(width, height) {
|
||||
const atTop = this.toolboxPosition_ == Position.TOP;
|
||||
// Start at top left.
|
||||
var path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)];
|
||||
const path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)];
|
||||
|
||||
if (atTop) {
|
||||
// Top.
|
||||
@@ -169,20 +169,24 @@ Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function(
|
||||
// Right.
|
||||
path.push('v', height);
|
||||
// Bottom.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
path.push(
|
||||
'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
-this.CORNER_RADIUS, this.CORNER_RADIUS);
|
||||
path.push('h', -width);
|
||||
// Left.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
path.push(
|
||||
'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
-this.CORNER_RADIUS, -this.CORNER_RADIUS);
|
||||
path.push('z');
|
||||
} else {
|
||||
// Top.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
path.push(
|
||||
'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
this.CORNER_RADIUS, -this.CORNER_RADIUS);
|
||||
path.push('h', width);
|
||||
// Right.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
path.push(
|
||||
'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
|
||||
this.CORNER_RADIUS, this.CORNER_RADIUS);
|
||||
path.push('v', height);
|
||||
// Bottom.
|
||||
@@ -196,7 +200,7 @@ Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function(
|
||||
/**
|
||||
* Scroll the flyout to the top.
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.scrollToStart = function() {
|
||||
HorizontalFlyout.prototype.scrollToStart = function() {
|
||||
this.workspace_.scrollbar.setX(this.RTL ? Infinity : 0);
|
||||
};
|
||||
|
||||
@@ -205,20 +209,20 @@ Blockly.HorizontalFlyout.prototype.scrollToStart = function() {
|
||||
* @param {!Event} e Mouse wheel scroll event.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
|
||||
var scrollDelta = Blockly.utils.getScrollDeltaPixels(e);
|
||||
var delta = scrollDelta.x || scrollDelta.y;
|
||||
HorizontalFlyout.prototype.wheel_ = function(e) {
|
||||
const scrollDelta = getScrollDeltaPixels(e);
|
||||
const delta = scrollDelta.x || scrollDelta.y;
|
||||
|
||||
if (delta) {
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
const metricsManager = this.workspace_.getMetricsManager();
|
||||
const scrollMetrics = metricsManager.getScrollMetrics();
|
||||
const viewMetrics = metricsManager.getViewMetrics();
|
||||
|
||||
var pos = (viewMetrics.left - scrollMetrics.left) + delta;
|
||||
const pos = (viewMetrics.left - scrollMetrics.left) + delta;
|
||||
this.workspace_.scrollbar.setX(pos);
|
||||
// When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
|
||||
Blockly.WidgetDiv.hide();
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
WidgetDiv.hide();
|
||||
DropDownDiv.hideWithoutAnimation();
|
||||
}
|
||||
|
||||
// Don't scroll the page.
|
||||
@@ -233,39 +237,40 @@ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
|
||||
* @param {!Array<number>} gaps The visible gaps between blocks.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
this.workspace_.scale = this.targetWorkspace.scale;
|
||||
var margin = this.MARGIN;
|
||||
var cursorX = margin + this.tabWidth_;
|
||||
var cursorY = margin;
|
||||
const margin = this.MARGIN;
|
||||
let cursorX = margin + this.tabWidth_;
|
||||
const cursorY = margin;
|
||||
if (this.RTL) {
|
||||
contents = contents.reverse();
|
||||
}
|
||||
|
||||
for (var i = 0, item; (item = contents[i]); i++) {
|
||||
for (let i = 0, item; (item = contents[i]); i++) {
|
||||
if (item.type == 'block') {
|
||||
var block = item.block;
|
||||
var allBlocks = block.getDescendants(false);
|
||||
for (var j = 0, child; (child = allBlocks[j]); j++) {
|
||||
const block = item.block;
|
||||
const allBlocks = block.getDescendants(false);
|
||||
for (let j = 0, child; (child = allBlocks[j]); j++) {
|
||||
// Mark blocks as being inside a flyout. This is used to detect and
|
||||
// prevent the closure of the flyout if the user right-clicks on such a
|
||||
// block.
|
||||
child.isInFlyout = true;
|
||||
}
|
||||
block.render();
|
||||
var root = block.getSvgRoot();
|
||||
var blockHW = block.getHeightWidth();
|
||||
const root = block.getSvgRoot();
|
||||
const blockHW = block.getHeightWidth();
|
||||
|
||||
// Figure out where to place the block.
|
||||
var tab = block.outputConnection ? this.tabWidth_ : 0;
|
||||
const tab = block.outputConnection ? this.tabWidth_ : 0;
|
||||
let moveX;
|
||||
if (this.RTL) {
|
||||
var moveX = cursorX + blockHW.width;
|
||||
moveX = cursorX + blockHW.width;
|
||||
} else {
|
||||
var moveX = cursorX - tab;
|
||||
moveX = cursorX - tab;
|
||||
}
|
||||
block.moveBy(moveX, cursorY);
|
||||
|
||||
var rect = this.createRect_(block, moveX, cursorY, blockHW, i);
|
||||
const rect = this.createRect_(block, moveX, cursorY, blockHW, i);
|
||||
cursorX += (blockHW.width + gaps[i]);
|
||||
|
||||
this.addBlockListeners_(root, block, rect);
|
||||
@@ -280,19 +285,19 @@ Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
* 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.
|
||||
* @package
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function(
|
||||
HorizontalFlyout.prototype.isDragTowardWorkspace = function(
|
||||
currentDragDeltaXY) {
|
||||
var dx = currentDragDeltaXY.x;
|
||||
var dy = currentDragDeltaXY.y;
|
||||
const dx = currentDragDeltaXY.x;
|
||||
const dy = currentDragDeltaXY.y;
|
||||
// Direction goes from -180 to 180, with 0 toward the right and 90 on top.
|
||||
var dragDirection = Math.atan2(dy, dx) / Math.PI * 180;
|
||||
const dragDirection = Math.atan2(dy, dx) / Math.PI * 180;
|
||||
|
||||
var range = this.dragAngleRange_;
|
||||
const range = this.dragAngleRange_;
|
||||
// Check for up or down dragging.
|
||||
if ((dragDirection < 90 + range && dragDirection > 90 - range) ||
|
||||
(dragDirection > -90 - range && dragDirection < -90 + range)) {
|
||||
@@ -304,28 +309,28 @@ Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = 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.HorizontalFlyout.prototype.getClientRect = function() {
|
||||
HorizontalFlyout.prototype.getClientRect = function() {
|
||||
if (!this.svgGroup_ || this.autoClose || !this.isVisible()) {
|
||||
// The bounding rectangle won't compute correctly if the flyout is closed
|
||||
// and auto-close flyouts aren't valid drag targets (or delete areas).
|
||||
return null;
|
||||
}
|
||||
|
||||
var flyoutRect = this.svgGroup_.getBoundingClientRect();
|
||||
const flyoutRect = this.svgGroup_.getBoundingClientRect();
|
||||
// BIG_NUM is offscreen padding so that blocks dragged beyond the shown flyout
|
||||
// area are still deleted. Must be larger than the largest screen size,
|
||||
// but be smaller than half Number.MAX_SAFE_INTEGER (not available on IE).
|
||||
var BIG_NUM = 1000000000;
|
||||
var top = flyoutRect.top;
|
||||
const BIG_NUM = 1000000000;
|
||||
const top = flyoutRect.top;
|
||||
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP) {
|
||||
var height = flyoutRect.height;
|
||||
return new Blockly.utils.Rect(-BIG_NUM, top + height, -BIG_NUM, BIG_NUM);
|
||||
if (this.toolboxPosition_ == Position.TOP) {
|
||||
const height = flyoutRect.height;
|
||||
return new Rect(-BIG_NUM, top + height, -BIG_NUM, BIG_NUM);
|
||||
} else { // Bottom.
|
||||
return new Blockly.utils.Rect(top, BIG_NUM, -BIG_NUM, BIG_NUM);
|
||||
return new Rect(top, BIG_NUM, -BIG_NUM, BIG_NUM);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -334,36 +339,37 @@ Blockly.HorizontalFlyout.prototype.getClientRect = function() {
|
||||
* For RTL: Lay out the blocks right-aligned.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() {
|
||||
HorizontalFlyout.prototype.reflowInternal_ = function() {
|
||||
this.workspace_.scale = this.getFlyoutScale();
|
||||
var flyoutHeight = 0;
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
for (var i = 0, block; (block = blocks[i]); i++) {
|
||||
let flyoutHeight = 0;
|
||||
const blocks = this.workspace_.getTopBlocks(false);
|
||||
for (let i = 0, block; (block = blocks[i]); i++) {
|
||||
flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height);
|
||||
}
|
||||
var buttons = this.buttons_;
|
||||
for (var i = 0, button; (button = buttons[i]); i++) {
|
||||
const buttons = this.buttons_;
|
||||
for (let i = 0, button; (button = buttons[i]); i++) {
|
||||
flyoutHeight = Math.max(flyoutHeight, button.height);
|
||||
}
|
||||
flyoutHeight += this.MARGIN * 1.5;
|
||||
flyoutHeight *= this.workspace_.scale;
|
||||
flyoutHeight += Blockly.Scrollbar.scrollbarThickness;
|
||||
flyoutHeight += Scrollbar.scrollbarThickness;
|
||||
|
||||
if (this.height_ != flyoutHeight) {
|
||||
for (var i = 0, block; (block = blocks[i]); i++) {
|
||||
for (let i = 0, block; (block = blocks[i]); i++) {
|
||||
if (block.flyoutRect_) {
|
||||
this.moveRectToBlock_(block.flyoutRect_, block);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_ &&
|
||||
this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP &&
|
||||
this.toolboxPosition_ == Position.TOP &&
|
||||
!this.targetWorkspace.getToolbox()) {
|
||||
// This flyout is a simple toolbox. Reposition the workspace so that (0,0)
|
||||
// is in the correct position relative to the new absolute edge (ie
|
||||
// toolbox edge).
|
||||
this.targetWorkspace.translate(
|
||||
this.targetWorkspace.scrollX, this.targetWorkspace.scrollY + flyoutHeight);
|
||||
this.targetWorkspace.scrollX,
|
||||
this.targetWorkspace.scrollY + flyoutHeight);
|
||||
}
|
||||
|
||||
// Record the height for workspace metrics and .position.
|
||||
@@ -373,5 +379,8 @@ Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() {
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.registry.register(Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX,
|
||||
Blockly.registry.DEFAULT, Blockly.HorizontalFlyout);
|
||||
registry.register(
|
||||
registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX, registry.DEFAULT,
|
||||
HorizontalFlyout);
|
||||
|
||||
exports = HorizontalFlyout;
|
||||
|
||||
@@ -10,43 +10,45 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.VerticalFlyout');
|
||||
goog.module('Blockly.VerticalFlyout');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const DropDownDiv = goog.require('Blockly.DropDownDiv');
|
||||
const Flyout = goog.require('Blockly.Flyout');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Options = goog.requireType('Blockly.Options');
|
||||
const Rect = goog.require('Blockly.utils.Rect');
|
||||
const Scrollbar = goog.require('Blockly.Scrollbar');
|
||||
const WidgetDiv = goog.require('Blockly.WidgetDiv');
|
||||
const registry = goog.require('Blockly.registry');
|
||||
const {Position} = goog.require('Blockly.utils.toolbox');
|
||||
const {getScrollDeltaPixels} = goog.require('Blockly.utils');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Block');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.constants');
|
||||
goog.require('Blockly.DropDownDiv');
|
||||
goog.require('Blockly.Flyout');
|
||||
goog.require('Blockly.registry');
|
||||
goog.require('Blockly.Scrollbar');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.Rect');
|
||||
goog.require('Blockly.utils.toolbox');
|
||||
goog.require('Blockly.WidgetDiv');
|
||||
|
||||
goog.requireType('Blockly.Options');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a flyout.
|
||||
* @param {!Blockly.Options} workspaceOptions Dictionary of options for the
|
||||
* @param {!Options} workspaceOptions Dictionary of options for the
|
||||
* workspace.
|
||||
* @extends {Blockly.Flyout}
|
||||
* @extends {Flyout}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.VerticalFlyout = function(workspaceOptions) {
|
||||
Blockly.VerticalFlyout.superClass_.constructor.call(this, workspaceOptions);
|
||||
const VerticalFlyout = function(workspaceOptions) {
|
||||
VerticalFlyout.superClass_.constructor.call(this, workspaceOptions);
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.VerticalFlyout, Blockly.Flyout);
|
||||
inherits(VerticalFlyout, Flyout);
|
||||
|
||||
/**
|
||||
* The name of the vertical flyout in the registry.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.VerticalFlyout.registryName = 'verticalFlyout';
|
||||
VerticalFlyout.registryName = 'verticalFlyout';
|
||||
|
||||
/**
|
||||
* Sets the translation of the flyout to match the scrollbars.
|
||||
@@ -55,21 +57,22 @@ Blockly.VerticalFlyout.registryName = 'verticalFlyout';
|
||||
* similar x property.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
VerticalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
if (!this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
const metricsManager = this.workspace_.getMetricsManager();
|
||||
const scrollMetrics = metricsManager.getScrollMetrics();
|
||||
const viewMetrics = metricsManager.getViewMetrics();
|
||||
const absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
|
||||
if (typeof xyRatio.y == 'number') {
|
||||
this.workspace_.scrollY =
|
||||
-(scrollMetrics.top +
|
||||
(scrollMetrics.height - viewMetrics.height) * xyRatio.y);
|
||||
(scrollMetrics.height - viewMetrics.height) * xyRatio.y);
|
||||
}
|
||||
this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left,
|
||||
this.workspace_.translate(
|
||||
this.workspace_.scrollX + absoluteMetrics.left,
|
||||
this.workspace_.scrollY + absoluteMetrics.top);
|
||||
};
|
||||
|
||||
@@ -77,28 +80,28 @@ Blockly.VerticalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
* Calculates the x coordinate for the flyout position.
|
||||
* @return {number} X coordinate.
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.getX = function() {
|
||||
VerticalFlyout.prototype.getX = function() {
|
||||
if (!this.isVisible()) {
|
||||
return 0;
|
||||
}
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var toolboxMetrics = metricsManager.getToolboxMetrics();
|
||||
var x = 0;
|
||||
const metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
const absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
const viewMetrics = metricsManager.getViewMetrics();
|
||||
const toolboxMetrics = metricsManager.getToolboxMetrics();
|
||||
let x = 0;
|
||||
|
||||
// If this flyout is not the trashcan flyout (e.g. toolbox or mutator).
|
||||
if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_) {
|
||||
// If there is a category toolbox.
|
||||
if (this.targetWorkspace.getToolbox()) {
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) {
|
||||
if (this.toolboxPosition_ == Position.LEFT) {
|
||||
x = toolboxMetrics.width;
|
||||
} else {
|
||||
x = viewMetrics.width - this.width_;
|
||||
}
|
||||
// Simple (flyout-only) toolbox.
|
||||
} else {
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) {
|
||||
if (this.toolboxPosition_ == Position.LEFT) {
|
||||
x = 0;
|
||||
} else {
|
||||
// The simple flyout does not cover the workspace.
|
||||
@@ -107,7 +110,7 @@ Blockly.VerticalFlyout.prototype.getX = function() {
|
||||
}
|
||||
// Trashcan flyout is opposite the main flyout.
|
||||
} else {
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) {
|
||||
if (this.toolboxPosition_ == Position.LEFT) {
|
||||
x = 0;
|
||||
} else {
|
||||
// Because the anchor point of the flyout is on the left, but we want
|
||||
@@ -125,7 +128,7 @@ Blockly.VerticalFlyout.prototype.getX = function() {
|
||||
* Calculates the y coordinate for the flyout position.
|
||||
* @return {number} Y coordinate.
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.getY = function() {
|
||||
VerticalFlyout.prototype.getY = function() {
|
||||
// Y is always 0 since this is a vertical flyout.
|
||||
return 0;
|
||||
};
|
||||
@@ -133,22 +136,22 @@ Blockly.VerticalFlyout.prototype.getY = function() {
|
||||
/**
|
||||
* Move the flyout to the edge of the workspace.
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.position = function() {
|
||||
VerticalFlyout.prototype.position = function() {
|
||||
if (!this.isVisible() || !this.targetWorkspace.isVisible()) {
|
||||
return;
|
||||
}
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var targetWorkspaceViewMetrics = metricsManager.getViewMetrics();
|
||||
const metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
const targetWorkspaceViewMetrics = metricsManager.getViewMetrics();
|
||||
|
||||
// Record the height for workspace metrics.
|
||||
this.height_ = targetWorkspaceViewMetrics.height;
|
||||
|
||||
var edgeWidth = this.width_ - this.CORNER_RADIUS;
|
||||
var edgeHeight = targetWorkspaceViewMetrics.height - 2 * this.CORNER_RADIUS;
|
||||
const edgeWidth = this.width_ - this.CORNER_RADIUS;
|
||||
const edgeHeight = targetWorkspaceViewMetrics.height - 2 * this.CORNER_RADIUS;
|
||||
this.setBackgroundPath_(edgeWidth, edgeHeight);
|
||||
|
||||
var x = this.getX();
|
||||
var y = this.getY();
|
||||
const x = this.getX();
|
||||
const y = this.getY();
|
||||
|
||||
this.positionAt_(this.width_, this.height_, x, y);
|
||||
};
|
||||
@@ -161,26 +164,24 @@ Blockly.VerticalFlyout.prototype.position = function() {
|
||||
* rounded corners.
|
||||
* @private
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) {
|
||||
var atRight = this.toolboxPosition_ == Blockly.utils.toolbox.Position.RIGHT;
|
||||
var totalWidth = width + this.CORNER_RADIUS;
|
||||
VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) {
|
||||
const atRight = this.toolboxPosition_ == Position.RIGHT;
|
||||
const totalWidth = width + this.CORNER_RADIUS;
|
||||
|
||||
// Decide whether to start on the left or right.
|
||||
var path = ['M ' + (atRight ? totalWidth : 0) + ',0'];
|
||||
const path = ['M ' + (atRight ? totalWidth : 0) + ',0'];
|
||||
// Top.
|
||||
path.push('h', atRight ? -width : width);
|
||||
// Rounded corner.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
|
||||
atRight ? 0 : 1,
|
||||
atRight ? -this.CORNER_RADIUS : this.CORNER_RADIUS,
|
||||
this.CORNER_RADIUS);
|
||||
path.push(
|
||||
'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, atRight ? 0 : 1,
|
||||
atRight ? -this.CORNER_RADIUS : this.CORNER_RADIUS, this.CORNER_RADIUS);
|
||||
// Side closest to workspace.
|
||||
path.push('v', Math.max(0, height));
|
||||
// Rounded corner.
|
||||
path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
|
||||
atRight ? 0 : 1,
|
||||
atRight ? this.CORNER_RADIUS : -this.CORNER_RADIUS,
|
||||
this.CORNER_RADIUS);
|
||||
path.push(
|
||||
'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, atRight ? 0 : 1,
|
||||
atRight ? this.CORNER_RADIUS : -this.CORNER_RADIUS, this.CORNER_RADIUS);
|
||||
// Bottom.
|
||||
path.push('h', atRight ? width : -width);
|
||||
path.push('z');
|
||||
@@ -190,7 +191,7 @@ Blockly.VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) {
|
||||
/**
|
||||
* Scroll the flyout to the top.
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.scrollToStart = function() {
|
||||
VerticalFlyout.prototype.scrollToStart = function() {
|
||||
this.workspace_.scrollbar.setY(0);
|
||||
};
|
||||
|
||||
@@ -199,19 +200,19 @@ Blockly.VerticalFlyout.prototype.scrollToStart = function() {
|
||||
* @param {!Event} e Mouse wheel scroll event.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.wheel_ = function(e) {
|
||||
var scrollDelta = Blockly.utils.getScrollDeltaPixels(e);
|
||||
VerticalFlyout.prototype.wheel_ = function(e) {
|
||||
const scrollDelta = getScrollDeltaPixels(e);
|
||||
|
||||
if (scrollDelta.y) {
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var pos = (viewMetrics.top - scrollMetrics.top) + scrollDelta.y;
|
||||
const metricsManager = this.workspace_.getMetricsManager();
|
||||
const scrollMetrics = metricsManager.getScrollMetrics();
|
||||
const viewMetrics = metricsManager.getViewMetrics();
|
||||
const pos = (viewMetrics.top - scrollMetrics.top) + scrollDelta.y;
|
||||
|
||||
this.workspace_.scrollbar.setY(pos);
|
||||
// When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
|
||||
Blockly.WidgetDiv.hide();
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
WidgetDiv.hide();
|
||||
DropDownDiv.hideWithoutAnimation();
|
||||
}
|
||||
|
||||
// Don't scroll the page.
|
||||
@@ -226,30 +227,30 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) {
|
||||
* @param {!Array<number>} gaps The visible gaps between blocks.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
VerticalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
this.workspace_.scale = this.targetWorkspace.scale;
|
||||
var margin = this.MARGIN;
|
||||
var cursorX = this.RTL ? margin : margin + this.tabWidth_;
|
||||
var cursorY = margin;
|
||||
const margin = this.MARGIN;
|
||||
const cursorX = this.RTL ? margin : margin + this.tabWidth_;
|
||||
let cursorY = margin;
|
||||
|
||||
for (var i = 0, item; (item = contents[i]); i++) {
|
||||
for (let i = 0, item; (item = contents[i]); i++) {
|
||||
if (item.type == 'block') {
|
||||
var block = item.block;
|
||||
var allBlocks = block.getDescendants(false);
|
||||
for (var j = 0, child; (child = allBlocks[j]); j++) {
|
||||
const block = item.block;
|
||||
const allBlocks = block.getDescendants(false);
|
||||
for (let j = 0, child; (child = allBlocks[j]); j++) {
|
||||
// Mark blocks as being inside a flyout. This is used to detect and
|
||||
// prevent the closure of the flyout if the user right-clicks on such a
|
||||
// block.
|
||||
child.isInFlyout = true;
|
||||
}
|
||||
block.render();
|
||||
var root = block.getSvgRoot();
|
||||
var blockHW = block.getHeightWidth();
|
||||
var moveX = block.outputConnection ? cursorX - this.tabWidth_ : cursorX;
|
||||
const root = block.getSvgRoot();
|
||||
const blockHW = block.getHeightWidth();
|
||||
const moveX = block.outputConnection ? cursorX - this.tabWidth_ : cursorX;
|
||||
block.moveBy(moveX, cursorY);
|
||||
|
||||
var rect = this.createRect_(block,
|
||||
this.RTL ? moveX - blockHW.width : moveX, cursorY, blockHW, i);
|
||||
const rect = this.createRect_(
|
||||
block, this.RTL ? moveX - blockHW.width : moveX, cursorY, blockHW, i);
|
||||
|
||||
this.addBlockListeners_(root, block, rect);
|
||||
|
||||
@@ -265,19 +266,18 @@ Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
* 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.
|
||||
* @package
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = function(
|
||||
currentDragDeltaXY) {
|
||||
var dx = currentDragDeltaXY.x;
|
||||
var dy = currentDragDeltaXY.y;
|
||||
VerticalFlyout.prototype.isDragTowardWorkspace = function(currentDragDeltaXY) {
|
||||
const dx = currentDragDeltaXY.x;
|
||||
const dy = currentDragDeltaXY.y;
|
||||
// Direction goes from -180 to 180, with 0 toward the right and 90 on top.
|
||||
var dragDirection = Math.atan2(dy, dx) / Math.PI * 180;
|
||||
const dragDirection = Math.atan2(dy, dx) / Math.PI * 180;
|
||||
|
||||
var range = this.dragAngleRange_;
|
||||
const range = this.dragAngleRange_;
|
||||
// Check for left or right dragging.
|
||||
if ((dragDirection < range && dragDirection > -range) ||
|
||||
(dragDirection < -180 + range || dragDirection > 180 - range)) {
|
||||
@@ -289,28 +289,28 @@ Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = 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.VerticalFlyout.prototype.getClientRect = function() {
|
||||
VerticalFlyout.prototype.getClientRect = function() {
|
||||
if (!this.svgGroup_ || this.autoClose || !this.isVisible()) {
|
||||
// The bounding rectangle won't compute correctly if the flyout is closed
|
||||
// and auto-close flyouts aren't valid drag targets (or delete areas).
|
||||
return null;
|
||||
}
|
||||
|
||||
var flyoutRect = this.svgGroup_.getBoundingClientRect();
|
||||
const flyoutRect = this.svgGroup_.getBoundingClientRect();
|
||||
// BIG_NUM is offscreen padding so that blocks dragged beyond the shown flyout
|
||||
// area are still deleted. Must be larger than the largest screen size,
|
||||
// but be smaller than half Number.MAX_SAFE_INTEGER (not available on IE).
|
||||
var BIG_NUM = 1000000000;
|
||||
var left = flyoutRect.left;
|
||||
const BIG_NUM = 1000000000;
|
||||
const left = flyoutRect.left;
|
||||
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) {
|
||||
var width = flyoutRect.width;
|
||||
return new Blockly.utils.Rect(-BIG_NUM, BIG_NUM, -BIG_NUM, left + width);
|
||||
if (this.toolboxPosition_ == Position.LEFT) {
|
||||
const width = flyoutRect.width;
|
||||
return new Rect(-BIG_NUM, BIG_NUM, -BIG_NUM, left + width);
|
||||
} else { // Right
|
||||
return new Blockly.utils.Rect(-BIG_NUM, BIG_NUM, left, BIG_NUM);
|
||||
return new Rect(-BIG_NUM, BIG_NUM, left, BIG_NUM);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -319,30 +319,30 @@ Blockly.VerticalFlyout.prototype.getClientRect = function() {
|
||||
* For RTL: Lay out the blocks and buttons to be right-aligned.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.reflowInternal_ = function() {
|
||||
VerticalFlyout.prototype.reflowInternal_ = function() {
|
||||
this.workspace_.scale = this.getFlyoutScale();
|
||||
var flyoutWidth = 0;
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
for (var i = 0, block; (block = blocks[i]); i++) {
|
||||
var width = block.getHeightWidth().width;
|
||||
let flyoutWidth = 0;
|
||||
const blocks = this.workspace_.getTopBlocks(false);
|
||||
for (let i = 0, block; (block = blocks[i]); i++) {
|
||||
let width = block.getHeightWidth().width;
|
||||
if (block.outputConnection) {
|
||||
width -= this.tabWidth_;
|
||||
}
|
||||
flyoutWidth = Math.max(flyoutWidth, width);
|
||||
}
|
||||
for (var i = 0, button; (button = this.buttons_[i]); i++) {
|
||||
for (let i = 0, button; (button = this.buttons_[i]); i++) {
|
||||
flyoutWidth = Math.max(flyoutWidth, button.width);
|
||||
}
|
||||
flyoutWidth += this.MARGIN * 1.5 + this.tabWidth_;
|
||||
flyoutWidth *= this.workspace_.scale;
|
||||
flyoutWidth += Blockly.Scrollbar.scrollbarThickness;
|
||||
flyoutWidth += Scrollbar.scrollbarThickness;
|
||||
|
||||
if (this.width_ != flyoutWidth) {
|
||||
for (var i = 0, block; (block = blocks[i]); i++) {
|
||||
for (let i = 0, block; (block = blocks[i]); i++) {
|
||||
if (this.RTL) {
|
||||
// With the flyoutWidth known, right-align the blocks.
|
||||
var oldX = block.getRelativeToSurfaceXY().x;
|
||||
var newX = flyoutWidth / this.workspace_.scale - this.MARGIN;
|
||||
const oldX = block.getRelativeToSurfaceXY().x;
|
||||
let newX = flyoutWidth / this.workspace_.scale - this.MARGIN;
|
||||
if (!block.outputConnection) {
|
||||
newX -= this.tabWidth_;
|
||||
}
|
||||
@@ -354,22 +354,23 @@ Blockly.VerticalFlyout.prototype.reflowInternal_ = function() {
|
||||
}
|
||||
if (this.RTL) {
|
||||
// With the flyoutWidth known, right-align the buttons.
|
||||
for (var i = 0, button; (button = this.buttons_[i]); i++) {
|
||||
var y = button.getPosition().y;
|
||||
var x = flyoutWidth / this.workspace_.scale - button.width -
|
||||
for (let i = 0, button; (button = this.buttons_[i]); i++) {
|
||||
const y = button.getPosition().y;
|
||||
const x = flyoutWidth / this.workspace_.scale - button.width -
|
||||
this.MARGIN - this.tabWidth_;
|
||||
button.moveTo(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_ &&
|
||||
this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT &&
|
||||
this.toolboxPosition_ == Position.LEFT &&
|
||||
!this.targetWorkspace.getToolbox()) {
|
||||
// This flyout is a simple toolbox. Reposition the workspace so that (0,0)
|
||||
// is in the correct position relative to the new absolute edge (ie
|
||||
// toolbox edge).
|
||||
this.targetWorkspace.translate(
|
||||
this.targetWorkspace.scrollX + flyoutWidth, this.targetWorkspace.scrollY);
|
||||
this.targetWorkspace.scrollX + flyoutWidth,
|
||||
this.targetWorkspace.scrollY);
|
||||
}
|
||||
|
||||
// Record the width for workspace metrics and .position.
|
||||
@@ -379,5 +380,7 @@ Blockly.VerticalFlyout.prototype.reflowInternal_ = function() {
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.registry.register(Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX,
|
||||
Blockly.registry.DEFAULT, Blockly.VerticalFlyout);
|
||||
registry.register(
|
||||
registry.Type.FLYOUTS_VERTICAL_TOOLBOX, registry.DEFAULT, VerticalFlyout);
|
||||
|
||||
exports = VerticalFlyout;
|
||||
|
||||
@@ -11,14 +11,18 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Generator');
|
||||
goog.module('Blockly.Generator');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Block');
|
||||
goog.require('Blockly.internalConstants');
|
||||
goog.require('Blockly.utils.deprecation');
|
||||
|
||||
goog.requireType('Blockly.Names');
|
||||
goog.requireType('Blockly.Workspace');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Names = goog.requireType('Blockly.Names');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
const internalConstants = goog.require('Blockly.internalConstants');
|
||||
const deprecation = goog.require('Blockly.utils.deprecation');
|
||||
const {getMainWorkspace} = goog.require('Blockly');
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,7 +30,7 @@ goog.requireType('Blockly.Workspace');
|
||||
* @param {string} name Language name of this generator.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Generator = function(name) {
|
||||
const Generator = function(name) {
|
||||
this.name_ = name;
|
||||
this.FUNCTION_NAME_PLACEHOLDER_REGEXP_ =
|
||||
new RegExp(this.FUNCTION_NAME_PLACEHOLDER_, 'g');
|
||||
@@ -38,7 +42,7 @@ Blockly.Generator = function(name) {
|
||||
* E.g. ' checkTimeout(%1);\n'
|
||||
* @type {?string}
|
||||
*/
|
||||
Blockly.Generator.prototype.INFINITE_LOOP_TRAP = null;
|
||||
Generator.prototype.INFINITE_LOOP_TRAP = null;
|
||||
|
||||
/**
|
||||
* Arbitrary code to inject before every statement.
|
||||
@@ -46,7 +50,7 @@ Blockly.Generator.prototype.INFINITE_LOOP_TRAP = null;
|
||||
* E.g. 'highlight(%1);\n'
|
||||
* @type {?string}
|
||||
*/
|
||||
Blockly.Generator.prototype.STATEMENT_PREFIX = null;
|
||||
Generator.prototype.STATEMENT_PREFIX = null;
|
||||
|
||||
/**
|
||||
* Arbitrary code to inject after every statement.
|
||||
@@ -54,27 +58,27 @@ Blockly.Generator.prototype.STATEMENT_PREFIX = null;
|
||||
* E.g. 'highlight(%1);\n'
|
||||
* @type {?string}
|
||||
*/
|
||||
Blockly.Generator.prototype.STATEMENT_SUFFIX = null;
|
||||
Generator.prototype.STATEMENT_SUFFIX = null;
|
||||
|
||||
/**
|
||||
* The method of indenting. Defaults to two spaces, but language generators
|
||||
* may override this to increase indent or change to tabs.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.Generator.prototype.INDENT = ' ';
|
||||
Generator.prototype.INDENT = ' ';
|
||||
|
||||
/**
|
||||
* Maximum length for a comment before wrapping. Does not account for
|
||||
* indenting level.
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.Generator.prototype.COMMENT_WRAP = 60;
|
||||
Generator.prototype.COMMENT_WRAP = 60;
|
||||
|
||||
/**
|
||||
* List of outer-inner pairings that do NOT require parentheses.
|
||||
* @type {!Array<!Array<number>>}
|
||||
*/
|
||||
Blockly.Generator.prototype.ORDER_OVERRIDES = [];
|
||||
Generator.prototype.ORDER_OVERRIDES = [];
|
||||
|
||||
/**
|
||||
* Whether the init method has been called.
|
||||
@@ -83,24 +87,24 @@ Blockly.Generator.prototype.ORDER_OVERRIDES = [];
|
||||
* initialized. If this flag is untouched, it will have no effect.
|
||||
* @type {?boolean}
|
||||
*/
|
||||
Blockly.Generator.prototype.isInitialized = null;
|
||||
Generator.prototype.isInitialized = null;
|
||||
|
||||
/**
|
||||
* Generate code for all blocks in the workspace to the specified language.
|
||||
* @param {!Blockly.Workspace=} workspace Workspace to generate code from.
|
||||
* @param {!Workspace=} workspace Workspace to generate code from.
|
||||
* @return {string} Generated code.
|
||||
*/
|
||||
Blockly.Generator.prototype.workspaceToCode = function(workspace) {
|
||||
Generator.prototype.workspaceToCode = function(workspace) {
|
||||
if (!workspace) {
|
||||
// Backwards compatibility from before there could be multiple workspaces.
|
||||
console.warn('No workspace specified in workspaceToCode call. Guessing.');
|
||||
workspace = Blockly.getMainWorkspace();
|
||||
workspace = getMainWorkspace();
|
||||
}
|
||||
var code = [];
|
||||
let code = [];
|
||||
this.init(workspace);
|
||||
var blocks = workspace.getTopBlocks(true);
|
||||
for (var i = 0, block; (block = blocks[i]); i++) {
|
||||
var line = this.blockToCode(block);
|
||||
const blocks = workspace.getTopBlocks(true);
|
||||
for (let i = 0, block; (block = blocks[i]); i++) {
|
||||
let line = this.blockToCode(block);
|
||||
if (Array.isArray(line)) {
|
||||
// Value blocks return tuples of code and operator order.
|
||||
// Top-level blocks don't care about operator order.
|
||||
@@ -140,20 +144,20 @@ Blockly.Generator.prototype.workspaceToCode = function(workspace) {
|
||||
* @param {string} prefix The common prefix.
|
||||
* @return {string} The prefixed lines of code.
|
||||
*/
|
||||
Blockly.Generator.prototype.prefixLines = function(text, prefix) {
|
||||
Generator.prototype.prefixLines = function(text, prefix) {
|
||||
return prefix + text.replace(/(?!\n$)\n/g, '\n' + prefix);
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively spider a tree of blocks, returning all their comments.
|
||||
* @param {!Blockly.Block} block The block from which to start spidering.
|
||||
* @param {!Block} block The block from which to start spidering.
|
||||
* @return {string} Concatenated list of comments.
|
||||
*/
|
||||
Blockly.Generator.prototype.allNestedComments = function(block) {
|
||||
var comments = [];
|
||||
var blocks = block.getDescendants(true);
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
var comment = blocks[i].getCommentText();
|
||||
Generator.prototype.allNestedComments = function(block) {
|
||||
const comments = [];
|
||||
const blocks = block.getDescendants(true);
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
const comment = blocks[i].getCommentText();
|
||||
if (comment) {
|
||||
comments.push(comment);
|
||||
}
|
||||
@@ -168,13 +172,13 @@ Blockly.Generator.prototype.allNestedComments = function(block) {
|
||||
/**
|
||||
* Generate code for the specified block (and attached blocks).
|
||||
* The generator must be initialized before calling this function.
|
||||
* @param {Blockly.Block} block The block to generate code for.
|
||||
* @param {Block} block The block to generate code for.
|
||||
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
|
||||
* @return {string|!Array} For statement blocks, the generated code.
|
||||
* For value blocks, an array containing the generated code and an
|
||||
* operator order value. Returns '' if block is null.
|
||||
*/
|
||||
Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) {
|
||||
Generator.prototype.blockToCode = function(block, opt_thisOnly) {
|
||||
if (this.isInitialized === false) {
|
||||
console.warn(
|
||||
'Generator init was not called before blockToCode was called.');
|
||||
@@ -191,16 +195,17 @@ Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) {
|
||||
return opt_thisOnly ? '' : this.blockToCode(block.getChildren(false)[0]);
|
||||
}
|
||||
|
||||
var func = this[block.type];
|
||||
const func = this[block.type];
|
||||
if (typeof func != 'function') {
|
||||
throw Error('Language "' + this.name_ + '" does not know how to generate ' +
|
||||
throw Error(
|
||||
'Language "' + this.name_ + '" does not know how to generate ' +
|
||||
'code for block type "' + block.type + '".');
|
||||
}
|
||||
// First argument to func.call is the value of 'this' in the generator.
|
||||
// Prior to 24 September 2013 'this' was the only way to access the block.
|
||||
// The current preferred method of accessing the block is through the second
|
||||
// argument to func.call, which becomes the first parameter to the generator.
|
||||
var code = func.call(block, block);
|
||||
let code = func.call(block, block);
|
||||
if (Array.isArray(code)) {
|
||||
// Value blocks return tuples of code and operator order.
|
||||
if (!block.outputConnection) {
|
||||
@@ -224,22 +229,22 @@ Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) {
|
||||
|
||||
/**
|
||||
* Generate code representing the specified value input.
|
||||
* @param {!Blockly.Block} block The block containing the input.
|
||||
* @param {!Block} block The block containing the input.
|
||||
* @param {string} name The name of the input.
|
||||
* @param {number} outerOrder The maximum binding strength (minimum order value)
|
||||
* of any operators adjacent to "block".
|
||||
* @return {string} Generated code or '' if no blocks are connected or the
|
||||
* specified input does not exist.
|
||||
*/
|
||||
Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) {
|
||||
Generator.prototype.valueToCode = function(block, name, outerOrder) {
|
||||
if (isNaN(outerOrder)) {
|
||||
throw TypeError('Expecting valid order from block: ' + block.type);
|
||||
}
|
||||
var targetBlock = block.getInputTargetBlock(name);
|
||||
const targetBlock = block.getInputTargetBlock(name);
|
||||
if (!targetBlock) {
|
||||
return '';
|
||||
}
|
||||
var tuple = this.blockToCode(targetBlock);
|
||||
const tuple = this.blockToCode(targetBlock);
|
||||
if (tuple === '') {
|
||||
// Disabled block.
|
||||
return '';
|
||||
@@ -249,20 +254,20 @@ Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) {
|
||||
if (!Array.isArray(tuple)) {
|
||||
throw TypeError('Expecting tuple from value block: ' + targetBlock.type);
|
||||
}
|
||||
var code = tuple[0];
|
||||
var innerOrder = tuple[1];
|
||||
let code = tuple[0];
|
||||
const innerOrder = tuple[1];
|
||||
if (isNaN(innerOrder)) {
|
||||
throw TypeError('Expecting valid order from value block: ' +
|
||||
targetBlock.type);
|
||||
throw TypeError(
|
||||
'Expecting valid order from value block: ' + targetBlock.type);
|
||||
}
|
||||
if (!code) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Add parentheses if needed.
|
||||
var parensNeeded = false;
|
||||
var outerOrderClass = Math.floor(outerOrder);
|
||||
var innerOrderClass = Math.floor(innerOrder);
|
||||
let parensNeeded = false;
|
||||
const outerOrderClass = Math.floor(outerOrder);
|
||||
const innerOrderClass = Math.floor(innerOrder);
|
||||
if (outerOrderClass <= innerOrderClass) {
|
||||
if (outerOrderClass == innerOrderClass &&
|
||||
(outerOrderClass == 0 || outerOrderClass == 99)) {
|
||||
@@ -276,7 +281,7 @@ Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) {
|
||||
// wrap the code in parentheses.
|
||||
parensNeeded = true;
|
||||
// Check for special exceptions.
|
||||
for (var i = 0; i < this.ORDER_OVERRIDES.length; i++) {
|
||||
for (let i = 0; i < this.ORDER_OVERRIDES.length; i++) {
|
||||
if (this.ORDER_OVERRIDES[i][0] == outerOrder &&
|
||||
this.ORDER_OVERRIDES[i][1] == innerOrder) {
|
||||
parensNeeded = false;
|
||||
@@ -298,17 +303,18 @@ Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) {
|
||||
* statement input. Indent the code.
|
||||
* This is mainly used in generators. When trying to generate code to evaluate
|
||||
* look at using workspaceToCode or blockToCode.
|
||||
* @param {!Blockly.Block} block The block containing the input.
|
||||
* @param {!Block} block The block containing the input.
|
||||
* @param {string} name The name of the input.
|
||||
* @return {string} Generated code or '' if no blocks are connected.
|
||||
*/
|
||||
Blockly.Generator.prototype.statementToCode = function(block, name) {
|
||||
var targetBlock = block.getInputTargetBlock(name);
|
||||
var code = this.blockToCode(targetBlock);
|
||||
Generator.prototype.statementToCode = function(block, name) {
|
||||
const targetBlock = block.getInputTargetBlock(name);
|
||||
let code = this.blockToCode(targetBlock);
|
||||
// Value blocks must return code and order of operations info.
|
||||
// Statement blocks must only return code.
|
||||
if (typeof code != 'string') {
|
||||
throw TypeError('Expecting code from statement block: ' +
|
||||
throw TypeError(
|
||||
'Expecting code from statement block: ' +
|
||||
(targetBlock && targetBlock.type));
|
||||
}
|
||||
if (code) {
|
||||
@@ -323,21 +329,24 @@ Blockly.Generator.prototype.statementToCode = function(block, name) {
|
||||
* statement executes), and a statement prefix to the end of the loop block
|
||||
* (right before the loop statement executes).
|
||||
* @param {string} branch Code for loop contents.
|
||||
* @param {!Blockly.Block} block Enclosing block.
|
||||
* @param {!Block} block Enclosing block.
|
||||
* @return {string} Loop contents, with infinite loop trap added.
|
||||
*/
|
||||
Blockly.Generator.prototype.addLoopTrap = function(branch, block) {
|
||||
Generator.prototype.addLoopTrap = function(branch, block) {
|
||||
if (this.INFINITE_LOOP_TRAP) {
|
||||
branch = this.prefixLines(this.injectId(this.INFINITE_LOOP_TRAP, block),
|
||||
this.INDENT) + branch;
|
||||
branch = this.prefixLines(
|
||||
this.injectId(this.INFINITE_LOOP_TRAP, block), this.INDENT) +
|
||||
branch;
|
||||
}
|
||||
if (this.STATEMENT_SUFFIX && !block.suppressPrefixSuffix) {
|
||||
branch = this.prefixLines(this.injectId(this.STATEMENT_SUFFIX, block),
|
||||
this.INDENT) + branch;
|
||||
branch = this.prefixLines(
|
||||
this.injectId(this.STATEMENT_SUFFIX, block), this.INDENT) +
|
||||
branch;
|
||||
}
|
||||
if (this.STATEMENT_PREFIX && !block.suppressPrefixSuffix) {
|
||||
branch = branch + this.prefixLines(this.injectId(this.STATEMENT_PREFIX,
|
||||
block), this.INDENT);
|
||||
branch = branch +
|
||||
this.prefixLines(
|
||||
this.injectId(this.STATEMENT_PREFIX, block), this.INDENT);
|
||||
}
|
||||
return branch;
|
||||
};
|
||||
@@ -346,11 +355,11 @@ Blockly.Generator.prototype.addLoopTrap = function(branch, block) {
|
||||
* Inject a block ID into a message to replace '%1'.
|
||||
* Used for STATEMENT_PREFIX, STATEMENT_SUFFIX, and INFINITE_LOOP_TRAP.
|
||||
* @param {string} msg Code snippet with '%1'.
|
||||
* @param {!Blockly.Block} block Block which has an ID.
|
||||
* @param {!Block} block Block which has an ID.
|
||||
* @return {string} Code snippet with ID.
|
||||
*/
|
||||
Blockly.Generator.prototype.injectId = function(msg, block) {
|
||||
var id = block.id.replace(/\$/g, '$$$$'); // Issue 251.
|
||||
Generator.prototype.injectId = function(msg, block) {
|
||||
const id = block.id.replace(/\$/g, '$$$$'); // Issue 251.
|
||||
return msg.replace(/%1/g, '\'' + id + '\'');
|
||||
};
|
||||
|
||||
@@ -359,33 +368,33 @@ Blockly.Generator.prototype.injectId = function(msg, block) {
|
||||
* @type {string}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Generator.prototype.RESERVED_WORDS_ = '';
|
||||
Generator.prototype.RESERVED_WORDS_ = '';
|
||||
|
||||
/**
|
||||
* Add one or more words to the list of reserved words for this language.
|
||||
* @param {string} words Comma-separated list of words to add to the list.
|
||||
* No spaces. Duplicates are ok.
|
||||
*/
|
||||
Blockly.Generator.prototype.addReservedWords = function(words) {
|
||||
Generator.prototype.addReservedWords = function(words) {
|
||||
this.RESERVED_WORDS_ += words + ',';
|
||||
};
|
||||
|
||||
/**
|
||||
* This is used as a placeholder in functions defined using
|
||||
* Blockly.Generator.provideFunction_. It must not be legal code that could
|
||||
* Generator.provideFunction_. It must not be legal code that could
|
||||
* legitimately appear in a function definition (or comment), and it must
|
||||
* not confuse the regular expression parser.
|
||||
* @type {string}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}';
|
||||
Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}';
|
||||
|
||||
/**
|
||||
* A dictionary of definitions to be printed before the code.
|
||||
* @type {!Object|undefined}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Generator.prototype.definitions_;
|
||||
Generator.prototype.definitions_;
|
||||
|
||||
/**
|
||||
* A dictionary mapping desired function names in definitions_ to actual
|
||||
@@ -393,36 +402,34 @@ Blockly.Generator.prototype.definitions_;
|
||||
* @type {!Object|undefined}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Generator.prototype.functionNames_;
|
||||
Generator.prototype.functionNames_;
|
||||
|
||||
/**
|
||||
* A database of variable and procedure names.
|
||||
* @type {!Blockly.Names|undefined}
|
||||
* @type {!Names|undefined}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Generator.prototype.nameDB_;
|
||||
Generator.prototype.nameDB_;
|
||||
|
||||
Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', {
|
||||
Object.defineProperty(Generator.prototype, 'variableDB_', {
|
||||
/**
|
||||
* Getter.
|
||||
* @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021).
|
||||
* @this {Blockly.Generator}
|
||||
* @return {!Blockly.Names|undefined} Name database.
|
||||
* @this {Generator}
|
||||
* @return {!Names|undefined} Name database.
|
||||
*/
|
||||
get: function() {
|
||||
Blockly.utils.deprecation.warn(
|
||||
'variableDB_', 'May 2021', 'May 2026', 'nameDB_');
|
||||
deprecation.warn('variableDB_', 'May 2021', 'May 2026', 'nameDB_');
|
||||
return this.nameDB_;
|
||||
},
|
||||
/**
|
||||
* Setter.
|
||||
* @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021).
|
||||
* @this {Blockly.Generator}
|
||||
* @param {!Blockly.Names|undefined} nameDb New name database.
|
||||
* @this {Generator}
|
||||
* @param {!Names|undefined} nameDb New name database.
|
||||
*/
|
||||
set: function(nameDb) {
|
||||
Blockly.utils.deprecation.warn(
|
||||
'variableDB_', 'May 2021', 'May 2026', 'nameDB_');
|
||||
deprecation.warn('variableDB_', 'May 2021', 'May 2026', 'nameDB_');
|
||||
this.nameDB_ = nameDb;
|
||||
}
|
||||
});
|
||||
@@ -439,7 +446,7 @@ Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', {
|
||||
* "listRandom", not "random"). There is no danger of colliding with reserved
|
||||
* words, or user-defined variable or procedure names.
|
||||
*
|
||||
* The code gets output when Blockly.Generator.finish() is called.
|
||||
* The code gets output when Generator.finish() is called.
|
||||
*
|
||||
* @param {string} desiredName The desired name of the function
|
||||
* (e.g. mathIsPrime).
|
||||
@@ -448,18 +455,18 @@ Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', {
|
||||
* from desiredName if the former has already been taken by the user.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) {
|
||||
Generator.prototype.provideFunction_ = function(desiredName, code) {
|
||||
if (!this.definitions_[desiredName]) {
|
||||
var functionName = this.nameDB_.getDistinctName(
|
||||
desiredName, Blockly.internalConstants.PROCEDURE_CATEGORY_NAME);
|
||||
const functionName = this.nameDB_.getDistinctName(
|
||||
desiredName, internalConstants.PROCEDURE_CATEGORY_NAME);
|
||||
this.functionNames_[desiredName] = functionName;
|
||||
var codeText = code.join('\n').replace(
|
||||
let codeText = code.join('\n').replace(
|
||||
this.FUNCTION_NAME_PLACEHOLDER_REGEXP_, functionName);
|
||||
// Change all ' ' indents into the desired indent.
|
||||
// To avoid an infinite loop of replacements, change all indents to '\0'
|
||||
// character first, then replace them all with the indent.
|
||||
// We are assuming that no provided functions contain a literal null char.
|
||||
var oldCodeText;
|
||||
let oldCodeText;
|
||||
while (oldCodeText != codeText) {
|
||||
oldCodeText = codeText;
|
||||
codeText = codeText.replace(/^(( {2})*) {2}/gm, '$1\0');
|
||||
@@ -474,9 +481,9 @@ Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) {
|
||||
* Hook for code to run before code generation starts.
|
||||
* Subclasses may override this, e.g. to initialise the database of variable
|
||||
* names.
|
||||
* @param {!Blockly.Workspace} _workspace Workspace to generate code from.
|
||||
* @param {!Workspace} _workspace Workspace to generate code from.
|
||||
*/
|
||||
Blockly.Generator.prototype.init = function(_workspace) {
|
||||
Generator.prototype.init = function(_workspace) {
|
||||
// Optionally override
|
||||
// Create a dictionary of definitions to be printed before the code.
|
||||
this.definitions_ = Object.create(null);
|
||||
@@ -492,14 +499,14 @@ Blockly.Generator.prototype.init = function(_workspace) {
|
||||
* Subclasses may override this, e.g. to generate code for statements following
|
||||
* the block, or to handle comments for the specified block and any connected
|
||||
* value blocks.
|
||||
* @param {!Blockly.Block} _block The current block.
|
||||
* @param {!Block} _block The current block.
|
||||
* @param {string} code The code created for this block.
|
||||
* @param {boolean=} _opt_thisOnly True to generate code for only this
|
||||
* statement.
|
||||
* @return {string} Code with comments and subsequent blocks added.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) {
|
||||
Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) {
|
||||
// Optionally override
|
||||
return code;
|
||||
};
|
||||
@@ -511,7 +518,7 @@ Blockly.Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) {
|
||||
* @param {string} code Generated code.
|
||||
* @return {string} Completed code.
|
||||
*/
|
||||
Blockly.Generator.prototype.finish = function(code) {
|
||||
Generator.prototype.finish = function(code) {
|
||||
// Optionally override
|
||||
// Clean up temporary data.
|
||||
delete this.definitions_;
|
||||
@@ -527,7 +534,9 @@ Blockly.Generator.prototype.finish = function(code) {
|
||||
* @param {string} line Line of generated code.
|
||||
* @return {string} Legal line of code.
|
||||
*/
|
||||
Blockly.Generator.prototype.scrubNakedValue = function(line) {
|
||||
Generator.prototype.scrubNakedValue = function(line) {
|
||||
// Optionally override
|
||||
return line;
|
||||
};
|
||||
|
||||
exports = Generator;
|
||||
|
||||
294
core/gesture.js
294
core/gesture.js
@@ -11,30 +11,41 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Gesture');
|
||||
goog.module('Blockly.Gesture');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.blockAnimations');
|
||||
// TODO(#5073): Add Blockly require after fixing circular dependency.
|
||||
// goog.require('Blockly');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const BubbleDragger = goog.require('Blockly.BubbleDragger');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Events = goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Field = goog.requireType('Blockly.Field');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IBlockDragger = goog.requireType('Blockly.IBlockDragger');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IBubble = goog.requireType('Blockly.IBubble');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IFlyout = goog.requireType('Blockly.IFlyout');
|
||||
const Tooltip = goog.require('Blockly.Tooltip');
|
||||
const Touch = goog.require('Blockly.Touch');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Workspace = goog.require('Blockly.Workspace');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const WorkspaceDragger = goog.require('Blockly.WorkspaceDragger');
|
||||
const blockAnimations = goog.require('Blockly.blockAnimations');
|
||||
const browserEvents = goog.require('Blockly.browserEvents');
|
||||
const internalConstants = goog.require('Blockly.internalConstants');
|
||||
const registry = goog.require('Blockly.registry');
|
||||
const utils = goog.require('Blockly.utils');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.BlockDragger');
|
||||
goog.require('Blockly.browserEvents');
|
||||
goog.require('Blockly.BubbleDragger');
|
||||
goog.require('Blockly.Events');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.Click');
|
||||
goog.require('Blockly.internalConstants');
|
||||
goog.require('Blockly.Tooltip');
|
||||
goog.require('Blockly.Touch');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.Workspace');
|
||||
goog.require('Blockly.WorkspaceDragger');
|
||||
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.Field');
|
||||
goog.requireType('Blockly.IBlockDragger');
|
||||
goog.requireType('Blockly.IBubble');
|
||||
goog.requireType('Blockly.IFlyout');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
@@ -46,15 +57,15 @@ goog.requireType('Blockly.WorkspaceSvg');
|
||||
/**
|
||||
* Class for one gesture.
|
||||
* @param {!Event} e The event that kicked off this gesture.
|
||||
* @param {!Blockly.WorkspaceSvg} creatorWorkspace The workspace that created
|
||||
* @param {!WorkspaceSvg} creatorWorkspace The workspace that created
|
||||
* this gesture and has a reference to it.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
const Gesture = function(e, creatorWorkspace) {
|
||||
/**
|
||||
* The position of the mouse when the gesture started. Units are CSS pixels,
|
||||
* with (0, 0) at the top left of the browser window (mouseEvent clientX/Y).
|
||||
* @type {Blockly.utils.Coordinate}
|
||||
* @type {Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.mouseDownXY_ = null;
|
||||
@@ -62,15 +73,15 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
/**
|
||||
* How far the mouse has moved during this drag, in pixel units.
|
||||
* (0, 0) is at this.mouseDownXY_.
|
||||
* @type {!Blockly.utils.Coordinate}
|
||||
* @type {!Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.currentDragDeltaXY_ = new Blockly.utils.Coordinate(0, 0);
|
||||
this.currentDragDeltaXY_ = new Coordinate(0, 0);
|
||||
|
||||
/**
|
||||
* The bubble that the gesture started on, or null if it did not start on a
|
||||
* bubble.
|
||||
* @type {Blockly.IBubble}
|
||||
* @type {IBubble}
|
||||
* @private
|
||||
*/
|
||||
this.startBubble_ = null;
|
||||
@@ -78,7 +89,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
/**
|
||||
* The field that the gesture started on, or null if it did not start on a
|
||||
* field.
|
||||
* @type {Blockly.Field}
|
||||
* @type {Field}
|
||||
* @private
|
||||
*/
|
||||
this.startField_ = null;
|
||||
@@ -86,7 +97,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
/**
|
||||
* The block that the gesture started on, or null if it did not start on a
|
||||
* block.
|
||||
* @type {Blockly.BlockSvg}
|
||||
* @type {BlockSvg}
|
||||
* @private
|
||||
*/
|
||||
this.startBlock_ = null;
|
||||
@@ -96,7 +107,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
* shadow block, this is the first non-shadow parent of the block. If the
|
||||
* gesture started in the flyout, this is the root block of the block group
|
||||
* that was clicked or dragged.
|
||||
* @type {Blockly.BlockSvg}
|
||||
* @type {BlockSvg}
|
||||
* @private
|
||||
*/
|
||||
this.targetBlock_ = null;
|
||||
@@ -105,7 +116,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
* The workspace that the gesture started on. There may be multiple
|
||||
* workspaces on a page; this is more accurate than using
|
||||
* Blockly.getMainWorkspace().
|
||||
* @type {Blockly.WorkspaceSvg}
|
||||
* @type {WorkspaceSvg}
|
||||
* @protected
|
||||
*/
|
||||
this.startWorkspace_ = null;
|
||||
@@ -115,7 +126,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
* to the gesture, which will need to be cleared at deletion.
|
||||
* This may be different from the start workspace. For instance, a flyout is
|
||||
* a workspace, but its parent workspace manages gestures for it.
|
||||
* @type {!Blockly.WorkspaceSvg}
|
||||
* @type {!WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
this.creatorWorkspace_ = creatorWorkspace;
|
||||
@@ -160,7 +171,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
/**
|
||||
* A handle to use to unbind a mouse move listener at the end of a drag.
|
||||
* Opaque data returned from Blockly.bindEventWithChecks_.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @protected
|
||||
*/
|
||||
this.onMoveWrapper_ = null;
|
||||
@@ -168,21 +179,21 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
/**
|
||||
* A handle to use to unbind a mouse up listener at the end of a drag.
|
||||
* Opaque data returned from Blockly.bindEventWithChecks_.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @protected
|
||||
*/
|
||||
this.onUpWrapper_ = null;
|
||||
|
||||
/**
|
||||
* The object tracking a bubble drag, or null if none is in progress.
|
||||
* @type {Blockly.BubbleDragger}
|
||||
* @type {BubbleDragger}
|
||||
* @private
|
||||
*/
|
||||
this.bubbleDragger_ = null;
|
||||
|
||||
/**
|
||||
* The object tracking a block drag, or null if none is in progress.
|
||||
* @type {?Blockly.IBlockDragger}
|
||||
* @type {?IBlockDragger}
|
||||
* @private
|
||||
*/
|
||||
this.blockDragger_ = null;
|
||||
@@ -190,14 +201,14 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
/**
|
||||
* The object tracking a workspace or flyout workspace drag, or null if none
|
||||
* is in progress.
|
||||
* @type {Blockly.WorkspaceDragger}
|
||||
* @type {WorkspaceDragger}
|
||||
* @private
|
||||
*/
|
||||
this.workspaceDragger_ = null;
|
||||
|
||||
/**
|
||||
* The flyout a gesture started in, if any.
|
||||
* @type {Blockly.IFlyout}
|
||||
* @type {IFlyout}
|
||||
* @private
|
||||
*/
|
||||
this.flyout_ = null;
|
||||
@@ -229,24 +240,24 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.healStack_ = !Blockly.internalConstants.DRAG_STACK;
|
||||
this.healStack_ = !internalConstants.DRAG_STACK;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sever all links from this object.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.dispose = function() {
|
||||
Blockly.Touch.clearTouchIdentifier();
|
||||
Blockly.Tooltip.unblock();
|
||||
Gesture.prototype.dispose = function() {
|
||||
Touch.clearTouchIdentifier();
|
||||
Tooltip.unblock();
|
||||
// Clear the owner's reference to this gesture.
|
||||
this.creatorWorkspace_.clearGesture();
|
||||
|
||||
if (this.onMoveWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onMoveWrapper_);
|
||||
browserEvents.unbind(this.onMoveWrapper_);
|
||||
}
|
||||
if (this.onUpWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onUpWrapper_);
|
||||
browserEvents.unbind(this.onUpWrapper_);
|
||||
}
|
||||
|
||||
if (this.blockDragger_) {
|
||||
@@ -265,9 +276,9 @@ Blockly.Gesture.prototype.dispose = function() {
|
||||
* @param {!Event} e The most recent mouse or touch event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateFromEvent_ = function(e) {
|
||||
var currentXY = new Blockly.utils.Coordinate(e.clientX, e.clientY);
|
||||
var changed = this.updateDragDelta_(currentXY);
|
||||
Gesture.prototype.updateFromEvent_ = function(e) {
|
||||
const currentXY = new Coordinate(e.clientX, e.clientY);
|
||||
const changed = this.updateDragDelta_(currentXY);
|
||||
// Exceeded the drag radius for the first time.
|
||||
if (changed) {
|
||||
this.updateIsDragging_();
|
||||
@@ -278,25 +289,23 @@ Blockly.Gesture.prototype.updateFromEvent_ = function(e) {
|
||||
|
||||
/**
|
||||
* DO MATH to set currentDragDeltaXY_ based on the most recent mouse position.
|
||||
* @param {!Blockly.utils.Coordinate} currentXY The most recent mouse/pointer
|
||||
* @param {!Coordinate} currentXY The most recent mouse/pointer
|
||||
* position, in pixel units, with (0, 0) at the window's top left corner.
|
||||
* @return {boolean} True if the drag just exceeded the drag radius for the
|
||||
* first time.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateDragDelta_ = function(currentXY) {
|
||||
this.currentDragDeltaXY_ = Blockly.utils.Coordinate.difference(
|
||||
Gesture.prototype.updateDragDelta_ = function(currentXY) {
|
||||
this.currentDragDeltaXY_ = Coordinate.difference(
|
||||
currentXY,
|
||||
/** @type {!Blockly.utils.Coordinate} */ (this.mouseDownXY_));
|
||||
/** @type {!Coordinate} */ (this.mouseDownXY_));
|
||||
|
||||
if (!this.hasExceededDragRadius_) {
|
||||
var currentDragDelta =
|
||||
Blockly.utils.Coordinate.magnitude(this.currentDragDeltaXY_);
|
||||
const currentDragDelta = Coordinate.magnitude(this.currentDragDeltaXY_);
|
||||
|
||||
// The flyout has a different drag radius from the rest of Blockly.
|
||||
var limitRadius = this.flyout_ ?
|
||||
Blockly.internalConstants.FLYOUT_DRAG_RADIUS :
|
||||
Blockly.internalConstants.DRAG_RADIUS;
|
||||
const limitRadius = this.flyout_ ? internalConstants.FLYOUT_DRAG_RADIUS :
|
||||
internalConstants.DRAG_RADIUS;
|
||||
|
||||
this.hasExceededDragRadius_ = currentDragDelta > limitRadius;
|
||||
return this.hasExceededDragRadius_;
|
||||
@@ -314,7 +323,7 @@ Blockly.Gesture.prototype.updateDragDelta_ = function(currentXY) {
|
||||
* @return {boolean} True if a block is being dragged from the flyout.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateIsDraggingFromFlyout_ = function() {
|
||||
Gesture.prototype.updateIsDraggingFromFlyout_ = function() {
|
||||
if (!this.targetBlock_) {
|
||||
return false;
|
||||
}
|
||||
@@ -327,8 +336,8 @@ Blockly.Gesture.prototype.updateIsDraggingFromFlyout_ = function() {
|
||||
this.startWorkspace_.updateScreenCalculationsIfScrolled();
|
||||
// Start the event group now, so that the same event group is used for block
|
||||
// creation and block dragging.
|
||||
if (!Blockly.Events.getGroup()) {
|
||||
Blockly.Events.setGroup(true);
|
||||
if (!Events.getGroup()) {
|
||||
Events.setGroup(true);
|
||||
}
|
||||
// The start block is no longer relevant, because this is a drag.
|
||||
this.startBlock_ = null;
|
||||
@@ -348,7 +357,7 @@ Blockly.Gesture.prototype.updateIsDraggingFromFlyout_ = function() {
|
||||
* @return {boolean} True if a bubble is being dragged.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateIsDraggingBubble_ = function() {
|
||||
Gesture.prototype.updateIsDraggingBubble_ = function() {
|
||||
if (!this.startBubble_) {
|
||||
return false;
|
||||
}
|
||||
@@ -367,7 +376,7 @@ Blockly.Gesture.prototype.updateIsDraggingBubble_ = function() {
|
||||
* @return {boolean} True if a block is being dragged.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateIsDraggingBlock_ = function() {
|
||||
Gesture.prototype.updateIsDraggingBlock_ = function() {
|
||||
if (!this.targetBlock_) {
|
||||
return false;
|
||||
}
|
||||
@@ -393,8 +402,8 @@ Blockly.Gesture.prototype.updateIsDraggingBlock_ = function() {
|
||||
* WorkspaceDragger and starts the drag.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() {
|
||||
var wsMovable = this.flyout_ ?
|
||||
Gesture.prototype.updateIsDraggingWorkspace_ = function() {
|
||||
const wsMovable = this.flyout_ ?
|
||||
this.flyout_.isScrollable() :
|
||||
this.startWorkspace_ && this.startWorkspace_.isDraggable();
|
||||
|
||||
@@ -402,8 +411,8 @@ Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() {
|
||||
return;
|
||||
}
|
||||
|
||||
this.workspaceDragger_ = new Blockly.WorkspaceDragger(
|
||||
/** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_));
|
||||
this.workspaceDragger_ = new WorkspaceDragger(
|
||||
/** @type {!WorkspaceSvg} */ (this.startWorkspace_));
|
||||
|
||||
this.isDraggingWorkspace_ = true;
|
||||
this.workspaceDragger_.startDrag();
|
||||
@@ -415,7 +424,7 @@ Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() {
|
||||
* drag radius is exceeded. It should be called no more than once per gesture.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateIsDragging_ = function() {
|
||||
Gesture.prototype.updateIsDragging_ = function() {
|
||||
// Sanity check.
|
||||
if (this.calledUpdateIsDragging_) {
|
||||
throw Error('updateIsDragging_ should only be called once per gesture.');
|
||||
@@ -438,13 +447,13 @@ Blockly.Gesture.prototype.updateIsDragging_ = function() {
|
||||
* Create a block dragger and start dragging the selected block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.startDraggingBlock_ = function() {
|
||||
var BlockDraggerClass = Blockly.registry.getClassFromOptions(
|
||||
Blockly.registry.Type.BLOCK_DRAGGER, this.creatorWorkspace_.options, true);
|
||||
Gesture.prototype.startDraggingBlock_ = function() {
|
||||
const BlockDraggerClass = registry.getClassFromOptions(
|
||||
registry.Type.BLOCK_DRAGGER, this.creatorWorkspace_.options, true);
|
||||
|
||||
this.blockDragger_ = new BlockDraggerClass(
|
||||
/** @type {!Blockly.BlockSvg} */ (this.targetBlock_),
|
||||
/** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_));
|
||||
/** @type {!BlockSvg} */ (this.targetBlock_),
|
||||
/** @type {!WorkspaceSvg} */ (this.startWorkspace_));
|
||||
this.blockDragger_.startDrag(this.currentDragDeltaXY_, this.healStack_);
|
||||
this.blockDragger_.drag(this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
};
|
||||
@@ -454,10 +463,10 @@ Blockly.Gesture.prototype.startDraggingBlock_ = function() {
|
||||
* @private
|
||||
*/
|
||||
// TODO (fenichel): Possibly combine this and startDraggingBlock_.
|
||||
Blockly.Gesture.prototype.startDraggingBubble_ = function() {
|
||||
this.bubbleDragger_ = new Blockly.BubbleDragger(
|
||||
/** @type {!Blockly.IBubble} */ (this.startBubble_),
|
||||
/** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_));
|
||||
Gesture.prototype.startDraggingBubble_ = function() {
|
||||
this.bubbleDragger_ = new BubbleDragger(
|
||||
/** @type {!IBubble} */ (this.startBubble_),
|
||||
/** @type {!WorkspaceSvg} */ (this.startWorkspace_));
|
||||
this.bubbleDragger_.startBubbleDrag();
|
||||
this.bubbleDragger_.dragBubble(
|
||||
this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
@@ -468,14 +477,14 @@ Blockly.Gesture.prototype.startDraggingBubble_ = function() {
|
||||
* @param {!Event} e A mouse down or touch start event.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.doStart = function(e) {
|
||||
if (Blockly.utils.isTargetInput(e)) {
|
||||
Gesture.prototype.doStart = function(e) {
|
||||
if (utils.isTargetInput(e)) {
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
this.hasStarted_ = true;
|
||||
|
||||
Blockly.blockAnimations.disconnectUiStop();
|
||||
blockAnimations.disconnectUiStop();
|
||||
this.startWorkspace_.updateScreenCalculationsIfScrolled();
|
||||
if (this.startWorkspace_.isMutator) {
|
||||
// Mutator's coordinate system could be out of date because the bubble was
|
||||
@@ -490,13 +499,13 @@ Blockly.Gesture.prototype.doStart = function(e) {
|
||||
this.startWorkspace_.markFocused();
|
||||
this.mostRecentEvent_ = e;
|
||||
|
||||
Blockly.Tooltip.block();
|
||||
Tooltip.block();
|
||||
|
||||
if (this.targetBlock_) {
|
||||
this.targetBlock_.select();
|
||||
}
|
||||
|
||||
if (Blockly.utils.isRightButton(e)) {
|
||||
if (utils.isRightButton(e)) {
|
||||
this.handleRightClick(e);
|
||||
return;
|
||||
}
|
||||
@@ -507,7 +516,7 @@ Blockly.Gesture.prototype.doStart = function(e) {
|
||||
Blockly.longStart(e, this);
|
||||
}
|
||||
|
||||
this.mouseDownXY_ = new Blockly.utils.Coordinate(e.clientX, e.clientY);
|
||||
this.mouseDownXY_ = new Coordinate(e.clientX, e.clientY);
|
||||
this.healStack_ = e.altKey || e.ctrlKey || e.metaKey;
|
||||
|
||||
this.bindMouseEvents(e);
|
||||
@@ -518,10 +527,10 @@ Blockly.Gesture.prototype.doStart = function(e) {
|
||||
* @param {!Event} e A mouse down or touch start event.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.bindMouseEvents = function(e) {
|
||||
this.onMoveWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
Gesture.prototype.bindMouseEvents = function(e) {
|
||||
this.onMoveWrapper_ = browserEvents.conditionalBind(
|
||||
document, 'mousemove', null, this.handleMove.bind(this));
|
||||
this.onUpWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
this.onUpWrapper_ = browserEvents.conditionalBind(
|
||||
document, 'mouseup', null, this.handleUp.bind(this));
|
||||
|
||||
e.preventDefault();
|
||||
@@ -533,13 +542,12 @@ Blockly.Gesture.prototype.bindMouseEvents = function(e) {
|
||||
* @param {!Event} e A mouse move or touch move event.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.handleMove = function(e) {
|
||||
Gesture.prototype.handleMove = function(e) {
|
||||
this.updateFromEvent_(e);
|
||||
if (this.isDraggingWorkspace_) {
|
||||
this.workspaceDragger_.drag(this.currentDragDeltaXY_);
|
||||
} else if (this.isDraggingBlock_) {
|
||||
this.blockDragger_.drag(
|
||||
this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
this.blockDragger_.drag(this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
} else if (this.isDraggingBubble_) {
|
||||
this.bubbleDragger_.dragBubble(
|
||||
this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
@@ -553,7 +561,7 @@ Blockly.Gesture.prototype.handleMove = function(e) {
|
||||
* @param {!Event} e A mouse up or touch end event.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.handleUp = function(e) {
|
||||
Gesture.prototype.handleUp = function(e) {
|
||||
this.updateFromEvent_(e);
|
||||
Blockly.longStop_();
|
||||
|
||||
@@ -595,7 +603,7 @@ Blockly.Gesture.prototype.handleUp = function(e) {
|
||||
* end the drag at the most recent location.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.cancel = function() {
|
||||
Gesture.prototype.cancel = function() {
|
||||
// Disposing of a block cancels in-progress drags, but dragging to a delete
|
||||
// area disposes of a block and leads to recursive disposal. Break that cycle.
|
||||
if (this.isEnding_) {
|
||||
@@ -606,8 +614,7 @@ Blockly.Gesture.prototype.cancel = function() {
|
||||
this.bubbleDragger_.endBubbleDrag(
|
||||
this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
} else if (this.isDraggingBlock_) {
|
||||
this.blockDragger_.endDrag(
|
||||
this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
this.blockDragger_.endDrag(this.mostRecentEvent_, this.currentDragDeltaXY_);
|
||||
} else if (this.isDraggingWorkspace_) {
|
||||
this.workspaceDragger_.endDrag(this.currentDragDeltaXY_);
|
||||
}
|
||||
@@ -619,7 +626,7 @@ Blockly.Gesture.prototype.cancel = function() {
|
||||
* @param {!Event} e A mouse move or touch move event.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.handleRightClick = function(e) {
|
||||
Gesture.prototype.handleRightClick = function(e) {
|
||||
if (this.targetBlock_) {
|
||||
this.bringBlockToFront_();
|
||||
Blockly.hideChaff(!!this.flyout_);
|
||||
@@ -641,10 +648,10 @@ Blockly.Gesture.prototype.handleRightClick = function(e) {
|
||||
/**
|
||||
* Handle a mousedown/touchstart event on a workspace.
|
||||
* @param {!Event} e A mouse down or touch start event.
|
||||
* @param {!Blockly.WorkspaceSvg} ws The workspace the event hit.
|
||||
* @param {!WorkspaceSvg} ws The workspace the event hit.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.handleWsStart = function(e, ws) {
|
||||
Gesture.prototype.handleWsStart = function(e, ws) {
|
||||
if (this.hasStarted_) {
|
||||
throw Error(
|
||||
'Tried to call gesture.handleWsStart, ' +
|
||||
@@ -657,21 +664,20 @@ Blockly.Gesture.prototype.handleWsStart = function(e, ws) {
|
||||
|
||||
/**
|
||||
* Fires a workspace click event.
|
||||
* @param {!Blockly.WorkspaceSvg} ws The workspace that a user clicks on.
|
||||
* @param {!WorkspaceSvg} ws The workspace that a user clicks on.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.fireWorkspaceClick_ = function(ws) {
|
||||
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.CLICK))(
|
||||
null, ws.id, 'workspace'));
|
||||
Gesture.prototype.fireWorkspaceClick_ = function(ws) {
|
||||
Events.fire(new (Events.get(Events.CLICK))(null, ws.id, 'workspace'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mousedown/touchstart event on a flyout.
|
||||
* @param {!Event} e A mouse down or touch start event.
|
||||
* @param {!Blockly.IFlyout} flyout The flyout the event hit.
|
||||
* @param {!IFlyout} flyout The flyout the event hit.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.handleFlyoutStart = function(e, flyout) {
|
||||
Gesture.prototype.handleFlyoutStart = function(e, flyout) {
|
||||
if (this.hasStarted_) {
|
||||
throw Error(
|
||||
'Tried to call gesture.handleFlyoutStart, ' +
|
||||
@@ -684,10 +690,10 @@ Blockly.Gesture.prototype.handleFlyoutStart = function(e, flyout) {
|
||||
/**
|
||||
* Handle a mousedown/touchstart event on a block.
|
||||
* @param {!Event} e A mouse down or touch start event.
|
||||
* @param {!Blockly.BlockSvg} block The block the event hit.
|
||||
* @param {!BlockSvg} block The block the event hit.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.handleBlockStart = function(e, block) {
|
||||
Gesture.prototype.handleBlockStart = function(e, block) {
|
||||
if (this.hasStarted_) {
|
||||
throw Error(
|
||||
'Tried to call gesture.handleBlockStart, ' +
|
||||
@@ -700,10 +706,10 @@ Blockly.Gesture.prototype.handleBlockStart = function(e, block) {
|
||||
/**
|
||||
* Handle a mousedown/touchstart event on a bubble.
|
||||
* @param {!Event} e A mouse down or touch start event.
|
||||
* @param {!Blockly.IBubble} bubble The bubble the event hit.
|
||||
* @param {!IBubble} bubble The bubble the event hit.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.handleBubbleStart = function(e, bubble) {
|
||||
Gesture.prototype.handleBubbleStart = function(e, bubble) {
|
||||
if (this.hasStarted_) {
|
||||
throw Error(
|
||||
'Tried to call gesture.handleBubbleStart, ' +
|
||||
@@ -721,7 +727,7 @@ Blockly.Gesture.prototype.handleBubbleStart = function(e, bubble) {
|
||||
* Execute a bubble click.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.doBubbleClick_ = function() {
|
||||
Gesture.prototype.doBubbleClick_ = function() {
|
||||
// TODO (#1673): Consistent handling of single clicks.
|
||||
this.startBubble_.setFocus && this.startBubble_.setFocus();
|
||||
this.startBubble_.select && this.startBubble_.select();
|
||||
@@ -731,7 +737,7 @@ Blockly.Gesture.prototype.doBubbleClick_ = function() {
|
||||
* Execute a field click.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.doFieldClick_ = function() {
|
||||
Gesture.prototype.doFieldClick_ = function() {
|
||||
this.startField_.showEditor(this.mostRecentEvent_);
|
||||
this.bringBlockToFront_();
|
||||
};
|
||||
@@ -740,24 +746,24 @@ Blockly.Gesture.prototype.doFieldClick_ = function() {
|
||||
* Execute a block click.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.doBlockClick_ = function() {
|
||||
Gesture.prototype.doBlockClick_ = function() {
|
||||
// Block click in an autoclosing flyout.
|
||||
if (this.flyout_ && this.flyout_.autoClose) {
|
||||
if (this.targetBlock_.isEnabled()) {
|
||||
if (!Blockly.Events.getGroup()) {
|
||||
Blockly.Events.setGroup(true);
|
||||
if (!Events.getGroup()) {
|
||||
Events.setGroup(true);
|
||||
}
|
||||
var newBlock = this.flyout_.createBlock(this.targetBlock_);
|
||||
const newBlock = this.flyout_.createBlock(this.targetBlock_);
|
||||
newBlock.scheduleSnapAndBump();
|
||||
}
|
||||
} else {
|
||||
// Clicks events are on the start block, even if it was a shadow.
|
||||
var event = new (Blockly.Events.get(Blockly.Events.CLICK))(
|
||||
const event = new (Events.get(Events.CLICK))(
|
||||
this.startBlock_, this.startWorkspace_.id, 'block');
|
||||
Blockly.Events.fire(event);
|
||||
Events.fire(event);
|
||||
}
|
||||
this.bringBlockToFront_();
|
||||
Blockly.Events.setGroup(false);
|
||||
Events.setGroup(false);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -766,8 +772,8 @@ Blockly.Gesture.prototype.doBlockClick_ = function() {
|
||||
* @param {!Event} _e A mouse up or touch end event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.doWorkspaceClick_ = function(_e) {
|
||||
var ws = this.creatorWorkspace_;
|
||||
Gesture.prototype.doWorkspaceClick_ = function(_e) {
|
||||
const ws = this.creatorWorkspace_;
|
||||
if (Blockly.selected) {
|
||||
Blockly.selected.unselect();
|
||||
}
|
||||
@@ -783,7 +789,7 @@ Blockly.Gesture.prototype.doWorkspaceClick_ = function(_e) {
|
||||
* not occluded by other blocks.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.bringBlockToFront_ = function() {
|
||||
Gesture.prototype.bringBlockToFront_ = function() {
|
||||
// Blocks in the flyout don't overlap, so skip the work.
|
||||
if (this.targetBlock_ && !this.flyout_) {
|
||||
this.targetBlock_.bringToFront();
|
||||
@@ -794,10 +800,10 @@ Blockly.Gesture.prototype.bringBlockToFront_ = function() {
|
||||
|
||||
/**
|
||||
* Record the field that a gesture started on.
|
||||
* @param {Blockly.Field} field The field the gesture started on.
|
||||
* @param {Field} field The field the gesture started on.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.setStartField = function(field) {
|
||||
Gesture.prototype.setStartField = function(field) {
|
||||
if (this.hasStarted_) {
|
||||
throw Error(
|
||||
'Tried to call gesture.setStartField, ' +
|
||||
@@ -810,10 +816,10 @@ Blockly.Gesture.prototype.setStartField = function(field) {
|
||||
|
||||
/**
|
||||
* Record the bubble that a gesture started on
|
||||
* @param {Blockly.IBubble} bubble The bubble the gesture started on.
|
||||
* @param {IBubble} bubble The bubble the gesture started on.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.setStartBubble = function(bubble) {
|
||||
Gesture.prototype.setStartBubble = function(bubble) {
|
||||
if (!this.startBubble_) {
|
||||
this.startBubble_ = bubble;
|
||||
}
|
||||
@@ -822,10 +828,10 @@ Blockly.Gesture.prototype.setStartBubble = function(bubble) {
|
||||
/**
|
||||
* Record the block that a gesture started on, and set the target block
|
||||
* appropriately.
|
||||
* @param {Blockly.BlockSvg} block The block the gesture started on.
|
||||
* @param {BlockSvg} block The block the gesture started on.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.setStartBlock = function(block) {
|
||||
Gesture.prototype.setStartBlock = function(block) {
|
||||
// If the gesture already went through a bubble, don't set the start block.
|
||||
if (!this.startBlock_ && !this.startBubble_) {
|
||||
this.startBlock_ = block;
|
||||
@@ -841,10 +847,10 @@ Blockly.Gesture.prototype.setStartBlock = function(block) {
|
||||
* Record the block that a gesture targets, meaning the block that will be
|
||||
* dragged if this turns into a drag. If this block is a shadow, that will be
|
||||
* its first non-shadow parent.
|
||||
* @param {Blockly.BlockSvg} block The block the gesture targets.
|
||||
* @param {BlockSvg} block The block the gesture targets.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.setTargetBlock_ = function(block) {
|
||||
Gesture.prototype.setTargetBlock_ = function(block) {
|
||||
if (block.isShadow()) {
|
||||
this.setTargetBlock_(block.getParent());
|
||||
} else {
|
||||
@@ -854,10 +860,10 @@ Blockly.Gesture.prototype.setTargetBlock_ = function(block) {
|
||||
|
||||
/**
|
||||
* Record the workspace that a gesture started on.
|
||||
* @param {Blockly.WorkspaceSvg} ws The workspace the gesture started on.
|
||||
* @param {WorkspaceSvg} ws The workspace the gesture started on.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.setStartWorkspace_ = function(ws) {
|
||||
Gesture.prototype.setStartWorkspace_ = function(ws) {
|
||||
if (!this.startWorkspace_) {
|
||||
this.startWorkspace_ = ws;
|
||||
}
|
||||
@@ -865,10 +871,10 @@ Blockly.Gesture.prototype.setStartWorkspace_ = function(ws) {
|
||||
|
||||
/**
|
||||
* Record the flyout that a gesture started on.
|
||||
* @param {Blockly.IFlyout} flyout The flyout the gesture started on.
|
||||
* @param {IFlyout} flyout The flyout the gesture started on.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.setStartFlyout_ = function(flyout) {
|
||||
Gesture.prototype.setStartFlyout_ = function(flyout) {
|
||||
if (!this.flyout_) {
|
||||
this.flyout_ = flyout;
|
||||
}
|
||||
@@ -886,9 +892,9 @@ Blockly.Gesture.prototype.setStartFlyout_ = function(flyout) {
|
||||
* @return {boolean} Whether this gesture was a click on a bubble.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.isBubbleClick_ = function() {
|
||||
Gesture.prototype.isBubbleClick_ = function() {
|
||||
// A bubble click starts on a bubble and never escapes the drag radius.
|
||||
var hasStartBubble = !!this.startBubble_;
|
||||
const hasStartBubble = !!this.startBubble_;
|
||||
return hasStartBubble && !this.hasExceededDragRadius_;
|
||||
};
|
||||
|
||||
@@ -898,10 +904,10 @@ Blockly.Gesture.prototype.isBubbleClick_ = function() {
|
||||
* @return {boolean} Whether this gesture was a click on a block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.isBlockClick_ = function() {
|
||||
Gesture.prototype.isBlockClick_ = function() {
|
||||
// A block click starts on a block, never escapes the drag radius, and is not
|
||||
// a field click.
|
||||
var hasStartBlock = !!this.startBlock_;
|
||||
const hasStartBlock = !!this.startBlock_;
|
||||
return hasStartBlock && !this.hasExceededDragRadius_ && !this.isFieldClick_();
|
||||
};
|
||||
|
||||
@@ -911,8 +917,8 @@ Blockly.Gesture.prototype.isBlockClick_ = function() {
|
||||
* @return {boolean} Whether this gesture was a click on a field.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.isFieldClick_ = function() {
|
||||
var fieldClickable =
|
||||
Gesture.prototype.isFieldClick_ = function() {
|
||||
const fieldClickable =
|
||||
this.startField_ ? this.startField_.isClickable() : false;
|
||||
return fieldClickable && !this.hasExceededDragRadius_ &&
|
||||
(!this.flyout_ || !this.flyout_.autoClose);
|
||||
@@ -924,8 +930,8 @@ Blockly.Gesture.prototype.isFieldClick_ = function() {
|
||||
* @return {boolean} Whether this gesture was a click on a workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.isWorkspaceClick_ = function() {
|
||||
var onlyTouchedWorkspace =
|
||||
Gesture.prototype.isWorkspaceClick_ = function() {
|
||||
const onlyTouchedWorkspace =
|
||||
!this.startBlock_ && !this.startBubble_ && !this.startField_;
|
||||
return onlyTouchedWorkspace && !this.hasExceededDragRadius_;
|
||||
};
|
||||
@@ -939,7 +945,7 @@ Blockly.Gesture.prototype.isWorkspaceClick_ = function() {
|
||||
* @return {boolean} True if this gesture is a drag of a workspace or block.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.isDragging = function() {
|
||||
Gesture.prototype.isDragging = function() {
|
||||
return this.isDraggingWorkspace_ || this.isDraggingBlock_ ||
|
||||
this.isDraggingBubble_;
|
||||
};
|
||||
@@ -951,18 +957,18 @@ Blockly.Gesture.prototype.isDragging = function() {
|
||||
* @return {boolean} Whether this gesture was a click on a workspace.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.hasStarted = function() {
|
||||
Gesture.prototype.hasStarted = function() {
|
||||
return this.hasStarted_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a list of the insertion markers that currently exist. Block drags have
|
||||
* 0, 1, or 2 insertion markers.
|
||||
* @return {!Array<!Blockly.BlockSvg>} A possibly empty list of insertion
|
||||
* @return {!Array<!BlockSvg>} A possibly empty list of insertion
|
||||
* marker blocks.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.getInsertionMarkers = function() {
|
||||
Gesture.prototype.getInsertionMarkers = function() {
|
||||
if (this.blockDragger_) {
|
||||
return this.blockDragger_.getInsertionMarkers();
|
||||
}
|
||||
@@ -972,10 +978,10 @@ Blockly.Gesture.prototype.getInsertionMarkers = function() {
|
||||
/**
|
||||
* Gets the current dragger if an item is being dragged. Null if nothing is
|
||||
* being dragged.
|
||||
* @return {!Blockly.WorkspaceDragger|!Blockly.BubbleDragger|!Blockly.IBlockDragger|null}
|
||||
* @return {!WorkspaceDragger|!BubbleDragger|!IBlockDragger|null}
|
||||
* The dragger that is currently in use or null if no drag is in progress.
|
||||
*/
|
||||
Blockly.Gesture.prototype.getCurrentDragger = function() {
|
||||
Gesture.prototype.getCurrentDragger = function() {
|
||||
if (this.isDraggingBlock_) {
|
||||
return this.blockDragger_;
|
||||
} else if (this.isDraggingWorkspace_) {
|
||||
@@ -990,12 +996,14 @@ Blockly.Gesture.prototype.getCurrentDragger = function() {
|
||||
* Is a drag or other gesture currently in progress on any workspace?
|
||||
* @return {boolean} True if gesture is occurring.
|
||||
*/
|
||||
Blockly.Gesture.inProgress = function() {
|
||||
var workspaces = Blockly.Workspace.getAll();
|
||||
for (var i = 0, workspace; (workspace = workspaces[i]); i++) {
|
||||
Gesture.inProgress = function() {
|
||||
const workspaces = Workspace.getAll();
|
||||
for (let i = 0, workspace; (workspace = workspaces[i]); i++) {
|
||||
if (workspace.currentGesture_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
exports = Gesture;
|
||||
|
||||
69
core/grid.js
69
core/grid.js
@@ -11,11 +11,12 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Grid');
|
||||
goog.module('Blockly.Grid');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
goog.require('Blockly.utils.userAgent');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const userAgent = goog.require('Blockly.utils.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@ goog.require('Blockly.utils.userAgent');
|
||||
* https://developers.google.com/blockly/guides/configure/web/grid
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Grid = function(pattern, options) {
|
||||
const Grid = function(pattern, options) {
|
||||
/**
|
||||
* The grid's SVG pattern, created during injection.
|
||||
* @type {!SVGElement}
|
||||
@@ -61,8 +62,8 @@ Blockly.Grid = function(pattern, options) {
|
||||
* @type {SVGElement}
|
||||
* @private
|
||||
*/
|
||||
this.line2_ = this.line1_ &&
|
||||
(/** @type {SVGElement} */ (this.line1_.nextSibling));
|
||||
this.line2_ =
|
||||
this.line1_ && (/** @type {SVGElement} */ (this.line1_.nextSibling));
|
||||
|
||||
/**
|
||||
* Whether blocks should snap to the grid.
|
||||
@@ -78,14 +79,14 @@ Blockly.Grid = function(pattern, options) {
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.Grid.prototype.scale_ = 1;
|
||||
Grid.prototype.scale_ = 1;
|
||||
|
||||
/**
|
||||
* Dispose of this grid and unlink from the DOM.
|
||||
* @package
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
Blockly.Grid.prototype.dispose = function() {
|
||||
Grid.prototype.dispose = function() {
|
||||
this.gridPattern_ = null;
|
||||
};
|
||||
|
||||
@@ -94,7 +95,7 @@ Blockly.Grid.prototype.dispose = function() {
|
||||
* @return {boolean} True if blocks should snap, false otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Grid.prototype.shouldSnap = function() {
|
||||
Grid.prototype.shouldSnap = function() {
|
||||
return this.snapToGrid_;
|
||||
};
|
||||
|
||||
@@ -103,7 +104,7 @@ Blockly.Grid.prototype.shouldSnap = function() {
|
||||
* @return {number} The spacing of the grid points.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Grid.prototype.getSpacing = function() {
|
||||
Grid.prototype.getSpacing = function() {
|
||||
return this.spacing_;
|
||||
};
|
||||
|
||||
@@ -113,7 +114,7 @@ Blockly.Grid.prototype.getSpacing = function() {
|
||||
* @return {string} The pattern ID.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Grid.prototype.getPatternId = function() {
|
||||
Grid.prototype.getPatternId = function() {
|
||||
return this.gridPattern_.id;
|
||||
};
|
||||
|
||||
@@ -122,17 +123,17 @@ Blockly.Grid.prototype.getPatternId = function() {
|
||||
* @param {number} scale The new workspace scale.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Grid.prototype.update = function(scale) {
|
||||
Grid.prototype.update = function(scale) {
|
||||
this.scale_ = scale;
|
||||
// MSIE freaks if it sees a 0x0 pattern, so set empty patterns to 100x100.
|
||||
var safeSpacing = (this.spacing_ * scale) || 100;
|
||||
const safeSpacing = (this.spacing_ * scale) || 100;
|
||||
|
||||
this.gridPattern_.setAttribute('width', safeSpacing);
|
||||
this.gridPattern_.setAttribute('height', safeSpacing);
|
||||
|
||||
var half = Math.floor(this.spacing_ / 2) + 0.5;
|
||||
var start = half - this.length_ / 2;
|
||||
var end = half + this.length_ / 2;
|
||||
let half = Math.floor(this.spacing_ / 2) + 0.5;
|
||||
let start = half - this.length_ / 2;
|
||||
let end = half + this.length_ / 2;
|
||||
|
||||
half *= scale;
|
||||
start *= scale;
|
||||
@@ -153,8 +154,7 @@ Blockly.Grid.prototype.update = function(scale) {
|
||||
* @param {number} y2 The new y end position of the line (in px).
|
||||
* @private
|
||||
*/
|
||||
Blockly.Grid.prototype.setLineAttributes_ = function(line, width,
|
||||
x1, x2, y1, y2) {
|
||||
Grid.prototype.setLineAttributes_ = function(line, width, x1, x2, y1, y2) {
|
||||
if (line) {
|
||||
line.setAttribute('stroke-width', width);
|
||||
line.setAttribute('x1', x1);
|
||||
@@ -171,11 +171,11 @@ Blockly.Grid.prototype.setLineAttributes_ = function(line, width,
|
||||
* @param {number} y The new y position of the grid (in px).
|
||||
* @package
|
||||
*/
|
||||
Blockly.Grid.prototype.moveTo = function(x, y) {
|
||||
Grid.prototype.moveTo = function(x, y) {
|
||||
this.gridPattern_.setAttribute('x', x);
|
||||
this.gridPattern_.setAttribute('y', y);
|
||||
|
||||
if (Blockly.utils.userAgent.IE || Blockly.utils.userAgent.EDGE) {
|
||||
if (userAgent.IE || userAgent.EDGE) {
|
||||
// IE/Edge doesn't notice that the x/y offsets have changed.
|
||||
// Force an update.
|
||||
this.update(this.scale_);
|
||||
@@ -190,33 +190,30 @@ Blockly.Grid.prototype.moveTo = function(x, y) {
|
||||
* @return {!SVGElement} The SVG element for the grid pattern.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Grid.createDom = function(rnd, gridOptions, defs) {
|
||||
Grid.createDom = function(rnd, gridOptions, defs) {
|
||||
/*
|
||||
<pattern id="blocklyGridPattern837493" patternUnits="userSpaceOnUse">
|
||||
<rect stroke="#888" />
|
||||
<rect stroke="#888" />
|
||||
</pattern>
|
||||
*/
|
||||
var gridPattern = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATTERN,
|
||||
{
|
||||
'id': 'blocklyGridPattern' + rnd,
|
||||
'patternUnits': 'userSpaceOnUse'
|
||||
}, defs);
|
||||
const gridPattern = dom.createSvgElement(
|
||||
Svg.PATTERN,
|
||||
{'id': 'blocklyGridPattern' + rnd, 'patternUnits': 'userSpaceOnUse'},
|
||||
defs);
|
||||
if (gridOptions['length'] > 0 && gridOptions['spacing'] > 0) {
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.LINE,
|
||||
{'stroke': gridOptions['colour']}, gridPattern);
|
||||
dom.createSvgElement(
|
||||
Svg.LINE, {'stroke': gridOptions['colour']}, gridPattern);
|
||||
if (gridOptions['length'] > 1) {
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.LINE,
|
||||
{'stroke': gridOptions['colour']}, gridPattern);
|
||||
dom.createSvgElement(
|
||||
Svg.LINE, {'stroke': gridOptions['colour']}, gridPattern);
|
||||
}
|
||||
// x1, y1, x1, x2 properties will be set later in update.
|
||||
} else {
|
||||
// Edge 16 doesn't handle empty patterns
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.LINE, {}, gridPattern);
|
||||
dom.createSvgElement(Svg.LINE, {}, gridPattern);
|
||||
}
|
||||
return gridPattern;
|
||||
};
|
||||
|
||||
exports = Grid;
|
||||
|
||||
97
core/icon.js
97
core/icon.js
@@ -10,29 +10,31 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Icon');
|
||||
goog.module('Blockly.Icon');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.browserEvents');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.Size');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.Bubble');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Bubble = goog.requireType('Blockly.Bubble');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
const Size = goog.require('Blockly.utils.Size');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const browserEvents = goog.require('Blockly.browserEvents');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const {getRelativeXY, isRightButton} = goog.require('Blockly.utils');
|
||||
|
||||
|
||||
/**
|
||||
* Class for an icon.
|
||||
* @param {Blockly.BlockSvg} block The block associated with this icon.
|
||||
* @param {BlockSvg} block The block associated with this icon.
|
||||
* @constructor
|
||||
* @abstract
|
||||
*/
|
||||
Blockly.Icon = function(block) {
|
||||
const Icon = function(block) {
|
||||
/**
|
||||
* The block this icon is attached to.
|
||||
* @type {Blockly.BlockSvg}
|
||||
* @type {BlockSvg}
|
||||
* @protected
|
||||
*/
|
||||
this.block_ = block;
|
||||
@@ -47,31 +49,32 @@ Blockly.Icon = function(block) {
|
||||
/**
|
||||
* Does this icon get hidden when the block is collapsed.
|
||||
*/
|
||||
Blockly.Icon.prototype.collapseHidden = true;
|
||||
Icon.prototype.collapseHidden = true;
|
||||
|
||||
/**
|
||||
* Height and width of icons.
|
||||
* @const
|
||||
*/
|
||||
Blockly.Icon.prototype.SIZE = 17;
|
||||
Icon.prototype.SIZE = 17;
|
||||
|
||||
/**
|
||||
* Bubble UI (if visible).
|
||||
* @type {?Blockly.Bubble}
|
||||
* @type {?Bubble}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Icon.prototype.bubble_ = null;
|
||||
Icon.prototype.bubble_ = null;
|
||||
|
||||
/**
|
||||
* Absolute coordinate of icon's center.
|
||||
* @type {?Blockly.utils.Coordinate}
|
||||
* @type {?Coordinate}
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Icon.prototype.iconXY_ = null;
|
||||
Icon.prototype.iconXY_ = null;
|
||||
|
||||
/**
|
||||
* Create the icon on the block.
|
||||
*/
|
||||
Blockly.Icon.prototype.createIcon = function() {
|
||||
Icon.prototype.createIcon = function() {
|
||||
if (this.iconGroup_) {
|
||||
// Icon already exists.
|
||||
return;
|
||||
@@ -81,17 +84,16 @@ Blockly.Icon.prototype.createIcon = function() {
|
||||
...
|
||||
</g>
|
||||
*/
|
||||
this.iconGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G,
|
||||
{'class': 'blocklyIconGroup'}, null);
|
||||
this.iconGroup_ =
|
||||
dom.createSvgElement(Svg.G, {'class': 'blocklyIconGroup'}, null);
|
||||
if (this.block_.isInFlyout) {
|
||||
Blockly.utils.dom.addClass(
|
||||
dom.addClass(
|
||||
/** @type {!Element} */ (this.iconGroup_), 'blocklyIconGroupReadonly');
|
||||
}
|
||||
this.drawIcon_(this.iconGroup_);
|
||||
|
||||
this.block_.getSvgRoot().appendChild(this.iconGroup_);
|
||||
Blockly.browserEvents.conditionalBind(
|
||||
browserEvents.conditionalBind(
|
||||
this.iconGroup_, 'mouseup', this, this.iconClick_);
|
||||
this.updateEditable();
|
||||
};
|
||||
@@ -99,9 +101,9 @@ Blockly.Icon.prototype.createIcon = function() {
|
||||
/**
|
||||
* Dispose of this icon.
|
||||
*/
|
||||
Blockly.Icon.prototype.dispose = function() {
|
||||
Icon.prototype.dispose = function() {
|
||||
// Dispose of and unlink the icon.
|
||||
Blockly.utils.dom.removeNode(this.iconGroup_);
|
||||
dom.removeNode(this.iconGroup_);
|
||||
this.iconGroup_ = null;
|
||||
// Dispose of and unlink the bubble.
|
||||
this.setVisible(false);
|
||||
@@ -111,7 +113,7 @@ Blockly.Icon.prototype.dispose = function() {
|
||||
/**
|
||||
* Add or remove the UI indicating if this icon may be clicked or not.
|
||||
*/
|
||||
Blockly.Icon.prototype.updateEditable = function() {
|
||||
Icon.prototype.updateEditable = function() {
|
||||
// No-op on the base class.
|
||||
};
|
||||
|
||||
@@ -119,7 +121,7 @@ Blockly.Icon.prototype.updateEditable = function() {
|
||||
* Is the associated bubble visible?
|
||||
* @return {boolean} True if the bubble is visible.
|
||||
*/
|
||||
Blockly.Icon.prototype.isVisible = function() {
|
||||
Icon.prototype.isVisible = function() {
|
||||
return !!this.bubble_;
|
||||
};
|
||||
|
||||
@@ -128,12 +130,12 @@ Blockly.Icon.prototype.isVisible = function() {
|
||||
* @param {!Event} e Mouse click event.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Icon.prototype.iconClick_ = function(e) {
|
||||
Icon.prototype.iconClick_ = function(e) {
|
||||
if (this.block_.workspace.isDragging()) {
|
||||
// Drag operation is concluding. Don't open the editor.
|
||||
return;
|
||||
}
|
||||
if (!this.block_.isInFlyout && !Blockly.utils.isRightButton(e)) {
|
||||
if (!this.block_.isInFlyout && !isRightButton(e)) {
|
||||
this.setVisible(!this.isVisible());
|
||||
}
|
||||
};
|
||||
@@ -141,7 +143,7 @@ Blockly.Icon.prototype.iconClick_ = function(e) {
|
||||
/**
|
||||
* Change the colour of the associated bubble to match its block.
|
||||
*/
|
||||
Blockly.Icon.prototype.applyColour = function() {
|
||||
Icon.prototype.applyColour = function() {
|
||||
if (this.isVisible()) {
|
||||
this.bubble_.setColour(this.block_.style.colourPrimary);
|
||||
}
|
||||
@@ -149,9 +151,9 @@ Blockly.Icon.prototype.applyColour = function() {
|
||||
|
||||
/**
|
||||
* Notification that the icon has moved. Update the arrow accordingly.
|
||||
* @param {!Blockly.utils.Coordinate} xy Absolute location in workspace coordinates.
|
||||
* @param {!Coordinate} xy Absolute location in workspace coordinates.
|
||||
*/
|
||||
Blockly.Icon.prototype.setIconLocation = function(xy) {
|
||||
Icon.prototype.setIconLocation = function(xy) {
|
||||
this.iconXY_ = xy;
|
||||
if (this.isVisible()) {
|
||||
this.bubble_.setAnchorLocation(xy);
|
||||
@@ -162,25 +164,25 @@ Blockly.Icon.prototype.setIconLocation = function(xy) {
|
||||
* Notification that the icon has moved, but we don't really know where.
|
||||
* Recompute the icon's location from scratch.
|
||||
*/
|
||||
Blockly.Icon.prototype.computeIconLocation = function() {
|
||||
Icon.prototype.computeIconLocation = function() {
|
||||
// Find coordinates for the centre of the icon and update the arrow.
|
||||
var blockXY = this.block_.getRelativeToSurfaceXY();
|
||||
var iconXY = Blockly.utils.getRelativeXY(
|
||||
const blockXY = this.block_.getRelativeToSurfaceXY();
|
||||
const iconXY = getRelativeXY(
|
||||
/** @type {!SVGElement} */ (this.iconGroup_));
|
||||
var newXY = new Blockly.utils.Coordinate(
|
||||
const newXY = new Coordinate(
|
||||
blockXY.x + iconXY.x + this.SIZE / 2,
|
||||
blockXY.y + iconXY.y + this.SIZE / 2);
|
||||
if (!Blockly.utils.Coordinate.equals(this.getIconLocation(), newXY)) {
|
||||
if (!Coordinate.equals(this.getIconLocation(), newXY)) {
|
||||
this.setIconLocation(newXY);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the center of the block's icon relative to the surface.
|
||||
* @return {?Blockly.utils.Coordinate} Object with x and y properties in
|
||||
* @return {?Coordinate} Object with x and y properties in
|
||||
* workspace coordinates.
|
||||
*/
|
||||
Blockly.Icon.prototype.getIconLocation = function() {
|
||||
Icon.prototype.getIconLocation = function() {
|
||||
return this.iconXY_;
|
||||
};
|
||||
|
||||
@@ -188,12 +190,11 @@ Blockly.Icon.prototype.getIconLocation = function() {
|
||||
* Get the size of the icon as used for rendering.
|
||||
* This differs from the actual size of the icon, because it bulges slightly
|
||||
* out of its row rather than increasing the height of its row.
|
||||
* @return {!Blockly.utils.Size} Height and width.
|
||||
* @return {!Size} Height and width.
|
||||
*/
|
||||
// TODO (#2562): Remove getCorrectedSize.
|
||||
Blockly.Icon.prototype.getCorrectedSize = function() {
|
||||
return new Blockly.utils.Size(
|
||||
Blockly.Icon.prototype.SIZE, Blockly.Icon.prototype.SIZE - 2);
|
||||
Icon.prototype.getCorrectedSize = function() {
|
||||
return new Size(Icon.prototype.SIZE, Icon.prototype.SIZE - 2);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -201,10 +202,12 @@ Blockly.Icon.prototype.getCorrectedSize = function() {
|
||||
* @param {!Element} group The icon group.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Icon.prototype.drawIcon_;
|
||||
Icon.prototype.drawIcon_;
|
||||
|
||||
/**
|
||||
* Show or hide the icon.
|
||||
* @param {boolean} visible True if the icon should be visible.
|
||||
*/
|
||||
Blockly.Icon.prototype.setVisible;
|
||||
Icon.prototype.setVisible;
|
||||
|
||||
exports = Icon;
|
||||
|
||||
113
core/input.js
113
core/input.js
@@ -10,31 +10,36 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Input');
|
||||
goog.module('Blockly.Input');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Connection');
|
||||
goog.require('Blockly.fieldRegistry');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Connection = goog.require('Blockly.Connection');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Field = goog.requireType('Blockly.Field');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const RenderedConnection = goog.requireType('Blockly.RenderedConnection');
|
||||
const constants = goog.require('Blockly.constants');
|
||||
const fieldRegistry = goog.require('Blockly.fieldRegistry');
|
||||
const inputTypes = goog.require('Blockly.inputTypes');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.FieldLabel');
|
||||
goog.require('Blockly.inputTypes');
|
||||
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.Field');
|
||||
goog.requireType('Blockly.RenderedConnection');
|
||||
|
||||
|
||||
/**
|
||||
* Class for an input with an optional field.
|
||||
* @param {number} type The type of the input.
|
||||
* @param {string} name Language-neutral identifier which may used to find this
|
||||
* input again.
|
||||
* @param {!Blockly.Block} block The block containing this input.
|
||||
* @param {Blockly.Connection} connection Optional connection for this input.
|
||||
* @param {!Block} block The block containing this input.
|
||||
* @param {Connection} connection Optional connection for this input.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Input = function(type, name, block, connection) {
|
||||
if (type != Blockly.inputTypes.DUMMY && !name) {
|
||||
const Input = function(type, name, block, connection) {
|
||||
if (type != inputTypes.DUMMY && !name) {
|
||||
throw Error('Value inputs and statement inputs must have non-empty name.');
|
||||
}
|
||||
/** @type {number} */
|
||||
@@ -42,13 +47,13 @@ Blockly.Input = function(type, name, block, connection) {
|
||||
/** @type {string} */
|
||||
this.name = name;
|
||||
/**
|
||||
* @type {!Blockly.Block}
|
||||
* @type {!Block}
|
||||
* @private
|
||||
*/
|
||||
this.sourceBlock_ = block;
|
||||
/** @type {Blockly.Connection} */
|
||||
/** @type {Connection} */
|
||||
this.connection = connection;
|
||||
/** @type {!Array<!Blockly.Field>} */
|
||||
/** @type {!Array<!Field>} */
|
||||
this.fieldRow = [];
|
||||
};
|
||||
|
||||
@@ -56,32 +61,32 @@ Blockly.Input = function(type, name, block, connection) {
|
||||
* Alignment of input's fields (left, right or centre).
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.Input.prototype.align = Blockly.constants.ALIGN.LEFT;
|
||||
Input.prototype.align = constants.ALIGN.LEFT;
|
||||
|
||||
/**
|
||||
* Is the input visible?
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
Blockly.Input.prototype.visible_ = true;
|
||||
Input.prototype.visible_ = true;
|
||||
|
||||
/**
|
||||
* Get the source block for this input.
|
||||
* @return {?Blockly.Block} The source block, or null if there is none.
|
||||
* @return {?Block} The source block, or null if there is none.
|
||||
*/
|
||||
Blockly.Input.prototype.getSourceBlock = function() {
|
||||
Input.prototype.getSourceBlock = function() {
|
||||
return this.sourceBlock_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a field (or label from string), and all prefix and suffix fields, to the
|
||||
* end of the input's field row.
|
||||
* @param {string|!Blockly.Field} field Something to add as a field.
|
||||
* @param {string|!Field} field Something to add as a field.
|
||||
* @param {string=} opt_name Language-neutral identifier which may used to find
|
||||
* this field again. Should be unique to the host block.
|
||||
* @return {!Blockly.Input} The input being append to (to allow chaining).
|
||||
* @return {!Input} The input being append to (to allow chaining).
|
||||
*/
|
||||
Blockly.Input.prototype.appendField = function(field, opt_name) {
|
||||
Input.prototype.appendField = function(field, opt_name) {
|
||||
this.insertFieldAt(this.fieldRow.length, field, opt_name);
|
||||
return this;
|
||||
};
|
||||
@@ -90,12 +95,12 @@ Blockly.Input.prototype.appendField = function(field, opt_name) {
|
||||
* Inserts a field (or label from string), and all prefix and suffix fields, at
|
||||
* the location of the input's field row.
|
||||
* @param {number} index The index at which to insert field.
|
||||
* @param {string|!Blockly.Field} field Something to add as a field.
|
||||
* @param {string|!Field} field Something to add as a field.
|
||||
* @param {string=} opt_name Language-neutral identifier which may used to find
|
||||
* this field again. Should be unique to the host block.
|
||||
* @return {number} The index following the last inserted field.
|
||||
*/
|
||||
Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) {
|
||||
Input.prototype.insertFieldAt = function(index, field, opt_name) {
|
||||
if (index < 0 || index > this.fieldRow.length) {
|
||||
throw Error('index ' + index + ' out of bounds.');
|
||||
}
|
||||
@@ -107,7 +112,7 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) {
|
||||
|
||||
// Generate a FieldLabel when given a plain text field.
|
||||
if (typeof field == 'string') {
|
||||
field = /** @type {!Blockly.Field} **/ (Blockly.fieldRegistry.fromJson({
|
||||
field = /** @type {!Field} **/ (fieldRegistry.fromJson({
|
||||
'type': 'field_label',
|
||||
'text': field,
|
||||
}));
|
||||
@@ -134,7 +139,7 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) {
|
||||
}
|
||||
|
||||
if (this.sourceBlock_.rendered) {
|
||||
this.sourceBlock_ = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_);
|
||||
this.sourceBlock_ = /** @type {!BlockSvg} */ (this.sourceBlock_);
|
||||
this.sourceBlock_.render();
|
||||
// Adding a field will cause the block to change shape.
|
||||
this.sourceBlock_.bumpNeighbours();
|
||||
@@ -150,13 +155,13 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) {
|
||||
* and opt_quiet is true.
|
||||
* @throws {Error} if the field is not present and opt_quiet is false.
|
||||
*/
|
||||
Blockly.Input.prototype.removeField = function(name, opt_quiet) {
|
||||
for (var i = 0, field; (field = this.fieldRow[i]); i++) {
|
||||
Input.prototype.removeField = function(name, opt_quiet) {
|
||||
for (let i = 0, field; (field = this.fieldRow[i]); i++) {
|
||||
if (field.name === name) {
|
||||
field.dispose();
|
||||
this.fieldRow.splice(i, 1);
|
||||
if (this.sourceBlock_.rendered) {
|
||||
this.sourceBlock_ = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_);
|
||||
this.sourceBlock_ = /** @type {!BlockSvg} */ (this.sourceBlock_);
|
||||
this.sourceBlock_.render();
|
||||
// Removing a field will cause the block to change shape.
|
||||
this.sourceBlock_.bumpNeighbours();
|
||||
@@ -174,7 +179,7 @@ Blockly.Input.prototype.removeField = function(name, opt_quiet) {
|
||||
* Gets whether this input is visible or not.
|
||||
* @return {boolean} True if visible.
|
||||
*/
|
||||
Blockly.Input.prototype.isVisible = function() {
|
||||
Input.prototype.isVisible = function() {
|
||||
return this.visible_;
|
||||
};
|
||||
|
||||
@@ -182,32 +187,32 @@ Blockly.Input.prototype.isVisible = function() {
|
||||
* Sets whether this input is visible or not.
|
||||
* Should only be used to collapse/uncollapse a block.
|
||||
* @param {boolean} visible True if visible.
|
||||
* @return {!Array<!Blockly.BlockSvg>} List of blocks to render.
|
||||
* @return {!Array<!BlockSvg>} List of blocks to render.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Input.prototype.setVisible = function(visible) {
|
||||
Input.prototype.setVisible = function(visible) {
|
||||
// Note: Currently there are only unit tests for block.setCollapsed()
|
||||
// because this function is package. If this function goes back to being a
|
||||
// public API tests (lots of tests) should be added.
|
||||
var renderList = [];
|
||||
let renderList = [];
|
||||
if (this.visible_ == visible) {
|
||||
return renderList;
|
||||
}
|
||||
this.visible_ = visible;
|
||||
|
||||
for (var y = 0, field; (field = this.fieldRow[y]); y++) {
|
||||
for (let y = 0, field; (field = this.fieldRow[y]); y++) {
|
||||
field.setVisible(visible);
|
||||
}
|
||||
if (this.connection) {
|
||||
this.connection =
|
||||
/** @type {!Blockly.RenderedConnection} */ (this.connection);
|
||||
/** @type {!RenderedConnection} */ (this.connection);
|
||||
// Has a connection.
|
||||
if (visible) {
|
||||
renderList = this.connection.startTrackingAll();
|
||||
} else {
|
||||
this.connection.stopTrackingAll();
|
||||
}
|
||||
var child = this.connection.targetBlock();
|
||||
const child = this.connection.targetBlock();
|
||||
if (child) {
|
||||
child.getSvgRoot().style.display = visible ? 'block' : 'none';
|
||||
}
|
||||
@@ -219,8 +224,8 @@ Blockly.Input.prototype.setVisible = function(visible) {
|
||||
* Mark all fields on this input as dirty.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Input.prototype.markDirty = function() {
|
||||
for (var y = 0, field; (field = this.fieldRow[y]); y++) {
|
||||
Input.prototype.markDirty = function() {
|
||||
for (let y = 0, field; (field = this.fieldRow[y]); y++) {
|
||||
field.markDirty();
|
||||
}
|
||||
};
|
||||
@@ -229,9 +234,9 @@ Blockly.Input.prototype.markDirty = function() {
|
||||
* Change a connection's compatibility.
|
||||
* @param {string|Array<string>|null} check Compatible value type or
|
||||
* list of value types. Null if all types are compatible.
|
||||
* @return {!Blockly.Input} The input being modified (to allow chaining).
|
||||
* @return {!Input} The input being modified (to allow chaining).
|
||||
*/
|
||||
Blockly.Input.prototype.setCheck = function(check) {
|
||||
Input.prototype.setCheck = function(check) {
|
||||
if (!this.connection) {
|
||||
throw Error('This input does not have a connection.');
|
||||
}
|
||||
@@ -241,14 +246,14 @@ Blockly.Input.prototype.setCheck = function(check) {
|
||||
|
||||
/**
|
||||
* Change the alignment of the connection's field(s).
|
||||
* @param {number} align One of the values of Blockly.constants.ALIGN.
|
||||
* @param {number} align One of the values of constants.ALIGN.
|
||||
* In RTL mode directions are reversed, and ALIGN.RIGHT aligns to the left.
|
||||
* @return {!Blockly.Input} The input being modified (to allow chaining).
|
||||
* @return {!Input} The input being modified (to allow chaining).
|
||||
*/
|
||||
Blockly.Input.prototype.setAlign = function(align) {
|
||||
Input.prototype.setAlign = function(align) {
|
||||
this.align = align;
|
||||
if (this.sourceBlock_.rendered) {
|
||||
this.sourceBlock_ = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_);
|
||||
this.sourceBlock_ = /** @type {!BlockSvg} */ (this.sourceBlock_);
|
||||
this.sourceBlock_.render();
|
||||
}
|
||||
return this;
|
||||
@@ -257,9 +262,9 @@ Blockly.Input.prototype.setAlign = function(align) {
|
||||
/**
|
||||
* Changes the connection's shadow block.
|
||||
* @param {?Element} shadow DOM representation of a block or null.
|
||||
* @return {!Blockly.Input} The input being modified (to allow chaining).
|
||||
* @return {!Input} The input being modified (to allow chaining).
|
||||
*/
|
||||
Blockly.Input.prototype.setShadowDom = function(shadow) {
|
||||
Input.prototype.setShadowDom = function(shadow) {
|
||||
if (!this.connection) {
|
||||
throw Error('This input does not have a connection.');
|
||||
}
|
||||
@@ -271,7 +276,7 @@ Blockly.Input.prototype.setShadowDom = function(shadow) {
|
||||
* Returns the XML representation of the connection's shadow block.
|
||||
* @return {?Element} Shadow DOM representation of a block or null.
|
||||
*/
|
||||
Blockly.Input.prototype.getShadowDom = function() {
|
||||
Input.prototype.getShadowDom = function() {
|
||||
if (!this.connection) {
|
||||
throw Error('This input does not have a connection.');
|
||||
}
|
||||
@@ -281,11 +286,11 @@ Blockly.Input.prototype.getShadowDom = function() {
|
||||
/**
|
||||
* Initialize the fields on this input.
|
||||
*/
|
||||
Blockly.Input.prototype.init = function() {
|
||||
Input.prototype.init = function() {
|
||||
if (!this.sourceBlock_.workspace.rendered) {
|
||||
return; // Headless blocks don't need fields initialized.
|
||||
}
|
||||
for (var i = 0; i < this.fieldRow.length; i++) {
|
||||
for (let i = 0; i < this.fieldRow.length; i++) {
|
||||
this.fieldRow[i].init();
|
||||
}
|
||||
};
|
||||
@@ -294,8 +299,8 @@ Blockly.Input.prototype.init = function() {
|
||||
* Sever all links to this input.
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
Blockly.Input.prototype.dispose = function() {
|
||||
for (var i = 0, field; (field = this.fieldRow[i]); i++) {
|
||||
Input.prototype.dispose = function() {
|
||||
for (let i = 0, field; (field = this.fieldRow[i]); i++) {
|
||||
field.dispose();
|
||||
}
|
||||
if (this.connection) {
|
||||
@@ -303,3 +308,5 @@ Blockly.Input.prototype.dispose = function() {
|
||||
}
|
||||
this.sourceBlock_ = null;
|
||||
};
|
||||
|
||||
exports = Input;
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
goog.module('Blockly.ICollapsibleToolboxItem');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ISelectableToolboxItem = goog.require('Blockly.ISelectableToolboxItem');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IToolboxItem = goog.requireType('Blockly.IToolboxItem');
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ goog.module('Blockly.IKeyboardAccessible');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const {KeyboardShortcut} = goog.requireType('Blockly.ShortcutRegistry');
|
||||
const ShortcutRegistry = goog.requireType('Blockly.ShortcutRegistry');
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,7 +26,8 @@ const IKeyboardAccessible = function() {};
|
||||
|
||||
/**
|
||||
* Handles the given keyboard shortcut.
|
||||
* @param {!KeyboardShortcut} shortcut The shortcut to be handled.
|
||||
* @param {!ShortcutRegistry.KeyboardShortcut} shortcut The shortcut to be
|
||||
* handled.
|
||||
* @return {boolean} True if the shortcut has been handled, false otherwise.
|
||||
*/
|
||||
IKeyboardAccessible.prototype.onShortcut;
|
||||
|
||||
@@ -11,92 +11,96 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.IMetricsManager');
|
||||
goog.module('Blockly.IMetricsManager');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.requireType('Blockly.MetricsManager');
|
||||
goog.requireType('Blockly.utils.Metrics');
|
||||
goog.requireType('Blockly.utils.Size');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Metrics = goog.requireType('Blockly.utils.Metrics');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Size = goog.requireType('Blockly.utils.Size');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const {AbsoluteMetrics, ContainerRegion, ToolboxMetrics} = goog.requireType('Blockly.MetricsManager');
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a metrics manager.
|
||||
* @interface
|
||||
*/
|
||||
Blockly.IMetricsManager = function() {};
|
||||
const IMetricsManager = function() {};
|
||||
|
||||
/**
|
||||
* Returns whether the scroll area has fixed edges.
|
||||
* @return {boolean} Whether the scroll area has fixed edges.
|
||||
* @package
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.hasFixedEdges;
|
||||
IMetricsManager.prototype.hasFixedEdges;
|
||||
|
||||
/**
|
||||
* Returns the metrics for the scroll area of the workspace.
|
||||
* @param {boolean=} opt_getWorkspaceCoordinates True to get the scroll metrics
|
||||
* in workspace coordinates, false to get them in pixel coordinates.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_viewMetrics The view
|
||||
* @param {!ContainerRegion=} opt_viewMetrics The view
|
||||
* metrics if they have been previously computed. Passing in null may cause
|
||||
* the view metrics to be computed again, if it is needed.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_contentMetrics The
|
||||
* @param {!ContainerRegion=} opt_contentMetrics The
|
||||
* content metrics if they have been previously computed. Passing in null
|
||||
* may cause the content metrics to be computed again, if it is needed.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The metrics for the scroll
|
||||
* @return {!ContainerRegion} The metrics for the scroll
|
||||
* container
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getScrollMetrics;
|
||||
IMetricsManager.prototype.getScrollMetrics;
|
||||
|
||||
/**
|
||||
* Gets the width and the height of the flyout on the workspace in pixel
|
||||
* coordinates. Returns 0 for the width and height if the workspace has a
|
||||
* category toolbox instead of a simple toolbox.
|
||||
* @param {boolean=} opt_own Whether to only return the workspace's own flyout.
|
||||
* @return {!Blockly.MetricsManager.ToolboxMetrics} The width and height of the
|
||||
* @return {!ToolboxMetrics} The width and height of the
|
||||
* flyout.
|
||||
* @public
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getFlyoutMetrics;
|
||||
IMetricsManager.prototype.getFlyoutMetrics;
|
||||
|
||||
/**
|
||||
* Gets the width, height and position of the toolbox on the workspace in pixel
|
||||
* coordinates. Returns 0 for the width and height if the workspace has a simple
|
||||
* toolbox instead of a category toolbox. To get the width and height of a
|
||||
* simple toolbox @see {@link getFlyoutMetrics}.
|
||||
* @return {!Blockly.MetricsManager.ToolboxMetrics} The object with the width,
|
||||
* @return {!ToolboxMetrics} The object with the width,
|
||||
* height and position of the toolbox.
|
||||
* @public
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getToolboxMetrics;
|
||||
IMetricsManager.prototype.getToolboxMetrics;
|
||||
|
||||
/**
|
||||
* Gets the width and height of the workspace's parent SVG element in pixel
|
||||
* coordinates. This area includes the toolbox and the visible workspace area.
|
||||
* @return {!Blockly.utils.Size} The width and height of the workspace's parent
|
||||
* @return {!Size} The width and height of the workspace's parent
|
||||
* SVG element.
|
||||
* @public
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getSvgMetrics;
|
||||
IMetricsManager.prototype.getSvgMetrics;
|
||||
|
||||
/**
|
||||
* Gets the absolute left and absolute top in pixel coordinates.
|
||||
* This is where the visible workspace starts in relation to the SVG container.
|
||||
* @return {!Blockly.MetricsManager.AbsoluteMetrics} The absolute metrics for
|
||||
* @return {!AbsoluteMetrics} The absolute metrics for
|
||||
* the workspace.
|
||||
* @public
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getAbsoluteMetrics;
|
||||
IMetricsManager.prototype.getAbsoluteMetrics;
|
||||
|
||||
/**
|
||||
* Gets the metrics for the visible workspace in either pixel or workspace
|
||||
* coordinates. The visible workspace does not include the toolbox or flyout.
|
||||
* @param {boolean=} opt_getWorkspaceCoordinates True to get the view metrics in
|
||||
* workspace coordinates, false to get them in pixel coordinates.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The width, height, top and
|
||||
* @return {!ContainerRegion} The width, height, top and
|
||||
* left of the viewport in either workspace coordinates or pixel
|
||||
* coordinates.
|
||||
* @public
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getViewMetrics;
|
||||
IMetricsManager.prototype.getViewMetrics;
|
||||
|
||||
/**
|
||||
* Gets content metrics in either pixel or workspace coordinates.
|
||||
@@ -104,11 +108,11 @@ Blockly.IMetricsManager.prototype.getViewMetrics;
|
||||
* workspace (workspace comments and blocks).
|
||||
* @param {boolean=} opt_getWorkspaceCoordinates True to get the content metrics
|
||||
* in workspace coordinates, false to get them in pixel coordinates.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The
|
||||
* @return {!ContainerRegion} The
|
||||
* metrics for the content container.
|
||||
* @public
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getContentMetrics;
|
||||
IMetricsManager.prototype.getContentMetrics;
|
||||
|
||||
/**
|
||||
* Returns an object with all the metrics required to size scrollbars for a
|
||||
@@ -138,8 +142,10 @@ Blockly.IMetricsManager.prototype.getContentMetrics;
|
||||
* .flyoutHeight: Height of the flyout if it is always open. Otherwise zero.
|
||||
* .toolboxPosition: Top, bottom, left or right. Use TOOLBOX_AT constants to
|
||||
* compare.
|
||||
* @return {!Blockly.utils.Metrics} Contains size and position metrics of a top
|
||||
* @return {!Metrics} Contains size and position metrics of a top
|
||||
* level workspace.
|
||||
* @public
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getMetrics;
|
||||
IMetricsManager.prototype.getMetrics;
|
||||
|
||||
exports = IMetricsManager;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
goog.module('Blockly.IRegistrableField');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Field = goog.requireType('Blockly.Field');
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
goog.module('Blockly.ISelectableToolboxItem');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IToolboxItem = goog.require('Blockly.IToolboxItem');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const {FlyoutItemInfoArray} = goog.requireType('Blockly.utils.toolbox');
|
||||
|
||||
|
||||
|
||||
@@ -10,18 +10,25 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ASTNode');
|
||||
goog.module('Blockly.ASTNode');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.connectionTypes');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.Connection');
|
||||
goog.requireType('Blockly.Field');
|
||||
goog.requireType('Blockly.IASTNodeLocation');
|
||||
goog.requireType('Blockly.IASTNodeLocationWithBlock');
|
||||
goog.requireType('Blockly.Input');
|
||||
goog.requireType('Blockly.Workspace');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Connection = goog.requireType('Blockly.Connection');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Field = goog.requireType('Blockly.Field');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IASTNodeLocation = goog.requireType('Blockly.IASTNodeLocation');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IASTNodeLocationWithBlock = goog.requireType('Blockly.IASTNodeLocationWithBlock');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Input = goog.requireType('Blockly.Input');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
const connectionTypes = goog.require('Blockly.connectionTypes');
|
||||
|
||||
|
||||
/**
|
||||
@@ -29,19 +36,19 @@ goog.requireType('Blockly.Workspace');
|
||||
* It is recommended that you use one of the createNode methods instead of
|
||||
* creating a node directly.
|
||||
* @param {string} type The type of the location.
|
||||
* Must be in Blockly.ASTNode.types.
|
||||
* @param {!Blockly.IASTNodeLocation} location The position in the AST.
|
||||
* @param {!Blockly.ASTNode.Params=} opt_params Optional dictionary of options.
|
||||
* Must be in ASTNode.types.
|
||||
* @param {!IASTNodeLocation} location The position in the AST.
|
||||
* @param {!ASTNode.Params=} opt_params Optional dictionary of options.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.ASTNode = function(type, location, opt_params) {
|
||||
const ASTNode = function(type, location, opt_params) {
|
||||
if (!location) {
|
||||
throw Error('Cannot create a node without a location.');
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the location.
|
||||
* One of Blockly.ASTNode.types
|
||||
* One of ASTNode.types
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
@@ -52,18 +59,18 @@ Blockly.ASTNode = function(type, location, opt_params) {
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isConnection_ = Blockly.ASTNode.isConnectionType_(type);
|
||||
this.isConnection_ = ASTNode.isConnectionType_(type);
|
||||
|
||||
/**
|
||||
* The location of the AST node.
|
||||
* @type {!Blockly.IASTNodeLocation}
|
||||
* @type {!IASTNodeLocation}
|
||||
* @private
|
||||
*/
|
||||
this.location_ = location;
|
||||
|
||||
/**
|
||||
* The coordinate on the workspace.
|
||||
* @type {Blockly.utils.Coordinate}
|
||||
* @type {Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.wsCoordinate_ = null;
|
||||
@@ -73,16 +80,16 @@ Blockly.ASTNode = function(type, location, opt_params) {
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* wsCoordinate: Blockly.utils.Coordinate
|
||||
* wsCoordinate: Coordinate
|
||||
* }}
|
||||
*/
|
||||
Blockly.ASTNode.Params;
|
||||
ASTNode.Params;
|
||||
|
||||
/**
|
||||
* Object holding different types for an AST node.
|
||||
* @enum {string}
|
||||
*/
|
||||
Blockly.ASTNode.types = {
|
||||
ASTNode.types = {
|
||||
FIELD: 'field',
|
||||
BLOCK: 'block',
|
||||
INPUT: 'input',
|
||||
@@ -97,7 +104,7 @@ Blockly.ASTNode.types = {
|
||||
* True to navigate to all fields. False to only navigate to clickable fields.
|
||||
* @type {boolean}
|
||||
*/
|
||||
Blockly.ASTNode.NAVIGATE_ALL_FIELDS = false;
|
||||
ASTNode.NAVIGATE_ALL_FIELDS = false;
|
||||
|
||||
/**
|
||||
* The default y offset to use when moving the cursor from a stack to the
|
||||
@@ -105,20 +112,20 @@ Blockly.ASTNode.NAVIGATE_ALL_FIELDS = false;
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.DEFAULT_OFFSET_Y = -20;
|
||||
ASTNode.DEFAULT_OFFSET_Y = -20;
|
||||
|
||||
/**
|
||||
* Whether an AST node of the given type points to a connection.
|
||||
* @param {string} type The type to check. One of Blockly.ASTNode.types.
|
||||
* @param {string} type The type to check. One of ASTNode.types.
|
||||
* @return {boolean} True if a node of the given type points to a connection.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.isConnectionType_ = function(type) {
|
||||
ASTNode.isConnectionType_ = function(type) {
|
||||
switch (type) {
|
||||
case Blockly.ASTNode.types.PREVIOUS:
|
||||
case Blockly.ASTNode.types.NEXT:
|
||||
case Blockly.ASTNode.types.INPUT:
|
||||
case Blockly.ASTNode.types.OUTPUT:
|
||||
case ASTNode.types.PREVIOUS:
|
||||
case ASTNode.types.NEXT:
|
||||
case ASTNode.types.INPUT:
|
||||
case ASTNode.types.OUTPUT:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -126,39 +133,39 @@ Blockly.ASTNode.isConnectionType_ = function(type) {
|
||||
|
||||
/**
|
||||
* Create an AST node pointing to a field.
|
||||
* @param {Blockly.Field} field The location of the AST node.
|
||||
* @return {Blockly.ASTNode} An AST node pointing to a field.
|
||||
* @param {Field} field The location of the AST node.
|
||||
* @return {ASTNode} An AST node pointing to a field.
|
||||
*/
|
||||
Blockly.ASTNode.createFieldNode = function(field) {
|
||||
ASTNode.createFieldNode = function(field) {
|
||||
if (!field) {
|
||||
return null;
|
||||
}
|
||||
return new Blockly.ASTNode(Blockly.ASTNode.types.FIELD, field);
|
||||
return new ASTNode(ASTNode.types.FIELD, field);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an AST node pointing to a connection. If the connection has a parent
|
||||
* input then create an AST node of type input that will hold the connection.
|
||||
* @param {Blockly.Connection} connection This is the connection the node will
|
||||
* @param {Connection} connection This is the connection the node will
|
||||
* point to.
|
||||
* @return {Blockly.ASTNode} An AST node pointing to a connection.
|
||||
* @return {ASTNode} An AST node pointing to a connection.
|
||||
*/
|
||||
Blockly.ASTNode.createConnectionNode = function(connection) {
|
||||
ASTNode.createConnectionNode = function(connection) {
|
||||
if (!connection) {
|
||||
return null;
|
||||
}
|
||||
var type = connection.type;
|
||||
if (type == Blockly.connectionTypes.INPUT_VALUE) {
|
||||
return Blockly.ASTNode.createInputNode(connection.getParentInput());
|
||||
} else if (type == Blockly.connectionTypes.NEXT_STATEMENT &&
|
||||
connection.getParentInput()) {
|
||||
return Blockly.ASTNode.createInputNode(connection.getParentInput());
|
||||
} else if (type == Blockly.connectionTypes.NEXT_STATEMENT) {
|
||||
return new Blockly.ASTNode(Blockly.ASTNode.types.NEXT, connection);
|
||||
} else if (type == Blockly.connectionTypes.OUTPUT_VALUE) {
|
||||
return new Blockly.ASTNode(Blockly.ASTNode.types.OUTPUT, connection);
|
||||
} else if (type == Blockly.connectionTypes.PREVIOUS_STATEMENT) {
|
||||
return new Blockly.ASTNode(Blockly.ASTNode.types.PREVIOUS, connection);
|
||||
const type = connection.type;
|
||||
if (type == connectionTypes.INPUT_VALUE) {
|
||||
return ASTNode.createInputNode(connection.getParentInput());
|
||||
} else if (
|
||||
type == connectionTypes.NEXT_STATEMENT && connection.getParentInput()) {
|
||||
return ASTNode.createInputNode(connection.getParentInput());
|
||||
} else if (type == connectionTypes.NEXT_STATEMENT) {
|
||||
return new ASTNode(ASTNode.types.NEXT, connection);
|
||||
} else if (type == connectionTypes.OUTPUT_VALUE) {
|
||||
return new ASTNode(ASTNode.types.OUTPUT, connection);
|
||||
} else if (type == connectionTypes.PREVIOUS_STATEMENT) {
|
||||
return new ASTNode(ASTNode.types.PREVIOUS, connection);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -166,86 +173,83 @@ Blockly.ASTNode.createConnectionNode = function(connection) {
|
||||
/**
|
||||
* Creates an AST node pointing to an input. Stores the input connection as the
|
||||
* location.
|
||||
* @param {Blockly.Input} input The input used to create an AST node.
|
||||
* @return {Blockly.ASTNode} An AST node pointing to a input.
|
||||
* @param {Input} input The input used to create an AST node.
|
||||
* @return {ASTNode} An AST node pointing to a input.
|
||||
*/
|
||||
Blockly.ASTNode.createInputNode = function(input) {
|
||||
ASTNode.createInputNode = function(input) {
|
||||
if (!input || !input.connection) {
|
||||
return null;
|
||||
}
|
||||
return new Blockly.ASTNode(Blockly.ASTNode.types.INPUT, input.connection);
|
||||
return new ASTNode(ASTNode.types.INPUT, input.connection);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an AST node pointing to a block.
|
||||
* @param {Blockly.Block} block The block used to create an AST node.
|
||||
* @return {Blockly.ASTNode} An AST node pointing to a block.
|
||||
* @param {Block} block The block used to create an AST node.
|
||||
* @return {ASTNode} An AST node pointing to a block.
|
||||
*/
|
||||
Blockly.ASTNode.createBlockNode = function(block) {
|
||||
ASTNode.createBlockNode = function(block) {
|
||||
if (!block) {
|
||||
return null;
|
||||
}
|
||||
return new Blockly.ASTNode(Blockly.ASTNode.types.BLOCK, block);
|
||||
return new ASTNode(ASTNode.types.BLOCK, block);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an AST node of type stack. A stack, represented by its top block, is
|
||||
* the set of all blocks connected to a top block, including the top block.
|
||||
* @param {Blockly.Block} topBlock A top block has no parent and can be found
|
||||
* @param {Block} topBlock A top block has no parent and can be found
|
||||
* in the list returned by workspace.getTopBlocks().
|
||||
* @return {Blockly.ASTNode} An AST node of type stack that points to the top
|
||||
* @return {ASTNode} An AST node of type stack that points to the top
|
||||
* block on the stack.
|
||||
*/
|
||||
Blockly.ASTNode.createStackNode = function(topBlock) {
|
||||
ASTNode.createStackNode = function(topBlock) {
|
||||
if (!topBlock) {
|
||||
return null;
|
||||
}
|
||||
return new Blockly.ASTNode(Blockly.ASTNode.types.STACK, topBlock);
|
||||
return new ASTNode(ASTNode.types.STACK, topBlock);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an AST node pointing to a workspace.
|
||||
* @param {!Blockly.Workspace} workspace The workspace that we are on.
|
||||
* @param {Blockly.utils.Coordinate} wsCoordinate The position on the workspace
|
||||
* @param {!Workspace} workspace The workspace that we are on.
|
||||
* @param {Coordinate} wsCoordinate The position on the workspace
|
||||
* for this node.
|
||||
* @return {Blockly.ASTNode} An AST node pointing to a workspace and a position
|
||||
* @return {ASTNode} An AST node pointing to a workspace and a position
|
||||
* on the workspace.
|
||||
*/
|
||||
Blockly.ASTNode.createWorkspaceNode = function(workspace, wsCoordinate) {
|
||||
ASTNode.createWorkspaceNode = function(workspace, wsCoordinate) {
|
||||
if (!wsCoordinate || !workspace) {
|
||||
return null;
|
||||
}
|
||||
var params = {
|
||||
wsCoordinate: wsCoordinate
|
||||
};
|
||||
return new Blockly.ASTNode(
|
||||
Blockly.ASTNode.types.WORKSPACE, workspace, params);
|
||||
const params = {wsCoordinate: wsCoordinate};
|
||||
return new ASTNode(ASTNode.types.WORKSPACE, workspace, params);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an AST node for the top position on a block.
|
||||
* This is either an output connection, previous connection, or block.
|
||||
* @param {!Blockly.Block} block The block to find the top most AST node on.
|
||||
* @return {Blockly.ASTNode} The AST node holding the top most position on the
|
||||
* @param {!Block} block The block to find the top most AST node on.
|
||||
* @return {ASTNode} The AST node holding the top most position on the
|
||||
* block.
|
||||
*/
|
||||
Blockly.ASTNode.createTopNode = function(block) {
|
||||
var astNode;
|
||||
var topConnection = block.previousConnection || block.outputConnection;
|
||||
ASTNode.createTopNode = function(block) {
|
||||
let astNode;
|
||||
const topConnection = block.previousConnection || block.outputConnection;
|
||||
if (topConnection) {
|
||||
astNode = Blockly.ASTNode.createConnectionNode(topConnection);
|
||||
astNode = ASTNode.createConnectionNode(topConnection);
|
||||
} else {
|
||||
astNode = Blockly.ASTNode.createBlockNode(block);
|
||||
astNode = ASTNode.createBlockNode(block);
|
||||
}
|
||||
return astNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the optional parameters.
|
||||
* @param {?Blockly.ASTNode.Params} params The user specified parameters.
|
||||
* @param {?ASTNode.Params} params The user specified parameters.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.processParams_ = function(params) {
|
||||
ASTNode.prototype.processParams_ = function(params) {
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
@@ -258,28 +262,28 @@ Blockly.ASTNode.prototype.processParams_ = function(params) {
|
||||
* Gets the value pointed to by this node.
|
||||
* It is the callers responsibility to check the node type to figure out what
|
||||
* type of object they get back from this.
|
||||
* @return {!Blockly.IASTNodeLocation} The current field, connection, workspace, or
|
||||
* @return {!IASTNodeLocation} The current field, connection, workspace, or
|
||||
* block the cursor is on.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.getLocation = function() {
|
||||
ASTNode.prototype.getLocation = function() {
|
||||
return this.location_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the current location.
|
||||
* One of Blockly.ASTNode.types
|
||||
* One of ASTNode.types
|
||||
* @return {string} The type of the location.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.getType = function() {
|
||||
ASTNode.prototype.getType = function() {
|
||||
return this.type_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The coordinate on the workspace.
|
||||
* @return {Blockly.utils.Coordinate} The workspace coordinate or null if the
|
||||
* @return {Coordinate} The workspace coordinate or null if the
|
||||
* location is not a workspace.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.getWsCoordinate = function() {
|
||||
ASTNode.prototype.getWsCoordinate = function() {
|
||||
return this.wsCoordinate_;
|
||||
};
|
||||
|
||||
@@ -288,7 +292,7 @@ Blockly.ASTNode.prototype.getWsCoordinate = function() {
|
||||
* @return {boolean} [description]
|
||||
* @package
|
||||
*/
|
||||
Blockly.ASTNode.prototype.isConnection = function() {
|
||||
ASTNode.prototype.isConnection = function() {
|
||||
return this.isConnection_;
|
||||
};
|
||||
|
||||
@@ -296,25 +300,27 @@ Blockly.ASTNode.prototype.isConnection = function() {
|
||||
* Given an input find the next editable field or an input with a non null
|
||||
* connection in the same block. The current location must be an input
|
||||
* connection.
|
||||
* @return {Blockly.ASTNode} The AST node holding the next field or connection
|
||||
* @return {ASTNode} The AST node holding the next field or connection
|
||||
* or null if there is no editable field or input connection after the given
|
||||
* input.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.findNextForInput_ = function() {
|
||||
var location = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
var parentInput = location.getParentInput();
|
||||
var block = parentInput.getSourceBlock();
|
||||
var curIdx = block.inputList.indexOf(parentInput);
|
||||
for (var i = curIdx + 1, input; (input = block.inputList[i]); i++) {
|
||||
var fieldRow = input.fieldRow;
|
||||
for (var j = 0, field; (field = fieldRow[j]); j++) {
|
||||
if (field.isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return Blockly.ASTNode.createFieldNode(field);
|
||||
ASTNode.prototype.findNextForInput_ = function() {
|
||||
const location = /** @type {!Connection} */ (this.location_);
|
||||
const parentInput = location.getParentInput();
|
||||
const block = parentInput.getSourceBlock();
|
||||
const curIdx = block.inputList.indexOf(parentInput);
|
||||
for (let i = curIdx + 1; i < block.inputList.length; i++) {
|
||||
const input = block.inputList[i];
|
||||
const fieldRow = input.fieldRow;
|
||||
for (let j = 0; j < fieldRow.length; j++) {
|
||||
const field = fieldRow[j];
|
||||
if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return ASTNode.createFieldNode(field);
|
||||
}
|
||||
}
|
||||
if (input.connection) {
|
||||
return Blockly.ASTNode.createInputNode(input);
|
||||
return ASTNode.createInputNode(input);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -323,28 +329,29 @@ Blockly.ASTNode.prototype.findNextForInput_ = function() {
|
||||
/**
|
||||
* Given a field find the next editable field or an input with a non null
|
||||
* connection in the same block. The current location must be a field.
|
||||
* @return {Blockly.ASTNode} The AST node pointing to the next field or
|
||||
* @return {ASTNode} The AST node pointing to the next field or
|
||||
* connection or null if there is no editable field or input connection
|
||||
* after the given input.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.findNextForField_ = function() {
|
||||
var location = /** @type {!Blockly.Field} */ (this.location_);
|
||||
var input = location.getParentInput();
|
||||
var block = location.getSourceBlock();
|
||||
var curIdx = block.inputList.indexOf(/** @type {!Blockly.Input} */ (input));
|
||||
var fieldIdx = input.fieldRow.indexOf(location) + 1;
|
||||
for (var i = curIdx, newInput; (newInput = block.inputList[i]); i++) {
|
||||
var fieldRow = newInput.fieldRow;
|
||||
ASTNode.prototype.findNextForField_ = function() {
|
||||
const location = /** @type {!Field} */ (this.location_);
|
||||
const input = location.getParentInput();
|
||||
const block = location.getSourceBlock();
|
||||
const curIdx = block.inputList.indexOf(/** @type {!Input} */ (input));
|
||||
let fieldIdx = input.fieldRow.indexOf(location) + 1;
|
||||
for (let i = curIdx; i < block.inputList.length; i++) {
|
||||
const newInput = block.inputList[i];
|
||||
const fieldRow = newInput.fieldRow;
|
||||
while (fieldIdx < fieldRow.length) {
|
||||
if (fieldRow[fieldIdx].isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return Blockly.ASTNode.createFieldNode(fieldRow[fieldIdx]);
|
||||
if (fieldRow[fieldIdx].isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return ASTNode.createFieldNode(fieldRow[fieldIdx]);
|
||||
}
|
||||
fieldIdx++;
|
||||
}
|
||||
fieldIdx = 0;
|
||||
if (newInput.connection) {
|
||||
return Blockly.ASTNode.createInputNode(newInput);
|
||||
return ASTNode.createInputNode(newInput);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -354,23 +361,25 @@ Blockly.ASTNode.prototype.findNextForField_ = function() {
|
||||
* Given an input find the previous editable field or an input with a non null
|
||||
* connection in the same block. The current location must be an input
|
||||
* connection.
|
||||
* @return {Blockly.ASTNode} The AST node holding the previous field or
|
||||
* @return {ASTNode} The AST node holding the previous field or
|
||||
* connection.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.findPrevForInput_ = function() {
|
||||
var location = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
var parentInput = location.getParentInput();
|
||||
var block = parentInput.getSourceBlock();
|
||||
var curIdx = block.inputList.indexOf(parentInput);
|
||||
for (var i = curIdx, input; (input = block.inputList[i]); i--) {
|
||||
ASTNode.prototype.findPrevForInput_ = function() {
|
||||
const location = /** @type {!Connection} */ (this.location_);
|
||||
const parentInput = location.getParentInput();
|
||||
const block = parentInput.getSourceBlock();
|
||||
const curIdx = block.inputList.indexOf(parentInput);
|
||||
for (let i = curIdx; i >= 0; i--) {
|
||||
const input = block.inputList[i];
|
||||
if (input.connection && input !== parentInput) {
|
||||
return Blockly.ASTNode.createInputNode(input);
|
||||
return ASTNode.createInputNode(input);
|
||||
}
|
||||
var fieldRow = input.fieldRow;
|
||||
for (var j = fieldRow.length - 1, field; (field = fieldRow[j]); j--) {
|
||||
if (field.isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return Blockly.ASTNode.createFieldNode(field);
|
||||
const fieldRow = input.fieldRow;
|
||||
for (let j = fieldRow.length - 1; j >= 0; j--) {
|
||||
const field = fieldRow[j];
|
||||
if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return ASTNode.createFieldNode(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,24 +389,25 @@ Blockly.ASTNode.prototype.findPrevForInput_ = function() {
|
||||
/**
|
||||
* Given a field find the previous editable field or an input with a non null
|
||||
* connection in the same block. The current location must be a field.
|
||||
* @return {Blockly.ASTNode} The AST node holding the previous input or field.
|
||||
* @return {ASTNode} The AST node holding the previous input or field.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.findPrevForField_ = function() {
|
||||
var location = /** @type {!Blockly.Field} */ (this.location_);
|
||||
var parentInput = location.getParentInput();
|
||||
var block = location.getSourceBlock();
|
||||
var curIdx = block.inputList.indexOf(
|
||||
/** @type {!Blockly.Input} */ (parentInput));
|
||||
var fieldIdx = parentInput.fieldRow.indexOf(location) - 1;
|
||||
for (var i = curIdx, input; (input = block.inputList[i]); i--) {
|
||||
ASTNode.prototype.findPrevForField_ = function() {
|
||||
const location = /** @type {!Field} */ (this.location_);
|
||||
const parentInput = location.getParentInput();
|
||||
const block = location.getSourceBlock();
|
||||
const curIdx = block.inputList.indexOf(
|
||||
/** @type {!Input} */ (parentInput));
|
||||
let fieldIdx = parentInput.fieldRow.indexOf(location) - 1;
|
||||
for (let i = curIdx; i >= 0; i--) {
|
||||
const input = block.inputList[i];
|
||||
if (input.connection && input !== parentInput) {
|
||||
return Blockly.ASTNode.createInputNode(input);
|
||||
return ASTNode.createInputNode(input);
|
||||
}
|
||||
var fieldRow = input.fieldRow;
|
||||
const fieldRow = input.fieldRow;
|
||||
while (fieldIdx > -1) {
|
||||
if (fieldRow[fieldIdx].isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return Blockly.ASTNode.createFieldNode(fieldRow[fieldIdx]);
|
||||
if (fieldRow[fieldIdx].isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return ASTNode.createFieldNode(fieldRow[fieldIdx]);
|
||||
}
|
||||
fieldIdx--;
|
||||
}
|
||||
@@ -412,29 +422,30 @@ Blockly.ASTNode.prototype.findPrevForField_ = function() {
|
||||
/**
|
||||
* Navigate between stacks of blocks on the workspace.
|
||||
* @param {boolean} forward True to go forward. False to go backwards.
|
||||
* @return {Blockly.ASTNode} The first block of the next stack or null if there
|
||||
* @return {ASTNode} The first block of the next stack or null if there
|
||||
* are no blocks on the workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.navigateBetweenStacks_ = function(forward) {
|
||||
ASTNode.prototype.navigateBetweenStacks_ = function(forward) {
|
||||
var curLocation = this.getLocation();
|
||||
if (curLocation.getSourceBlock) {
|
||||
curLocation = /** @type {!Blockly.IASTNodeLocationWithBlock} */ (
|
||||
curLocation).getSourceBlock();
|
||||
curLocation = /** @type {!IASTNodeLocationWithBlock} */ (curLocation)
|
||||
.getSourceBlock();
|
||||
}
|
||||
if (!curLocation || !curLocation.workspace) {
|
||||
return null;
|
||||
}
|
||||
var curRoot = curLocation.getRootBlock();
|
||||
var topBlocks = curRoot.workspace.getTopBlocks(true);
|
||||
for (var i = 0, topBlock; (topBlock = topBlocks[i]); i++) {
|
||||
const curRoot = curLocation.getRootBlock();
|
||||
const topBlocks = curRoot.workspace.getTopBlocks(true);
|
||||
for (let i = 0; i < topBlocks.length; i++) {
|
||||
const topBlock = topBlocks[i];
|
||||
if (curRoot.id == topBlock.id) {
|
||||
var offset = forward ? 1 : -1;
|
||||
var resultIndex = i + offset;
|
||||
const offset = forward ? 1 : -1;
|
||||
const resultIndex = i + offset;
|
||||
if (resultIndex == -1 || resultIndex == topBlocks.length) {
|
||||
return null;
|
||||
}
|
||||
return Blockly.ASTNode.createStackNode(topBlocks[resultIndex]);
|
||||
return ASTNode.createStackNode(topBlocks[resultIndex]);
|
||||
}
|
||||
}
|
||||
throw Error('Couldn\'t find ' + (forward ? 'next' : 'previous') + ' stack?!');
|
||||
@@ -444,69 +455,71 @@ Blockly.ASTNode.prototype.navigateBetweenStacks_ = function(forward) {
|
||||
* Finds the top most AST node for a given block.
|
||||
* This is either the previous connection, output connection or block depending
|
||||
* on what kind of connections the block has.
|
||||
* @param {!Blockly.Block} block The block that we want to find the top
|
||||
* @param {!Block} block The block that we want to find the top
|
||||
* connection on.
|
||||
* @return {!Blockly.ASTNode} The AST node containing the top connection.
|
||||
* @return {!ASTNode} The AST node containing the top connection.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.findTopASTNodeForBlock_ = function(block) {
|
||||
var topConnection = block.previousConnection || block.outputConnection;
|
||||
ASTNode.prototype.findTopASTNodeForBlock_ = function(block) {
|
||||
const topConnection = block.previousConnection || block.outputConnection;
|
||||
if (topConnection) {
|
||||
return /** @type {!Blockly.ASTNode} */ (Blockly.ASTNode.createConnectionNode(
|
||||
topConnection));
|
||||
return /** @type {!ASTNode} */ (
|
||||
ASTNode.createConnectionNode(topConnection));
|
||||
} else {
|
||||
return /** @type {!Blockly.ASTNode} */ (Blockly.ASTNode.createBlockNode(
|
||||
block));
|
||||
return /** @type {!ASTNode} */ (ASTNode.createBlockNode(block));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the AST node pointing to the input that the block is nested under or if
|
||||
* the block is not nested then get the stack AST node.
|
||||
* @param {Blockly.Block} block The source block of the current location.
|
||||
* @return {Blockly.ASTNode} The AST node pointing to the input connection or
|
||||
* @param {Block} block The source block of the current location.
|
||||
* @return {ASTNode} The AST node pointing to the input connection or
|
||||
* the top block of the stack this block is in.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.getOutAstNodeForBlock_ = function(block) {
|
||||
ASTNode.prototype.getOutAstNodeForBlock_ = function(block) {
|
||||
if (!block) {
|
||||
return null;
|
||||
}
|
||||
var topBlock;
|
||||
let topBlock;
|
||||
// If the block doesn't have a previous connection then it is the top of the
|
||||
// substack.
|
||||
topBlock = block.getTopStackBlock();
|
||||
var topConnection = topBlock.previousConnection || topBlock.outputConnection;
|
||||
const topConnection =
|
||||
topBlock.previousConnection || topBlock.outputConnection;
|
||||
// If the top connection has a parentInput, create an AST node pointing to
|
||||
// that input.
|
||||
if (topConnection && topConnection.targetConnection &&
|
||||
topConnection.targetConnection.getParentInput()) {
|
||||
return Blockly.ASTNode.createInputNode(
|
||||
return ASTNode.createInputNode(
|
||||
topConnection.targetConnection.getParentInput());
|
||||
} else {
|
||||
// Go to stack level if you are not underneath an input.
|
||||
return Blockly.ASTNode.createStackNode(topBlock);
|
||||
return ASTNode.createStackNode(topBlock);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the first editable field or input with a connection on a given block.
|
||||
* @param {!Blockly.Block} block The source block of the current location.
|
||||
* @return {Blockly.ASTNode} An AST node pointing to the first field or input.
|
||||
* @param {!Block} block The source block of the current location.
|
||||
* @return {ASTNode} An AST node pointing to the first field or input.
|
||||
* Null if there are no editable fields or inputs with connections on the block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ASTNode.prototype.findFirstFieldOrInput_ = function(block) {
|
||||
var inputs = block.inputList;
|
||||
for (var i = 0, input; (input = inputs[i]); i++) {
|
||||
var fieldRow = input.fieldRow;
|
||||
for (var j = 0, field; (field = fieldRow[j]); j++) {
|
||||
if (field.isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return Blockly.ASTNode.createFieldNode(field);
|
||||
ASTNode.prototype.findFirstFieldOrInput_ = function(block) {
|
||||
const inputs = block.inputList;
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i];
|
||||
const fieldRow = input.fieldRow;
|
||||
for (let j = 0; j < fieldRow.length; j++) {
|
||||
const field = fieldRow[j];
|
||||
if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) {
|
||||
return ASTNode.createFieldNode(field);
|
||||
}
|
||||
}
|
||||
if (input.connection) {
|
||||
return Blockly.ASTNode.createInputNode(input);
|
||||
return ASTNode.createInputNode(input);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -514,55 +527,56 @@ Blockly.ASTNode.prototype.findFirstFieldOrInput_ = function(block) {
|
||||
|
||||
/**
|
||||
* Finds the source block of the location of this node.
|
||||
* @return {Blockly.Block} The source block of the location, or null if the node
|
||||
* @return {Block} The source block of the location, or null if the node
|
||||
* is of type workspace.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.getSourceBlock = function() {
|
||||
if (this.getType() === Blockly.ASTNode.types.BLOCK) {
|
||||
return /** @type {Blockly.Block} */ (this.getLocation());
|
||||
} else if (this.getType() === Blockly.ASTNode.types.STACK) {
|
||||
return /** @type {Blockly.Block} */ (this.getLocation());
|
||||
} else if (this.getType() === Blockly.ASTNode.types.WORKSPACE) {
|
||||
ASTNode.prototype.getSourceBlock = function() {
|
||||
if (this.getType() === ASTNode.types.BLOCK) {
|
||||
return /** @type {Block} */ (this.getLocation());
|
||||
} else if (this.getType() === ASTNode.types.STACK) {
|
||||
return /** @type {Block} */ (this.getLocation());
|
||||
} else if (this.getType() === ASTNode.types.WORKSPACE) {
|
||||
return null;
|
||||
} else {
|
||||
return /** @type {Blockly.IASTNodeLocationWithBlock} */ (
|
||||
this.getLocation()).getSourceBlock();
|
||||
return /** @type {IASTNodeLocationWithBlock} */ (this.getLocation())
|
||||
.getSourceBlock();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the element to the right of the current element in the AST.
|
||||
* @return {Blockly.ASTNode} An AST node that wraps the next field, connection,
|
||||
* @return {ASTNode} An AST node that wraps the next field, connection,
|
||||
* block, or workspace. Or null if there is no node to the right.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.next = function() {
|
||||
ASTNode.prototype.next = function() {
|
||||
switch (this.type_) {
|
||||
case Blockly.ASTNode.types.STACK:
|
||||
case ASTNode.types.STACK:
|
||||
return this.navigateBetweenStacks_(true);
|
||||
|
||||
case Blockly.ASTNode.types.OUTPUT:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
return Blockly.ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
|
||||
case Blockly.ASTNode.types.FIELD:
|
||||
case ASTNode.types.OUTPUT: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
return ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
}
|
||||
case ASTNode.types.FIELD:
|
||||
return this.findNextForField_();
|
||||
|
||||
case Blockly.ASTNode.types.INPUT:
|
||||
case ASTNode.types.INPUT:
|
||||
return this.findNextForInput_();
|
||||
|
||||
case Blockly.ASTNode.types.BLOCK:
|
||||
var block = /** @type {!Blockly.Block} */ (this.location_);
|
||||
var nextConnection = block.nextConnection;
|
||||
return Blockly.ASTNode.createConnectionNode(nextConnection);
|
||||
|
||||
case Blockly.ASTNode.types.PREVIOUS:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
return Blockly.ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
|
||||
case Blockly.ASTNode.types.NEXT:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
var targetConnection = connection.targetConnection;
|
||||
return Blockly.ASTNode.createConnectionNode(targetConnection);
|
||||
case ASTNode.types.BLOCK: {
|
||||
const block = /** @type {!Block} */ (this.location_);
|
||||
const nextConnection = block.nextConnection;
|
||||
return ASTNode.createConnectionNode(nextConnection);
|
||||
}
|
||||
case ASTNode.types.PREVIOUS: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
return ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
}
|
||||
case ASTNode.types.NEXT: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
const targetConnection = connection.targetConnection;
|
||||
return ASTNode.createConnectionNode(targetConnection);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -571,31 +585,32 @@ Blockly.ASTNode.prototype.next = function() {
|
||||
/**
|
||||
* Find the element one level below and all the way to the left of the current
|
||||
* location.
|
||||
* @return {Blockly.ASTNode} An AST node that wraps the next field, connection,
|
||||
* @return {ASTNode} An AST node that wraps the next field, connection,
|
||||
* workspace, or block. Or null if there is nothing below this node.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.in = function() {
|
||||
ASTNode.prototype.in = function() {
|
||||
switch (this.type_) {
|
||||
case Blockly.ASTNode.types.WORKSPACE:
|
||||
var workspace = /** @type {!Blockly.Workspace} */ (this.location_);
|
||||
var topBlocks = workspace.getTopBlocks(true);
|
||||
case ASTNode.types.WORKSPACE: {
|
||||
const workspace = /** @type {!Workspace} */ (this.location_);
|
||||
const topBlocks = workspace.getTopBlocks(true);
|
||||
if (topBlocks.length > 0) {
|
||||
return Blockly.ASTNode.createStackNode(topBlocks[0]);
|
||||
return ASTNode.createStackNode(topBlocks[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case Blockly.ASTNode.types.STACK:
|
||||
var block = /** @type {!Blockly.Block} */ (this.location_);
|
||||
}
|
||||
case ASTNode.types.STACK: {
|
||||
const block = /** @type {!Block} */ (this.location_);
|
||||
return this.findTopASTNodeForBlock_(block);
|
||||
|
||||
case Blockly.ASTNode.types.BLOCK:
|
||||
var block = /** @type {!Blockly.Block} */ (this.location_);
|
||||
}
|
||||
case ASTNode.types.BLOCK: {
|
||||
const block = /** @type {!Block} */ (this.location_);
|
||||
return this.findFirstFieldOrInput_(block);
|
||||
|
||||
case Blockly.ASTNode.types.INPUT:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
var targetConnection = connection.targetConnection;
|
||||
return Blockly.ASTNode.createConnectionNode(targetConnection);
|
||||
}
|
||||
case ASTNode.types.INPUT: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
const targetConnection = connection.targetConnection;
|
||||
return ASTNode.createConnectionNode(targetConnection);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -603,40 +618,41 @@ Blockly.ASTNode.prototype.in = function() {
|
||||
|
||||
/**
|
||||
* Find the element to the left of the current element in the AST.
|
||||
* @return {Blockly.ASTNode} An AST node that wraps the previous field,
|
||||
* @return {ASTNode} An AST node that wraps the previous field,
|
||||
* connection, workspace or block. Or null if no node exists to the left.
|
||||
* null.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.prev = function() {
|
||||
ASTNode.prototype.prev = function() {
|
||||
switch (this.type_) {
|
||||
case Blockly.ASTNode.types.STACK:
|
||||
case ASTNode.types.STACK:
|
||||
return this.navigateBetweenStacks_(false);
|
||||
|
||||
case Blockly.ASTNode.types.OUTPUT:
|
||||
case ASTNode.types.OUTPUT:
|
||||
return null;
|
||||
|
||||
case Blockly.ASTNode.types.FIELD:
|
||||
case ASTNode.types.FIELD:
|
||||
return this.findPrevForField_();
|
||||
|
||||
case Blockly.ASTNode.types.INPUT:
|
||||
case ASTNode.types.INPUT:
|
||||
return this.findPrevForInput_();
|
||||
|
||||
case Blockly.ASTNode.types.BLOCK:
|
||||
var block = /** @type {!Blockly.Block} */ (this.location_);
|
||||
var topConnection = block.previousConnection || block.outputConnection;
|
||||
return Blockly.ASTNode.createConnectionNode(topConnection);
|
||||
|
||||
case Blockly.ASTNode.types.PREVIOUS:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
var targetConnection = connection.targetConnection;
|
||||
case ASTNode.types.BLOCK: {
|
||||
const block = /** @type {!Block} */ (this.location_);
|
||||
const topConnection = block.previousConnection || block.outputConnection;
|
||||
return ASTNode.createConnectionNode(topConnection);
|
||||
}
|
||||
case ASTNode.types.PREVIOUS: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
const targetConnection = connection.targetConnection;
|
||||
if (targetConnection && !targetConnection.getParentInput()) {
|
||||
return Blockly.ASTNode.createConnectionNode(targetConnection);
|
||||
return ASTNode.createConnectionNode(targetConnection);
|
||||
}
|
||||
break;
|
||||
|
||||
case Blockly.ASTNode.types.NEXT:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
return Blockly.ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
}
|
||||
case ASTNode.types.NEXT: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
return ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -645,47 +661,50 @@ Blockly.ASTNode.prototype.prev = function() {
|
||||
/**
|
||||
* Find the next element that is one position above and all the way to the left
|
||||
* of the current location.
|
||||
* @return {Blockly.ASTNode} An AST node that wraps the next field, connection,
|
||||
* @return {ASTNode} An AST node that wraps the next field, connection,
|
||||
* workspace or block. Or null if we are at the workspace level.
|
||||
*/
|
||||
Blockly.ASTNode.prototype.out = function() {
|
||||
ASTNode.prototype.out = function() {
|
||||
switch (this.type_) {
|
||||
case Blockly.ASTNode.types.STACK:
|
||||
var block = /** @type {!Blockly.Block} */ (this.location_);
|
||||
var blockPos = block.getRelativeToSurfaceXY();
|
||||
case ASTNode.types.STACK: {
|
||||
const block = /** @type {!Block} */ (this.location_);
|
||||
const blockPos = block.getRelativeToSurfaceXY();
|
||||
// TODO: Make sure this is in the bounds of the workspace.
|
||||
var wsCoordinate = new Blockly.utils.Coordinate(
|
||||
blockPos.x, blockPos.y + Blockly.ASTNode.DEFAULT_OFFSET_Y);
|
||||
return Blockly.ASTNode.createWorkspaceNode(block.workspace, wsCoordinate);
|
||||
|
||||
case Blockly.ASTNode.types.OUTPUT:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
var target = connection.targetConnection;
|
||||
const wsCoordinate =
|
||||
new Coordinate(blockPos.x, blockPos.y + ASTNode.DEFAULT_OFFSET_Y);
|
||||
return ASTNode.createWorkspaceNode(block.workspace, wsCoordinate);
|
||||
}
|
||||
case ASTNode.types.OUTPUT: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
const target = connection.targetConnection;
|
||||
if (target) {
|
||||
return Blockly.ASTNode.createConnectionNode(target);
|
||||
return ASTNode.createConnectionNode(target);
|
||||
}
|
||||
return Blockly.ASTNode.createStackNode(connection.getSourceBlock());
|
||||
|
||||
case Blockly.ASTNode.types.FIELD:
|
||||
var field = /** @type {!Blockly.Field} */ (this.location_);
|
||||
return Blockly.ASTNode.createBlockNode(field.getSourceBlock());
|
||||
|
||||
case Blockly.ASTNode.types.INPUT:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
return Blockly.ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
|
||||
case Blockly.ASTNode.types.BLOCK:
|
||||
var block = /** @type {!Blockly.Block} */ (this.location_);
|
||||
return ASTNode.createStackNode(connection.getSourceBlock());
|
||||
}
|
||||
case ASTNode.types.FIELD: {
|
||||
const field = /** @type {!Field} */ (this.location_);
|
||||
return ASTNode.createBlockNode(field.getSourceBlock());
|
||||
}
|
||||
case ASTNode.types.INPUT: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
return ASTNode.createBlockNode(connection.getSourceBlock());
|
||||
}
|
||||
case ASTNode.types.BLOCK: {
|
||||
const block = /** @type {!Block} */ (this.location_);
|
||||
return this.getOutAstNodeForBlock_(block);
|
||||
|
||||
case Blockly.ASTNode.types.PREVIOUS:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
}
|
||||
case ASTNode.types.PREVIOUS: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
return this.getOutAstNodeForBlock_(connection.getSourceBlock());
|
||||
|
||||
case Blockly.ASTNode.types.NEXT:
|
||||
var connection = /** @type {!Blockly.Connection} */ (this.location_);
|
||||
}
|
||||
case ASTNode.types.NEXT: {
|
||||
const connection = /** @type {!Connection} */ (this.location_);
|
||||
return this.getOutAstNodeForBlock_(connection.getSourceBlock());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
exports = ASTNode;
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Marker');
|
||||
goog.module('Blockly.Marker');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.ASTNode');
|
||||
|
||||
goog.requireType('Blockly.blockRendering.MarkerSvg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ASTNode = goog.requireType('Blockly.ASTNode');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const MarkerSvg = goog.requireType('Blockly.blockRendering.MarkerSvg');
|
||||
|
||||
|
||||
/**
|
||||
@@ -23,7 +25,7 @@ goog.requireType('Blockly.blockRendering.MarkerSvg');
|
||||
* This is used in keyboard navigation to save a location in the Blockly AST.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Marker = function() {
|
||||
const Marker = function() {
|
||||
/**
|
||||
* The colour of the marker.
|
||||
* @type {?string}
|
||||
@@ -32,14 +34,15 @@ Blockly.Marker = function() {
|
||||
|
||||
/**
|
||||
* The current location of the marker.
|
||||
* @type {Blockly.ASTNode}
|
||||
* @type {ASTNode}
|
||||
* @private
|
||||
*/
|
||||
this.curNode_ = null;
|
||||
|
||||
/**
|
||||
* The object in charge of drawing the visual representation of the current node.
|
||||
* @type {Blockly.blockRendering.MarkerSvg}
|
||||
* The object in charge of drawing the visual representation of the current
|
||||
* node.
|
||||
* @type {MarkerSvg}
|
||||
* @private
|
||||
*/
|
||||
this.drawer_ = null;
|
||||
@@ -53,28 +56,28 @@ Blockly.Marker = function() {
|
||||
|
||||
/**
|
||||
* Sets the object in charge of drawing the marker.
|
||||
* @param {Blockly.blockRendering.MarkerSvg} drawer The object in charge of
|
||||
* @param {MarkerSvg} drawer The object in charge of
|
||||
* drawing the marker.
|
||||
*/
|
||||
Blockly.Marker.prototype.setDrawer = function(drawer) {
|
||||
Marker.prototype.setDrawer = function(drawer) {
|
||||
this.drawer_ = drawer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current drawer for the marker.
|
||||
* @return {Blockly.blockRendering.MarkerSvg} The object in charge of drawing
|
||||
* @return {MarkerSvg} The object in charge of drawing
|
||||
* the marker.
|
||||
*/
|
||||
Blockly.Marker.prototype.getDrawer = function() {
|
||||
Marker.prototype.getDrawer = function() {
|
||||
return this.drawer_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the current location of the marker.
|
||||
* @return {Blockly.ASTNode} The current field, connection, or block the marker
|
||||
* @return {ASTNode} The current field, connection, or block the marker
|
||||
* is on.
|
||||
*/
|
||||
Blockly.Marker.prototype.getCurNode = function() {
|
||||
Marker.prototype.getCurNode = function() {
|
||||
return this.curNode_;
|
||||
};
|
||||
|
||||
@@ -82,10 +85,10 @@ Blockly.Marker.prototype.getCurNode = function() {
|
||||
* Set the location of the marker and call the update method.
|
||||
* Setting isStack to true will only work if the newLocation is the top most
|
||||
* output or previous connection on a stack.
|
||||
* @param {Blockly.ASTNode} newNode The new location of the marker.
|
||||
* @param {ASTNode} newNode The new location of the marker.
|
||||
*/
|
||||
Blockly.Marker.prototype.setCurNode = function(newNode) {
|
||||
var oldNode = this.curNode_;
|
||||
Marker.prototype.setCurNode = function(newNode) {
|
||||
const oldNode = this.curNode_;
|
||||
this.curNode_ = newNode;
|
||||
if (this.drawer_) {
|
||||
this.drawer_.draw(oldNode, this.curNode_);
|
||||
@@ -96,7 +99,7 @@ Blockly.Marker.prototype.setCurNode = function(newNode) {
|
||||
* Redraw the current marker.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Marker.prototype.draw = function() {
|
||||
Marker.prototype.draw = function() {
|
||||
if (this.drawer_) {
|
||||
this.drawer_.draw(this.curNode_, this.curNode_);
|
||||
}
|
||||
@@ -105,7 +108,7 @@ Blockly.Marker.prototype.draw = function() {
|
||||
/**
|
||||
* Hide the marker SVG.
|
||||
*/
|
||||
Blockly.Marker.prototype.hide = function() {
|
||||
Marker.prototype.hide = function() {
|
||||
if (this.drawer_) {
|
||||
this.drawer_.hide();
|
||||
}
|
||||
@@ -114,8 +117,10 @@ Blockly.Marker.prototype.hide = function() {
|
||||
/**
|
||||
* Dispose of this marker.
|
||||
*/
|
||||
Blockly.Marker.prototype.dispose = function() {
|
||||
Marker.prototype.dispose = function() {
|
||||
if (this.getDrawer()) {
|
||||
this.getDrawer().dispose();
|
||||
}
|
||||
};
|
||||
|
||||
exports = Marker;
|
||||
|
||||
@@ -16,6 +16,7 @@ goog.module.declareLegacyNamespace();
|
||||
|
||||
const ASTNode = goog.require('Blockly.ASTNode');
|
||||
const BasicCursor = goog.require('Blockly.BasicCursor');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Field = goog.requireType('Blockly.Field');
|
||||
const {inherits} = goog.require('Blockly.utils.object');
|
||||
|
||||
|
||||
@@ -10,24 +10,26 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.MarkerManager');
|
||||
goog.module('Blockly.MarkerManager');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Cursor');
|
||||
goog.require('Blockly.Marker');
|
||||
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Cursor = goog.requireType('Blockly.Cursor');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Marker = goog.requireType('Blockly.Marker');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
* Class to manage the multiple markers and the cursor on a workspace.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace for the marker manager.
|
||||
* @param {!WorkspaceSvg} workspace The workspace for the marker manager.
|
||||
* @constructor
|
||||
* @package
|
||||
*/
|
||||
Blockly.MarkerManager = function(workspace){
|
||||
const MarkerManager = function(workspace) {
|
||||
/**
|
||||
* The cursor.
|
||||
* @type {?Blockly.Cursor}
|
||||
* @type {?Cursor}
|
||||
* @private
|
||||
*/
|
||||
this.cursor_ = null;
|
||||
@@ -41,14 +43,14 @@ Blockly.MarkerManager = function(workspace){
|
||||
|
||||
/**
|
||||
* The map of markers for the workspace.
|
||||
* @type {!Object<string, !Blockly.Marker>}
|
||||
* @type {!Object<string, !Marker>}
|
||||
* @private
|
||||
*/
|
||||
this.markers_ = Object.create(null);
|
||||
|
||||
/**
|
||||
* The workspace this marker manager is associated with.
|
||||
* @type {!Blockly.WorkspaceSvg}
|
||||
* @type {!WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
this.workspace_ = workspace;
|
||||
@@ -59,19 +61,19 @@ Blockly.MarkerManager = function(workspace){
|
||||
* @type {string}
|
||||
* @const
|
||||
*/
|
||||
Blockly.MarkerManager.LOCAL_MARKER = 'local_marker_1';
|
||||
MarkerManager.LOCAL_MARKER = 'local_marker_1';
|
||||
|
||||
/**
|
||||
* Register the marker by adding it to the map of markers.
|
||||
* @param {string} id A unique identifier for the marker.
|
||||
* @param {!Blockly.Marker} marker The marker to register.
|
||||
* @param {!Marker} marker The marker to register.
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.registerMarker = function(id, marker) {
|
||||
MarkerManager.prototype.registerMarker = function(id, marker) {
|
||||
if (this.markers_[id]) {
|
||||
this.unregisterMarker(id);
|
||||
}
|
||||
marker.setDrawer(this.workspace_.getRenderer()
|
||||
.makeMarkerDrawer(this.workspace_, marker));
|
||||
marker.setDrawer(
|
||||
this.workspace_.getRenderer().makeMarkerDrawer(this.workspace_, marker));
|
||||
this.setMarkerSvg(marker.getDrawer().createDom());
|
||||
this.markers_[id] = marker;
|
||||
};
|
||||
@@ -80,47 +82,48 @@ Blockly.MarkerManager.prototype.registerMarker = function(id, marker) {
|
||||
* Unregister the marker by removing it from the map of markers.
|
||||
* @param {string} id The ID of the marker to unregister.
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.unregisterMarker = function(id) {
|
||||
var marker = this.markers_[id];
|
||||
MarkerManager.prototype.unregisterMarker = function(id) {
|
||||
const marker = this.markers_[id];
|
||||
if (marker) {
|
||||
marker.dispose();
|
||||
delete this.markers_[id];
|
||||
} else {
|
||||
throw Error('Marker with ID ' + id + ' does not exist. ' +
|
||||
throw Error(
|
||||
'Marker with ID ' + id + ' does not exist. ' +
|
||||
'Can only unregister markers that exist.');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the cursor for the workspace.
|
||||
* @return {?Blockly.Cursor} The cursor for this workspace.
|
||||
* @return {?Cursor} The cursor for this workspace.
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.getCursor = function() {
|
||||
MarkerManager.prototype.getCursor = function() {
|
||||
return this.cursor_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a single marker that corresponds to the given ID.
|
||||
* @param {string} id A unique identifier for the marker.
|
||||
* @return {?Blockly.Marker} The marker that corresponds to the given ID,
|
||||
* @return {?Marker} The marker that corresponds to the given ID,
|
||||
* or null if none exists.
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.getMarker = function(id) {
|
||||
MarkerManager.prototype.getMarker = function(id) {
|
||||
return this.markers_[id] || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the cursor and initializes the drawer for use with keyboard navigation.
|
||||
* @param {Blockly.Cursor} cursor The cursor used to move around this workspace.
|
||||
* @param {Cursor} cursor The cursor used to move around this workspace.
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.setCursor = function(cursor) {
|
||||
MarkerManager.prototype.setCursor = function(cursor) {
|
||||
if (this.cursor_ && this.cursor_.getDrawer()) {
|
||||
this.cursor_.getDrawer().dispose();
|
||||
}
|
||||
this.cursor_ = cursor;
|
||||
if (this.cursor_) {
|
||||
var drawer = this.workspace_.getRenderer()
|
||||
.makeMarkerDrawer(this.workspace_, this.cursor_);
|
||||
const drawer = this.workspace_.getRenderer().makeMarkerDrawer(
|
||||
this.workspace_, this.cursor_);
|
||||
this.cursor_.setDrawer(drawer);
|
||||
this.setCursorSvg(this.cursor_.getDrawer().createDom());
|
||||
}
|
||||
@@ -132,7 +135,7 @@ Blockly.MarkerManager.prototype.setCursor = function(cursor) {
|
||||
* workspace SVG group.
|
||||
* @package
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) {
|
||||
MarkerManager.prototype.setCursorSvg = function(cursorSvg) {
|
||||
if (!cursorSvg) {
|
||||
this.cursorSvg_ = null;
|
||||
return;
|
||||
@@ -148,7 +151,7 @@ Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) {
|
||||
* workspace SVG group.
|
||||
* @package
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) {
|
||||
MarkerManager.prototype.setMarkerSvg = function(markerSvg) {
|
||||
if (!markerSvg) {
|
||||
this.markerSvg_ = null;
|
||||
return;
|
||||
@@ -167,7 +170,7 @@ Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) {
|
||||
* Redraw the attached cursor SVG if needed.
|
||||
* @package
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.updateMarkers = function() {
|
||||
MarkerManager.prototype.updateMarkers = function() {
|
||||
if (this.workspace_.keyboardAccessibilityMode && this.cursorSvg_) {
|
||||
this.workspace_.getCursor().draw();
|
||||
}
|
||||
@@ -179,9 +182,9 @@ Blockly.MarkerManager.prototype.updateMarkers = function() {
|
||||
* @suppress {checkTypes}
|
||||
* @package
|
||||
*/
|
||||
Blockly.MarkerManager.prototype.dispose = function() {
|
||||
var markerIds = Object.keys(this.markers_);
|
||||
for (var i = 0, markerId; (markerId = markerIds[i]); i++) {
|
||||
MarkerManager.prototype.dispose = function() {
|
||||
const markerIds = Object.keys(this.markers_);
|
||||
for (let i = 0, markerId; (markerId = markerIds[i]); i++) {
|
||||
this.unregisterMarker(markerId);
|
||||
}
|
||||
this.markers_ = null;
|
||||
@@ -190,3 +193,6 @@ Blockly.MarkerManager.prototype.dispose = function() {
|
||||
this.cursor_ = null;
|
||||
}
|
||||
};
|
||||
|
||||
/** @package */
|
||||
exports = MarkerManager;
|
||||
|
||||
195
core/menu.js
195
core/menu.js
@@ -10,29 +10,31 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Menu');
|
||||
goog.module('Blockly.Menu');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.browserEvents');
|
||||
goog.require('Blockly.utils.aria');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.KeyCodes');
|
||||
goog.require('Blockly.utils.style');
|
||||
|
||||
goog.requireType('Blockly.MenuItem');
|
||||
goog.requireType('Blockly.utils.Size');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const MenuItem = goog.requireType('Blockly.MenuItem');
|
||||
const KeyCodes = goog.require('Blockly.utils.KeyCodes');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Size = goog.requireType('Blockly.utils.Size');
|
||||
const aria = goog.require('Blockly.utils.aria');
|
||||
const browserEvents = goog.require('Blockly.browserEvents');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const style = goog.require('Blockly.utils.style');
|
||||
|
||||
|
||||
/**
|
||||
* A basic menu class.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Menu = function() {
|
||||
const Menu = function() {
|
||||
/**
|
||||
* Array of menu items.
|
||||
* (Nulls are never in the array, but typing the array as nullable prevents
|
||||
* the compiler from objecting to .indexOf(null))
|
||||
* @type {!Array<Blockly.MenuItem>}
|
||||
* @type {!Array<MenuItem>}
|
||||
* @private
|
||||
*/
|
||||
this.menuItems_ = [];
|
||||
@@ -41,7 +43,7 @@ Blockly.Menu = function() {
|
||||
* Coordinates of the mousedown event that caused this menu to open. Used to
|
||||
* prevent the consequent mouseup event due to a simple click from activating
|
||||
* a menu item immediately.
|
||||
* @type {?Blockly.utils.Coordinate}
|
||||
* @type {?Coordinate}
|
||||
* @package
|
||||
*/
|
||||
this.openingCoords = null;
|
||||
@@ -49,42 +51,42 @@ Blockly.Menu = function() {
|
||||
/**
|
||||
* This is the element that we will listen to the real focus events on.
|
||||
* A value of null means no menu item is highlighted.
|
||||
* @type {?Blockly.MenuItem}
|
||||
* @type {?MenuItem}
|
||||
* @private
|
||||
*/
|
||||
this.highlightedItem_ = null;
|
||||
|
||||
/**
|
||||
* Mouse over event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.mouseOverHandler_ = null;
|
||||
|
||||
/**
|
||||
* Click event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.clickHandler_ = null;
|
||||
|
||||
/**
|
||||
* Mouse enter event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.mouseEnterHandler_ = null;
|
||||
|
||||
/**
|
||||
* Mouse leave event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.mouseLeaveHandler_ = null;
|
||||
|
||||
/**
|
||||
* Key down event data.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.onKeyDownHandler_ = null;
|
||||
@@ -98,7 +100,7 @@ Blockly.Menu = function() {
|
||||
|
||||
/**
|
||||
* ARIA name for this menu.
|
||||
* @type {?Blockly.utils.aria.Role}
|
||||
* @type {?aria.Role}
|
||||
* @private
|
||||
*/
|
||||
this.roleName_ = null;
|
||||
@@ -107,9 +109,9 @@ Blockly.Menu = function() {
|
||||
|
||||
/**
|
||||
* Add a new menu item to the bottom of this menu.
|
||||
* @param {!Blockly.MenuItem} menuItem Menu item to append.
|
||||
* @param {!MenuItem} menuItem Menu item to append.
|
||||
*/
|
||||
Blockly.Menu.prototype.addChild = function(menuItem) {
|
||||
Menu.prototype.addChild = function(menuItem) {
|
||||
this.menuItems_.push(menuItem);
|
||||
};
|
||||
|
||||
@@ -117,32 +119,33 @@ Blockly.Menu.prototype.addChild = function(menuItem) {
|
||||
* Creates the menu DOM.
|
||||
* @param {!Element} container Element upon which to append this menu.
|
||||
*/
|
||||
Blockly.Menu.prototype.render = function(container) {
|
||||
var element = /** @type {!HTMLDivElement} */ (document.createElement('div'));
|
||||
Menu.prototype.render = function(container) {
|
||||
const element =
|
||||
/** @type {!HTMLDivElement} */ (document.createElement('div'));
|
||||
// goog-menu is deprecated, use blocklyMenu. May 2020.
|
||||
element.className = 'blocklyMenu goog-menu blocklyNonSelectable';
|
||||
element.tabIndex = 0;
|
||||
if (this.roleName_) {
|
||||
Blockly.utils.aria.setRole(element, this.roleName_);
|
||||
aria.setRole(element, this.roleName_);
|
||||
}
|
||||
this.element_ = element;
|
||||
|
||||
// Add menu items.
|
||||
for (var i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) {
|
||||
for (let i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) {
|
||||
element.appendChild(menuItem.createDom());
|
||||
}
|
||||
|
||||
// Add event handlers.
|
||||
this.mouseOverHandler_ = Blockly.browserEvents.conditionalBind(
|
||||
element, 'mouseover', this, this.handleMouseOver_, true);
|
||||
this.clickHandler_ = Blockly.browserEvents.conditionalBind(
|
||||
element, 'click', this, this.handleClick_, true);
|
||||
this.mouseEnterHandler_ = Blockly.browserEvents.conditionalBind(
|
||||
this.mouseOverHandler_ =
|
||||
browserEvents.conditionalBind(element, 'mouseover', this, this.handleMouseOver_, true);
|
||||
this.clickHandler_ =
|
||||
browserEvents.conditionalBind(element, 'click', this, this.handleClick_, true);
|
||||
this.mouseEnterHandler_ = browserEvents.conditionalBind(
|
||||
element, 'mouseenter', this, this.handleMouseEnter_, true);
|
||||
this.mouseLeaveHandler_ = Blockly.browserEvents.conditionalBind(
|
||||
this.mouseLeaveHandler_ = browserEvents.conditionalBind(
|
||||
element, 'mouseleave', this, this.handleMouseLeave_, true);
|
||||
this.onKeyDownHandler_ = Blockly.browserEvents.conditionalBind(
|
||||
element, 'keydown', this, this.handleKeyEvent_);
|
||||
this.onKeyDownHandler_ =
|
||||
browserEvents.conditionalBind(element, 'keydown', this, this.handleKeyEvent_);
|
||||
|
||||
container.appendChild(element);
|
||||
};
|
||||
@@ -152,7 +155,7 @@ Blockly.Menu.prototype.render = function(container) {
|
||||
* @return {?Element} The DOM element.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Menu.prototype.getElement = function() {
|
||||
Menu.prototype.getElement = function() {
|
||||
return this.element_;
|
||||
};
|
||||
|
||||
@@ -160,11 +163,11 @@ Blockly.Menu.prototype.getElement = function() {
|
||||
* Focus the menu element.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Menu.prototype.focus = function() {
|
||||
var el = this.getElement();
|
||||
Menu.prototype.focus = function() {
|
||||
const el = this.getElement();
|
||||
if (el) {
|
||||
el.focus({preventScroll:true});
|
||||
Blockly.utils.dom.addClass(el, 'blocklyFocused');
|
||||
el.focus({preventScroll: true});
|
||||
dom.addClass(el, 'blocklyFocused');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -172,51 +175,51 @@ Blockly.Menu.prototype.focus = function() {
|
||||
* Blur the menu element.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.blur_ = function() {
|
||||
var el = this.getElement();
|
||||
Menu.prototype.blur_ = function() {
|
||||
const el = this.getElement();
|
||||
if (el) {
|
||||
el.blur();
|
||||
Blockly.utils.dom.removeClass(el, 'blocklyFocused');
|
||||
dom.removeClass(el, 'blocklyFocused');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the menu accessibility role.
|
||||
* @param {!Blockly.utils.aria.Role} roleName role name.
|
||||
* @param {!aria.Role} roleName role name.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Menu.prototype.setRole = function(roleName) {
|
||||
Menu.prototype.setRole = function(roleName) {
|
||||
this.roleName_ = roleName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispose of this menu.
|
||||
*/
|
||||
Blockly.Menu.prototype.dispose = function() {
|
||||
Menu.prototype.dispose = function() {
|
||||
// Remove event handlers.
|
||||
if (this.mouseOverHandler_) {
|
||||
Blockly.browserEvents.unbind(this.mouseOverHandler_);
|
||||
browserEvents.unbind(this.mouseOverHandler_);
|
||||
this.mouseOverHandler_ = null;
|
||||
}
|
||||
if (this.clickHandler_) {
|
||||
Blockly.browserEvents.unbind(this.clickHandler_);
|
||||
browserEvents.unbind(this.clickHandler_);
|
||||
this.clickHandler_ = null;
|
||||
}
|
||||
if (this.mouseEnterHandler_) {
|
||||
Blockly.browserEvents.unbind(this.mouseEnterHandler_);
|
||||
browserEvents.unbind(this.mouseEnterHandler_);
|
||||
this.mouseEnterHandler_ = null;
|
||||
}
|
||||
if (this.mouseLeaveHandler_) {
|
||||
Blockly.browserEvents.unbind(this.mouseLeaveHandler_);
|
||||
browserEvents.unbind(this.mouseLeaveHandler_);
|
||||
this.mouseLeaveHandler_ = null;
|
||||
}
|
||||
if (this.onKeyDownHandler_) {
|
||||
Blockly.browserEvents.unbind(this.onKeyDownHandler_);
|
||||
browserEvents.unbind(this.onKeyDownHandler_);
|
||||
this.onKeyDownHandler_ = null;
|
||||
}
|
||||
|
||||
// Remove menu items.
|
||||
for (var i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) {
|
||||
for (let i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) {
|
||||
menuItem.dispose();
|
||||
}
|
||||
this.element_ = null;
|
||||
@@ -228,19 +231,19 @@ Blockly.Menu.prototype.dispose = function() {
|
||||
* Returns the child menu item that owns the given DOM element,
|
||||
* or null if no such menu item is found.
|
||||
* @param {Element} elem DOM element whose owner is to be returned.
|
||||
* @return {?Blockly.MenuItem} Menu item for which the DOM element belongs to.
|
||||
* @return {?MenuItem} Menu item for which the DOM element belongs to.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.getMenuItem_ = function(elem) {
|
||||
var menuElem = this.getElement();
|
||||
Menu.prototype.getMenuItem_ = function(elem) {
|
||||
const menuElem = this.getElement();
|
||||
// Node might be the menu border (resulting in no associated menu item), or
|
||||
// a menu item's div, or some element within the menu item.
|
||||
// Walk up parents until one meets either the menu's root element, or
|
||||
// a menu item's div.
|
||||
while (elem && elem != menuElem) {
|
||||
if (Blockly.utils.dom.hasClass(elem, 'blocklyMenuItem')) {
|
||||
if (dom.hasClass(elem, 'blocklyMenuItem')) {
|
||||
// Having found a menu item's div, locate that menu item in this menu.
|
||||
for (var i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) {
|
||||
for (let i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) {
|
||||
if (menuItem.getElement() == elem) {
|
||||
return menuItem;
|
||||
}
|
||||
@@ -255,11 +258,11 @@ Blockly.Menu.prototype.getMenuItem_ = function(elem) {
|
||||
|
||||
/**
|
||||
* Highlights the given menu item, or clears highlighting if null.
|
||||
* @param {?Blockly.MenuItem} item Item to highlight, or null.
|
||||
* @param {?MenuItem} item Item to highlight, or null.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Menu.prototype.setHighlighted = function(item) {
|
||||
var currentHighlighted = this.highlightedItem_;
|
||||
Menu.prototype.setHighlighted = function(item) {
|
||||
const currentHighlighted = this.highlightedItem_;
|
||||
if (currentHighlighted) {
|
||||
currentHighlighted.setHighlighted(false);
|
||||
this.highlightedItem_ = null;
|
||||
@@ -269,12 +272,11 @@ Blockly.Menu.prototype.setHighlighted = function(item) {
|
||||
this.highlightedItem_ = item;
|
||||
// Bring the highlighted item into view. This has no effect if the menu is
|
||||
// not scrollable.
|
||||
var el = /** @type {!Element} */ (this.getElement());
|
||||
Blockly.utils.style.scrollIntoContainerView(
|
||||
const el = /** @type {!Element} */ (this.getElement());
|
||||
style.scrollIntoContainerView(
|
||||
/** @type {!Element} */ (item.getElement()), el);
|
||||
|
||||
Blockly.utils.aria.setState(el, Blockly.utils.aria.State.ACTIVEDESCENDANT,
|
||||
item.getId());
|
||||
aria.setState(el, aria.State.ACTIVEDESCENDANT, item.getId());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -283,8 +285,8 @@ Blockly.Menu.prototype.setHighlighted = function(item) {
|
||||
* highlighted).
|
||||
* @package
|
||||
*/
|
||||
Blockly.Menu.prototype.highlightNext = function() {
|
||||
var index = this.menuItems_.indexOf(this.highlightedItem_);
|
||||
Menu.prototype.highlightNext = function() {
|
||||
const index = this.menuItems_.indexOf(this.highlightedItem_);
|
||||
this.highlightHelper_(index, 1);
|
||||
};
|
||||
|
||||
@@ -293,8 +295,8 @@ Blockly.Menu.prototype.highlightNext = function() {
|
||||
* currently highlighted).
|
||||
* @package
|
||||
*/
|
||||
Blockly.Menu.prototype.highlightPrevious = function() {
|
||||
var index = this.menuItems_.indexOf(this.highlightedItem_);
|
||||
Menu.prototype.highlightPrevious = function() {
|
||||
const index = this.menuItems_.indexOf(this.highlightedItem_);
|
||||
this.highlightHelper_(index < 0 ? this.menuItems_.length : index, -1);
|
||||
};
|
||||
|
||||
@@ -302,7 +304,7 @@ Blockly.Menu.prototype.highlightPrevious = function() {
|
||||
* Highlights the first highlightable item.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.highlightFirst_ = function() {
|
||||
Menu.prototype.highlightFirst_ = function() {
|
||||
this.highlightHelper_(-1, 1);
|
||||
};
|
||||
|
||||
@@ -310,7 +312,7 @@ Blockly.Menu.prototype.highlightFirst_ = function() {
|
||||
* Highlights the last highlightable item.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.highlightLast_ = function() {
|
||||
Menu.prototype.highlightLast_ = function() {
|
||||
this.highlightHelper_(this.menuItems_.length, -1);
|
||||
};
|
||||
|
||||
@@ -321,9 +323,9 @@ Blockly.Menu.prototype.highlightLast_ = function() {
|
||||
* @param {number} delta Step direction: 1 to go down, -1 to go up.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.highlightHelper_ = function(startIndex, delta) {
|
||||
var index = startIndex + delta;
|
||||
var menuItem;
|
||||
Menu.prototype.highlightHelper_ = function(startIndex, delta) {
|
||||
let index = startIndex + delta;
|
||||
let menuItem;
|
||||
while ((menuItem = this.menuItems_[index])) {
|
||||
if (menuItem.isEnabled()) {
|
||||
this.setHighlighted(menuItem);
|
||||
@@ -340,8 +342,8 @@ Blockly.Menu.prototype.highlightHelper_ = function(startIndex, delta) {
|
||||
* @param {!Event} e Mouse event to handle.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.handleMouseOver_ = function(e) {
|
||||
var menuItem = this.getMenuItem_(/** @type {Element} */ (e.target));
|
||||
Menu.prototype.handleMouseOver_ = function(e) {
|
||||
const menuItem = this.getMenuItem_(/** @type {Element} */ (e.target));
|
||||
|
||||
if (menuItem) {
|
||||
if (menuItem.isEnabled()) {
|
||||
@@ -359,13 +361,13 @@ Blockly.Menu.prototype.handleMouseOver_ = function(e) {
|
||||
* @param {!Event} e Click event to handle.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.handleClick_ = function(e) {
|
||||
var oldCoords = this.openingCoords;
|
||||
Menu.prototype.handleClick_ = function(e) {
|
||||
const oldCoords = this.openingCoords;
|
||||
// Clear out the saved opening coords immediately so they're not used twice.
|
||||
this.openingCoords = null;
|
||||
if (oldCoords && typeof e.clientX == 'number') {
|
||||
var newCoords = new Blockly.utils.Coordinate(e.clientX, e.clientY);
|
||||
if (Blockly.utils.Coordinate.distance(oldCoords, newCoords) < 1) {
|
||||
const newCoords = new Coordinate(e.clientX, e.clientY);
|
||||
if (Coordinate.distance(oldCoords, newCoords) < 1) {
|
||||
// This menu was opened by a mousedown and we're handling the consequent
|
||||
// click event. The coords haven't changed, meaning this was the same
|
||||
// opening event. Don't do the usual behavior because the menu just popped
|
||||
@@ -374,7 +376,7 @@ Blockly.Menu.prototype.handleClick_ = function(e) {
|
||||
}
|
||||
}
|
||||
|
||||
var menuItem = this.getMenuItem_(/** @type {Element} */ (e.target));
|
||||
const menuItem = this.getMenuItem_(/** @type {Element} */ (e.target));
|
||||
if (menuItem) {
|
||||
menuItem.performAction();
|
||||
}
|
||||
@@ -385,7 +387,7 @@ Blockly.Menu.prototype.handleClick_ = function(e) {
|
||||
* @param {!Event} _e Mouse event to handle.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.handleMouseEnter_ = function(_e) {
|
||||
Menu.prototype.handleMouseEnter_ = function(_e) {
|
||||
this.focus();
|
||||
};
|
||||
|
||||
@@ -394,7 +396,7 @@ Blockly.Menu.prototype.handleMouseEnter_ = function(_e) {
|
||||
* @param {!Event} _e Mouse event to handle.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.handleMouseLeave_ = function(_e) {
|
||||
Menu.prototype.handleMouseLeave_ = function(_e) {
|
||||
if (this.getElement()) {
|
||||
this.blur_();
|
||||
this.setHighlighted(null);
|
||||
@@ -409,7 +411,7 @@ Blockly.Menu.prototype.handleMouseLeave_ = function(_e) {
|
||||
* @param {!Event} e Key event to handle.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.handleKeyEvent_ = function(e) {
|
||||
Menu.prototype.handleKeyEvent_ = function(e) {
|
||||
if (!this.menuItems_.length) {
|
||||
// Empty menu.
|
||||
return;
|
||||
@@ -419,30 +421,30 @@ Blockly.Menu.prototype.handleKeyEvent_ = function(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
var highlighted = this.highlightedItem_;
|
||||
const highlighted = this.highlightedItem_;
|
||||
switch (e.keyCode) {
|
||||
case Blockly.utils.KeyCodes.ENTER:
|
||||
case Blockly.utils.KeyCodes.SPACE:
|
||||
case KeyCodes.ENTER:
|
||||
case KeyCodes.SPACE:
|
||||
if (highlighted) {
|
||||
highlighted.performAction();
|
||||
}
|
||||
break;
|
||||
|
||||
case Blockly.utils.KeyCodes.UP:
|
||||
case KeyCodes.UP:
|
||||
this.highlightPrevious();
|
||||
break;
|
||||
|
||||
case Blockly.utils.KeyCodes.DOWN:
|
||||
case KeyCodes.DOWN:
|
||||
this.highlightNext();
|
||||
break;
|
||||
|
||||
case Blockly.utils.KeyCodes.PAGE_UP:
|
||||
case Blockly.utils.KeyCodes.HOME:
|
||||
case KeyCodes.PAGE_UP:
|
||||
case KeyCodes.HOME:
|
||||
this.highlightFirst_();
|
||||
break;
|
||||
|
||||
case Blockly.utils.KeyCodes.PAGE_DOWN:
|
||||
case Blockly.utils.KeyCodes.END:
|
||||
case KeyCodes.PAGE_DOWN:
|
||||
case KeyCodes.END:
|
||||
this.highlightLast_();
|
||||
break;
|
||||
|
||||
@@ -457,13 +459,16 @@ Blockly.Menu.prototype.handleKeyEvent_ = function(e) {
|
||||
|
||||
/**
|
||||
* Get the size of a rendered menu.
|
||||
* @return {!Blockly.utils.Size} Object with width and height properties.
|
||||
* @return {!Size} Object with width and height properties.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Menu.prototype.getSize = function() {
|
||||
var menuDom = this.getElement();
|
||||
var menuSize = Blockly.utils.style.getSize(/** @type {!Element} */ (menuDom));
|
||||
Menu.prototype.getSize = function() {
|
||||
const menuDom = this.getElement();
|
||||
const menuSize = style.getSize(/** @type {!Element} */
|
||||
(menuDom));
|
||||
// Recalculate height for the total content, not only box height.
|
||||
menuSize.height = menuDom.scrollHeight;
|
||||
return menuSize;
|
||||
};
|
||||
|
||||
exports = Menu;
|
||||
|
||||
300
core/mutator.js
300
core/mutator.js
@@ -11,81 +11,88 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Mutator');
|
||||
goog.module('Blockly.Mutator');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Bubble');
|
||||
goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Abstract = goog.requireType('Blockly.Events.Abstract');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Blockly = goog.requireType('Blockly');
|
||||
const Bubble = goog.require('Blockly.Bubble');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Connection = goog.requireType('Blockly.Connection');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
const Icon = goog.require('Blockly.Icon');
|
||||
const Options = goog.require('Blockly.Options');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
const WorkspaceSvg = goog.require('Blockly.WorkspaceSvg');
|
||||
const Xml = goog.require('Blockly.Xml');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const internalConstants = goog.require('Blockly.internalConstants');
|
||||
const object = goog.require('Blockly.utils.object');
|
||||
const toolbox = goog.require('Blockly.utils.toolbox');
|
||||
const xml = goog.require('Blockly.utils.xml');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.BlockChange');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.BubbleOpen');
|
||||
goog.require('Blockly.Icon');
|
||||
goog.require('Blockly.internalConstants');
|
||||
goog.require('Blockly.Options');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
goog.require('Blockly.utils.toolbox');
|
||||
goog.require('Blockly.utils.xml');
|
||||
goog.require('Blockly.WorkspaceSvg');
|
||||
goog.require('Blockly.Xml');
|
||||
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.Connection');
|
||||
goog.requireType('Blockly.Events.Abstract');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
goog.requireType('Blockly.Workspace');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a mutator dialog.
|
||||
* @param {!Array<string>} quarkNames List of names of sub-blocks for flyout.
|
||||
* @extends {Blockly.Icon}
|
||||
* @extends {Icon}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Mutator = function(quarkNames) {
|
||||
Blockly.Mutator.superClass_.constructor.call(this, null);
|
||||
const Mutator = function(quarkNames) {
|
||||
Mutator.superClass_.constructor.call(this, null);
|
||||
this.quarkNames_ = quarkNames;
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.Mutator, Blockly.Icon);
|
||||
object.inherits(Mutator, Icon);
|
||||
|
||||
/**
|
||||
* Workspace in the mutator's bubble.
|
||||
* @type {?Blockly.WorkspaceSvg}
|
||||
* @type {?WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
Blockly.Mutator.prototype.workspace_ = null;
|
||||
Mutator.prototype.workspace_ = null;
|
||||
|
||||
/**
|
||||
* Width of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Mutator.prototype.workspaceWidth_ = 0;
|
||||
Mutator.prototype.workspaceWidth_ = 0;
|
||||
|
||||
/**
|
||||
* Height of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Mutator.prototype.workspaceHeight_ = 0;
|
||||
Mutator.prototype.workspaceHeight_ = 0;
|
||||
|
||||
/**
|
||||
* Set the block this mutator is associated with.
|
||||
* @param {!Blockly.BlockSvg} block The block associated with this mutator.
|
||||
* @param {!BlockSvg} block The block associated with this mutator.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Mutator.prototype.setBlock = function(block) {
|
||||
Mutator.prototype.setBlock = function(block) {
|
||||
this.block_ = block;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the workspace inside this mutator icon's bubble.
|
||||
* @return {?Blockly.WorkspaceSvg} The workspace inside this mutator icon's
|
||||
* @return {?WorkspaceSvg} The workspace inside this mutator icon's
|
||||
* bubble or null if the mutator isn't open.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Mutator.prototype.getWorkspace = function() {
|
||||
Mutator.prototype.getWorkspace = function() {
|
||||
return this.workspace_;
|
||||
};
|
||||
|
||||
@@ -94,11 +101,10 @@ Blockly.Mutator.prototype.getWorkspace = function() {
|
||||
* @param {!Element} group The icon group.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Mutator.prototype.drawIcon_ = function(group) {
|
||||
Mutator.prototype.drawIcon_ = function(group) {
|
||||
// Square with rounded corners.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
dom.createSvgElement(
|
||||
Svg.RECT, {
|
||||
'class': 'blocklyIconShape',
|
||||
'rx': '4',
|
||||
'ry': '4',
|
||||
@@ -107,29 +113,22 @@ Blockly.Mutator.prototype.drawIcon_ = function(group) {
|
||||
},
|
||||
group);
|
||||
// Gear teeth.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATH,
|
||||
{
|
||||
dom.createSvgElement(
|
||||
Svg.PATH, {
|
||||
'class': 'blocklyIconSymbol',
|
||||
'd': 'm4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,' +
|
||||
'0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,' +
|
||||
'-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,' +
|
||||
'-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,' +
|
||||
'-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 ' +
|
||||
'-0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,' +
|
||||
'0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z'
|
||||
'0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,' +
|
||||
'-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,' +
|
||||
'-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,' +
|
||||
'-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 ' +
|
||||
'-0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,' +
|
||||
'0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z'
|
||||
},
|
||||
group);
|
||||
// Axle hole.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.CIRCLE,
|
||||
{
|
||||
'class': 'blocklyIconShape',
|
||||
'r': '2.7',
|
||||
'cx': '8',
|
||||
'cy': '8'
|
||||
},
|
||||
group);
|
||||
dom.createSvgElement(
|
||||
Svg.CIRCLE,
|
||||
{'class': 'blocklyIconShape', 'r': '2.7', 'cx': '8', 'cy': '8'}, group);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -139,9 +138,9 @@ Blockly.Mutator.prototype.drawIcon_ = function(group) {
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
Blockly.Mutator.prototype.iconClick_ = function(e) {
|
||||
Mutator.prototype.iconClick_ = function(e) {
|
||||
if (this.block_.isEditable()) {
|
||||
Blockly.Icon.prototype.iconClick_.call(this, e);
|
||||
Icon.prototype.iconClick_.call(this, e);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -150,28 +149,27 @@ Blockly.Mutator.prototype.iconClick_ = function(e) {
|
||||
* @return {!SVGElement} The top-level node of the editor.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Mutator.prototype.createEditor_ = function() {
|
||||
Mutator.prototype.createEditor_ = function() {
|
||||
/* Create the editor. Here's the markup that will be generated:
|
||||
<svg>
|
||||
[Workspace]
|
||||
</svg>
|
||||
*/
|
||||
this.svgDialog_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.SVG,
|
||||
{'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH},
|
||||
null);
|
||||
this.svgDialog_ = dom.createSvgElement(
|
||||
Svg.SVG, {'x': Bubble.BORDER_WIDTH, 'y': Bubble.BORDER_WIDTH}, null);
|
||||
// Convert the list of names into a list of XML objects for the flyout.
|
||||
let quarkXml;
|
||||
if (this.quarkNames_.length) {
|
||||
var quarkXml = Blockly.utils.xml.createElement('xml');
|
||||
for (var i = 0, quarkName; (quarkName = this.quarkNames_[i]); i++) {
|
||||
var element = Blockly.utils.xml.createElement('block');
|
||||
quarkXml = xml.createElement('xml');
|
||||
for (let i = 0, quarkName; (quarkName = this.quarkNames_[i]); i++) {
|
||||
const element = xml.createElement('block');
|
||||
element.setAttribute('type', quarkName);
|
||||
quarkXml.appendChild(element);
|
||||
}
|
||||
} else {
|
||||
var quarkXml = null;
|
||||
quarkXml = null;
|
||||
}
|
||||
var workspaceOptions = new Blockly.Options(
|
||||
const workspaceOptions = new Options(
|
||||
/** @type {!Blockly.BlocklyOptions} */
|
||||
({
|
||||
// If you want to enable disabling, also remove the
|
||||
@@ -184,25 +182,22 @@ Blockly.Mutator.prototype.createEditor_ = function() {
|
||||
'renderer': this.block_.workspace.options.renderer,
|
||||
'rendererOverrides': this.block_.workspace.options.rendererOverrides
|
||||
}));
|
||||
workspaceOptions.toolboxPosition = this.block_.RTL ?
|
||||
Blockly.utils.toolbox.Position.RIGHT :
|
||||
Blockly.utils.toolbox.Position.LEFT;
|
||||
var hasFlyout = !!quarkXml;
|
||||
workspaceOptions.toolboxPosition =
|
||||
this.block_.RTL ? toolbox.Position.RIGHT : toolbox.Position.LEFT;
|
||||
const hasFlyout = !!quarkXml;
|
||||
if (hasFlyout) {
|
||||
workspaceOptions.languageTree =
|
||||
Blockly.utils.toolbox.convertToolboxDefToJson(quarkXml);
|
||||
workspaceOptions.languageTree = toolbox.convertToolboxDefToJson(quarkXml);
|
||||
}
|
||||
this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions);
|
||||
this.workspace_ = new WorkspaceSvg(workspaceOptions);
|
||||
this.workspace_.isMutator = true;
|
||||
this.workspace_.addChangeListener(Blockly.Events.disableOrphans);
|
||||
this.workspace_.addChangeListener(Events.disableOrphans);
|
||||
|
||||
// Mutator flyouts go inside the mutator workspace's <g> rather than in
|
||||
// a top level SVG. Instead of handling scale themselves, mutators
|
||||
// inherit scale from the parent workspace.
|
||||
// To fix this, scale needs to be applied at a different level in the DOM.
|
||||
var flyoutSvg = hasFlyout ?
|
||||
this.workspace_.addFlyout(Blockly.utils.Svg.G) : null;
|
||||
var background = this.workspace_.createDom('blocklyMutatorBackground');
|
||||
const flyoutSvg = hasFlyout ? this.workspace_.addFlyout(Svg.G) : null;
|
||||
const background = this.workspace_.createDom('blocklyMutatorBackground');
|
||||
|
||||
if (flyoutSvg) {
|
||||
// Insert the flyout after the <rect> but before the block canvas so that
|
||||
@@ -218,12 +213,12 @@ Blockly.Mutator.prototype.createEditor_ = function() {
|
||||
/**
|
||||
* Add or remove the UI indicating if this icon may be clicked or not.
|
||||
*/
|
||||
Blockly.Mutator.prototype.updateEditable = function() {
|
||||
Blockly.Mutator.superClass_.updateEditable.call(this);
|
||||
Mutator.prototype.updateEditable = function() {
|
||||
Mutator.superClass_.updateEditable.call(this);
|
||||
if (!this.block_.isInFlyout) {
|
||||
if (this.block_.isEditable()) {
|
||||
if (this.iconGroup_) {
|
||||
Blockly.utils.dom.removeClass(
|
||||
dom.removeClass(
|
||||
/** @type {!Element} */ (this.iconGroup_),
|
||||
'blocklyIconGroupReadonly');
|
||||
}
|
||||
@@ -231,7 +226,7 @@ Blockly.Mutator.prototype.updateEditable = function() {
|
||||
// Close any mutator bubble. Icon is not clickable.
|
||||
this.setVisible(false);
|
||||
if (this.iconGroup_) {
|
||||
Blockly.utils.dom.addClass(
|
||||
dom.addClass(
|
||||
/** @type {!Element} */ (this.iconGroup_),
|
||||
'blocklyIconGroupReadonly');
|
||||
}
|
||||
@@ -243,15 +238,15 @@ Blockly.Mutator.prototype.updateEditable = function() {
|
||||
* Resize the bubble to match the size of the workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Mutator.prototype.resizeBubble_ = function() {
|
||||
var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH;
|
||||
var workspaceSize = this.workspace_.getCanvas().getBBox();
|
||||
var width = workspaceSize.width + workspaceSize.x;
|
||||
var height = workspaceSize.height + doubleBorderWidth * 3;
|
||||
var flyout = this.workspace_.getFlyout();
|
||||
Mutator.prototype.resizeBubble_ = function() {
|
||||
const doubleBorderWidth = 2 * Bubble.BORDER_WIDTH;
|
||||
const workspaceSize = this.workspace_.getCanvas().getBBox();
|
||||
let width = workspaceSize.width + workspaceSize.x;
|
||||
let height = workspaceSize.height + doubleBorderWidth * 3;
|
||||
const flyout = this.workspace_.getFlyout();
|
||||
if (flyout) {
|
||||
var flyoutScrollMetrics = flyout.getWorkspace().getMetricsManager()
|
||||
.getScrollMetrics();
|
||||
const flyoutScrollMetrics =
|
||||
flyout.getWorkspace().getMetricsManager().getScrollMetrics();
|
||||
height = Math.max(height, flyoutScrollMetrics.height + 20);
|
||||
width += flyout.getWidth();
|
||||
}
|
||||
@@ -276,7 +271,7 @@ Blockly.Mutator.prototype.resizeBubble_ = function() {
|
||||
|
||||
if (this.block_.RTL) {
|
||||
// Scroll the workspace to always left-align.
|
||||
var translation = 'translate(' + this.workspaceWidth_ + ',0)';
|
||||
const translation = 'translate(' + this.workspaceWidth_ + ',0)';
|
||||
this.workspace_.getCanvas().setAttribute('transform', translation);
|
||||
}
|
||||
this.workspace_.resize();
|
||||
@@ -286,7 +281,7 @@ Blockly.Mutator.prototype.resizeBubble_ = function() {
|
||||
* A method handler for when the bubble is moved.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Mutator.prototype.onBubbleMove_ = function() {
|
||||
Mutator.prototype.onBubbleMove_ = function() {
|
||||
if (this.workspace_) {
|
||||
this.workspace_.recordDragTargets();
|
||||
}
|
||||
@@ -296,43 +291,44 @@ Blockly.Mutator.prototype.onBubbleMove_ = function() {
|
||||
* Show or hide the mutator bubble.
|
||||
* @param {boolean} visible True if the bubble should be visible.
|
||||
*/
|
||||
Blockly.Mutator.prototype.setVisible = function(visible) {
|
||||
Mutator.prototype.setVisible = function(visible) {
|
||||
if (visible == this.isVisible()) {
|
||||
// No change.
|
||||
return;
|
||||
}
|
||||
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BUBBLE_OPEN))(
|
||||
this.block_, visible, 'mutator'));
|
||||
Events.fire(
|
||||
new (Events.get(Events.BUBBLE_OPEN))(this.block_, visible, 'mutator'));
|
||||
if (visible) {
|
||||
// Create the bubble.
|
||||
this.bubble_ = new Blockly.Bubble(
|
||||
/** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace),
|
||||
this.bubble_ = new Bubble(
|
||||
/** @type {!WorkspaceSvg} */ (this.block_.workspace),
|
||||
this.createEditor_(), this.block_.pathObject.svgPath,
|
||||
/** @type {!Blockly.utils.Coordinate} */ (this.iconXY_), null, null);
|
||||
/** @type {!Coordinate} */ (this.iconXY_), null, null);
|
||||
// Expose this mutator's block's ID on its top-level SVG group.
|
||||
this.bubble_.setSvgId(this.block_.id);
|
||||
this.bubble_.registerMoveEvent(this.onBubbleMove_.bind(this));
|
||||
var tree = this.workspace_.options.languageTree;
|
||||
var flyout = this.workspace_.getFlyout();
|
||||
const tree = this.workspace_.options.languageTree;
|
||||
const flyout = this.workspace_.getFlyout();
|
||||
if (tree) {
|
||||
flyout.init(this.workspace_);
|
||||
flyout.show(tree);
|
||||
}
|
||||
|
||||
this.rootBlock_ = this.block_.decompose(this.workspace_);
|
||||
var blocks = this.rootBlock_.getDescendants(false);
|
||||
for (var i = 0, child; (child = blocks[i]); i++) {
|
||||
const blocks = this.rootBlock_.getDescendants(false);
|
||||
for (let i = 0, child; (child = blocks[i]); i++) {
|
||||
child.render();
|
||||
}
|
||||
// The root block should not be draggable or deletable.
|
||||
this.rootBlock_.setMovable(false);
|
||||
this.rootBlock_.setDeletable(false);
|
||||
let margin, x;
|
||||
if (flyout) {
|
||||
var margin = flyout.CORNER_RADIUS * 2;
|
||||
var x = this.rootBlock_.RTL ? flyout.getWidth() + margin : margin;
|
||||
margin = flyout.CORNER_RADIUS * 2;
|
||||
x = this.rootBlock_.RTL ? flyout.getWidth() + margin : margin;
|
||||
} else {
|
||||
var margin = 16;
|
||||
var x = margin;
|
||||
margin = 16;
|
||||
x = margin;
|
||||
}
|
||||
if (this.block_.RTL) {
|
||||
x = -x;
|
||||
@@ -340,10 +336,9 @@ Blockly.Mutator.prototype.setVisible = function(visible) {
|
||||
this.rootBlock_.moveBy(x, margin);
|
||||
// Save the initial connections, then listen for further changes.
|
||||
if (this.block_.saveConnections) {
|
||||
var thisMutator = this;
|
||||
var mutatorBlock =
|
||||
/** @type {{saveConnections: function(!Blockly.Block)}} */ (
|
||||
this.block_);
|
||||
const thisMutator = this;
|
||||
const mutatorBlock =
|
||||
/** @type {{saveConnections: function(!Block)}} */ (this.block_);
|
||||
mutatorBlock.saveConnections(this.rootBlock_);
|
||||
this.sourceListener_ = function() {
|
||||
mutatorBlock.saveConnections(thisMutator.rootBlock_);
|
||||
@@ -375,21 +370,20 @@ Blockly.Mutator.prototype.setVisible = function(visible) {
|
||||
* Update the source block when the mutator's blocks are changed.
|
||||
* Bump down any block that's too high.
|
||||
* Fired whenever a change is made to the mutator's workspace.
|
||||
* @param {!Blockly.Events.Abstract} e Custom data for event.
|
||||
* @param {!Abstract} e Custom data for event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Mutator.prototype.workspaceChanged_ = function(e) {
|
||||
if (e.isUiEvent ||
|
||||
(e.type == Blockly.Events.CHANGE && e.element == 'disabled')) {
|
||||
Mutator.prototype.workspaceChanged_ = function(e) {
|
||||
if (e.isUiEvent || (e.type == Events.CHANGE && e.element == 'disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.workspace_.isDragging()) {
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
var MARGIN = 20;
|
||||
const blocks = this.workspace_.getTopBlocks(false);
|
||||
const MARGIN = 20;
|
||||
|
||||
for (var b = 0, block; (block = blocks[b]); b++) {
|
||||
var blockXY = block.getRelativeToSurfaceXY();
|
||||
for (let b = 0, block; (block = blocks[b]); b++) {
|
||||
const blockXY = block.getRelativeToSurfaceXY();
|
||||
|
||||
// Bump any block that's above the top back inside.
|
||||
if (blockXY.y < MARGIN) {
|
||||
@@ -397,8 +391,8 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) {
|
||||
}
|
||||
// Bump any block overlapping the flyout back inside.
|
||||
if (block.RTL) {
|
||||
var right = -MARGIN;
|
||||
var flyout = this.workspace_.getFlyout();
|
||||
let right = -MARGIN;
|
||||
const flyout = this.workspace_.getFlyout();
|
||||
if (flyout) {
|
||||
right -= flyout.getWidth();
|
||||
}
|
||||
@@ -413,13 +407,13 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) {
|
||||
|
||||
// When the mutator's workspace changes, update the source block.
|
||||
if (this.rootBlock_.workspace == this.workspace_) {
|
||||
Blockly.Events.setGroup(true);
|
||||
var block = this.block_;
|
||||
var oldMutationDom = block.mutationToDom();
|
||||
var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom);
|
||||
Events.setGroup(true);
|
||||
const block = this.block_;
|
||||
const oldMutationDom = block.mutationToDom();
|
||||
const oldMutation = oldMutationDom && Xml.domToText(oldMutationDom);
|
||||
|
||||
// Switch off rendering while the source block is rebuilt.
|
||||
var savedRendered = block.rendered;
|
||||
const savedRendered = block.rendered;
|
||||
// TODO(#4288): We should not be setting the rendered property to false.
|
||||
block.rendered = false;
|
||||
|
||||
@@ -434,18 +428,18 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) {
|
||||
block.render();
|
||||
}
|
||||
|
||||
var newMutationDom = block.mutationToDom();
|
||||
var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom);
|
||||
const newMutationDom = block.mutationToDom();
|
||||
const newMutation = newMutationDom && Xml.domToText(newMutationDom);
|
||||
if (oldMutation != newMutation) {
|
||||
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))(
|
||||
Events.fire(new (Events.get(Events.BLOCK_CHANGE))(
|
||||
block, 'mutation', null, oldMutation, newMutation));
|
||||
// Ensure that any bump is part of this mutation's event group.
|
||||
var group = Blockly.Events.getGroup();
|
||||
const group = Events.getGroup();
|
||||
setTimeout(function() {
|
||||
Blockly.Events.setGroup(group);
|
||||
Events.setGroup(group);
|
||||
block.bumpNeighbours();
|
||||
Blockly.Events.setGroup(false);
|
||||
}, Blockly.internalConstants.BUMP_DELAY);
|
||||
Events.setGroup(false);
|
||||
}, internalConstants.BUMP_DELAY);
|
||||
}
|
||||
|
||||
// Don't update the bubble until the drag has ended, to avoid moving blocks
|
||||
@@ -453,35 +447,35 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) {
|
||||
if (!this.workspace_.isDragging()) {
|
||||
this.resizeBubble_();
|
||||
}
|
||||
Blockly.Events.setGroup(false);
|
||||
Events.setGroup(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispose of this mutator.
|
||||
*/
|
||||
Blockly.Mutator.prototype.dispose = function() {
|
||||
Mutator.prototype.dispose = function() {
|
||||
this.block_.mutator = null;
|
||||
Blockly.Icon.prototype.dispose.call(this);
|
||||
Icon.prototype.dispose.call(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the styles on all blocks in the mutator.
|
||||
* @public
|
||||
*/
|
||||
Blockly.Mutator.prototype.updateBlockStyle = function() {
|
||||
var ws = this.workspace_;
|
||||
Mutator.prototype.updateBlockStyle = function() {
|
||||
const ws = this.workspace_;
|
||||
|
||||
if (ws && ws.getAllBlocks(false)) {
|
||||
var workspaceBlocks = ws.getAllBlocks(false);
|
||||
for (var i = 0, block; (block = workspaceBlocks[i]); i++) {
|
||||
const workspaceBlocks = ws.getAllBlocks(false);
|
||||
for (let i = 0, block; (block = workspaceBlocks[i]); i++) {
|
||||
block.setStyle(block.getStyleName());
|
||||
}
|
||||
|
||||
var flyout = ws.getFlyout();
|
||||
const flyout = ws.getFlyout();
|
||||
if (flyout) {
|
||||
var flyoutBlocks = flyout.workspace_.getAllBlocks(false);
|
||||
for (var i = 0, block; (block = flyoutBlocks[i]); i++) {
|
||||
const flyoutBlocks = flyout.workspace_.getAllBlocks(false);
|
||||
for (let i = 0, block; (block = flyoutBlocks[i]); i++) {
|
||||
block.setStyle(block.getStyleName());
|
||||
}
|
||||
}
|
||||
@@ -490,17 +484,17 @@ Blockly.Mutator.prototype.updateBlockStyle = function() {
|
||||
|
||||
/**
|
||||
* Reconnect an block to a mutated input.
|
||||
* @param {Blockly.Connection} connectionChild Connection on child block.
|
||||
* @param {!Blockly.Block} block Parent block.
|
||||
* @param {Connection} connectionChild Connection on child block.
|
||||
* @param {!Block} block Parent block.
|
||||
* @param {string} inputName Name of input on parent block.
|
||||
* @return {boolean} True iff a reconnection was made, false otherwise.
|
||||
*/
|
||||
Blockly.Mutator.reconnect = function(connectionChild, block, inputName) {
|
||||
Mutator.reconnect = function(connectionChild, block, inputName) {
|
||||
if (!connectionChild || !connectionChild.getSourceBlock().workspace) {
|
||||
return false; // No connection or block has been deleted.
|
||||
}
|
||||
var connectionParent = block.getInput(inputName).connection;
|
||||
var currentParent = connectionChild.targetBlock();
|
||||
const connectionParent = block.getInput(inputName).connection;
|
||||
const currentParent = connectionChild.targetBlock();
|
||||
if ((!currentParent || currentParent == block) &&
|
||||
connectionParent.targetConnection != connectionChild) {
|
||||
if (connectionParent.isConnected()) {
|
||||
@@ -516,14 +510,14 @@ Blockly.Mutator.reconnect = function(connectionChild, block, inputName) {
|
||||
/**
|
||||
* Get the parent workspace of a workspace that is inside a mutator, taking into
|
||||
* account whether it is a flyout.
|
||||
* @param {Blockly.Workspace} workspace The workspace that is inside a mutator.
|
||||
* @return {?Blockly.Workspace} The mutator's parent workspace or null.
|
||||
* @param {Workspace} workspace The workspace that is inside a mutator.
|
||||
* @return {?Workspace} The mutator's parent workspace or null.
|
||||
* @public
|
||||
*/
|
||||
Blockly.Mutator.findParentWs = function(workspace) {
|
||||
var outerWs = null;
|
||||
Mutator.findParentWs = function(workspace) {
|
||||
let outerWs = null;
|
||||
if (workspace && workspace.options) {
|
||||
var parent = workspace.options.parentWorkspace;
|
||||
const parent = workspace.options.parentWorkspace;
|
||||
// If we were in a flyout in a mutator, need to go up two levels to find
|
||||
// the actual parent.
|
||||
if (workspace.isFlyout) {
|
||||
@@ -536,3 +530,5 @@ Blockly.Mutator.findParentWs = function(workspace) {
|
||||
}
|
||||
return outerWs;
|
||||
};
|
||||
|
||||
exports = Mutator;
|
||||
|
||||
185
core/registry.js
185
core/registry.js
@@ -11,20 +11,33 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.registry');
|
||||
goog.module('Blockly.registry');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.requireType('Blockly.blockRendering.Renderer');
|
||||
goog.requireType('Blockly.Cursor');
|
||||
goog.requireType('Blockly.Events.Abstract');
|
||||
goog.requireType('Blockly.Field');
|
||||
goog.requireType('Blockly.IBlockDragger');
|
||||
goog.requireType('Blockly.IConnectionChecker');
|
||||
goog.requireType('Blockly.IFlyout');
|
||||
goog.requireType('Blockly.IMetricsManager');
|
||||
goog.requireType('Blockly.IToolbox');
|
||||
goog.requireType('Blockly.Options');
|
||||
goog.requireType('Blockly.Theme');
|
||||
goog.requireType('Blockly.ToolboxItem');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Abstract = goog.requireType('Blockly.Events.Abstract');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Cursor = goog.requireType('Blockly.Cursor');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Field = goog.requireType('Blockly.Field');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IBlockDragger = goog.requireType('Blockly.IBlockDragger');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IConnectionChecker = goog.requireType('Blockly.IConnectionChecker');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IFlyout = goog.requireType('Blockly.IFlyout');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IMetricsManager = goog.requireType('Blockly.IMetricsManager');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IToolbox = goog.requireType('Blockly.IToolbox');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Options = goog.requireType('Blockly.Options');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Renderer = goog.requireType('Blockly.blockRendering.Renderer');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Theme = goog.requireType('Blockly.Theme');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ToolboxItem = goog.requireType('Blockly.ToolboxItem');
|
||||
|
||||
|
||||
/**
|
||||
@@ -34,13 +47,16 @@ goog.requireType('Blockly.ToolboxItem');
|
||||
*
|
||||
* @type {Object<string, Object<string, function(new:?)>>}
|
||||
*/
|
||||
Blockly.registry.typeMap_ = Object.create(null);
|
||||
const typeMap = Object.create(null);
|
||||
/** @private */
|
||||
exports.typeMap_ = typeMap;
|
||||
|
||||
/**
|
||||
* The string used to register the default class for a type of plugin.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.registry.DEFAULT = 'default';
|
||||
const DEFAULT = 'default';
|
||||
exports.DEFAULT = DEFAULT;
|
||||
|
||||
/**
|
||||
* A name with the type of the element stored in the generic.
|
||||
@@ -48,67 +64,63 @@ Blockly.registry.DEFAULT = 'default';
|
||||
* @constructor
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.Type = function(name) {
|
||||
const Type = function(name) {
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.name_ = name;
|
||||
};
|
||||
exports.Type = Type;
|
||||
|
||||
/**
|
||||
* Returns the name of the type.
|
||||
* @return {string} The name.
|
||||
* @override
|
||||
*/
|
||||
Blockly.registry.Type.prototype.toString = function() {
|
||||
Type.prototype.toString = function() {
|
||||
return this.name_;
|
||||
};
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.IConnectionChecker>} */
|
||||
Blockly.registry.Type.CONNECTION_CHECKER =
|
||||
new Blockly.registry.Type('connectionChecker');
|
||||
/** @type {!Type<IConnectionChecker>} */
|
||||
Type.CONNECTION_CHECKER = new Type('connectionChecker');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.Cursor>} */
|
||||
Blockly.registry.Type.CURSOR = new Blockly.registry.Type('cursor');
|
||||
/** @type {!Type<Cursor>} */
|
||||
Type.CURSOR = new Type('cursor');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.Events.Abstract>} */
|
||||
Blockly.registry.Type.EVENT = new Blockly.registry.Type('event');
|
||||
/** @type {!Type<Abstract>} */
|
||||
Type.EVENT = new Type('event');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.Field>} */
|
||||
Blockly.registry.Type.FIELD = new Blockly.registry.Type('field');
|
||||
/** @type {!Type<Field>} */
|
||||
Type.FIELD = new Type('field');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.blockRendering.Renderer>} */
|
||||
Blockly.registry.Type.RENDERER = new Blockly.registry.Type('renderer');
|
||||
/** @type {!Type<Renderer>} */
|
||||
Type.RENDERER = new Type('renderer');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.IToolbox>} */
|
||||
Blockly.registry.Type.TOOLBOX = new Blockly.registry.Type('toolbox');
|
||||
/** @type {!Type<IToolbox>} */
|
||||
Type.TOOLBOX = new Type('toolbox');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.Theme>} */
|
||||
Blockly.registry.Type.THEME = new Blockly.registry.Type('theme');
|
||||
/** @type {!Type<Theme>} */
|
||||
Type.THEME = new Type('theme');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.ToolboxItem>} */
|
||||
Blockly.registry.Type.TOOLBOX_ITEM = new Blockly.registry.Type('toolboxItem');
|
||||
/** @type {!Type<ToolboxItem>} */
|
||||
Type.TOOLBOX_ITEM = new Type('toolboxItem');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.IFlyout>} */
|
||||
Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX =
|
||||
new Blockly.registry.Type('flyoutsVerticalToolbox');
|
||||
/** @type {!Type<IFlyout>} */
|
||||
Type.FLYOUTS_VERTICAL_TOOLBOX = new Type('flyoutsVerticalToolbox');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.IFlyout>} */
|
||||
Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX =
|
||||
new Blockly.registry.Type('flyoutsHorizontalToolbox');
|
||||
/** @type {!Type<IFlyout>} */
|
||||
Type.FLYOUTS_HORIZONTAL_TOOLBOX = new Type('flyoutsHorizontalToolbox');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.IMetricsManager>} */
|
||||
Blockly.registry.Type.METRICS_MANAGER =
|
||||
new Blockly.registry.Type('metricsManager');
|
||||
/** @type {!Type<IMetricsManager>} */
|
||||
Type.METRICS_MANAGER = new Type('metricsManager');
|
||||
|
||||
/** @type {!Blockly.registry.Type<Blockly.IBlockDragger>} */
|
||||
Blockly.registry.Type.BLOCK_DRAGGER =
|
||||
new Blockly.registry.Type('blockDragger');
|
||||
/** @type {!Type<IBlockDragger>} */
|
||||
Type.BLOCK_DRAGGER = new Type('blockDragger');
|
||||
|
||||
/**
|
||||
* Registers a class based on a type and name.
|
||||
* @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {string|!Type<T>} type The type of the plugin.
|
||||
* (e.g. Field, Renderer)
|
||||
* @param {string} name The plugin's name. (Ex. field_angle, geras)
|
||||
* @param {?function(new:T, ...?)|Object} registryItem The class or object to
|
||||
@@ -120,9 +132,8 @@ Blockly.registry.Type.BLOCK_DRAGGER =
|
||||
* it's type.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.register = function(
|
||||
type, name, registryItem, opt_allowOverrides) {
|
||||
if ((!(type instanceof Blockly.registry.Type) && typeof type != 'string') ||
|
||||
const register = function(type, name, registryItem, opt_allowOverrides) {
|
||||
if ((!(type instanceof Type) && typeof type != 'string') ||
|
||||
String(type).trim() == '') {
|
||||
throw Error(
|
||||
'Invalid type "' + type + '". The type must be a' +
|
||||
@@ -139,14 +150,14 @@ Blockly.registry.register = function(
|
||||
if (!registryItem) {
|
||||
throw Error('Can not register a null value');
|
||||
}
|
||||
var typeRegistry = Blockly.registry.typeMap_[type];
|
||||
let typeRegistry = typeMap[type];
|
||||
// If the type registry has not been created, create it.
|
||||
if (!typeRegistry) {
|
||||
typeRegistry = Blockly.registry.typeMap_[type] = Object.create(null);
|
||||
typeRegistry = typeMap[type] = Object.create(null);
|
||||
}
|
||||
|
||||
// Validate that the given class has all the required properties.
|
||||
Blockly.registry.validate_(type, registryItem);
|
||||
validate(type, registryItem);
|
||||
|
||||
// Don't throw an error if opt_allowOverrides is true.
|
||||
if (!opt_allowOverrides && typeRegistry[name]) {
|
||||
@@ -155,6 +166,7 @@ Blockly.registry.register = function(
|
||||
}
|
||||
typeRegistry[name] = registryItem;
|
||||
};
|
||||
exports.register = register;
|
||||
|
||||
/**
|
||||
* Checks the given registry item for properties that are required based on the
|
||||
@@ -162,11 +174,10 @@ Blockly.registry.register = function(
|
||||
* @param {string} type The type of the plugin. (e.g. Field, Renderer)
|
||||
* @param {Function|Object} registryItem A class or object that we are checking
|
||||
* for the required properties.
|
||||
* @private
|
||||
*/
|
||||
Blockly.registry.validate_ = function(type, registryItem) {
|
||||
const validate = function(type, registryItem) {
|
||||
switch (type) {
|
||||
case String(Blockly.registry.Type.FIELD):
|
||||
case String(Type.FIELD):
|
||||
if (typeof registryItem.fromJson != 'function') {
|
||||
throw Error('Type "' + type + '" must have a fromJson function');
|
||||
}
|
||||
@@ -176,27 +187,29 @@ Blockly.registry.validate_ = function(type, registryItem) {
|
||||
|
||||
/**
|
||||
* Unregisters the registry item with the given type and name.
|
||||
* @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {string|!Type<T>} type The type of the plugin.
|
||||
* (e.g. Field, Renderer)
|
||||
* @param {string} name The plugin's name. (Ex. field_angle, geras)
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.unregister = function(type, name) {
|
||||
const unregister = function(type, name) {
|
||||
type = String(type).toLowerCase();
|
||||
name = name.toLowerCase();
|
||||
var typeRegistry = Blockly.registry.typeMap_[type];
|
||||
const typeRegistry = typeMap[type];
|
||||
if (!typeRegistry || !typeRegistry[name]) {
|
||||
console.warn('Unable to unregister [' + name + '][' + type + '] from the ' +
|
||||
'registry.');
|
||||
console.warn(
|
||||
'Unable to unregister [' + name + '][' + type + '] from the ' +
|
||||
'registry.');
|
||||
return;
|
||||
}
|
||||
delete Blockly.registry.typeMap_[type][name];
|
||||
delete typeMap[type][name];
|
||||
};
|
||||
exports.unregister = unregister;
|
||||
|
||||
/**
|
||||
* Gets the registry item for the given name and type. This can be either a
|
||||
* class or an object.
|
||||
* @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {string|!Type<T>} type The type of the plugin.
|
||||
* (e.g. Field, Renderer)
|
||||
* @param {string} name The plugin's name. (Ex. field_angle, geras)
|
||||
* @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
|
||||
@@ -205,15 +218,15 @@ Blockly.registry.unregister = function(type, name) {
|
||||
* name and type or null if none exists.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.getItem_ = function(type, name, opt_throwIfMissing) {
|
||||
const getItem = function(type, name, opt_throwIfMissing) {
|
||||
type = String(type).toLowerCase();
|
||||
name = name.toLowerCase();
|
||||
var typeRegistry = Blockly.registry.typeMap_[type];
|
||||
const typeRegistry = typeMap[type];
|
||||
if (!typeRegistry || !typeRegistry[name]) {
|
||||
var msg = 'Unable to find [' + name + '][' + type + '] in the registry.';
|
||||
const msg = 'Unable to find [' + name + '][' + type + '] in the registry.';
|
||||
if (opt_throwIfMissing) {
|
||||
throw new Error(msg + ' You must require or register a ' + type +
|
||||
' plugin.');
|
||||
throw new Error(
|
||||
msg + ' You must require or register a ' + type + ' plugin.');
|
||||
} else {
|
||||
console.warn(msg);
|
||||
}
|
||||
@@ -225,26 +238,27 @@ Blockly.registry.getItem_ = function(type, name, opt_throwIfMissing) {
|
||||
/**
|
||||
* Returns whether or not the registry contains an item with the given type and
|
||||
* name.
|
||||
* @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {string|!Type<T>} type The type of the plugin.
|
||||
* (e.g. Field, Renderer)
|
||||
* @param {string} name The plugin's name. (Ex. field_angle, geras)
|
||||
* @return {boolean} True if the registry has an item with the given type and
|
||||
* name, false otherwise.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.hasItem = function(type, name) {
|
||||
const hasItem = function(type, name) {
|
||||
type = String(type).toLowerCase();
|
||||
name = name.toLowerCase();
|
||||
var typeRegistry = Blockly.registry.typeMap_[type];
|
||||
const typeRegistry = typeMap[type];
|
||||
if (!typeRegistry) {
|
||||
return false;
|
||||
}
|
||||
return !!(typeRegistry[name]);
|
||||
};
|
||||
exports.hasItem = hasItem;
|
||||
|
||||
/**
|
||||
* Gets the class for the given name and type.
|
||||
* @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {string|!Type<T>} type The type of the plugin.
|
||||
* (e.g. Field, Renderer)
|
||||
* @param {string} name The plugin's name. (Ex. field_angle, geras)
|
||||
* @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
|
||||
@@ -253,14 +267,15 @@ Blockly.registry.hasItem = function(type, name) {
|
||||
* null if none exists.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.getClass = function(type, name, opt_throwIfMissing) {
|
||||
const getClass = function(type, name, opt_throwIfMissing) {
|
||||
return /** @type {?function(new:T, ...?)} */ (
|
||||
Blockly.registry.getItem_(type, name, opt_throwIfMissing));
|
||||
getItem(type, name, opt_throwIfMissing));
|
||||
};
|
||||
exports.getClass = getClass;
|
||||
|
||||
/**
|
||||
* Gets the object for the given name and type.
|
||||
* @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {string|!Type<T>} type The type of the plugin.
|
||||
* (e.g. Category)
|
||||
* @param {string} name The plugin's name. (Ex. logic_category)
|
||||
* @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
|
||||
@@ -268,30 +283,30 @@ Blockly.registry.getClass = function(type, name, opt_throwIfMissing) {
|
||||
* @return {?T} The object with the given name and type or null if none exists.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.getObject = function(type, name, opt_throwIfMissing) {
|
||||
return /** @type {T} */ (
|
||||
Blockly.registry.getItem_(type, name, opt_throwIfMissing));
|
||||
const getObject = function(type, name, opt_throwIfMissing) {
|
||||
return /** @type {T} */ (getItem(type, name, opt_throwIfMissing));
|
||||
};
|
||||
exports.getObject = getObject;
|
||||
|
||||
/**
|
||||
* Gets the class from Blockly options for the given type.
|
||||
* This is used for plugins that override a built in feature. (e.g. Toolbox)
|
||||
* @param {!Blockly.registry.Type<T>} type The type of the plugin.
|
||||
* @param {!Blockly.Options} options The option object to check for the given
|
||||
* @param {!Type<T>} type The type of the plugin.
|
||||
* @param {!Options} options The option object to check for the given
|
||||
* plugin.
|
||||
* @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
|
||||
* are unable to find the plugin.
|
||||
* @return {?function(new:T, ...?)} The class for the plugin.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.registry.getClassFromOptions = function(type, options,
|
||||
opt_throwIfMissing) {
|
||||
var typeName = type.toString();
|
||||
var plugin = options.plugins[typeName] || Blockly.registry.DEFAULT;
|
||||
const getClassFromOptions = function(type, options, opt_throwIfMissing) {
|
||||
const typeName = type.toString();
|
||||
const plugin = options.plugins[typeName] || DEFAULT;
|
||||
|
||||
// If the user passed in a plugin class instead of a registered plugin name.
|
||||
if (typeof plugin == 'function') {
|
||||
return plugin;
|
||||
}
|
||||
return Blockly.registry.getClass(type, plugin, opt_throwIfMissing);
|
||||
return getClass(type, plugin, opt_throwIfMissing);
|
||||
};
|
||||
exports.getClassFromOptions = getClassFromOptions;
|
||||
|
||||
@@ -10,36 +10,40 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.RenderedConnection');
|
||||
goog.module('Blockly.RenderedConnection');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Connection');
|
||||
goog.require('Blockly.connectionTypes');
|
||||
goog.require('Blockly.internalConstants');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.deprecation');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.ConnectionDB');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const Connection = goog.require('Blockly.Connection');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ConnectionDB = goog.requireType('Blockly.ConnectionDB');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const connectionTypes = goog.require('Blockly.connectionTypes');
|
||||
const deprecation = goog.require('Blockly.utils.deprecation');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const internalConstants = goog.require('Blockly.internalConstants');
|
||||
const object = goog.require('Blockly.utils.object');
|
||||
const utils = goog.require('Blockly.utils');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a connection between blocks that may be rendered on screen.
|
||||
* @param {!Blockly.BlockSvg} source The block establishing this connection.
|
||||
* @param {!BlockSvg} source The block establishing this connection.
|
||||
* @param {number} type The type of the connection.
|
||||
* @extends {Blockly.Connection}
|
||||
* @extends {Connection}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.RenderedConnection = function(source, type) {
|
||||
Blockly.RenderedConnection.superClass_.constructor.call(this, source, type);
|
||||
const RenderedConnection = function(source, type) {
|
||||
RenderedConnection.superClass_.constructor.call(this, source, type);
|
||||
|
||||
/**
|
||||
* Connection database for connections of this type on the current workspace.
|
||||
* @const {!Blockly.ConnectionDB}
|
||||
* @const {!ConnectionDB}
|
||||
* @private
|
||||
*/
|
||||
this.db_ = source.workspace.connectionDBList[type];
|
||||
@@ -47,34 +51,33 @@ Blockly.RenderedConnection = function(source, type) {
|
||||
/**
|
||||
* Connection database for connections compatible with this type on the
|
||||
* current workspace.
|
||||
* @const {!Blockly.ConnectionDB}
|
||||
* @const {!ConnectionDB}
|
||||
* @private
|
||||
*/
|
||||
this.dbOpposite_ =
|
||||
source.workspace
|
||||
.connectionDBList[Blockly.internalConstants.OPPOSITE_TYPE[type]];
|
||||
source.workspace.connectionDBList[internalConstants.OPPOSITE_TYPE[type]];
|
||||
|
||||
/**
|
||||
* Workspace units, (0, 0) is top left of block.
|
||||
* @type {!Blockly.utils.Coordinate}
|
||||
* @type {!Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.offsetInBlock_ = new Blockly.utils.Coordinate(0, 0);
|
||||
this.offsetInBlock_ = new Coordinate(0, 0);
|
||||
|
||||
/**
|
||||
* Describes the state of this connection's tracked-ness.
|
||||
* @type {Blockly.RenderedConnection.TrackedState}
|
||||
* @type {RenderedConnection.TrackedState}
|
||||
* @private
|
||||
*/
|
||||
this.trackedState_ = Blockly.RenderedConnection.TrackedState.WILL_TRACK;
|
||||
this.trackedState_ = RenderedConnection.TrackedState.WILL_TRACK;
|
||||
|
||||
/**
|
||||
* Connection this connection connects to. Null if not connected.
|
||||
* @type {Blockly.RenderedConnection}
|
||||
* @type {RenderedConnection}
|
||||
*/
|
||||
this.targetConnection = null;
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.RenderedConnection, Blockly.Connection);
|
||||
object.inherits(RenderedConnection, Connection);
|
||||
|
||||
/**
|
||||
* Enum for different kinds of tracked states.
|
||||
@@ -88,7 +91,7 @@ Blockly.utils.object.inherits(Blockly.RenderedConnection, Blockly.Connection);
|
||||
* TRACKED means that this connection is currently being tracked.
|
||||
* @enum {number}
|
||||
*/
|
||||
Blockly.RenderedConnection.TrackedState = {
|
||||
RenderedConnection.TrackedState = {
|
||||
WILL_TRACK: -1,
|
||||
UNTRACKED: 0,
|
||||
TRACKED: 1
|
||||
@@ -100,65 +103,65 @@ Blockly.RenderedConnection.TrackedState = {
|
||||
* @override
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.dispose = function() {
|
||||
Blockly.RenderedConnection.superClass_.dispose.call(this);
|
||||
if (this.trackedState_ == Blockly.RenderedConnection.TrackedState.TRACKED) {
|
||||
RenderedConnection.prototype.dispose = function() {
|
||||
RenderedConnection.superClass_.dispose.call(this);
|
||||
if (this.trackedState_ == RenderedConnection.TrackedState.TRACKED) {
|
||||
this.db_.removeConnection(this, this.y);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the source block for this connection.
|
||||
* @return {!Blockly.BlockSvg} The source block.
|
||||
* @return {!BlockSvg} The source block.
|
||||
* @override
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.getSourceBlock = function() {
|
||||
return /** @type {!Blockly.BlockSvg} */ (
|
||||
Blockly.RenderedConnection.superClass_.getSourceBlock.call(this));
|
||||
RenderedConnection.prototype.getSourceBlock = function() {
|
||||
return /** @type {!BlockSvg} */ (
|
||||
RenderedConnection.superClass_.getSourceBlock.call(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the block that this connection connects to.
|
||||
* @return {?Blockly.BlockSvg} The connected block or null if none is connected.
|
||||
* @return {?BlockSvg} The connected block or null if none is connected.
|
||||
* @override
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.targetBlock = function() {
|
||||
return /** @type {Blockly.BlockSvg} */ (
|
||||
Blockly.RenderedConnection.superClass_.targetBlock.call(this));
|
||||
RenderedConnection.prototype.targetBlock = function() {
|
||||
return /** @type {BlockSvg} */ (
|
||||
RenderedConnection.superClass_.targetBlock.call(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the distance between this connection and another connection in
|
||||
* workspace units.
|
||||
* @param {!Blockly.Connection} otherConnection The other connection to measure
|
||||
* @param {!Connection} otherConnection The other connection to measure
|
||||
* the distance to.
|
||||
* @return {number} The distance between connections, in workspace units.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.distanceFrom = function(otherConnection) {
|
||||
var xDiff = this.x - otherConnection.x;
|
||||
var yDiff = this.y - otherConnection.y;
|
||||
RenderedConnection.prototype.distanceFrom = function(otherConnection) {
|
||||
const xDiff = this.x - otherConnection.x;
|
||||
const yDiff = this.y - otherConnection.y;
|
||||
return Math.sqrt(xDiff * xDiff + yDiff * yDiff);
|
||||
};
|
||||
|
||||
/**
|
||||
* Move the block(s) belonging to the connection to a point where they don't
|
||||
* visually interfere with the specified connection.
|
||||
* @param {!Blockly.Connection} staticConnection The connection to move away
|
||||
* @param {!Connection} staticConnection The connection to move away
|
||||
* from.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) {
|
||||
RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) {
|
||||
if (this.sourceBlock_.workspace.isDragging()) {
|
||||
// Don't move blocks around while the user is doing the same.
|
||||
return;
|
||||
}
|
||||
// Move the root block.
|
||||
var rootBlock = this.sourceBlock_.getRootBlock();
|
||||
let rootBlock = this.sourceBlock_.getRootBlock();
|
||||
if (rootBlock.isInFlyout) {
|
||||
// Don't move blocks around in a flyout.
|
||||
return;
|
||||
}
|
||||
var reverse = false;
|
||||
let reverse = false;
|
||||
if (!rootBlock.isMovable()) {
|
||||
// Can't bump an uneditable block away.
|
||||
// Check to see if the other block is movable.
|
||||
@@ -171,24 +174,21 @@ Blockly.RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) {
|
||||
reverse = true;
|
||||
}
|
||||
// Raise it to the top for extra visibility.
|
||||
var selected = Blockly.selected == rootBlock;
|
||||
const selected = Blockly.selected == rootBlock;
|
||||
selected || rootBlock.addSelect();
|
||||
var dx =
|
||||
(staticConnection.x + Blockly.internalConstants.SNAP_RADIUS +
|
||||
Math.floor(Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) -
|
||||
let dx = (staticConnection.x + internalConstants.SNAP_RADIUS +
|
||||
Math.floor(Math.random() * internalConstants.BUMP_RANDOMNESS)) -
|
||||
this.x;
|
||||
var dy =
|
||||
(staticConnection.y + Blockly.internalConstants.SNAP_RADIUS +
|
||||
Math.floor(Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) -
|
||||
let dy = (staticConnection.y + internalConstants.SNAP_RADIUS +
|
||||
Math.floor(Math.random() * internalConstants.BUMP_RANDOMNESS)) -
|
||||
this.y;
|
||||
if (reverse) {
|
||||
// When reversing a bump due to an uneditable block, bump up.
|
||||
dy = -dy;
|
||||
}
|
||||
if (rootBlock.RTL) {
|
||||
dx = (staticConnection.x - Blockly.internalConstants.SNAP_RADIUS -
|
||||
Math.floor(
|
||||
Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) -
|
||||
dx = (staticConnection.x - internalConstants.SNAP_RADIUS -
|
||||
Math.floor(Math.random() * internalConstants.BUMP_RANDOMNESS)) -
|
||||
this.x;
|
||||
}
|
||||
rootBlock.moveBy(dx, dy);
|
||||
@@ -200,12 +200,11 @@ Blockly.RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) {
|
||||
* @param {number} x New absolute x coordinate, in workspace coordinates.
|
||||
* @param {number} y New absolute y coordinate, in workspace coordinates.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.moveTo = function(x, y) {
|
||||
if (this.trackedState_ == Blockly.RenderedConnection.TrackedState.WILL_TRACK) {
|
||||
RenderedConnection.prototype.moveTo = function(x, y) {
|
||||
if (this.trackedState_ == RenderedConnection.TrackedState.WILL_TRACK) {
|
||||
this.db_.addConnection(this, y);
|
||||
this.trackedState_ = Blockly.RenderedConnection.TrackedState.TRACKED;
|
||||
} else if (this.trackedState_ == Blockly.RenderedConnection
|
||||
.TrackedState.TRACKED) {
|
||||
this.trackedState_ = RenderedConnection.TrackedState.TRACKED;
|
||||
} else if (this.trackedState_ == RenderedConnection.TrackedState.TRACKED) {
|
||||
this.db_.removeConnection(this, this.y);
|
||||
this.db_.addConnection(this, y);
|
||||
}
|
||||
@@ -218,19 +217,19 @@ Blockly.RenderedConnection.prototype.moveTo = function(x, y) {
|
||||
* @param {number} dx Change to x coordinate, in workspace units.
|
||||
* @param {number} dy Change to y coordinate, in workspace units.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.moveBy = function(dx, dy) {
|
||||
RenderedConnection.prototype.moveBy = function(dx, dy) {
|
||||
this.moveTo(this.x + dx, this.y + dy);
|
||||
};
|
||||
|
||||
/**
|
||||
* Move this connection to the location given by its offset within the block and
|
||||
* the location of the block's top left corner.
|
||||
* @param {!Blockly.utils.Coordinate} blockTL The location of the top left
|
||||
* @param {!Coordinate} blockTL The location of the top left
|
||||
* corner of the block, in workspace coordinates.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.moveToOffset = function(blockTL) {
|
||||
this.moveTo(blockTL.x + this.offsetInBlock_.x,
|
||||
blockTL.y + this.offsetInBlock_.y);
|
||||
RenderedConnection.prototype.moveToOffset = function(blockTL) {
|
||||
this.moveTo(
|
||||
blockTL.x + this.offsetInBlock_.x, blockTL.y + this.offsetInBlock_.y);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -238,17 +237,17 @@ Blockly.RenderedConnection.prototype.moveToOffset = function(blockTL) {
|
||||
* @param {number} x The new relative x, in workspace units.
|
||||
* @param {number} y The new relative y, in workspace units.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.setOffsetInBlock = function(x, y) {
|
||||
RenderedConnection.prototype.setOffsetInBlock = function(x, y) {
|
||||
this.offsetInBlock_.x = x;
|
||||
this.offsetInBlock_.y = y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the offset of this connection relative to the top left of its block.
|
||||
* @return {!Blockly.utils.Coordinate} The offset of the connection.
|
||||
* @return {!Coordinate} The offset of the connection.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.getOffsetInBlock = function() {
|
||||
RenderedConnection.prototype.getOffsetInBlock = function() {
|
||||
return this.offsetInBlock_;
|
||||
};
|
||||
|
||||
@@ -256,19 +255,19 @@ Blockly.RenderedConnection.prototype.getOffsetInBlock = function() {
|
||||
* Move the blocks on either side of this connection right next to each other.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.tighten = function() {
|
||||
var dx = this.targetConnection.x - this.x;
|
||||
var dy = this.targetConnection.y - this.y;
|
||||
RenderedConnection.prototype.tighten = function() {
|
||||
const dx = this.targetConnection.x - this.x;
|
||||
const dy = this.targetConnection.y - this.y;
|
||||
if (dx != 0 || dy != 0) {
|
||||
var block = this.targetBlock();
|
||||
var svgRoot = block.getSvgRoot();
|
||||
const block = this.targetBlock();
|
||||
const svgRoot = block.getSvgRoot();
|
||||
if (!svgRoot) {
|
||||
throw Error('block is not rendered.');
|
||||
}
|
||||
// Workspace coordinates.
|
||||
var xy = Blockly.utils.getRelativeXY(svgRoot);
|
||||
block.getSvgRoot().setAttribute('transform',
|
||||
'translate(' + (xy.x - dx) + ',' + (xy.y - dy) + ')');
|
||||
const xy = utils.getRelativeXY(svgRoot);
|
||||
block.getSvgRoot().setAttribute(
|
||||
'transform', 'translate(' + (xy.x - dx) + ',' + (xy.y - dy) + ')');
|
||||
block.moveConnections(-dx, -dy);
|
||||
}
|
||||
};
|
||||
@@ -277,47 +276,44 @@ Blockly.RenderedConnection.prototype.tighten = function() {
|
||||
* Find the closest compatible connection to this connection.
|
||||
* All parameters are in workspace units.
|
||||
* @param {number} maxLimit The maximum radius to another connection.
|
||||
* @param {!Blockly.utils.Coordinate} dxy Offset between this connection's location
|
||||
* @param {!Coordinate} dxy Offset between this connection's location
|
||||
* in the database and the current location (as a result of dragging).
|
||||
* @return {!{connection: ?Blockly.Connection, radius: number}} Contains two
|
||||
* @return {!{connection: ?Connection, radius: number}} Contains two
|
||||
* properties: 'connection' which is either another connection or null,
|
||||
* and 'radius' which is the distance.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.closest = function(maxLimit, dxy) {
|
||||
RenderedConnection.prototype.closest = function(maxLimit, dxy) {
|
||||
return this.dbOpposite_.searchForClosest(this, maxLimit, dxy);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add highlighting around this connection.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.highlight = function() {
|
||||
var steps;
|
||||
var sourceBlockSvg = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_);
|
||||
var renderConstants = sourceBlockSvg.workspace.getRenderer().getConstants();
|
||||
var shape = renderConstants.shapeFor(this);
|
||||
if (this.type == Blockly.connectionTypes.INPUT_VALUE ||
|
||||
this.type == Blockly.connectionTypes.OUTPUT_VALUE) {
|
||||
RenderedConnection.prototype.highlight = function() {
|
||||
let steps;
|
||||
const sourceBlockSvg = /** @type {!BlockSvg} */ (this.sourceBlock_);
|
||||
const renderConstants = sourceBlockSvg.workspace.getRenderer().getConstants();
|
||||
const shape = renderConstants.shapeFor(this);
|
||||
if (this.type == connectionTypes.INPUT_VALUE ||
|
||||
this.type == connectionTypes.OUTPUT_VALUE) {
|
||||
// Vertical line, puzzle tab, vertical line.
|
||||
var yLen = renderConstants.TAB_OFFSET_FROM_TOP;
|
||||
steps = Blockly.utils.svgPaths.moveBy(0, -yLen) +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', yLen) +
|
||||
shape.pathDown +
|
||||
Blockly.utils.svgPaths.lineOnAxis('v', yLen);
|
||||
const yLen = renderConstants.TAB_OFFSET_FROM_TOP;
|
||||
steps = utils.svgPaths.moveBy(0, -yLen) +
|
||||
utils.svgPaths.lineOnAxis('v', yLen) + shape.pathDown +
|
||||
utils.svgPaths.lineOnAxis('v', yLen);
|
||||
} else {
|
||||
var xLen =
|
||||
const xLen =
|
||||
renderConstants.NOTCH_OFFSET_LEFT - renderConstants.CORNER_RADIUS;
|
||||
// Horizontal line, notch, horizontal line.
|
||||
steps = Blockly.utils.svgPaths.moveBy(-xLen, 0) +
|
||||
Blockly.utils.svgPaths.lineOnAxis('h', xLen) +
|
||||
shape.pathLeft +
|
||||
Blockly.utils.svgPaths.lineOnAxis('h', xLen);
|
||||
steps = utils.svgPaths.moveBy(-xLen, 0) +
|
||||
utils.svgPaths.lineOnAxis('h', xLen) + shape.pathLeft +
|
||||
utils.svgPaths.lineOnAxis('h', xLen);
|
||||
}
|
||||
var xy = this.sourceBlock_.getRelativeToSurfaceXY();
|
||||
var x = this.x - xy.x;
|
||||
var y = this.y - xy.y;
|
||||
Blockly.Connection.highlightedPath_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATH,
|
||||
{
|
||||
const xy = this.sourceBlock_.getRelativeToSurfaceXY();
|
||||
const x = this.x - xy.x;
|
||||
const y = this.y - xy.y;
|
||||
Connection.highlightedPath_ = dom.createSvgElement(
|
||||
Svg.PATH, {
|
||||
'class': 'blocklyHighlightedConnectionPath',
|
||||
'd': steps,
|
||||
transform: 'translate(' + x + ',' + y + ')' +
|
||||
@@ -329,9 +325,9 @@ Blockly.RenderedConnection.prototype.highlight = function() {
|
||||
/**
|
||||
* Remove the highlighting around this connection.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.unhighlight = function() {
|
||||
Blockly.utils.dom.removeNode(Blockly.Connection.highlightedPath_);
|
||||
delete Blockly.Connection.highlightedPath_;
|
||||
RenderedConnection.prototype.unhighlight = function() {
|
||||
dom.removeNode(Connection.highlightedPath_);
|
||||
delete Connection.highlightedPath_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -339,11 +335,11 @@ Blockly.RenderedConnection.prototype.unhighlight = function() {
|
||||
* @param {boolean} doTracking If true, start tracking. If false, stop tracking.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.setTracking = function(doTracking) {
|
||||
if ((doTracking && this.trackedState_ ==
|
||||
Blockly.RenderedConnection.TrackedState.TRACKED) ||
|
||||
(!doTracking && this.trackedState_ ==
|
||||
Blockly.RenderedConnection.TrackedState.UNTRACKED)) {
|
||||
RenderedConnection.prototype.setTracking = function(doTracking) {
|
||||
if ((doTracking &&
|
||||
this.trackedState_ == RenderedConnection.TrackedState.TRACKED) ||
|
||||
(!doTracking &&
|
||||
this.trackedState_ == RenderedConnection.TrackedState.UNTRACKED)) {
|
||||
return;
|
||||
}
|
||||
if (this.sourceBlock_.isInFlyout) {
|
||||
@@ -352,13 +348,13 @@ Blockly.RenderedConnection.prototype.setTracking = function(doTracking) {
|
||||
}
|
||||
if (doTracking) {
|
||||
this.db_.addConnection(this, this.y);
|
||||
this.trackedState_ = Blockly.RenderedConnection.TrackedState.TRACKED;
|
||||
this.trackedState_ = RenderedConnection.TrackedState.TRACKED;
|
||||
return;
|
||||
}
|
||||
if (this.trackedState_ == Blockly.RenderedConnection.TrackedState.TRACKED) {
|
||||
if (this.trackedState_ == RenderedConnection.TrackedState.TRACKED) {
|
||||
this.db_.removeConnection(this, this.y);
|
||||
}
|
||||
this.trackedState_ = Blockly.RenderedConnection.TrackedState.UNTRACKED;
|
||||
this.trackedState_ = RenderedConnection.TrackedState.UNTRACKED;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -369,20 +365,20 @@ Blockly.RenderedConnection.prototype.setTracking = function(doTracking) {
|
||||
* Also closes down-stream icons/bubbles.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.stopTrackingAll = function() {
|
||||
RenderedConnection.prototype.stopTrackingAll = function() {
|
||||
this.setTracking(false);
|
||||
if (this.targetConnection) {
|
||||
var blocks = this.targetBlock().getDescendants(false);
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
var block = blocks[i];
|
||||
const blocks = this.targetBlock().getDescendants(false);
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
const block = blocks[i];
|
||||
// Stop tracking connections of all children.
|
||||
var connections = block.getConnections_(true);
|
||||
for (var j = 0; j < connections.length; j++) {
|
||||
const connections = block.getConnections_(true);
|
||||
for (let j = 0; j < connections.length; j++) {
|
||||
connections[j].setTracking(false);
|
||||
}
|
||||
// Close all bubbles of all children.
|
||||
var icons = block.getIcons();
|
||||
for (var j = 0; j < icons.length; j++) {
|
||||
const icons = block.getIcons();
|
||||
for (let j = 0; j < icons.length; j++) {
|
||||
icons[j].setVisible(false);
|
||||
}
|
||||
}
|
||||
@@ -392,23 +388,23 @@ Blockly.RenderedConnection.prototype.stopTrackingAll = function() {
|
||||
/**
|
||||
* Start tracking this connection, as well as all down-stream connections on
|
||||
* any block attached to this connection. This happens when a block is expanded.
|
||||
* @return {!Array<!Blockly.Block>} List of blocks to render.
|
||||
* @return {!Array<!Block>} List of blocks to render.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.startTrackingAll = function() {
|
||||
RenderedConnection.prototype.startTrackingAll = function() {
|
||||
this.setTracking(true);
|
||||
// All blocks that are not tracked must start tracking before any
|
||||
// rendering takes place, since rendering requires knowing the dimensions
|
||||
// of lower blocks. Also, since rendering a block renders all its parents,
|
||||
// we only need to render the leaf nodes.
|
||||
var renderList = [];
|
||||
if (this.type != Blockly.connectionTypes.INPUT_VALUE &&
|
||||
this.type != Blockly.connectionTypes.NEXT_STATEMENT) {
|
||||
const renderList = [];
|
||||
if (this.type != connectionTypes.INPUT_VALUE &&
|
||||
this.type != connectionTypes.NEXT_STATEMENT) {
|
||||
// Only spider down.
|
||||
return renderList;
|
||||
}
|
||||
var block = this.targetBlock();
|
||||
const block = this.targetBlock();
|
||||
if (block) {
|
||||
var connections;
|
||||
let connections;
|
||||
if (block.isCollapsed()) {
|
||||
// This block should only be partially revealed since it is collapsed.
|
||||
connections = [];
|
||||
@@ -419,7 +415,7 @@ Blockly.RenderedConnection.prototype.startTrackingAll = function() {
|
||||
// Show all connections of this block.
|
||||
connections = block.getConnections_(true);
|
||||
}
|
||||
for (var i = 0; i < connections.length; i++) {
|
||||
for (let i = 0; i < connections.length; i++) {
|
||||
renderList.push.apply(renderList, connections[i].startTrackingAll());
|
||||
}
|
||||
if (!renderList.length) {
|
||||
@@ -432,62 +428,60 @@ Blockly.RenderedConnection.prototype.startTrackingAll = function() {
|
||||
|
||||
/**
|
||||
* Check if the two connections can be dragged to connect to each other.
|
||||
* @param {!Blockly.Connection} candidate A nearby connection to check.
|
||||
* @param {!Connection} candidate A nearby connection to check.
|
||||
* @param {number=} maxRadius The maximum radius allowed for connections, in
|
||||
* workspace units.
|
||||
* @return {boolean} True if the connection is allowed, false otherwise.
|
||||
* @deprecated July 2020
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.isConnectionAllowed = function(candidate,
|
||||
maxRadius) {
|
||||
Blockly.utils.deprecation.warn(
|
||||
'RenderedConnection.prototype.isConnectionAllowed',
|
||||
'July 2020',
|
||||
RenderedConnection.prototype.isConnectionAllowed = function(
|
||||
candidate, maxRadius) {
|
||||
deprecation.warn(
|
||||
'RenderedConnection.prototype.isConnectionAllowed', 'July 2020',
|
||||
'July 2021',
|
||||
'Blockly.Workspace.prototype.getConnectionChecker().canConnect');
|
||||
if (this.distanceFrom(candidate) > maxRadius) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Blockly.RenderedConnection.superClass_.isConnectionAllowed.call(this,
|
||||
candidate);
|
||||
return RenderedConnection.superClass_.isConnectionAllowed.call(
|
||||
this, candidate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Behavior after a connection attempt fails.
|
||||
* Bumps this connection away from the other connection. Called when an
|
||||
* attempted connection fails.
|
||||
* @param {!Blockly.Connection} otherConnection Connection that this connection
|
||||
* @param {!Connection} otherConnection Connection that this connection
|
||||
* failed to connect to.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.onFailedConnect =
|
||||
function(otherConnection) {
|
||||
var block = this.getSourceBlock();
|
||||
if (Blockly.Events.recordUndo) {
|
||||
var group = Blockly.Events.getGroup();
|
||||
setTimeout(function() {
|
||||
if (!block.isDisposed() && !block.getParent()) {
|
||||
Blockly.Events.setGroup(group);
|
||||
this.bumpAwayFrom(otherConnection);
|
||||
Blockly.Events.setGroup(false);
|
||||
}
|
||||
}.bind(this), Blockly.internalConstants.BUMP_DELAY);
|
||||
RenderedConnection.prototype.onFailedConnect = function(otherConnection) {
|
||||
const block = this.getSourceBlock();
|
||||
if (Events.recordUndo) {
|
||||
const group = Events.getGroup();
|
||||
setTimeout(function() {
|
||||
if (!block.isDisposed() && !block.getParent()) {
|
||||
Events.setGroup(group);
|
||||
this.bumpAwayFrom(otherConnection);
|
||||
Events.setGroup(false);
|
||||
}
|
||||
};
|
||||
}.bind(this), internalConstants.BUMP_DELAY);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Disconnect two blocks that are connected by this connection.
|
||||
* @param {!Blockly.Block} parentBlock The superior block.
|
||||
* @param {!Blockly.Block} childBlock The inferior block.
|
||||
* @param {!Block} parentBlock The superior block.
|
||||
* @param {!Block} childBlock The inferior block.
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock,
|
||||
childBlock) {
|
||||
Blockly.RenderedConnection.superClass_.disconnectInternal_.call(this,
|
||||
parentBlock, childBlock);
|
||||
RenderedConnection.prototype.disconnectInternal_ = function(
|
||||
parentBlock, childBlock) {
|
||||
RenderedConnection.superClass_.disconnectInternal_.call(
|
||||
this, parentBlock, childBlock);
|
||||
// Rerender the parent so that it may reflow.
|
||||
if (parentBlock.rendered) {
|
||||
parentBlock.render();
|
||||
@@ -506,9 +500,9 @@ Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock,
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.respawnShadow_ = function() {
|
||||
Blockly.RenderedConnection.superClass_.respawnShadow_.call(this);
|
||||
var blockShadow = this.targetBlock();
|
||||
RenderedConnection.prototype.respawnShadow_ = function() {
|
||||
RenderedConnection.superClass_.respawnShadow_.call(this);
|
||||
const blockShadow = this.targetBlock();
|
||||
if (!blockShadow) {
|
||||
// This connection must not have a shadowDom_.
|
||||
return;
|
||||
@@ -516,7 +510,7 @@ Blockly.RenderedConnection.prototype.respawnShadow_ = function() {
|
||||
blockShadow.initSvg();
|
||||
blockShadow.render(false);
|
||||
|
||||
var parentBlock = this.getSourceBlock();
|
||||
const parentBlock = this.getSourceBlock();
|
||||
if (parentBlock.rendered) {
|
||||
parentBlock.render();
|
||||
}
|
||||
@@ -527,27 +521,27 @@ Blockly.RenderedConnection.prototype.respawnShadow_ = function() {
|
||||
* Type checking does not apply, since this function is used for bumping.
|
||||
* @param {number} maxLimit The maximum radius to another connection, in
|
||||
* workspace units.
|
||||
* @return {!Array<!Blockly.Connection>} List of connections.
|
||||
* @return {!Array<!Connection>} List of connections.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.neighbours = function(maxLimit) {
|
||||
RenderedConnection.prototype.neighbours = function(maxLimit) {
|
||||
return this.dbOpposite_.getNeighbours(this, maxLimit);
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect two connections together. This is the connection on the superior
|
||||
* block. Rerender blocks as needed.
|
||||
* @param {!Blockly.Connection} childConnection Connection on inferior block.
|
||||
* @param {!Connection} childConnection Connection on inferior block.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.connect_ = function(childConnection) {
|
||||
Blockly.RenderedConnection.superClass_.connect_.call(this, childConnection);
|
||||
RenderedConnection.prototype.connect_ = function(childConnection) {
|
||||
RenderedConnection.superClass_.connect_.call(this, childConnection);
|
||||
|
||||
var parentConnection = this;
|
||||
var parentBlock = parentConnection.getSourceBlock();
|
||||
var childBlock = childConnection.getSourceBlock();
|
||||
var parentRendered = parentBlock.rendered;
|
||||
var childRendered = childBlock.rendered;
|
||||
const parentConnection = this;
|
||||
const parentBlock = parentConnection.getSourceBlock();
|
||||
const childBlock = childConnection.getSourceBlock();
|
||||
const parentRendered = parentBlock.rendered;
|
||||
const childRendered = childBlock.rendered;
|
||||
|
||||
if (parentRendered) {
|
||||
parentBlock.updateDisabled();
|
||||
@@ -556,8 +550,8 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) {
|
||||
childBlock.updateDisabled();
|
||||
}
|
||||
if (parentRendered && childRendered) {
|
||||
if (parentConnection.type == Blockly.connectionTypes.NEXT_STATEMENT ||
|
||||
parentConnection.type == Blockly.connectionTypes.PREVIOUS_STATEMENT) {
|
||||
if (parentConnection.type == connectionTypes.NEXT_STATEMENT ||
|
||||
parentConnection.type == connectionTypes.PREVIOUS_STATEMENT) {
|
||||
// Child block may need to square off its corners if it is in a stack.
|
||||
// Rendering a child will render its parent.
|
||||
childBlock.render();
|
||||
@@ -569,9 +563,9 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) {
|
||||
}
|
||||
|
||||
// The input the child block is connected to (if any).
|
||||
var parentInput = parentBlock.getInputWithBlock(childBlock);
|
||||
const parentInput = parentBlock.getInputWithBlock(childBlock);
|
||||
if (parentInput) {
|
||||
var visible = parentInput.isVisible();
|
||||
const visible = parentInput.isVisible();
|
||||
childBlock.getSvgRoot().style.display = visible ? 'block' : 'none';
|
||||
}
|
||||
};
|
||||
@@ -580,14 +574,17 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) {
|
||||
* Function to be called when this connection's compatible types have changed.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.onCheckChanged_ = function() {
|
||||
RenderedConnection.prototype.onCheckChanged_ = function() {
|
||||
// The new value type may not be compatible with the existing connection.
|
||||
if (this.isConnected() && (!this.targetConnection ||
|
||||
!this.getConnectionChecker().canConnect(
|
||||
this, this.targetConnection, false))) {
|
||||
var child = this.isSuperior() ? this.targetBlock() : this.sourceBlock_;
|
||||
if (this.isConnected() &&
|
||||
(!this.targetConnection ||
|
||||
!this.getConnectionChecker().canConnect(
|
||||
this, this.targetConnection, false))) {
|
||||
const child = this.isSuperior() ? this.targetBlock() : this.sourceBlock_;
|
||||
child.unplug();
|
||||
// Bump away.
|
||||
this.sourceBlock_.bumpNeighbours();
|
||||
}
|
||||
};
|
||||
|
||||
exports = RenderedConnection;
|
||||
|
||||
@@ -10,19 +10,20 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.blockRendering.ConstantProvider');
|
||||
goog.module('Blockly.blockRendering.ConstantProvider');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.connectionTypes');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.colour');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
goog.require('Blockly.utils.svgPaths');
|
||||
goog.require('Blockly.utils.userAgent');
|
||||
|
||||
goog.requireType('Blockly.blockRendering.Debug');
|
||||
goog.requireType('Blockly.RenderedConnection');
|
||||
goog.requireType('Blockly.Theme');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const RenderedConnection = goog.requireType('Blockly.RenderedConnection');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Theme = goog.requireType('Blockly.Theme');
|
||||
const colour = goog.require('Blockly.utils.colour');
|
||||
const connectionTypes = goog.require('Blockly.connectionTypes');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const svgPaths = goog.require('Blockly.utils.svgPaths');
|
||||
const userAgent = goog.require('Blockly.utils.userAgent');
|
||||
const utils = goog.require('Blockly.utils');
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,8 +31,7 @@ goog.requireType('Blockly.Theme');
|
||||
* @constructor
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider = function() {
|
||||
|
||||
const ConstantProvider = function() {
|
||||
/**
|
||||
* The size of an empty spacer.
|
||||
* @type {number}
|
||||
@@ -214,15 +214,15 @@ Blockly.blockRendering.ConstantProvider = function() {
|
||||
this.EXTERNAL_VALUE_INPUT_PADDING = 2;
|
||||
|
||||
/**
|
||||
* The height of an empty statement input. Note that in the old rendering this
|
||||
* varies slightly depending on whether the block has external or inline inputs.
|
||||
* In the new rendering this is consistent. It seems unlikely that the old
|
||||
* behaviour was intentional.
|
||||
* The height of an empty statement input. Note that in the old rendering
|
||||
* this varies slightly depending on whether the block has external or inline
|
||||
* inputs. In the new rendering this is consistent. It seems unlikely that
|
||||
* the old behaviour was intentional.
|
||||
* @type {number}
|
||||
*/
|
||||
this.EMPTY_STATEMENT_INPUT_HEIGHT = this.MIN_BLOCK_HEIGHT;
|
||||
|
||||
this.START_POINT = Blockly.utils.svgPaths.moveBy(0, 0);
|
||||
this.START_POINT = svgPaths.moveBy(0, 0);
|
||||
|
||||
/**
|
||||
* Height of SVG path for jagged teeth at the end of collapsed blocks.
|
||||
@@ -303,8 +303,7 @@ Blockly.blockRendering.ConstantProvider = function() {
|
||||
* A field's text element's dominant baseline.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.FIELD_TEXT_BASELINE_CENTER =
|
||||
!Blockly.utils.userAgent.IE && !Blockly.utils.userAgent.EDGE;
|
||||
this.FIELD_TEXT_BASELINE_CENTER = !userAgent.IE && !userAgent.EDGE;
|
||||
|
||||
/**
|
||||
* A dropdown field's border rect height.
|
||||
@@ -349,17 +348,17 @@ Blockly.blockRendering.ConstantProvider = function() {
|
||||
* @type {string}
|
||||
*/
|
||||
this.FIELD_DROPDOWN_SVG_ARROW_DATAURI =
|
||||
'data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllci' +
|
||||
'AxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMi43MSIgaG' +
|
||||
'VpZ2h0PSI4Ljc5IiB2aWV3Qm94PSIwIDAgMTIuNzEgOC43OSI+PHRpdGxlPmRyb3Bkb3duLW' +
|
||||
'Fycm93PC90aXRsZT48ZyBvcGFjaXR5PSIwLjEiPjxwYXRoIGQ9Ik0xMi43MSwyLjQ0QTIuND' +
|
||||
'EsMi40MSwwLDAsMSwxMiw0LjE2TDguMDgsOC4wOGEyLjQ1LDIuNDUsMCwwLDEtMy40NSwwTD' +
|
||||
'AuNzIsNC4xNkEyLjQyLDIuNDIsMCwwLDEsMCwyLjQ0LDIuNDgsMi40OCwwLDAsMSwuNzEuNz' +
|
||||
'FDMSwwLjQ3LDEuNDMsMCw2LjM2LDBTMTEuNzUsMC40NiwxMiwuNzFBMi40NCwyLjQ0LDAsMC' +
|
||||
'wxLDEyLjcxLDIuNDRaIiBmaWxsPSIjMjMxZjIwIi8+PC9nPjxwYXRoIGQ9Ik02LjM2LDcuNz' +
|
||||
'lhMS40MywxLjQzLDAsMCwxLTEtLjQyTDEuNDIsMy40NWExLjQ0LDEuNDQsMCwwLDEsMC0yYz' +
|
||||
'AuNTYtLjU2LDkuMzEtMC41Niw5Ljg3LDBhMS40NCwxLjQ0LDAsMCwxLDAsMkw3LjM3LDcuMz' +
|
||||
'dBMS40MywxLjQzLDAsMCwxLDYuMzYsNy43OVoiIGZpbGw9IiNmZmYiLz48L3N2Zz4=';
|
||||
'data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllci' +
|
||||
'AxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMi43MSIgaG' +
|
||||
'VpZ2h0PSI4Ljc5IiB2aWV3Qm94PSIwIDAgMTIuNzEgOC43OSI+PHRpdGxlPmRyb3Bkb3duLW' +
|
||||
'Fycm93PC90aXRsZT48ZyBvcGFjaXR5PSIwLjEiPjxwYXRoIGQ9Ik0xMi43MSwyLjQ0QTIuND' +
|
||||
'EsMi40MSwwLDAsMSwxMiw0LjE2TDguMDgsOC4wOGEyLjQ1LDIuNDUsMCwwLDEtMy40NSwwTD' +
|
||||
'AuNzIsNC4xNkEyLjQyLDIuNDIsMCwwLDEsMCwyLjQ0LDIuNDgsMi40OCwwLDAsMSwuNzEuNz' +
|
||||
'FDMSwwLjQ3LDEuNDMsMCw2LjM2LDBTMTEuNzUsMC40NiwxMiwuNzFBMi40NCwyLjQ0LDAsMC' +
|
||||
'wxLDEyLjcxLDIuNDRaIiBmaWxsPSIjMjMxZjIwIi8+PC9nPjxwYXRoIGQ9Ik02LjM2LDcuNz' +
|
||||
'lhMS40MywxLjQzLDAsMCwxLTEtLjQyTDEuNDIsMy40NWExLjQ0LDEuNDQsMCwwLDEsMC0yYz' +
|
||||
'AuNTYtLjU2LDkuMzEtMC41Niw5Ljg3LDBhMS40NCwxLjQ0LDAsMCwxLDAsMkw3LjM3LDcuMz' +
|
||||
'dBMS40MywxLjQzLDAsMCwxLDYuMzYsNy43OVoiIGZpbGw9IiNmZmYiLz48L3N2Zz4=';
|
||||
|
||||
/**
|
||||
* Whether or not to show a box shadow around the widget div. This is only a
|
||||
@@ -401,6 +400,14 @@ Blockly.blockRendering.ConstantProvider = function() {
|
||||
*/
|
||||
this.randomIdentifier = String(Math.random()).substring(2);
|
||||
|
||||
/**
|
||||
* The defs tag that contains all filters and patterns for this Blockly
|
||||
* instance.
|
||||
* @type {?SVGElement}
|
||||
* @private
|
||||
*/
|
||||
this.defs_ = null;
|
||||
|
||||
/**
|
||||
* The ID of the emboss filter, or the empty string if no filter is set.
|
||||
* @type {string}
|
||||
@@ -525,18 +532,14 @@ Blockly.blockRendering.ConstantProvider = function() {
|
||||
* Enum for connection shapes.
|
||||
* @enum {number}
|
||||
*/
|
||||
this.SHAPES = {
|
||||
PUZZLE: 1,
|
||||
NOTCH: 2
|
||||
};
|
||||
this.SHAPES = {PUZZLE: 1, NOTCH: 2};
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize shape objects based on the constants set in the constructor.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.init = function() {
|
||||
|
||||
ConstantProvider.prototype.init = function() {
|
||||
/**
|
||||
* An object containing sizing and path information about collapsed block
|
||||
* indicators.
|
||||
@@ -577,21 +580,19 @@ Blockly.blockRendering.ConstantProvider.prototype.init = function() {
|
||||
|
||||
/**
|
||||
* Refresh constants properties that depend on the theme.
|
||||
* @param {!Blockly.Theme} theme The current workspace theme.
|
||||
* @param {!Theme} theme The current workspace theme.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.setTheme = function(
|
||||
theme) {
|
||||
|
||||
ConstantProvider.prototype.setTheme = function(theme) {
|
||||
/**
|
||||
* The block styles map.
|
||||
* @type {Object<string, !Blockly.Theme.BlockStyle>}
|
||||
* @type {Object<string, !Theme.BlockStyle>}
|
||||
* @package
|
||||
*/
|
||||
this.blockStyles = Object.create(null);
|
||||
|
||||
var blockStyles = theme.blockStyles;
|
||||
for (var key in blockStyles) {
|
||||
const blockStyles = theme.blockStyles;
|
||||
for (const key in blockStyles) {
|
||||
this.blockStyles[key] = this.validatedBlockStyle_(blockStyles[key]);
|
||||
}
|
||||
|
||||
@@ -600,39 +601,38 @@ Blockly.blockRendering.ConstantProvider.prototype.setTheme = function(
|
||||
|
||||
/**
|
||||
* Sets dynamic properties that depend on other values or theme properties.
|
||||
* @param {!Blockly.Theme} theme The current workspace theme.
|
||||
* @param {!Theme} theme The current workspace theme.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.setDynamicProperties_ =
|
||||
function(theme) {
|
||||
/* eslint-disable indent */
|
||||
ConstantProvider.prototype.setDynamicProperties_ = function(theme) {
|
||||
this.setFontConstants_(theme);
|
||||
this.setComponentConstants_(theme);
|
||||
|
||||
this.ADD_START_HATS = theme.startHats != null ? theme.startHats :
|
||||
this.ADD_START_HATS;
|
||||
}; /* eslint-enable indent */
|
||||
this.ADD_START_HATS =
|
||||
theme.startHats != null ? theme.startHats : this.ADD_START_HATS;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set constants related to fonts.
|
||||
* @param {!Blockly.Theme} theme The current workspace theme.
|
||||
* @param {!Theme} theme The current workspace theme.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.setFontConstants_ = function(
|
||||
theme) {
|
||||
ConstantProvider.prototype.setFontConstants_ = function(theme) {
|
||||
this.FIELD_TEXT_FONTFAMILY =
|
||||
theme.fontStyle && theme.fontStyle['family'] != undefined ?
|
||||
theme.fontStyle['family'] : this.FIELD_TEXT_FONTFAMILY;
|
||||
theme.fontStyle['family'] :
|
||||
this.FIELD_TEXT_FONTFAMILY;
|
||||
this.FIELD_TEXT_FONTWEIGHT =
|
||||
theme.fontStyle && theme.fontStyle['weight'] != undefined ?
|
||||
theme.fontStyle['weight'] : this.FIELD_TEXT_FONTWEIGHT;
|
||||
theme.fontStyle['weight'] :
|
||||
this.FIELD_TEXT_FONTWEIGHT;
|
||||
this.FIELD_TEXT_FONTSIZE =
|
||||
theme.fontStyle && theme.fontStyle['size'] != undefined ?
|
||||
theme.fontStyle['size'] : this.FIELD_TEXT_FONTSIZE;
|
||||
theme.fontStyle['size'] :
|
||||
this.FIELD_TEXT_FONTSIZE;
|
||||
|
||||
var fontMetrics = Blockly.utils.dom.measureFontMetrics('Hg',
|
||||
this.FIELD_TEXT_FONTSIZE + 'pt',
|
||||
this.FIELD_TEXT_FONTWEIGHT,
|
||||
const fontMetrics = dom.measureFontMetrics(
|
||||
'Hg', this.FIELD_TEXT_FONTSIZE + 'pt', this.FIELD_TEXT_FONTWEIGHT,
|
||||
this.FIELD_TEXT_FONTFAMILY);
|
||||
|
||||
this.FIELD_TEXT_HEIGHT = fontMetrics.height;
|
||||
@@ -641,68 +641,60 @@ Blockly.blockRendering.ConstantProvider.prototype.setFontConstants_ = function(
|
||||
|
||||
/**
|
||||
* Set constants from a theme's component styles.
|
||||
* @param {!Blockly.Theme} theme The current workspace theme.
|
||||
* @param {!Theme} theme The current workspace theme.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.setComponentConstants_ =
|
||||
function(theme) {
|
||||
/* eslint-disable indent */
|
||||
this.CURSOR_COLOUR = theme.getComponentStyle('cursorColour') ||
|
||||
this.CURSOR_COLOUR;
|
||||
this.MARKER_COLOUR = theme.getComponentStyle('markerColour') ||
|
||||
this.MARKER_COLOUR;
|
||||
ConstantProvider.prototype.setComponentConstants_ = function(theme) {
|
||||
this.CURSOR_COLOUR =
|
||||
theme.getComponentStyle('cursorColour') || this.CURSOR_COLOUR;
|
||||
this.MARKER_COLOUR =
|
||||
theme.getComponentStyle('markerColour') || this.MARKER_COLOUR;
|
||||
this.INSERTION_MARKER_COLOUR =
|
||||
theme.getComponentStyle('insertionMarkerColour') ||
|
||||
this.INSERTION_MARKER_COLOUR;
|
||||
theme.getComponentStyle('insertionMarkerColour') ||
|
||||
this.INSERTION_MARKER_COLOUR;
|
||||
this.INSERTION_MARKER_OPACITY =
|
||||
Number(theme.getComponentStyle('insertionMarkerOpacity')) ||
|
||||
this.INSERTION_MARKER_OPACITY;
|
||||
}; /* eslint-enable indent */
|
||||
Number(theme.getComponentStyle('insertionMarkerOpacity')) ||
|
||||
this.INSERTION_MARKER_OPACITY;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get or create a block style based on a single colour value. Generate a name
|
||||
* for the style based on the colour.
|
||||
* @param {string} colour #RRGGBB colour string.
|
||||
* @return {{style: !Blockly.Theme.BlockStyle, name: string}} An object
|
||||
* @return {{style: !Theme.BlockStyle, name: string}} An object
|
||||
* containing the style and an autogenerated name for that style.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.getBlockStyleForColour =
|
||||
function(colour) {
|
||||
/* eslint-disable indent */
|
||||
var name = 'auto_' + colour;
|
||||
ConstantProvider.prototype.getBlockStyleForColour = function(colour) {
|
||||
const name = 'auto_' + colour;
|
||||
if (!this.blockStyles[name]) {
|
||||
this.blockStyles[name] = this.createBlockStyle_(colour);
|
||||
}
|
||||
return {style: this.blockStyles[name], name: name};
|
||||
}; /* eslint-enable indent */
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the BlockStyle for the given block style name.
|
||||
* @param {?string} blockStyleName The name of the block style.
|
||||
* @return {!Blockly.Theme.BlockStyle} The named block style, or a default style
|
||||
* @return {!Theme.BlockStyle} The named block style, or a default style
|
||||
* if no style with the given name was found.
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.getBlockStyle = function(
|
||||
blockStyleName) {
|
||||
ConstantProvider.prototype.getBlockStyle = function(blockStyleName) {
|
||||
return this.blockStyles[blockStyleName || ''] ||
|
||||
(blockStyleName && blockStyleName.indexOf('auto_') == 0 ?
|
||||
this.getBlockStyleForColour(blockStyleName.substring(5)).style :
|
||||
this.createBlockStyle_('#000000'));
|
||||
this.getBlockStyleForColour(blockStyleName.substring(5)).style :
|
||||
this.createBlockStyle_('#000000'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a block style object based on the given colour.
|
||||
* @param {string} colour #RRGGBB colour string.
|
||||
* @return {!Blockly.Theme.BlockStyle} A populated block style based on the
|
||||
* @return {!Theme.BlockStyle} A populated block style based on the
|
||||
* given colour.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.createBlockStyle_ = function(
|
||||
colour) {
|
||||
return this.validatedBlockStyle_({
|
||||
'colourPrimary': colour
|
||||
});
|
||||
ConstantProvider.prototype.createBlockStyle_ = function(colour) {
|
||||
return this.validatedBlockStyle_({'colourPrimary': colour});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -715,56 +707,49 @@ Blockly.blockRendering.ConstantProvider.prototype.createBlockStyle_ = function(
|
||||
* hat:(string|undefined)
|
||||
* }} blockStyle A full or partial block style object.
|
||||
|
||||
* @return {!Blockly.Theme.BlockStyle} A full block style object, with all
|
||||
* @return {!Theme.BlockStyle} A full block style object, with all
|
||||
* required properties populated.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.validatedBlockStyle_ =
|
||||
function(blockStyle) {
|
||||
/* eslint-disable indent */
|
||||
ConstantProvider.prototype.validatedBlockStyle_ = function(blockStyle) {
|
||||
// Make a new object with all of the same properties.
|
||||
var valid = /** @type {!Blockly.Theme.BlockStyle} */ ({});
|
||||
const valid = /** @type {!Theme.BlockStyle} */ ({});
|
||||
if (blockStyle) {
|
||||
Blockly.utils.object.mixin(valid, blockStyle);
|
||||
utils.object.mixin(valid, blockStyle);
|
||||
}
|
||||
// Validate required properties.
|
||||
var parsedColour = Blockly.utils.parseBlockColour(
|
||||
valid['colourPrimary'] || '#000');
|
||||
const parsedColour = utils.parseBlockColour(valid['colourPrimary'] || '#000');
|
||||
valid.colourPrimary = parsedColour.hex;
|
||||
valid.colourSecondary = valid['colourSecondary'] ?
|
||||
Blockly.utils.parseBlockColour(valid['colourSecondary']).hex :
|
||||
utils.parseBlockColour(valid['colourSecondary']).hex :
|
||||
this.generateSecondaryColour_(valid.colourPrimary);
|
||||
valid.colourTertiary = valid['colourTertiary'] ?
|
||||
Blockly.utils.parseBlockColour(valid['colourTertiary']).hex :
|
||||
utils.parseBlockColour(valid['colourTertiary']).hex :
|
||||
this.generateTertiaryColour_(valid.colourPrimary);
|
||||
|
||||
valid.hat = valid['hat'] || '';
|
||||
return valid;
|
||||
}; /* eslint-enable indent */
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a secondary colour from the passed in primary colour.
|
||||
* @param {string} colour Primary colour.
|
||||
* @param {string} inputColour Primary colour.
|
||||
* @return {string} The generated secondary colour.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.generateSecondaryColour_ =
|
||||
function(colour) {
|
||||
/* eslint-disable indent */
|
||||
return Blockly.utils.colour.blend('#fff', colour, 0.6) || colour;
|
||||
}; /* eslint-enable indent */
|
||||
ConstantProvider.prototype.generateSecondaryColour_ = function(inputColour) {
|
||||
return colour.blend('#fff', inputColour, 0.6) || inputColour;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a tertiary colour from the passed in primary colour.
|
||||
* @param {string} colour Primary colour.
|
||||
* @param {string} inputColour Primary colour.
|
||||
* @return {string} The generated tertiary colour.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.generateTertiaryColour_ =
|
||||
function(colour) {
|
||||
/* eslint-disable indent */
|
||||
return Blockly.utils.colour.blend('#fff', colour, 0.3) || colour;
|
||||
}; /* eslint-enable indent */
|
||||
ConstantProvider.prototype.generateTertiaryColour_ = function(inputColour) {
|
||||
return colour.blend('#fff', inputColour, 0.3) || inputColour;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -772,15 +757,15 @@ Blockly.blockRendering.ConstantProvider.prototype.generateTertiaryColour_ =
|
||||
* Delete all DOM elements that this provider created.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.dispose = function() {
|
||||
ConstantProvider.prototype.dispose = function() {
|
||||
if (this.embossFilter_) {
|
||||
Blockly.utils.dom.removeNode(this.embossFilter_);
|
||||
dom.removeNode(this.embossFilter_);
|
||||
}
|
||||
if (this.disabledPattern_) {
|
||||
Blockly.utils.dom.removeNode(this.disabledPattern_);
|
||||
dom.removeNode(this.disabledPattern_);
|
||||
}
|
||||
if (this.debugFilter_) {
|
||||
Blockly.utils.dom.removeNode(this.debugFilter_);
|
||||
dom.removeNode(this.debugFilter_);
|
||||
}
|
||||
this.cssNode_ = null;
|
||||
};
|
||||
@@ -790,22 +775,15 @@ Blockly.blockRendering.ConstantProvider.prototype.dispose = function() {
|
||||
* collapsed block indicators.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.makeJaggedTeeth = function() {
|
||||
var height = this.JAGGED_TEETH_HEIGHT;
|
||||
var width = this.JAGGED_TEETH_WIDTH;
|
||||
ConstantProvider.prototype.makeJaggedTeeth = function() {
|
||||
const height = this.JAGGED_TEETH_HEIGHT;
|
||||
const width = this.JAGGED_TEETH_WIDTH;
|
||||
|
||||
var mainPath =
|
||||
Blockly.utils.svgPaths.line(
|
||||
[
|
||||
Blockly.utils.svgPaths.point(width, height / 4),
|
||||
Blockly.utils.svgPaths.point(-width * 2, height / 2),
|
||||
Blockly.utils.svgPaths.point(width, height / 4)
|
||||
]);
|
||||
return {
|
||||
height: height,
|
||||
width: width,
|
||||
path: mainPath
|
||||
};
|
||||
const mainPath = svgPaths.line([
|
||||
svgPaths.point(width, height / 4), svgPaths.point(-width * 2, height / 2),
|
||||
svgPaths.point(width, height / 4)
|
||||
]);
|
||||
return {height: height, width: width, path: mainPath};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -813,22 +791,15 @@ Blockly.blockRendering.ConstantProvider.prototype.makeJaggedTeeth = function() {
|
||||
* start hats.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.makeStartHat = function() {
|
||||
var height = this.START_HAT_HEIGHT;
|
||||
var width = this.START_HAT_WIDTH;
|
||||
ConstantProvider.prototype.makeStartHat = function() {
|
||||
const height = this.START_HAT_HEIGHT;
|
||||
const width = this.START_HAT_WIDTH;
|
||||
|
||||
var mainPath =
|
||||
Blockly.utils.svgPaths.curve('c',
|
||||
[
|
||||
Blockly.utils.svgPaths.point(30, -height),
|
||||
Blockly.utils.svgPaths.point(70, -height),
|
||||
Blockly.utils.svgPaths.point(width, 0)
|
||||
]);
|
||||
return {
|
||||
height: height,
|
||||
width: width,
|
||||
path: mainPath
|
||||
};
|
||||
const mainPath = svgPaths.curve('c', [
|
||||
svgPaths.point(30, -height), svgPaths.point(70, -height),
|
||||
svgPaths.point(width, 0)
|
||||
]);
|
||||
return {height: height, width: width, path: mainPath};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -836,9 +807,9 @@ Blockly.blockRendering.ConstantProvider.prototype.makeStartHat = function() {
|
||||
* puzzle tabs.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() {
|
||||
var width = this.TAB_WIDTH;
|
||||
var height = this.TAB_HEIGHT;
|
||||
ConstantProvider.prototype.makePuzzleTab = function() {
|
||||
const width = this.TAB_WIDTH;
|
||||
const height = this.TAB_HEIGHT;
|
||||
|
||||
// The main path for the puzzle tab is made out of a few curves (c and s).
|
||||
// Those curves are defined with relative positions. The 'up' and 'down'
|
||||
@@ -846,35 +817,32 @@ Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() {
|
||||
// are the signs to use to move the cursor in the direction that the path is
|
||||
// being drawn.
|
||||
function makeMainPath(up) {
|
||||
var forward = up ? -1 : 1;
|
||||
var back = -forward;
|
||||
const forward = up ? -1 : 1;
|
||||
const back = -forward;
|
||||
|
||||
var overlap = 2.5;
|
||||
var halfHeight = height / 2;
|
||||
var control1Y = halfHeight + overlap;
|
||||
var control2Y = halfHeight + 0.5;
|
||||
var control3Y = overlap; // 2.5
|
||||
const overlap = 2.5;
|
||||
const halfHeight = height / 2;
|
||||
const control1Y = halfHeight + overlap;
|
||||
const control2Y = halfHeight + 0.5;
|
||||
const control3Y = overlap; // 2.5
|
||||
|
||||
var endPoint1 = Blockly.utils.svgPaths.point(-width, forward * halfHeight);
|
||||
var endPoint2 = Blockly.utils.svgPaths.point(width, forward * halfHeight);
|
||||
const endPoint1 = svgPaths.point(-width, forward * halfHeight);
|
||||
const endPoint2 = svgPaths.point(width, forward * halfHeight);
|
||||
|
||||
return Blockly.utils.svgPaths.curve('c',
|
||||
[
|
||||
Blockly.utils.svgPaths.point(0, forward * control1Y),
|
||||
Blockly.utils.svgPaths.point(-width, back * control2Y),
|
||||
endPoint1
|
||||
]) +
|
||||
Blockly.utils.svgPaths.curve('s',
|
||||
[
|
||||
Blockly.utils.svgPaths.point(width, back * control3Y),
|
||||
endPoint2
|
||||
]);
|
||||
return svgPaths.curve(
|
||||
'c',
|
||||
[
|
||||
svgPaths.point(0, forward * control1Y),
|
||||
svgPaths.point(-width, back * control2Y), endPoint1
|
||||
]) +
|
||||
svgPaths.curve(
|
||||
's', [svgPaths.point(width, back * control3Y), endPoint2]);
|
||||
}
|
||||
|
||||
// c 0,-10 -8,8 -8,-7.5 s 8,2.5 8,-7.5
|
||||
var pathUp = makeMainPath(true);
|
||||
const pathUp = makeMainPath(true);
|
||||
// c 0,10 -8,-8 -8,7.5 s 8,-2.5 8,7.5
|
||||
var pathDown = makeMainPath(false);
|
||||
const pathDown = makeMainPath(false);
|
||||
|
||||
return {
|
||||
type: this.SHAPES.PUZZLE,
|
||||
@@ -890,21 +858,20 @@ Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() {
|
||||
* notches.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.makeNotch = function() {
|
||||
var width = this.NOTCH_WIDTH;
|
||||
var height = this.NOTCH_HEIGHT;
|
||||
var innerWidth = 3;
|
||||
var outerWidth = (width - innerWidth) / 2;
|
||||
ConstantProvider.prototype.makeNotch = function() {
|
||||
const width = this.NOTCH_WIDTH;
|
||||
const height = this.NOTCH_HEIGHT;
|
||||
const innerWidth = 3;
|
||||
const outerWidth = (width - innerWidth) / 2;
|
||||
function makeMainPath(dir) {
|
||||
return Blockly.utils.svgPaths.line(
|
||||
[
|
||||
Blockly.utils.svgPaths.point(dir * outerWidth, height),
|
||||
Blockly.utils.svgPaths.point(dir * innerWidth, 0),
|
||||
Blockly.utils.svgPaths.point(dir * outerWidth, -height)
|
||||
]);
|
||||
return svgPaths.line([
|
||||
svgPaths.point(dir * outerWidth, height),
|
||||
svgPaths.point(dir * innerWidth, 0),
|
||||
svgPaths.point(dir * outerWidth, -height)
|
||||
]);
|
||||
}
|
||||
var pathLeft = makeMainPath(1);
|
||||
var pathRight = makeMainPath(-1);
|
||||
const pathLeft = makeMainPath(1);
|
||||
const pathRight = makeMainPath(-1);
|
||||
|
||||
return {
|
||||
type: this.SHAPES.NOTCH,
|
||||
@@ -920,14 +887,14 @@ Blockly.blockRendering.ConstantProvider.prototype.makeNotch = function() {
|
||||
* inside corners.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.makeInsideCorners = function() {
|
||||
var radius = this.CORNER_RADIUS;
|
||||
ConstantProvider.prototype.makeInsideCorners = function() {
|
||||
const radius = this.CORNER_RADIUS;
|
||||
|
||||
var innerTopLeftCorner = Blockly.utils.svgPaths.arc('a', '0 0,0', radius,
|
||||
Blockly.utils.svgPaths.point(-radius, radius));
|
||||
const innerTopLeftCorner =
|
||||
svgPaths.arc('a', '0 0,0', radius, svgPaths.point(-radius, radius));
|
||||
|
||||
var innerBottomLeftCorner = Blockly.utils.svgPaths.arc('a', '0 0,0', radius,
|
||||
Blockly.utils.svgPaths.point(radius, radius));
|
||||
const innerBottomLeftCorner =
|
||||
svgPaths.arc('a', '0 0,0', radius, svgPaths.point(radius, radius));
|
||||
|
||||
return {
|
||||
width: radius,
|
||||
@@ -942,38 +909,35 @@ Blockly.blockRendering.ConstantProvider.prototype.makeInsideCorners = function()
|
||||
* outside corners.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.makeOutsideCorners = function() {
|
||||
var radius = this.CORNER_RADIUS;
|
||||
ConstantProvider.prototype.makeOutsideCorners = function() {
|
||||
const radius = this.CORNER_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing the rounded top-left corner.
|
||||
* @const
|
||||
*/
|
||||
var topLeft =
|
||||
Blockly.utils.svgPaths.moveBy(0, radius) +
|
||||
Blockly.utils.svgPaths.arc('a', '0 0,1', radius,
|
||||
Blockly.utils.svgPaths.point(radius, -radius));
|
||||
const topLeft = svgPaths.moveBy(0, radius) +
|
||||
svgPaths.arc('a', '0 0,1', radius, svgPaths.point(radius, -radius));
|
||||
|
||||
/**
|
||||
* SVG path for drawing the rounded top-right corner.
|
||||
* @const
|
||||
*/
|
||||
var topRight =
|
||||
Blockly.utils.svgPaths.arc('a', '0 0,1', radius,
|
||||
Blockly.utils.svgPaths.point(radius, radius));
|
||||
const topRight =
|
||||
svgPaths.arc('a', '0 0,1', radius, svgPaths.point(radius, radius));
|
||||
|
||||
/**
|
||||
* SVG path for drawing the rounded bottom-left corner.
|
||||
* @const
|
||||
*/
|
||||
var bottomLeft = Blockly.utils.svgPaths.arc('a', '0 0,1', radius,
|
||||
Blockly.utils.svgPaths.point(-radius, -radius));
|
||||
const bottomLeft =
|
||||
svgPaths.arc('a', '0 0,1', radius, svgPaths.point(-radius, -radius));
|
||||
|
||||
/**
|
||||
* SVG path for drawing the rounded bottom-right corner.
|
||||
* @const
|
||||
*/
|
||||
var bottomRight = Blockly.utils.svgPaths.arc('a', '0 0,1', radius,
|
||||
Blockly.utils.svgPaths.point(-radius, radius));
|
||||
const bottomRight =
|
||||
svgPaths.arc('a', '0 0,1', radius, svgPaths.point(-radius, radius));
|
||||
|
||||
return {
|
||||
topLeft: topLeft,
|
||||
@@ -987,19 +951,18 @@ Blockly.blockRendering.ConstantProvider.prototype.makeOutsideCorners = function(
|
||||
/**
|
||||
* Get an object with connection shape and sizing information based on the type
|
||||
* of the connection.
|
||||
* @param {!Blockly.RenderedConnection} connection The connection to find a
|
||||
* @param {!RenderedConnection} connection The connection to find a
|
||||
* shape object for
|
||||
* @return {!Object} The shape object for the connection.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.shapeFor = function(
|
||||
connection) {
|
||||
ConstantProvider.prototype.shapeFor = function(connection) {
|
||||
switch (connection.type) {
|
||||
case Blockly.connectionTypes.INPUT_VALUE:
|
||||
case Blockly.connectionTypes.OUTPUT_VALUE:
|
||||
case connectionTypes.INPUT_VALUE:
|
||||
case connectionTypes.OUTPUT_VALUE:
|
||||
return this.PUZZLE_TAB;
|
||||
case Blockly.connectionTypes.PREVIOUS_STATEMENT:
|
||||
case Blockly.connectionTypes.NEXT_STATEMENT:
|
||||
case connectionTypes.PREVIOUS_STATEMENT:
|
||||
case connectionTypes.NEXT_STATEMENT:
|
||||
return this.NOTCH;
|
||||
default:
|
||||
throw Error('Unknown connection type');
|
||||
@@ -1014,8 +977,7 @@ Blockly.blockRendering.ConstantProvider.prototype.shapeFor = function(
|
||||
* @suppress {strictModuleDepCheck} Debug renderer only included in playground.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg,
|
||||
tagName, selector) {
|
||||
ConstantProvider.prototype.createDom = function(svg, tagName, selector) {
|
||||
this.injectCSS_(tagName, selector);
|
||||
|
||||
/*
|
||||
@@ -1023,8 +985,7 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg,
|
||||
... filters go here ...
|
||||
</defs>
|
||||
*/
|
||||
var defs = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.DEFS, {}, svg);
|
||||
this.defs_ = dom.createSvgElement(Svg.DEFS, {}, svg);
|
||||
/*
|
||||
<filter id="blocklyEmbossFilter837493">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur" />
|
||||
@@ -1039,15 +1000,14 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg,
|
||||
k1="0" k2="1" k3="1" k4="0" />
|
||||
</filter>
|
||||
*/
|
||||
var embossFilter = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FILTER,
|
||||
{'id': 'blocklyEmbossFilter' + this.randomIdentifier}, defs);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FEGAUSSIANBLUR,
|
||||
const embossFilter = dom.createSvgElement(
|
||||
Svg.FILTER, {'id': 'blocklyEmbossFilter' + this.randomIdentifier},
|
||||
this.defs_);
|
||||
dom.createSvgElement(
|
||||
Svg.FEGAUSSIANBLUR,
|
||||
{'in': 'SourceAlpha', 'stdDeviation': 1, 'result': 'blur'}, embossFilter);
|
||||
var feSpecularLighting = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FESPECULARLIGHTING,
|
||||
{
|
||||
const feSpecularLighting = dom.createSvgElement(
|
||||
Svg.FESPECULARLIGHTING, {
|
||||
'in': 'blur',
|
||||
'surfaceScale': 1,
|
||||
'specularConstant': 0.5,
|
||||
@@ -1056,20 +1016,19 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg,
|
||||
'result': 'specOut'
|
||||
},
|
||||
embossFilter);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FEPOINTLIGHT,
|
||||
{'x': -5000, 'y': -10000, 'z': 20000}, feSpecularLighting);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FECOMPOSITE,
|
||||
{
|
||||
dom.createSvgElement(
|
||||
Svg.FEPOINTLIGHT, {'x': -5000, 'y': -10000, 'z': 20000},
|
||||
feSpecularLighting);
|
||||
dom.createSvgElement(
|
||||
Svg.FECOMPOSITE, {
|
||||
'in': 'specOut',
|
||||
'in2': 'SourceAlpha',
|
||||
'operator': 'in',
|
||||
'result': 'specOut'
|
||||
}, embossFilter);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FECOMPOSITE,
|
||||
{
|
||||
},
|
||||
embossFilter);
|
||||
dom.createSvgElement(
|
||||
Svg.FECOMPOSITE, {
|
||||
'in': 'SourceGraphic',
|
||||
'in2': 'specOut',
|
||||
'operator': 'arithmetic',
|
||||
@@ -1077,7 +1036,8 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg,
|
||||
'k2': 1,
|
||||
'k3': 1,
|
||||
'k4': 0
|
||||
}, embossFilter);
|
||||
},
|
||||
embossFilter);
|
||||
this.embossFilterId = embossFilter.id;
|
||||
this.embossFilter_ = embossFilter;
|
||||
|
||||
@@ -1088,59 +1048,60 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg,
|
||||
<path d="M 0 0 L 10 10 M 10 0 L 0 10" stroke="#cc0" />
|
||||
</pattern>
|
||||
*/
|
||||
var disabledPattern = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATTERN,
|
||||
{
|
||||
const disabledPattern = dom.createSvgElement(
|
||||
Svg.PATTERN, {
|
||||
'id': 'blocklyDisabledPattern' + this.randomIdentifier,
|
||||
'patternUnits': 'userSpaceOnUse',
|
||||
'width': 10,
|
||||
'height': 10
|
||||
}, defs);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATH,
|
||||
{'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, disabledPattern);
|
||||
},
|
||||
this.defs_);
|
||||
dom.createSvgElement(
|
||||
Svg.RECT, {'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern);
|
||||
dom.createSvgElement(
|
||||
Svg.PATH, {'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'},
|
||||
disabledPattern);
|
||||
this.disabledPatternId = disabledPattern.id;
|
||||
this.disabledPattern_ = disabledPattern;
|
||||
|
||||
if (Blockly.blockRendering.Debug) {
|
||||
var debugFilter = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FILTER,
|
||||
{
|
||||
this.createDebugFilter();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a filter for highlighting the currently rendering block during
|
||||
* render debugging.
|
||||
* @private
|
||||
*/
|
||||
ConstantProvider.prototype.createDebugFilter = function() {
|
||||
// Only create the debug filter once.
|
||||
if (!this.debugFilter_) {
|
||||
const debugFilter = dom.createSvgElement(
|
||||
Svg.FILTER, {
|
||||
'id': 'blocklyDebugFilter' + this.randomIdentifier,
|
||||
'height': '160%',
|
||||
'width': '180%',
|
||||
y: '-30%',
|
||||
x: '-40%'
|
||||
},
|
||||
defs);
|
||||
this.defs_);
|
||||
// Set all gaussian blur pixels to 1 opacity before applying flood
|
||||
var debugComponentTransfer = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FECOMPONENTTRANSFER, {
|
||||
'result': 'outBlur'
|
||||
}, debugFilter);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FEFUNCA,
|
||||
{
|
||||
'type': 'table', 'tableValues': '0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1'
|
||||
},
|
||||
const debugComponentTransfer = dom.createSvgElement(
|
||||
Svg.FECOMPONENTTRANSFER, {'result': 'outBlur'}, debugFilter);
|
||||
dom.createSvgElement(
|
||||
Svg.FEFUNCA,
|
||||
{'type': 'table', 'tableValues': '0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1'},
|
||||
debugComponentTransfer);
|
||||
// Color the highlight
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FEFLOOD,
|
||||
{
|
||||
'flood-color': '#ff0000',
|
||||
'flood-opacity': 0.5,
|
||||
'result': 'outColor'
|
||||
},
|
||||
dom.createSvgElement(
|
||||
Svg.FEFLOOD,
|
||||
{'flood-color': '#ff0000', 'flood-opacity': 0.5, 'result': 'outColor'},
|
||||
debugFilter);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FECOMPOSITE,
|
||||
{
|
||||
'in': 'outColor', 'in2': 'outBlur',
|
||||
'operator': 'in', 'result': 'outGlow'
|
||||
dom.createSvgElement(
|
||||
Svg.FECOMPOSITE, {
|
||||
'in': 'outColor',
|
||||
'in2': 'outBlur',
|
||||
'operator': 'in',
|
||||
'result': 'outGlow'
|
||||
},
|
||||
debugFilter);
|
||||
this.debugFilterId = debugFilter.id;
|
||||
@@ -1154,23 +1115,22 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg,
|
||||
* @param {string} selector The CSS selector to use.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.injectCSS_ = function(
|
||||
tagName, selector) {
|
||||
var cssArray = this.getCSS_(selector);
|
||||
var cssNodeId = 'blockly-renderer-style-' + tagName;
|
||||
ConstantProvider.prototype.injectCSS_ = function(tagName, selector) {
|
||||
const cssArray = this.getCSS_(selector);
|
||||
const cssNodeId = 'blockly-renderer-style-' + tagName;
|
||||
this.cssNode_ =
|
||||
/** @type {!HTMLStyleElement} */ (document.getElementById(cssNodeId));
|
||||
var text = cssArray.join('\n');
|
||||
/** @type {!HTMLStyleElement} */ (document.getElementById(cssNodeId));
|
||||
const text = cssArray.join('\n');
|
||||
if (this.cssNode_) {
|
||||
// Already injected, update if the theme changed.
|
||||
this.cssNode_.firstChild.textContent = text;
|
||||
return;
|
||||
}
|
||||
// Inject CSS tag at start of head.
|
||||
var cssNode =
|
||||
/** @type {!HTMLStyleElement} */ (document.createElement('style'));
|
||||
const cssNode =
|
||||
/** @type {!HTMLStyleElement} */ (document.createElement('style'));
|
||||
cssNode.id = cssNodeId;
|
||||
var cssTextNode = document.createTextNode(text);
|
||||
const cssTextNode = document.createTextNode(text);
|
||||
cssNode.appendChild(cssTextNode);
|
||||
document.head.insertBefore(cssNode, document.head.firstChild);
|
||||
this.cssNode_ = cssNode;
|
||||
@@ -1182,9 +1142,10 @@ Blockly.blockRendering.ConstantProvider.prototype.injectCSS_ = function(
|
||||
* @return {!Array<string>} Array of CSS strings.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.ConstantProvider.prototype.getCSS_ = function(selector) {
|
||||
ConstantProvider.prototype.getCSS_ = function(selector) {
|
||||
return [
|
||||
/* eslint-disable indent */
|
||||
/* clang-format off */
|
||||
// Text.
|
||||
selector + ' .blocklyText, ',
|
||||
selector + ' .blocklyFlyoutLabelText {',
|
||||
@@ -1254,6 +1215,9 @@ Blockly.blockRendering.ConstantProvider.prototype.getCSS_ = function(selector) {
|
||||
'fill-opacity: ' + this.INSERTION_MARKER_OPACITY + ';',
|
||||
'stroke: none;',
|
||||
'}',
|
||||
/* clang-format on */
|
||||
/* eslint-enable indent */
|
||||
];
|
||||
};
|
||||
|
||||
exports = ConstantProvider;
|
||||
|
||||
@@ -13,25 +13,33 @@
|
||||
goog.module('Blockly.blockRendering.RenderInfo');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const BottomRow = goog.require('Blockly.blockRendering.BottomRow');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ConstantProvider = goog.requireType('Blockly.blockRendering.ConstantProvider');
|
||||
const ExternalValueInput = goog.require('Blockly.blockRendering.ExternalValueInput');
|
||||
const Field = goog.require('Blockly.blockRendering.Field');
|
||||
const Hat = goog.require('Blockly.blockRendering.Hat');
|
||||
const Icon = goog.require('Blockly.blockRendering.Icon');
|
||||
const InlineInput = goog.require('Blockly.blockRendering.InlineInput');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Input = goog.requireType('Blockly.Input');
|
||||
const InputRow = goog.require('Blockly.blockRendering.InputRow');
|
||||
const InRowSpacer = goog.require('Blockly.blockRendering.InRowSpacer');
|
||||
const JaggedEdge = goog.require('Blockly.blockRendering.JaggedEdge');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Measurable = goog.require('Blockly.blockRendering.Measurable');
|
||||
const NextConnection = goog.require('Blockly.blockRendering.NextConnection');
|
||||
const OutputConnection = goog.require('Blockly.blockRendering.OutputConnection');
|
||||
const PreviousConnection = goog.require('Blockly.blockRendering.PreviousConnection');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const RenderedConnection = goog.requireType('Blockly.RenderedConnection');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Renderer = goog.requireType('Blockly.blockRendering.Renderer');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const RoundCorner = goog.require('Blockly.blockRendering.RoundCorner');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Row = goog.require('Blockly.blockRendering.Row');
|
||||
const SpacerRow = goog.require('Blockly.blockRendering.SpacerRow');
|
||||
const SquareCorner = goog.require('Blockly.blockRendering.SquareCorner');
|
||||
|
||||
@@ -11,34 +11,39 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.blockRendering.PathObject');
|
||||
goog.module('Blockly.blockRendering.PathObject');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.blockRendering.ConstantProvider');
|
||||
goog.require('Blockly.blockRendering.IPathObject');
|
||||
goog.require('Blockly.Theme');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.Connection');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Connection = goog.requireType('Blockly.Connection');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ConstantProvider = goog.requireType('Blockly.blockRendering.ConstantProvider');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IPathObject = goog.require('Blockly.blockRendering.IPathObject');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Theme = goog.requireType('Blockly.Theme');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
|
||||
|
||||
/**
|
||||
* An object that handles creating and setting each of the SVG elements
|
||||
* used by the renderer.
|
||||
* @param {!SVGElement} root The root SVG element.
|
||||
* @param {!Blockly.Theme.BlockStyle} style The style object to use for
|
||||
* @param {!Theme.BlockStyle} style The style object to use for
|
||||
* colouring.
|
||||
* @param {!Blockly.blockRendering.ConstantProvider} constants The renderer's
|
||||
* @param {!ConstantProvider} constants The renderer's
|
||||
* constants.
|
||||
* @constructor
|
||||
* @implements {Blockly.blockRendering.IPathObject}
|
||||
* @implements {IPathObject}
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject = function(root, style, constants) {
|
||||
const PathObject = function(root, style, constants) {
|
||||
/**
|
||||
* The renderer's constant provider.
|
||||
* @type {!Blockly.blockRendering.ConstantProvider}
|
||||
* @type {!ConstantProvider}
|
||||
* @package
|
||||
*/
|
||||
this.constants = constants;
|
||||
@@ -50,13 +55,12 @@ Blockly.blockRendering.PathObject = function(root, style, constants) {
|
||||
* @type {!SVGElement}
|
||||
* @package
|
||||
*/
|
||||
this.svgPath = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATH,
|
||||
{'class': 'blocklyPath'}, this.svgRoot);
|
||||
this.svgPath =
|
||||
dom.createSvgElement(Svg.PATH, {'class': 'blocklyPath'}, this.svgRoot);
|
||||
|
||||
/**
|
||||
* The style object to use when colouring block paths.
|
||||
* @type {!Blockly.Theme.BlockStyle}
|
||||
* @type {!Theme.BlockStyle}
|
||||
* @package
|
||||
*/
|
||||
this.style = style;
|
||||
@@ -83,7 +87,7 @@ Blockly.blockRendering.PathObject = function(root, style, constants) {
|
||||
* @param {string} pathString The path.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.setPath = function(pathString) {
|
||||
PathObject.prototype.setPath = function(pathString) {
|
||||
this.svgPath.setAttribute('d', pathString);
|
||||
};
|
||||
|
||||
@@ -91,7 +95,7 @@ Blockly.blockRendering.PathObject.prototype.setPath = function(pathString) {
|
||||
* Flip the SVG paths in RTL.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.flipRTL = function() {
|
||||
PathObject.prototype.flipRTL = function() {
|
||||
// Mirror the block's path.
|
||||
this.svgPath.setAttribute('transform', 'scale(-1 1)');
|
||||
};
|
||||
@@ -102,7 +106,7 @@ Blockly.blockRendering.PathObject.prototype.flipRTL = function() {
|
||||
* block SVG group.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) {
|
||||
PathObject.prototype.setCursorSvg = function(cursorSvg) {
|
||||
if (!cursorSvg) {
|
||||
this.cursorSvg = null;
|
||||
return;
|
||||
@@ -118,7 +122,7 @@ Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) {
|
||||
* block SVG group.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.setMarkerSvg = function(markerSvg) {
|
||||
PathObject.prototype.setMarkerSvg = function(markerSvg) {
|
||||
if (!markerSvg) {
|
||||
this.markerSvg = null;
|
||||
return;
|
||||
@@ -135,10 +139,10 @@ Blockly.blockRendering.PathObject.prototype.setMarkerSvg = function(markerSvg) {
|
||||
/**
|
||||
* Apply the stored colours to the block's path, taking into account whether
|
||||
* the paths belong to a shadow block.
|
||||
* @param {!Blockly.Block} block The source block.
|
||||
* @param {!Block} block The source block.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.applyColour = function(block) {
|
||||
PathObject.prototype.applyColour = function(block) {
|
||||
this.svgPath.setAttribute('stroke', this.style.colourTertiary);
|
||||
this.svgPath.setAttribute('fill', this.style.colourPrimary);
|
||||
|
||||
@@ -148,10 +152,10 @@ Blockly.blockRendering.PathObject.prototype.applyColour = function(block) {
|
||||
|
||||
/**
|
||||
* Set the style.
|
||||
* @param {!Blockly.Theme.BlockStyle} blockStyle The block style to use.
|
||||
* @param {!Theme.BlockStyle} blockStyle The block style to use.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.setStyle = function(blockStyle) {
|
||||
PathObject.prototype.setStyle = function(blockStyle) {
|
||||
this.style = blockStyle;
|
||||
};
|
||||
|
||||
@@ -162,14 +166,11 @@ Blockly.blockRendering.PathObject.prototype.setStyle = function(blockStyle) {
|
||||
* be removed.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.setClass_ = function(
|
||||
className, add) {
|
||||
PathObject.prototype.setClass_ = function(className, add) {
|
||||
if (add) {
|
||||
Blockly.utils.dom.addClass(/** @type {!Element} */ (this.svgRoot),
|
||||
className);
|
||||
dom.addClass(/** @type {!Element} */ (this.svgRoot), className);
|
||||
} else {
|
||||
Blockly.utils.dom.removeClass(/** @type {!Element} */ (this.svgRoot),
|
||||
className);
|
||||
dom.removeClass(/** @type {!Element} */ (this.svgRoot), className);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -179,11 +180,10 @@ Blockly.blockRendering.PathObject.prototype.setClass_ = function(
|
||||
* @param {boolean} enable True if highlighted.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateHighlighted = function(
|
||||
enable) {
|
||||
PathObject.prototype.updateHighlighted = function(enable) {
|
||||
if (enable) {
|
||||
this.svgPath.setAttribute('filter',
|
||||
'url(#' + this.constants.embossFilterId + ')');
|
||||
this.svgPath.setAttribute(
|
||||
'filter', 'url(#' + this.constants.embossFilterId + ')');
|
||||
} else {
|
||||
this.svgPath.setAttribute('filter', 'none');
|
||||
}
|
||||
@@ -194,7 +194,7 @@ Blockly.blockRendering.PathObject.prototype.updateHighlighted = function(
|
||||
* @param {boolean} shadow True if the block is a shadow block.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateShadow_ = function(shadow) {
|
||||
PathObject.prototype.updateShadow_ = function(shadow) {
|
||||
if (shadow) {
|
||||
this.svgPath.setAttribute('stroke', 'none');
|
||||
this.svgPath.setAttribute('fill', this.style.colourSecondary);
|
||||
@@ -206,12 +206,11 @@ Blockly.blockRendering.PathObject.prototype.updateShadow_ = function(shadow) {
|
||||
* @param {boolean} disabled True if disabled.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateDisabled_ = function(
|
||||
disabled) {
|
||||
PathObject.prototype.updateDisabled_ = function(disabled) {
|
||||
this.setClass_('blocklyDisabled', disabled);
|
||||
if (disabled) {
|
||||
this.svgPath.setAttribute('fill',
|
||||
'url(#' + this.constants.disabledPatternId + ')');
|
||||
this.svgPath.setAttribute(
|
||||
'fill', 'url(#' + this.constants.disabledPatternId + ')');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -220,7 +219,7 @@ Blockly.blockRendering.PathObject.prototype.updateDisabled_ = function(
|
||||
* @param {boolean} enable True if selection is enabled, false otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateSelected = function(enable) {
|
||||
PathObject.prototype.updateSelected = function(enable) {
|
||||
this.setClass_('blocklySelected', enable);
|
||||
};
|
||||
|
||||
@@ -230,8 +229,7 @@ Blockly.blockRendering.PathObject.prototype.updateSelected = function(enable) {
|
||||
* area, false otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateDraggingDelete = function(
|
||||
enable) {
|
||||
PathObject.prototype.updateDraggingDelete = function(enable) {
|
||||
this.setClass_('blocklyDraggingDelete', enable);
|
||||
};
|
||||
|
||||
@@ -241,8 +239,7 @@ Blockly.blockRendering.PathObject.prototype.updateDraggingDelete = function(
|
||||
* otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateInsertionMarker = function(
|
||||
enable) {
|
||||
PathObject.prototype.updateInsertionMarker = function(enable) {
|
||||
this.setClass_('blocklyInsertionMarker', enable);
|
||||
};
|
||||
|
||||
@@ -251,7 +248,7 @@ Blockly.blockRendering.PathObject.prototype.updateInsertionMarker = function(
|
||||
* @param {boolean} enable True if the block is movable, false otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateMovable = function(enable) {
|
||||
PathObject.prototype.updateMovable = function(enable) {
|
||||
this.setClass_('blocklyDraggable', enable);
|
||||
};
|
||||
|
||||
@@ -262,21 +259,19 @@ Blockly.blockRendering.PathObject.prototype.updateMovable = function(enable) {
|
||||
* @param {boolean} enable True if styling should be added.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateReplacementFade =
|
||||
function(enable) {
|
||||
/* eslint-disable indent */
|
||||
PathObject.prototype.updateReplacementFade = function(enable) {
|
||||
this.setClass_('blocklyReplaceable', enable);
|
||||
}; /* eslint-enable indent */
|
||||
};
|
||||
|
||||
/**
|
||||
* Add or remove styling that shows that if the dragging block is dropped, this
|
||||
* block will be connected to the input.
|
||||
* @param {Blockly.Connection} _conn The connection on the input to highlight.
|
||||
* @param {Connection} _conn The connection on the input to highlight.
|
||||
* @param {boolean} _enable True if styling should be added.
|
||||
* @package
|
||||
*/
|
||||
Blockly.blockRendering.PathObject.prototype.updateShapeForInputHighlight =
|
||||
function(_conn, _enable) {
|
||||
/* eslint-disable indent */
|
||||
PathObject.prototype.updateShapeForInputHighlight = function(_conn, _enable) {
|
||||
// NOP
|
||||
}; /* eslint-enable indent */
|
||||
};
|
||||
|
||||
exports = PathObject;
|
||||
|
||||
@@ -42,7 +42,6 @@ goog.require('Blockly.Trashcan');
|
||||
goog.require('Blockly.VariablesDynamic');
|
||||
// Only need to require these two if you're using workspace comments.
|
||||
// goog.require('Blockly.WorkspaceCommentSvg');
|
||||
// goog.require('Blockly.WorkspaceCommentSvg.render');
|
||||
// If zoom controls aren't required, then Blockly.inject's
|
||||
// "zoom"/"controls" configuration must be false.
|
||||
goog.require('Blockly.ZoomControls');
|
||||
|
||||
@@ -11,27 +11,28 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ShortcutRegistry');
|
||||
goog.module('Blockly.ShortcutRegistry');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.utils.KeyCodes');
|
||||
goog.require('Blockly.utils.object');
|
||||
|
||||
goog.requireType('Blockly.Workspace');
|
||||
const KeyCodes = goog.require('Blockly.utils.KeyCodes');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
const object = goog.require('Blockly.utils.object');
|
||||
|
||||
|
||||
/**
|
||||
* Class for the registry of keyboard shortcuts. This is intended to be a
|
||||
* singleton. You should not create a new instance, and only access this class
|
||||
* from Blockly.ShortcutRegistry.registry.
|
||||
* from ShortcutRegistry.registry.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.ShortcutRegistry = function() {
|
||||
const ShortcutRegistry = function() {
|
||||
// Singleton instance should be registered once.
|
||||
Blockly.ShortcutRegistry.registry = this;
|
||||
ShortcutRegistry.registry = this;
|
||||
|
||||
/**
|
||||
* Registry of all keyboard shortcuts, keyed by name of shortcut.
|
||||
* @type {!Object<string, !Blockly.ShortcutRegistry.KeyboardShortcut>}
|
||||
* @type {!Object<string, !ShortcutRegistry.KeyboardShortcut>}
|
||||
* @private
|
||||
*/
|
||||
this.registry_ = Object.create(null);
|
||||
@@ -46,39 +47,38 @@ Blockly.ShortcutRegistry = function() {
|
||||
|
||||
/**
|
||||
* Enum of valid modifiers.
|
||||
* @enum {!Blockly.utils.KeyCodes<number>}
|
||||
* @enum {!KeyCodes<number>}
|
||||
*/
|
||||
Blockly.ShortcutRegistry.modifierKeys = {
|
||||
'Shift': Blockly.utils.KeyCodes.SHIFT,
|
||||
'Control': Blockly.utils.KeyCodes.CTRL,
|
||||
'Alt': Blockly.utils.KeyCodes.ALT,
|
||||
'Meta': Blockly.utils.KeyCodes.META
|
||||
ShortcutRegistry.modifierKeys = {
|
||||
'Shift': KeyCodes.SHIFT,
|
||||
'Control': KeyCodes.CTRL,
|
||||
'Alt': KeyCodes.ALT,
|
||||
'Meta': KeyCodes.META
|
||||
};
|
||||
|
||||
/**
|
||||
* A keyboard shortcut.
|
||||
* @typedef {{
|
||||
* callback: ((function(!Blockly.Workspace, Event,
|
||||
* !Blockly.ShortcutRegistry.KeyboardShortcut):boolean)|undefined),
|
||||
* callback: ((function(!Workspace, Event,
|
||||
* !ShortcutRegistry.KeyboardShortcut):boolean)|undefined),
|
||||
* name: string,
|
||||
* preconditionFn: ((function(!Blockly.Workspace):boolean)|undefined),
|
||||
* preconditionFn: ((function(!Workspace):boolean)|undefined),
|
||||
* metadata: (Object|undefined)
|
||||
* }}
|
||||
*/
|
||||
Blockly.ShortcutRegistry.KeyboardShortcut;
|
||||
ShortcutRegistry.KeyboardShortcut;
|
||||
|
||||
/**
|
||||
* Registers a keyboard shortcut.
|
||||
* @param {!Blockly.ShortcutRegistry.KeyboardShortcut} shortcut The
|
||||
* @param {!ShortcutRegistry.KeyboardShortcut} shortcut The
|
||||
* shortcut for this key code.
|
||||
* @param {boolean=} opt_allowOverrides True to prevent a warning when
|
||||
* overriding an already registered item.
|
||||
* @throws {Error} if a shortcut with the same name already exists.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.register = function(
|
||||
shortcut, opt_allowOverrides) {
|
||||
var registeredShortcut = this.registry_[shortcut.name];
|
||||
ShortcutRegistry.prototype.register = function(shortcut, opt_allowOverrides) {
|
||||
const registeredShortcut = this.registry_[shortcut.name];
|
||||
if (registeredShortcut && !opt_allowOverrides) {
|
||||
throw new Error(
|
||||
'Shortcut with name "' + shortcut.name + '" already exists.');
|
||||
@@ -93,8 +93,8 @@ Blockly.ShortcutRegistry.prototype.register = function(
|
||||
* @return {boolean} True if an item was unregistered, false otherwise.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) {
|
||||
var shortcut = this.registry_[shortcutName];
|
||||
ShortcutRegistry.prototype.unregister = function(shortcutName) {
|
||||
const shortcut = this.registry_[shortcutName];
|
||||
|
||||
if (!shortcut) {
|
||||
console.warn(
|
||||
@@ -110,9 +110,9 @@ Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) {
|
||||
|
||||
/**
|
||||
* Adds a mapping between a keycode and a keyboard shortcut.
|
||||
* @param {string|Blockly.utils.KeyCodes} keyCode The key code for the keyboard
|
||||
* @param {string|KeyCodes} keyCode The key code for the keyboard
|
||||
* shortcut. If registering a key code with a modifier (ex: ctrl+c) use
|
||||
* Blockly.ShortcutRegistry.registry.createSerializedKey;
|
||||
* ShortcutRegistry.registry.createSerializedKey;
|
||||
* @param {string} shortcutName The name of the shortcut to execute when the
|
||||
* given keycode is pressed.
|
||||
* @param {boolean=} opt_allowCollision True to prevent an error when adding a
|
||||
@@ -120,10 +120,10 @@ Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) {
|
||||
* @throws {Error} if the given key code is already mapped to a shortcut.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.addKeyMapping = function(
|
||||
ShortcutRegistry.prototype.addKeyMapping = function(
|
||||
keyCode, shortcutName, opt_allowCollision) {
|
||||
keyCode = String(keyCode);
|
||||
var shortcutNames = this.keyMap_[keyCode];
|
||||
const shortcutNames = this.keyMap_[keyCode];
|
||||
if (shortcutNames && !opt_allowCollision) {
|
||||
throw new Error(
|
||||
'Shortcut with name "' + shortcutName + '" collides with shortcuts ' +
|
||||
@@ -139,7 +139,7 @@ Blockly.ShortcutRegistry.prototype.addKeyMapping = function(
|
||||
* Removes a mapping between a keycode and a keyboard shortcut.
|
||||
* @param {string} keyCode The key code for the keyboard shortcut. If
|
||||
* registering a key code with a modifier (ex: ctrl+c) use
|
||||
* Blockly.ShortcutRegistry.registry.createSerializedKey;
|
||||
* ShortcutRegistry.registry.createSerializedKey;
|
||||
* @param {string} shortcutName The name of the shortcut to execute when the
|
||||
* given keycode is pressed.
|
||||
* @param {boolean=} opt_quiet True to not console warn when there is no
|
||||
@@ -147,9 +147,9 @@ Blockly.ShortcutRegistry.prototype.addKeyMapping = function(
|
||||
* @return {boolean} True if a key mapping was removed, false otherwise.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.removeKeyMapping = function(
|
||||
ShortcutRegistry.prototype.removeKeyMapping = function(
|
||||
keyCode, shortcutName, opt_quiet) {
|
||||
var shortcutNames = this.keyMap_[keyCode];
|
||||
const shortcutNames = this.keyMap_[keyCode];
|
||||
|
||||
if (!shortcutNames && !opt_quiet) {
|
||||
console.warn(
|
||||
@@ -158,7 +158,7 @@ Blockly.ShortcutRegistry.prototype.removeKeyMapping = function(
|
||||
return false;
|
||||
}
|
||||
|
||||
var shortcutIdx = shortcutNames.indexOf(shortcutName);
|
||||
const shortcutIdx = shortcutNames.indexOf(shortcutName);
|
||||
if (shortcutIdx > -1) {
|
||||
shortcutNames.splice(shortcutIdx, 1);
|
||||
if (shortcutNames.length == 0) {
|
||||
@@ -167,7 +167,8 @@ Blockly.ShortcutRegistry.prototype.removeKeyMapping = function(
|
||||
return true;
|
||||
}
|
||||
if (!opt_quiet) {
|
||||
console.warn('No keyboard shortcut with name "' + shortcutName +
|
||||
console.warn(
|
||||
'No keyboard shortcut with name "' + shortcutName +
|
||||
'" registered with key code "' + keyCode + '"');
|
||||
}
|
||||
return false;
|
||||
@@ -175,13 +176,14 @@ Blockly.ShortcutRegistry.prototype.removeKeyMapping = function(
|
||||
|
||||
/**
|
||||
* Removes all the key mappings for a shortcut with the given name.
|
||||
* Useful when changing the default key mappings and the key codes registered to the shortcut are
|
||||
* unknown.
|
||||
* @param {string} shortcutName The name of the shortcut to remove from the key map.
|
||||
* Useful when changing the default key mappings and the key codes registered to
|
||||
* the shortcut are unknown.
|
||||
* @param {string} shortcutName The name of the shortcut to remove from the key
|
||||
* map.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.removeAllKeyMappings = function(shortcutName) {
|
||||
for (var keyCode in this.keyMap_) {
|
||||
ShortcutRegistry.prototype.removeAllKeyMappings = function(shortcutName) {
|
||||
for (const keyCode in this.keyMap_) {
|
||||
this.removeKeyMapping(keyCode, shortcutName, true);
|
||||
}
|
||||
};
|
||||
@@ -192,46 +194,46 @@ Blockly.ShortcutRegistry.prototype.removeAllKeyMappings = function(shortcutName)
|
||||
* shortcut names.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.setKeyMap = function(keyMap) {
|
||||
ShortcutRegistry.prototype.setKeyMap = function(keyMap) {
|
||||
this.keyMap_ = keyMap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the current key map.
|
||||
* @return {!Object<string,!Array<!Blockly.ShortcutRegistry.KeyboardShortcut>>}
|
||||
* The object holding key codes to Blockly.ShortcutRegistry.KeyboardShortcut.
|
||||
* @return {!Object<string,!Array<!ShortcutRegistry.KeyboardShortcut>>}
|
||||
* The object holding key codes to ShortcutRegistry.KeyboardShortcut.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.getKeyMap = function() {
|
||||
return Blockly.utils.object.deepMerge(Object.create(null), this.keyMap_);
|
||||
ShortcutRegistry.prototype.getKeyMap = function() {
|
||||
return object.deepMerge(Object.create(null), this.keyMap_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the registry of keyboard shortcuts.
|
||||
* @return {!Object<string, !Blockly.ShortcutRegistry.KeyboardShortcut>}
|
||||
* @return {!Object<string, !ShortcutRegistry.KeyboardShortcut>}
|
||||
* The registry of keyboard shortcuts.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.getRegistry = function() {
|
||||
return Blockly.utils.object.deepMerge(Object.create(null), this.registry_);
|
||||
ShortcutRegistry.prototype.getRegistry = function() {
|
||||
return object.deepMerge(Object.create(null), this.registry_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles key down events.
|
||||
* @param {!Blockly.Workspace} workspace The main workspace where the event was
|
||||
* @param {!Workspace} workspace The main workspace where the event was
|
||||
* captured.
|
||||
* @param {!Event} e The key down event.
|
||||
* @return {boolean} True if the event was handled, false otherwise.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.onKeyDown = function(workspace, e) {
|
||||
var key = this.serializeKeyEvent_(e);
|
||||
var shortcutNames = this.getShortcutNamesByKeyCode(key);
|
||||
ShortcutRegistry.prototype.onKeyDown = function(workspace, e) {
|
||||
const key = this.serializeKeyEvent_(e);
|
||||
const shortcutNames = this.getShortcutNamesByKeyCode(key);
|
||||
if (!shortcutNames) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0, shortcutName; (shortcutName = shortcutNames[i]); i++) {
|
||||
var shortcut = this.registry_[shortcutName];
|
||||
for (let i = 0, shortcutName; (shortcutName = shortcutNames[i]); i++) {
|
||||
const shortcut = this.registry_[shortcutName];
|
||||
if (!shortcut.preconditionFn || shortcut.preconditionFn(workspace)) {
|
||||
// If the key has been handled, stop processing shortcuts.
|
||||
if (shortcut.callback && shortcut.callback(workspace, e, shortcut)) {
|
||||
@@ -249,8 +251,7 @@ Blockly.ShortcutRegistry.prototype.onKeyDown = function(workspace, e) {
|
||||
* given keyCode is used. Undefined if no shortcuts exist.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.getShortcutNamesByKeyCode = function(
|
||||
keyCode) {
|
||||
ShortcutRegistry.prototype.getShortcutNamesByKeyCode = function(keyCode) {
|
||||
return this.keyMap_[keyCode] || [];
|
||||
};
|
||||
|
||||
@@ -262,12 +263,11 @@ Blockly.ShortcutRegistry.prototype.getShortcutNamesByKeyCode = function(
|
||||
* registered under.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.getKeyCodesByShortcutName = function(
|
||||
shortcutName) {
|
||||
var keys = [];
|
||||
for (var keyCode in this.keyMap_) {
|
||||
var shortcuts = this.keyMap_[keyCode];
|
||||
var shortcutIdx = shortcuts.indexOf(shortcutName);
|
||||
ShortcutRegistry.prototype.getKeyCodesByShortcutName = function(shortcutName) {
|
||||
const keys = [];
|
||||
for (const keyCode in this.keyMap_) {
|
||||
const shortcuts = this.keyMap_[keyCode];
|
||||
const shortcutIdx = shortcuts.indexOf(shortcutName);
|
||||
if (shortcutIdx > -1) {
|
||||
keys.push(keyCode);
|
||||
}
|
||||
@@ -281,9 +281,9 @@ Blockly.ShortcutRegistry.prototype.getKeyCodesByShortcutName = function(
|
||||
* @return {string} The serialized key code for the given event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.serializeKeyEvent_ = function(e) {
|
||||
var serializedKey = '';
|
||||
for (var modifier in Blockly.ShortcutRegistry.modifierKeys) {
|
||||
ShortcutRegistry.prototype.serializeKeyEvent_ = function(e) {
|
||||
let serializedKey = '';
|
||||
for (const modifier in ShortcutRegistry.modifierKeys) {
|
||||
if (e.getModifierState(modifier)) {
|
||||
if (serializedKey != '') {
|
||||
serializedKey += '+';
|
||||
@@ -305,11 +305,9 @@ Blockly.ShortcutRegistry.prototype.serializeKeyEvent_ = function(e) {
|
||||
* @throws {Error} if the modifier is not in the valid modifiers list.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.checkModifiers_ = function(
|
||||
modifiers) {
|
||||
var validModifiers = Blockly.utils.object.values(
|
||||
Blockly.ShortcutRegistry.modifierKeys);
|
||||
for (var i = 0, modifier; (modifier = modifiers[i]); i++) {
|
||||
ShortcutRegistry.prototype.checkModifiers_ = function(modifiers) {
|
||||
const validModifiers = object.values(ShortcutRegistry.modifierKeys);
|
||||
for (let i = 0, modifier; (modifier = modifiers[i]); i++) {
|
||||
if (validModifiers.indexOf(modifier) < 0) {
|
||||
throw new Error(modifier + ' is not a valid modifier key.');
|
||||
}
|
||||
@@ -321,19 +319,17 @@ Blockly.ShortcutRegistry.prototype.checkModifiers_ = function(
|
||||
* @param {number} keyCode Number code representing the key.
|
||||
* @param {?Array<string>} modifiers List of modifier key codes to be used with
|
||||
* the key. All valid modifiers can be found in the
|
||||
* Blockly.ShortcutRegistry.modifierKeys.
|
||||
* ShortcutRegistry.modifierKeys.
|
||||
* @return {string} The serialized key code for the given modifiers and key.
|
||||
* @public
|
||||
*/
|
||||
Blockly.ShortcutRegistry.prototype.createSerializedKey = function(
|
||||
keyCode, modifiers) {
|
||||
var serializedKey = '';
|
||||
ShortcutRegistry.prototype.createSerializedKey = function(keyCode, modifiers) {
|
||||
let serializedKey = '';
|
||||
|
||||
if (modifiers) {
|
||||
this.checkModifiers_(modifiers);
|
||||
for (var modifier in Blockly.ShortcutRegistry.modifierKeys) {
|
||||
var modifierKeyCode =
|
||||
Blockly.ShortcutRegistry.modifierKeys[modifier];
|
||||
for (const modifier in ShortcutRegistry.modifierKeys) {
|
||||
const modifierKeyCode = ShortcutRegistry.modifierKeys[modifier];
|
||||
if (modifiers.indexOf(modifierKeyCode) > -1) {
|
||||
if (serializedKey != '') {
|
||||
serializedKey += '+';
|
||||
@@ -352,4 +348,6 @@ Blockly.ShortcutRegistry.prototype.createSerializedKey = function(
|
||||
};
|
||||
|
||||
// Creates and assigns the singleton instance.
|
||||
new Blockly.ShortcutRegistry();
|
||||
new ShortcutRegistry();
|
||||
|
||||
exports = ShortcutRegistry;
|
||||
|
||||
@@ -12,47 +12,50 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ThemeManager');
|
||||
goog.module('Blockly.ThemeManager');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Theme');
|
||||
|
||||
goog.requireType('Blockly.Workspace');
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Theme = goog.requireType('Blockly.Theme');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
|
||||
|
||||
/**
|
||||
* Class for storing and updating a workspace's theme and UI components.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The main workspace.
|
||||
* @param {!Blockly.Theme} theme The workspace theme.
|
||||
* @param {!WorkspaceSvg} workspace The main workspace.
|
||||
* @param {!Theme} theme The workspace theme.
|
||||
* @constructor
|
||||
* @package
|
||||
*/
|
||||
Blockly.ThemeManager = function(workspace, theme) {
|
||||
|
||||
const ThemeManager = function(workspace, theme) {
|
||||
/**
|
||||
* The main workspace.
|
||||
* @type {!Blockly.WorkspaceSvg}
|
||||
* @type {!WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
this.workspace_ = workspace;
|
||||
|
||||
/**
|
||||
* The Blockly theme to use.
|
||||
* @type {!Blockly.Theme}
|
||||
* @type {!Theme}
|
||||
* @private
|
||||
*/
|
||||
this.theme_ = theme;
|
||||
|
||||
/**
|
||||
* A list of workspaces that are subscribed to this theme.
|
||||
* @type {!Array<Blockly.Workspace>}
|
||||
* @type {!Array<Workspace>}
|
||||
* @private
|
||||
*/
|
||||
this.subscribedWorkspaces_ = [];
|
||||
|
||||
/**
|
||||
* A map of subscribed UI components, keyed by component name.
|
||||
* @type {!Object<string, !Array<!Blockly.ThemeManager.Component>>}
|
||||
* @type {!Object<string, !Array<!ThemeManager.Component>>}
|
||||
* @private
|
||||
*/
|
||||
this.componentDB_ = Object.create(null);
|
||||
@@ -61,51 +64,51 @@ Blockly.ThemeManager = function(workspace, theme) {
|
||||
/**
|
||||
* A Blockly UI component type.
|
||||
* @typedef {{
|
||||
* element:!Element,
|
||||
* propertyName:string
|
||||
* }}
|
||||
*/
|
||||
Blockly.ThemeManager.Component;
|
||||
* element:!Element,
|
||||
* propertyName:string
|
||||
* }}
|
||||
*/
|
||||
ThemeManager.Component;
|
||||
|
||||
/**
|
||||
* Get the workspace theme.
|
||||
* @return {!Blockly.Theme} The workspace theme.
|
||||
* @return {!Theme} The workspace theme.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ThemeManager.prototype.getTheme = function() {
|
||||
ThemeManager.prototype.getTheme = function() {
|
||||
return this.theme_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the workspace theme, and refresh the workspace and all components.
|
||||
* @param {!Blockly.Theme} theme The workspace theme.
|
||||
* @param {!Theme} theme The workspace theme.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ThemeManager.prototype.setTheme = function(theme) {
|
||||
var prevTheme = this.theme_;
|
||||
ThemeManager.prototype.setTheme = function(theme) {
|
||||
const prevTheme = this.theme_;
|
||||
this.theme_ = theme;
|
||||
|
||||
// Set the theme name onto the injection div.
|
||||
var injectionDiv = this.workspace_.getInjectionDiv();
|
||||
const injectionDiv = this.workspace_.getInjectionDiv();
|
||||
if (injectionDiv) {
|
||||
if (prevTheme) {
|
||||
Blockly.utils.dom.removeClass(injectionDiv, prevTheme.getClassName());
|
||||
dom.removeClass(injectionDiv, prevTheme.getClassName());
|
||||
}
|
||||
Blockly.utils.dom.addClass(injectionDiv, this.theme_.getClassName());
|
||||
dom.addClass(injectionDiv, this.theme_.getClassName());
|
||||
}
|
||||
|
||||
// Refresh all subscribed workspaces.
|
||||
for (var i = 0, workspace; (workspace = this.subscribedWorkspaces_[i]); i++) {
|
||||
for (let i = 0, workspace; (workspace = this.subscribedWorkspaces_[i]); i++) {
|
||||
workspace.refreshTheme();
|
||||
}
|
||||
|
||||
// Refresh all registered Blockly UI components.
|
||||
for (var i = 0, keys = Object.keys(this.componentDB_),
|
||||
key; (key = keys[i]); i++) {
|
||||
for (var j = 0, component; (component = this.componentDB_[key][j]); j++) {
|
||||
var element = component.element;
|
||||
var propertyName = component.propertyName;
|
||||
var style = this.theme_ && this.theme_.getComponentStyle(key);
|
||||
for (let i = 0, keys = Object.keys(this.componentDB_), key; (key = keys[i]);
|
||||
i++) {
|
||||
for (let j = 0, component; (component = this.componentDB_[key][j]); j++) {
|
||||
const element = component.element;
|
||||
const propertyName = component.propertyName;
|
||||
const style = this.theme_ && this.theme_.getComponentStyle(key);
|
||||
element.style[propertyName] = style || '';
|
||||
}
|
||||
}
|
||||
@@ -116,20 +119,20 @@ Blockly.ThemeManager.prototype.setTheme = function(theme) {
|
||||
/**
|
||||
* Subscribe a workspace to changes to the selected theme. If a new theme is
|
||||
* set, the workspace is called to refresh its blocks.
|
||||
* @param {!Blockly.Workspace} workspace The workspace to subscribe.
|
||||
* @param {!Workspace} workspace The workspace to subscribe.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ThemeManager.prototype.subscribeWorkspace = function(workspace) {
|
||||
ThemeManager.prototype.subscribeWorkspace = function(workspace) {
|
||||
this.subscribedWorkspaces_.push(workspace);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unsubscribe a workspace to changes to the selected theme.
|
||||
* @param {!Blockly.Workspace} workspace The workspace to unsubscribe.
|
||||
* @param {!Workspace} workspace The workspace to unsubscribe.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ThemeManager.prototype.unsubscribeWorkspace = function(workspace) {
|
||||
var index = this.subscribedWorkspaces_.indexOf(workspace);
|
||||
ThemeManager.prototype.unsubscribeWorkspace = function(workspace) {
|
||||
const index = this.subscribedWorkspaces_.indexOf(workspace);
|
||||
if (index < 0) {
|
||||
throw Error('Cannot unsubscribe a workspace that hasn\'t been subscribed.');
|
||||
}
|
||||
@@ -145,20 +148,18 @@ Blockly.ThemeManager.prototype.unsubscribeWorkspace = function(workspace) {
|
||||
* @param {string} propertyName The inline style property name to update.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ThemeManager.prototype.subscribe = function(element, componentName,
|
||||
propertyName) {
|
||||
ThemeManager.prototype.subscribe = function(
|
||||
element, componentName, propertyName) {
|
||||
if (!this.componentDB_[componentName]) {
|
||||
this.componentDB_[componentName] = [];
|
||||
}
|
||||
|
||||
// Add the element to our component map.
|
||||
this.componentDB_[componentName].push({
|
||||
element: element,
|
||||
propertyName: propertyName
|
||||
});
|
||||
this.componentDB_[componentName].push(
|
||||
{element: element, propertyName: propertyName});
|
||||
|
||||
// Initialize the element with its corresponding theme style.
|
||||
var style = this.theme_ && this.theme_.getComponentStyle(componentName);
|
||||
const style = this.theme_ && this.theme_.getComponentStyle(componentName);
|
||||
element.style[propertyName] = style || '';
|
||||
};
|
||||
|
||||
@@ -167,15 +168,15 @@ Blockly.ThemeManager.prototype.subscribe = function(element, componentName,
|
||||
* @param {Element} element The element to unsubscribe.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ThemeManager.prototype.unsubscribe = function(element) {
|
||||
ThemeManager.prototype.unsubscribe = function(element) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
// Go through all component, and remove any references to this element.
|
||||
var componentNames = Object.keys(this.componentDB_);
|
||||
for (var c = 0, componentName; (componentName = componentNames[c]); c++) {
|
||||
var elements = this.componentDB_[componentName];
|
||||
for (var i = elements.length - 1; i >= 0; i--) {
|
||||
const componentNames = Object.keys(this.componentDB_);
|
||||
for (let c = 0, componentName; (componentName = componentNames[c]); c++) {
|
||||
const elements = this.componentDB_[componentName];
|
||||
for (let i = elements.length - 1; i >= 0; i--) {
|
||||
if (elements[i].element === element) {
|
||||
elements.splice(i, 1);
|
||||
}
|
||||
@@ -192,9 +193,11 @@ Blockly.ThemeManager.prototype.unsubscribe = function(element) {
|
||||
* @package
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
Blockly.ThemeManager.prototype.dispose = function() {
|
||||
ThemeManager.prototype.dispose = function() {
|
||||
this.owner_ = null;
|
||||
this.theme_ = null;
|
||||
this.subscribedWorkspaces_ = null;
|
||||
this.componentDB_ = null;
|
||||
};
|
||||
|
||||
exports = ThemeManager;
|
||||
|
||||
@@ -10,34 +10,36 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.CollapsibleToolboxCategory');
|
||||
goog.module('Blockly.CollapsibleToolboxCategory');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.ICollapsibleToolboxItem');
|
||||
goog.require('Blockly.registry');
|
||||
goog.require('Blockly.ToolboxCategory');
|
||||
goog.require('Blockly.ToolboxItem');
|
||||
goog.require('Blockly.ToolboxSeparator');
|
||||
goog.require('Blockly.utils.aria');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.utils.toolbox');
|
||||
|
||||
goog.requireType('Blockly.IToolbox');
|
||||
goog.requireType('Blockly.IToolboxItem');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ICollapsibleToolboxItem = goog.require('Blockly.ICollapsibleToolboxItem');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IToolbox = goog.requireType('Blockly.IToolbox');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IToolboxItem = goog.requireType('Blockly.IToolboxItem');
|
||||
const ToolboxCategory = goog.require('Blockly.ToolboxCategory');
|
||||
const ToolboxSeparator = goog.require('Blockly.ToolboxSeparator');
|
||||
const aria = goog.require('Blockly.utils.aria');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const object = goog.require('Blockly.utils.object');
|
||||
const registry = goog.require('Blockly.registry');
|
||||
const toolbox = goog.require('Blockly.utils.toolbox');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a category in a toolbox that can be collapsed.
|
||||
* @param {!Blockly.utils.toolbox.CategoryInfo} categoryDef The information needed
|
||||
* @param {!toolbox.CategoryInfo} categoryDef The information needed
|
||||
* to create a category in the toolbox.
|
||||
* @param {!Blockly.IToolbox} toolbox The parent toolbox for the category.
|
||||
* @param {Blockly.ICollapsibleToolboxItem=} opt_parent The parent category or null if
|
||||
* @param {!IToolbox} toolbox The parent toolbox for the category.
|
||||
* @param {ICollapsibleToolboxItem=} opt_parent The parent category or null if
|
||||
* the category does not have a parent.
|
||||
* @constructor
|
||||
* @extends {Blockly.ToolboxCategory}
|
||||
* @implements {Blockly.ICollapsibleToolboxItem}
|
||||
* @extends {ToolboxCategory}
|
||||
* @implements {ICollapsibleToolboxItem}
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory = function(categoryDef, toolbox, opt_parent) {
|
||||
const CollapsibleToolboxCategory = function(categoryDef, toolbox, opt_parent) {
|
||||
/**
|
||||
* Container for any child categories.
|
||||
* @type {?Element}
|
||||
@@ -54,16 +56,16 @@ Blockly.CollapsibleToolboxCategory = function(categoryDef, toolbox, opt_parent)
|
||||
|
||||
/**
|
||||
* The child toolbox items for this category.
|
||||
* @type {!Array<!Blockly.ToolboxItem>}
|
||||
* @type {!Array<!IToolboxItem>}
|
||||
* @protected
|
||||
*/
|
||||
this.toolboxItems_ = [];
|
||||
|
||||
Blockly.CollapsibleToolboxCategory.superClass_.constructor.call(
|
||||
CollapsibleToolboxCategory.superClass_.constructor.call(
|
||||
this, categoryDef, toolbox, opt_parent);
|
||||
};
|
||||
|
||||
Blockly.utils.object.inherits(Blockly.CollapsibleToolboxCategory, Blockly.ToolboxCategory);
|
||||
object.inherits(CollapsibleToolboxCategory, ToolboxCategory);
|
||||
|
||||
/**
|
||||
* All the CSS class names that are used to create a collapsible
|
||||
@@ -80,19 +82,20 @@ Blockly.utils.object.inherits(Blockly.CollapsibleToolboxCategory, Blockly.Toolbo
|
||||
* contents:?string
|
||||
* }}
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.CssConfig;
|
||||
CollapsibleToolboxCategory.CssConfig;
|
||||
|
||||
/**
|
||||
* Name used for registering a collapsible toolbox category.
|
||||
* @const {string}
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.registrationName = 'collapsibleCategory';
|
||||
CollapsibleToolboxCategory.registrationName = 'collapsibleCategory';
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.makeDefaultCssConfig_ = function() {
|
||||
var cssConfig = Blockly.CollapsibleToolboxCategory.superClass_.makeDefaultCssConfig_.call(this);
|
||||
CollapsibleToolboxCategory.prototype.makeDefaultCssConfig_ = function() {
|
||||
const cssConfig =
|
||||
CollapsibleToolboxCategory.superClass_.makeDefaultCssConfig_.call(this);
|
||||
cssConfig['contents'] = 'blocklyToolboxContents';
|
||||
return cssConfig;
|
||||
};
|
||||
@@ -100,20 +103,21 @@ Blockly.CollapsibleToolboxCategory.prototype.makeDefaultCssConfig_ = function()
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.parseContents_ = function(categoryDef) {
|
||||
var contents = categoryDef['contents'];
|
||||
var prevIsFlyoutItem = true;
|
||||
CollapsibleToolboxCategory.prototype.parseContents_ = function(categoryDef) {
|
||||
const contents = categoryDef['contents'];
|
||||
let prevIsFlyoutItem = true;
|
||||
|
||||
if (categoryDef['custom']) {
|
||||
this.flyoutItems_ = categoryDef['custom'];
|
||||
} else if (contents) {
|
||||
for (var i = 0, itemDef; (itemDef = contents[i]); i++) {
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
const itemDef = contents[i];
|
||||
// Separators can exist as either a flyout item or a toolbox item so
|
||||
// decide where it goes based on the type of the previous item.
|
||||
if (!Blockly.registry.hasItem(Blockly.registry.Type.TOOLBOX_ITEM, itemDef['kind']) ||
|
||||
(itemDef['kind'].toLowerCase() == Blockly.ToolboxSeparator.registrationName &&
|
||||
prevIsFlyoutItem)) {
|
||||
var flyoutItem = /** @type {Blockly.utils.toolbox.FlyoutItemInfo} */ (itemDef);
|
||||
if (!registry.hasItem(registry.Type.TOOLBOX_ITEM, itemDef['kind']) ||
|
||||
(itemDef['kind'].toLowerCase() == ToolboxSeparator.registrationName &&
|
||||
prevIsFlyoutItem)) {
|
||||
const flyoutItem = /** @type {toolbox.FlyoutItemInfo} */ (itemDef);
|
||||
this.flyoutItems_.push(flyoutItem);
|
||||
prevIsFlyoutItem = true;
|
||||
} else {
|
||||
@@ -126,46 +130,46 @@ Blockly.CollapsibleToolboxCategory.prototype.parseContents_ = function(categoryD
|
||||
|
||||
/**
|
||||
* Creates a toolbox item and adds it to the list of toolbox items.
|
||||
* @param {!Blockly.utils.toolbox.ToolboxItemInfo} itemDef The information needed
|
||||
* @param {!toolbox.ToolboxItemInfo} itemDef The information needed
|
||||
* to create a toolbox item.
|
||||
* @private
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.createToolboxItem_ = function(itemDef) {
|
||||
var registryName = itemDef['kind'];
|
||||
var categoryDef = /** @type {!Blockly.utils.toolbox.CategoryInfo} */ (itemDef);
|
||||
CollapsibleToolboxCategory.prototype.createToolboxItem_ = function(itemDef) {
|
||||
let registryName = itemDef['kind'];
|
||||
const categoryDef = /** @type {!toolbox.CategoryInfo} */ (itemDef);
|
||||
|
||||
// Categories that are collapsible are created using a class registered under
|
||||
// a diffferent name.
|
||||
if (registryName.toUpperCase() == 'CATEGORY' &&
|
||||
Blockly.utils.toolbox.isCategoryCollapsible(categoryDef)) {
|
||||
registryName = Blockly.CollapsibleToolboxCategory.registrationName;
|
||||
toolbox.isCategoryCollapsible(categoryDef)) {
|
||||
registryName = CollapsibleToolboxCategory.registrationName;
|
||||
}
|
||||
var ToolboxItemClass = Blockly.registry.getClass(
|
||||
Blockly.registry.Type.TOOLBOX_ITEM, registryName);
|
||||
var toolboxItem = new ToolboxItemClass(itemDef, this.parentToolbox_, this);
|
||||
const ToolboxItemClass =
|
||||
registry.getClass(registry.Type.TOOLBOX_ITEM, registryName);
|
||||
const toolboxItem = new ToolboxItemClass(itemDef, this.parentToolbox_, this);
|
||||
this.toolboxItems_.push(toolboxItem);
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.init = function() {
|
||||
Blockly.CollapsibleToolboxCategory.superClass_.init.call(this);
|
||||
CollapsibleToolboxCategory.prototype.init = function() {
|
||||
CollapsibleToolboxCategory.superClass_.init.call(this);
|
||||
|
||||
this.setExpanded(this.toolboxItemDef_['expanded'] == 'true' ||
|
||||
this.setExpanded(
|
||||
this.toolboxItemDef_['expanded'] == 'true' ||
|
||||
this.toolboxItemDef_['expanded']);
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.createDom_ = function() {
|
||||
Blockly.CollapsibleToolboxCategory.superClass_.createDom_.call(this);
|
||||
CollapsibleToolboxCategory.prototype.createDom_ = function() {
|
||||
CollapsibleToolboxCategory.superClass_.createDom_.call(this);
|
||||
|
||||
var subCategories = this.getChildToolboxItems();
|
||||
const subCategories = this.getChildToolboxItems();
|
||||
this.subcategoriesDiv_ = this.createSubCategoriesDom_(subCategories);
|
||||
Blockly.utils.aria.setRole(this.subcategoriesDiv_,
|
||||
Blockly.utils.aria.Role.GROUP);
|
||||
aria.setRole(this.subcategoriesDiv_, aria.Role.GROUP);
|
||||
this.htmlDiv_.appendChild(this.subcategoriesDiv_);
|
||||
|
||||
return this.htmlDiv_;
|
||||
@@ -174,10 +178,10 @@ Blockly.CollapsibleToolboxCategory.prototype.createDom_ = function() {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.createIconDom_ = function() {
|
||||
var toolboxIcon = document.createElement('span');
|
||||
CollapsibleToolboxCategory.prototype.createIconDom_ = function() {
|
||||
const toolboxIcon = document.createElement('span');
|
||||
if (!this.parentToolbox_.isHorizontal()) {
|
||||
Blockly.utils.dom.addClass(toolboxIcon, this.cssConfig_['icon']);
|
||||
dom.addClass(toolboxIcon, this.cssConfig_['icon']);
|
||||
toolboxIcon.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
@@ -187,18 +191,19 @@ Blockly.CollapsibleToolboxCategory.prototype.createIconDom_ = function() {
|
||||
|
||||
/**
|
||||
* Create the DOM for all subcategories.
|
||||
* @param {!Array<!Blockly.ToolboxItem>} subcategories The subcategories.
|
||||
* @param {!Array<!IToolboxItem>} subcategories The subcategories.
|
||||
* @return {!Element} The div holding all the subcategories.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.createSubCategoriesDom_ = function(subcategories) {
|
||||
var contentsContainer = document.createElement('div');
|
||||
Blockly.utils.dom.addClass(contentsContainer, this.cssConfig_['contents']);
|
||||
CollapsibleToolboxCategory.prototype.createSubCategoriesDom_ = function(
|
||||
subcategories) {
|
||||
const contentsContainer = document.createElement('div');
|
||||
dom.addClass(contentsContainer, this.cssConfig_['contents']);
|
||||
|
||||
for (var i = 0; i < subcategories.length; i++) {
|
||||
var newCategory = subcategories[i];
|
||||
for (let i = 0; i < subcategories.length; i++) {
|
||||
const newCategory = subcategories[i];
|
||||
newCategory.init();
|
||||
var newCategoryDiv = newCategory.getDiv();
|
||||
const newCategoryDiv = newCategory.getDiv();
|
||||
contentsContainer.appendChild(newCategoryDiv);
|
||||
if (newCategory.getClickTarget) {
|
||||
newCategory.getClickTarget().setAttribute('id', newCategory.getId());
|
||||
@@ -213,7 +218,7 @@ Blockly.CollapsibleToolboxCategory.prototype.createSubCategoriesDom_ = function(
|
||||
* @param {boolean} isExpanded True to expand the category, false to close.
|
||||
* @public
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded) {
|
||||
CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded) {
|
||||
if (this.expanded_ == isExpanded) {
|
||||
return;
|
||||
}
|
||||
@@ -225,8 +230,8 @@ Blockly.CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded)
|
||||
this.subcategoriesDiv_.style.display = 'none';
|
||||
this.closeIcon_(this.iconDom_);
|
||||
}
|
||||
Blockly.utils.aria.setState(/** @type {!Element} */ (this.htmlDiv_),
|
||||
Blockly.utils.aria.State.EXPANDED, isExpanded);
|
||||
aria.setState(
|
||||
/** @type {!Element} */ (this.htmlDiv_), aria.State.EXPANDED, isExpanded);
|
||||
|
||||
this.parentToolbox_.handleToolboxItemResize();
|
||||
};
|
||||
@@ -234,9 +239,11 @@ Blockly.CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded)
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.setVisible_ = function(isVisible) {
|
||||
CollapsibleToolboxCategory.prototype.setVisible_ = function(isVisible) {
|
||||
this.htmlDiv_.style.display = isVisible ? 'block' : 'none';
|
||||
for (var i = 0, child; (child = this.getChildToolboxItems()[i]); i++) {
|
||||
const childToolboxItems = this.getChildToolboxItems();
|
||||
for (let i = 0; i < childToolboxItems.length; i++) {
|
||||
const child = childToolboxItems[i];
|
||||
child.setVisible_(isVisible);
|
||||
}
|
||||
this.isHidden_ = !isVisible;
|
||||
@@ -252,21 +259,21 @@ Blockly.CollapsibleToolboxCategory.prototype.setVisible_ = function(isVisible) {
|
||||
* is collapsed.
|
||||
* @public
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.isExpanded = function() {
|
||||
CollapsibleToolboxCategory.prototype.isExpanded = function() {
|
||||
return this.expanded_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.isCollapsible = function() {
|
||||
CollapsibleToolboxCategory.prototype.isCollapsible = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.onClick = function(_e) {
|
||||
CollapsibleToolboxCategory.prototype.onClick = function(_e) {
|
||||
this.toggleExpanded();
|
||||
};
|
||||
|
||||
@@ -274,25 +281,28 @@ Blockly.CollapsibleToolboxCategory.prototype.onClick = function(_e) {
|
||||
* Toggles whether or not the category is expanded.
|
||||
* @public
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.toggleExpanded = function() {
|
||||
CollapsibleToolboxCategory.prototype.toggleExpanded = function() {
|
||||
this.setExpanded(!this.expanded_);
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.getDiv = function() {
|
||||
CollapsibleToolboxCategory.prototype.getDiv = function() {
|
||||
return this.htmlDiv_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets any children toolbox items. (ex. Gets the subcategories)
|
||||
* @return {!Array<!Blockly.IToolboxItem>} The child toolbox items.
|
||||
* @return {!Array<!IToolboxItem>} The child toolbox items.
|
||||
*/
|
||||
Blockly.CollapsibleToolboxCategory.prototype.getChildToolboxItems = function() {
|
||||
CollapsibleToolboxCategory.prototype.getChildToolboxItems = function() {
|
||||
return this.toolboxItems_;
|
||||
};
|
||||
|
||||
|
||||
Blockly.registry.register(Blockly.registry.Type.TOOLBOX_ITEM,
|
||||
Blockly.CollapsibleToolboxCategory.registrationName, Blockly.CollapsibleToolboxCategory);
|
||||
registry.register(
|
||||
registry.Type.TOOLBOX_ITEM, CollapsibleToolboxCategory.registrationName,
|
||||
CollapsibleToolboxCategory);
|
||||
|
||||
exports = CollapsibleToolboxCategory;
|
||||
|
||||
@@ -16,36 +16,37 @@
|
||||
* @name Blockly.utils.dom
|
||||
* @namespace
|
||||
*/
|
||||
goog.provide('Blockly.utils.dom');
|
||||
goog.module('Blockly.utils.dom');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.utils.Svg');
|
||||
goog.require('Blockly.utils.userAgent');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const userAgent = goog.require('Blockly.utils.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Required name space for SVG elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.utils.dom.SVG_NS = 'http://www.w3.org/2000/svg';
|
||||
const SVG_NS = 'http://www.w3.org/2000/svg';
|
||||
|
||||
/**
|
||||
* Required name space for HTML elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.utils.dom.HTML_NS = 'http://www.w3.org/1999/xhtml';
|
||||
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
||||
|
||||
/**
|
||||
* Required name space for XLINK elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.utils.dom.XLINK_NS = 'http://www.w3.org/1999/xlink';
|
||||
const XLINK_NS = 'http://www.w3.org/1999/xlink';
|
||||
|
||||
/**
|
||||
* Node type constants.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
||||
* @enum {number}
|
||||
*/
|
||||
Blockly.utils.dom.NodeType = {
|
||||
const NodeType = {
|
||||
ELEMENT_NODE: 1,
|
||||
TEXT_NODE: 3,
|
||||
COMMENT_NODE: 8,
|
||||
@@ -57,36 +58,35 @@ Blockly.utils.dom.NodeType = {
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.dom.cacheWidths_ = null;
|
||||
let cacheWidths = null;
|
||||
|
||||
/**
|
||||
* Number of current references to cache.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.dom.cacheReference_ = 0;
|
||||
let cacheReference = 0;
|
||||
|
||||
/**
|
||||
* A HTML canvas context used for computing text width.
|
||||
* @type {CanvasRenderingContext2D}
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.dom.canvasContext_ = null;
|
||||
let canvasContext = null;
|
||||
|
||||
/**
|
||||
* Helper method for creating SVG elements.
|
||||
* @param {string|Blockly.utils.Svg<T>} name Element's tag name.
|
||||
* @param {string|Svg<T>} name Element's tag name.
|
||||
* @param {!Object} attrs Dictionary of attribute names and values.
|
||||
* @param {Element=} opt_parent Optional parent on which to append the element.
|
||||
* @return {T} Newly created SVG element. The return type is {!SVGElement} if
|
||||
* name is a string or a more specific type if it a member of
|
||||
* Blockly.utils.Svg
|
||||
* name is a string or a more specific type if it a member of Svg.
|
||||
* @template T
|
||||
*/
|
||||
Blockly.utils.dom.createSvgElement = function(name, attrs, opt_parent) {
|
||||
var e = /** @type {T} */
|
||||
(document.createElementNS(Blockly.utils.dom.SVG_NS, String(name)));
|
||||
for (var key in attrs) {
|
||||
const createSvgElement = function(name, attrs, opt_parent) {
|
||||
const e = /** @type {T} */
|
||||
(document.createElementNS(SVG_NS, String(name)));
|
||||
for (const key in attrs) {
|
||||
e.setAttribute(key, attrs[key]);
|
||||
}
|
||||
// IE defines a unique attribute "runtimeStyle", it is NOT applied to
|
||||
@@ -108,8 +108,8 @@ Blockly.utils.dom.createSvgElement = function(name, attrs, opt_parent) {
|
||||
* @param {string} className Name of class to add.
|
||||
* @return {boolean} True if class was added, false if already present.
|
||||
*/
|
||||
Blockly.utils.dom.addClass = function(element, className) {
|
||||
var classes = element.getAttribute('class') || '';
|
||||
const addClass = function(element, className) {
|
||||
let classes = element.getAttribute('class') || '';
|
||||
if ((' ' + classes + ' ').indexOf(' ' + className + ' ') != -1) {
|
||||
return false;
|
||||
}
|
||||
@@ -126,11 +126,10 @@ Blockly.utils.dom.addClass = function(element, className) {
|
||||
* @param {string} classNames A string of one or multiple class names for an
|
||||
* element.
|
||||
*/
|
||||
Blockly.utils.dom.removeClasses = function(element, classNames) {
|
||||
var classList = classNames.split(' ');
|
||||
for (var i = 0; i < classList.length; i++) {
|
||||
var cssName = classList[i];
|
||||
Blockly.utils.dom.removeClass(element, cssName);
|
||||
const removeClasses = function(element, classNames) {
|
||||
const classList = classNames.split(' ');
|
||||
for (let i = 0; i < classList.length; i++) {
|
||||
removeClass(element, classList[i]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -141,13 +140,13 @@ Blockly.utils.dom.removeClasses = function(element, classNames) {
|
||||
* @param {string} className Name of class to remove.
|
||||
* @return {boolean} True if class was removed, false if never present.
|
||||
*/
|
||||
Blockly.utils.dom.removeClass = function(element, className) {
|
||||
var classes = element.getAttribute('class');
|
||||
const removeClass = function(element, className) {
|
||||
const classes = element.getAttribute('class');
|
||||
if ((' ' + classes + ' ').indexOf(' ' + className + ' ') == -1) {
|
||||
return false;
|
||||
}
|
||||
var classList = classes.split(/\s+/);
|
||||
for (var i = 0; i < classList.length; i++) {
|
||||
const classList = classes.split(/\s+/);
|
||||
for (let i = 0; i < classList.length; i++) {
|
||||
if (!classList[i] || classList[i] == className) {
|
||||
classList.splice(i, 1);
|
||||
i--;
|
||||
@@ -168,8 +167,8 @@ Blockly.utils.dom.removeClass = function(element, className) {
|
||||
* @param {string} className Name of class to check.
|
||||
* @return {boolean} True if class exists, false otherwise.
|
||||
*/
|
||||
Blockly.utils.dom.hasClass = function(element, className) {
|
||||
var classes = element.getAttribute('class');
|
||||
const hasClass = function(element, className) {
|
||||
const classes = element.getAttribute('class');
|
||||
return (' ' + classes + ' ').indexOf(' ' + className + ' ') != -1;
|
||||
};
|
||||
|
||||
@@ -179,7 +178,7 @@ Blockly.utils.dom.hasClass = function(element, className) {
|
||||
* @return {?Node} The node removed if removed; else, null.
|
||||
*/
|
||||
// Copied from Closure goog.dom.removeNode
|
||||
Blockly.utils.dom.removeNode = function(node) {
|
||||
const removeNode = function(node) {
|
||||
return node && node.parentNode ? node.parentNode.removeChild(node) : null;
|
||||
};
|
||||
|
||||
@@ -189,9 +188,9 @@ Blockly.utils.dom.removeNode = function(node) {
|
||||
* @param {!Element} newNode New element to insert.
|
||||
* @param {!Element} refNode Existing element to precede new node.
|
||||
*/
|
||||
Blockly.utils.dom.insertAfter = function(newNode, refNode) {
|
||||
var siblingNode = refNode.nextSibling;
|
||||
var parentNode = refNode.parentNode;
|
||||
const insertAfter = function(newNode, refNode) {
|
||||
const siblingNode = refNode.nextSibling;
|
||||
const parentNode = refNode.parentNode;
|
||||
if (!parentNode) {
|
||||
throw Error('Reference node has no parent.');
|
||||
}
|
||||
@@ -208,9 +207,10 @@ Blockly.utils.dom.insertAfter = function(newNode, refNode) {
|
||||
* @param {!Node} descendant The node to test presence of.
|
||||
* @return {boolean} Whether the parent node contains the descendant node.
|
||||
*/
|
||||
Blockly.utils.dom.containsNode = function(parent, descendant) {
|
||||
return !!(parent.compareDocumentPosition(descendant) &
|
||||
Blockly.utils.dom.NodeType.DOCUMENT_POSITION_CONTAINED_BY);
|
||||
const containsNode = function(parent, descendant) {
|
||||
return !!(
|
||||
parent.compareDocumentPosition(descendant) &
|
||||
NodeType.DOCUMENT_POSITION_CONTAINED_BY);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -220,7 +220,7 @@ Blockly.utils.dom.containsNode = function(parent, descendant) {
|
||||
* @param {!Element} element Element to which the CSS transform will be applied.
|
||||
* @param {string} transform The value of the CSS `transform` property.
|
||||
*/
|
||||
Blockly.utils.dom.setCssTransform = function(element, transform) {
|
||||
const setCssTransform = function(element, transform) {
|
||||
element.style['transform'] = transform;
|
||||
element.style['-webkit-transform'] = transform;
|
||||
};
|
||||
@@ -229,10 +229,10 @@ Blockly.utils.dom.setCssTransform = function(element, transform) {
|
||||
* Start caching text widths. Every call to this function MUST also call
|
||||
* stopTextWidthCache. Caches must not survive between execution threads.
|
||||
*/
|
||||
Blockly.utils.dom.startTextWidthCache = function() {
|
||||
Blockly.utils.dom.cacheReference_++;
|
||||
if (!Blockly.utils.dom.cacheWidths_) {
|
||||
Blockly.utils.dom.cacheWidths_ = Object.create(null);
|
||||
const startTextWidthCache = function() {
|
||||
cacheReference++;
|
||||
if (!cacheWidths) {
|
||||
cacheWidths = Object.create(null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -240,10 +240,10 @@ Blockly.utils.dom.startTextWidthCache = function() {
|
||||
* Stop caching field widths. Unless caching was already on when the
|
||||
* corresponding call to startTextWidthCache was made.
|
||||
*/
|
||||
Blockly.utils.dom.stopTextWidthCache = function() {
|
||||
Blockly.utils.dom.cacheReference_--;
|
||||
if (!Blockly.utils.dom.cacheReference_) {
|
||||
Blockly.utils.dom.cacheWidths_ = null;
|
||||
const stopTextWidthCache = function() {
|
||||
cacheReference--;
|
||||
if (!cacheReference) {
|
||||
cacheWidths = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -252,13 +252,13 @@ Blockly.utils.dom.stopTextWidthCache = function() {
|
||||
* @param {!Element} textElement An SVG 'text' element.
|
||||
* @return {number} Width of element.
|
||||
*/
|
||||
Blockly.utils.dom.getTextWidth = function(textElement) {
|
||||
var key = textElement.textContent + '\n' + textElement.className.baseVal;
|
||||
var width;
|
||||
const getTextWidth = function(textElement) {
|
||||
const key = textElement.textContent + '\n' + textElement.className.baseVal;
|
||||
let width;
|
||||
|
||||
// Return the cached width if it exists.
|
||||
if (Blockly.utils.dom.cacheWidths_) {
|
||||
width = Blockly.utils.dom.cacheWidths_[key];
|
||||
if (cacheWidths) {
|
||||
width = cacheWidths[key];
|
||||
if (width) {
|
||||
return width;
|
||||
}
|
||||
@@ -266,7 +266,7 @@ Blockly.utils.dom.getTextWidth = function(textElement) {
|
||||
|
||||
// Attempt to compute fetch the width of the SVG text element.
|
||||
try {
|
||||
if (Blockly.utils.userAgent.IE || Blockly.utils.userAgent.EDGE) {
|
||||
if (userAgent.IE || userAgent.EDGE) {
|
||||
width = textElement.getBBox().width;
|
||||
} else {
|
||||
width = textElement.getComputedTextLength();
|
||||
@@ -280,8 +280,8 @@ Blockly.utils.dom.getTextWidth = function(textElement) {
|
||||
}
|
||||
|
||||
// Cache the computed width and return.
|
||||
if (Blockly.utils.dom.cacheWidths_) {
|
||||
Blockly.utils.dom.cacheWidths_[key] = width;
|
||||
if (cacheWidths) {
|
||||
cacheWidths[key] = width;
|
||||
}
|
||||
return width;
|
||||
};
|
||||
@@ -296,10 +296,10 @@ Blockly.utils.dom.getTextWidth = function(textElement) {
|
||||
* @param {string} fontFamily The font family to use.
|
||||
* @return {number} Width of element.
|
||||
*/
|
||||
Blockly.utils.dom.getFastTextWidth = function(textElement,
|
||||
fontSize, fontWeight, fontFamily) {
|
||||
return Blockly.utils.dom.getFastTextWidthWithSizeString(textElement,
|
||||
fontSize + 'pt', fontWeight, fontFamily);
|
||||
const getFastTextWidth = function(
|
||||
textElement, fontSize, fontWeight, fontFamily) {
|
||||
return getFastTextWidthWithSizeString(
|
||||
textElement, fontSize + 'pt', fontWeight, fontFamily);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -314,41 +314,40 @@ Blockly.utils.dom.getFastTextWidth = function(textElement,
|
||||
* @param {string} fontFamily The font family to use.
|
||||
* @return {number} Width of element.
|
||||
*/
|
||||
Blockly.utils.dom.getFastTextWidthWithSizeString = function(textElement,
|
||||
fontSize, fontWeight, fontFamily) {
|
||||
var text = textElement.textContent;
|
||||
var key = text + '\n' + textElement.className.baseVal;
|
||||
var width;
|
||||
const getFastTextWidthWithSizeString = function(
|
||||
textElement, fontSize, fontWeight, fontFamily) {
|
||||
const text = textElement.textContent;
|
||||
const key = text + '\n' + textElement.className.baseVal;
|
||||
let width;
|
||||
|
||||
// Return the cached width if it exists.
|
||||
if (Blockly.utils.dom.cacheWidths_) {
|
||||
width = Blockly.utils.dom.cacheWidths_[key];
|
||||
if (cacheWidths) {
|
||||
width = cacheWidths[key];
|
||||
if (width) {
|
||||
return width;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Blockly.utils.dom.canvasContext_) {
|
||||
if (!canvasContext) {
|
||||
// Inject the canvas element used for computing text widths.
|
||||
var computeCanvas = document.createElement('canvas');
|
||||
const computeCanvas = document.createElement('canvas');
|
||||
computeCanvas.className = 'blocklyComputeCanvas';
|
||||
document.body.appendChild(computeCanvas);
|
||||
|
||||
// Initialize the HTML canvas context and set the font.
|
||||
// The context font must match blocklyText's fontsize and font-family
|
||||
// set in CSS.
|
||||
Blockly.utils.dom.canvasContext_ = computeCanvas.getContext('2d');
|
||||
canvasContext = computeCanvas.getContext('2d');
|
||||
}
|
||||
// Set the desired font size and family.
|
||||
Blockly.utils.dom.canvasContext_.font =
|
||||
fontWeight + ' ' + fontSize + ' ' + fontFamily;
|
||||
canvasContext.font = fontWeight + ' ' + fontSize + ' ' + fontFamily;
|
||||
|
||||
// Measure the text width using the helper canvas context.
|
||||
width = Blockly.utils.dom.canvasContext_.measureText(text).width;
|
||||
width = canvasContext.measureText(text).width;
|
||||
|
||||
// Cache the computed width and return.
|
||||
if (Blockly.utils.dom.cacheWidths_) {
|
||||
Blockly.utils.dom.cacheWidths_[key] = width;
|
||||
if (cacheWidths) {
|
||||
cacheWidths[key] = width;
|
||||
}
|
||||
return width;
|
||||
};
|
||||
@@ -361,18 +360,16 @@ Blockly.utils.dom.getFastTextWidthWithSizeString = function(textElement,
|
||||
* @param {string} fontFamily The font family to use.
|
||||
* @return {{height: number, baseline: number}} Font measurements.
|
||||
*/
|
||||
Blockly.utils.dom.measureFontMetrics = function(text, fontSize, fontWeight,
|
||||
fontFamily) {
|
||||
|
||||
var span = document.createElement('span');
|
||||
const measureFontMetrics = function(text, fontSize, fontWeight, fontFamily) {
|
||||
const span = document.createElement('span');
|
||||
span.style.font = fontWeight + ' ' + fontSize + ' ' + fontFamily;
|
||||
span.textContent = text;
|
||||
|
||||
var block = document.createElement('div');
|
||||
const block = document.createElement('div');
|
||||
block.style.width = '1px';
|
||||
block.style.height = 0;
|
||||
|
||||
var div = document.createElement('div');
|
||||
const div = document.createElement('div');
|
||||
div.setAttribute('style', 'position: fixed; top: 0; left: 0; display: flex;');
|
||||
div.appendChild(span);
|
||||
div.appendChild(block);
|
||||
@@ -389,3 +386,25 @@ Blockly.utils.dom.measureFontMetrics = function(text, fontSize, fontWeight,
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
exports = {
|
||||
SVG_NS,
|
||||
HTML_NS,
|
||||
XLINK_NS,
|
||||
NodeType,
|
||||
createSvgElement,
|
||||
addClass,
|
||||
removeClasses,
|
||||
removeClass,
|
||||
hasClass,
|
||||
removeNode,
|
||||
insertAfter,
|
||||
containsNode,
|
||||
setCssTransform,
|
||||
startTextWidthCache,
|
||||
stopTextWidthCache,
|
||||
getTextWidth,
|
||||
getFastTextWidth,
|
||||
getFastTextWidthWithSizeString,
|
||||
measureFontMetrics,
|
||||
};
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @name Blockly.utils.Size
|
||||
* @name Size
|
||||
* @namespace
|
||||
*/
|
||||
goog.provide('Blockly.utils.Size');
|
||||
goog.module('Blockly.utils.Size');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,7 +27,7 @@ goog.provide('Blockly.utils.Size');
|
||||
* @struct
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.utils.Size = function(width, height) {
|
||||
const Size = function(width, height) {
|
||||
/**
|
||||
* Width
|
||||
* @type {number}
|
||||
@@ -42,12 +43,12 @@ Blockly.utils.Size = function(width, height) {
|
||||
|
||||
/**
|
||||
* Compares sizes for equality.
|
||||
* @param {?Blockly.utils.Size} a A Size.
|
||||
* @param {?Blockly.utils.Size} b A Size.
|
||||
* @param {?Size} a A Size.
|
||||
* @param {?Size} b A Size.
|
||||
* @return {boolean} True iff the sizes have equal widths and equal
|
||||
* heights, or if both are null.
|
||||
*/
|
||||
Blockly.utils.Size.equals = function(a, b) {
|
||||
Size.equals = function(a, b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
@@ -56,3 +57,5 @@ Blockly.utils.Size.equals = function(a, b) {
|
||||
}
|
||||
return a.width == b.width && a.height == b.height;
|
||||
};
|
||||
|
||||
exports = Size;
|
||||
|
||||
@@ -10,51 +10,53 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Warning');
|
||||
goog.module('Blockly.Warning');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Bubble');
|
||||
goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockSvg = goog.requireType('Blockly.BlockSvg');
|
||||
const Bubble = goog.require('Blockly.Bubble');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Coordinate = goog.requireType('Blockly.utils.Coordinate');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
const Icon = goog.require('Blockly.Icon');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const object = goog.require('Blockly.utils.object');
|
||||
/** @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.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.BlockSvg');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a warning.
|
||||
* @param {!Blockly.Block} block The block associated with this warning.
|
||||
* @extends {Blockly.Icon}
|
||||
* @param {!Block} block The block associated with this warning.
|
||||
* @extends {Icon}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Warning = function(block) {
|
||||
Blockly.Warning.superClass_.constructor.call(this, block);
|
||||
const Warning = function(block) {
|
||||
Warning.superClass_.constructor.call(this, block);
|
||||
this.createIcon();
|
||||
// The text_ object can contain multiple warnings.
|
||||
this.text_ = Object.create(null);
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.Warning, Blockly.Icon);
|
||||
object.inherits(Warning, Icon);
|
||||
|
||||
/**
|
||||
* Does this icon get hidden when the block is collapsed.
|
||||
*/
|
||||
Blockly.Warning.prototype.collapseHidden = false;
|
||||
Warning.prototype.collapseHidden = false;
|
||||
|
||||
/**
|
||||
* Draw the warning icon.
|
||||
* @param {!Element} group The icon group.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Warning.prototype.drawIcon_ = function(group) {
|
||||
Warning.prototype.drawIcon_ = function(group) {
|
||||
// Triangle with rounded corners.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATH,
|
||||
{
|
||||
dom.createSvgElement(
|
||||
Svg.PATH, {
|
||||
'class': 'blocklyIconShape',
|
||||
'd': 'M2,15Q-1,15 0.5,12L6.5,1.7Q8,-1 9.5,1.7L15.5,12Q17,15 14,15z'
|
||||
},
|
||||
@@ -62,19 +64,20 @@ Blockly.Warning.prototype.drawIcon_ = function(group) {
|
||||
// Can't use a real '!' text character since different browsers and operating
|
||||
// systems render it differently.
|
||||
// Body of exclamation point.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.PATH,
|
||||
{
|
||||
dom.createSvgElement(
|
||||
Svg.PATH, {
|
||||
'class': 'blocklyIconSymbol',
|
||||
'd': 'm7,4.8v3.16l0.27,2.27h1.46l0.27,-2.27v-3.16z'
|
||||
},
|
||||
group);
|
||||
// Dot of exclamation point.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
dom.createSvgElement(
|
||||
Svg.RECT, {
|
||||
'class': 'blocklyIconSymbol',
|
||||
'x': '7', 'y': '11', 'height': '2', 'width': '2'
|
||||
'x': '7',
|
||||
'y': '11',
|
||||
'height': '2',
|
||||
'width': '2'
|
||||
},
|
||||
group);
|
||||
};
|
||||
@@ -83,12 +86,12 @@ Blockly.Warning.prototype.drawIcon_ = function(group) {
|
||||
* Show or hide the warning bubble.
|
||||
* @param {boolean} visible True if the bubble should be visible.
|
||||
*/
|
||||
Blockly.Warning.prototype.setVisible = function(visible) {
|
||||
Warning.prototype.setVisible = function(visible) {
|
||||
if (visible == this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BUBBLE_OPEN))(
|
||||
this.block_, visible, 'warning'));
|
||||
Events.fire(
|
||||
new (Events.get(Events.BUBBLE_OPEN))(this.block_, visible, 'warning'));
|
||||
if (visible) {
|
||||
this.createBubble_();
|
||||
} else {
|
||||
@@ -100,11 +103,11 @@ Blockly.Warning.prototype.setVisible = function(visible) {
|
||||
* Show the bubble.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Warning.prototype.createBubble_ = function() {
|
||||
this.paragraphElement_ = Blockly.Bubble.textToDom(this.getText());
|
||||
this.bubble_ = Blockly.Bubble.createNonEditableBubble(
|
||||
this.paragraphElement_, /** @type {!Blockly.BlockSvg} */ (this.block_),
|
||||
/** @type {!Blockly.utils.Coordinate} */ (this.iconXY_));
|
||||
Warning.prototype.createBubble_ = function() {
|
||||
this.paragraphElement_ = Bubble.textToDom(this.getText());
|
||||
this.bubble_ = Bubble.createNonEditableBubble(
|
||||
this.paragraphElement_, /** @type {!BlockSvg} */ (this.block_),
|
||||
/** @type {!Coordinate} */ (this.iconXY_));
|
||||
this.applyColour();
|
||||
};
|
||||
|
||||
@@ -112,7 +115,7 @@ Blockly.Warning.prototype.createBubble_ = function() {
|
||||
* Dispose of the bubble and references to it.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Warning.prototype.disposeBubble_ = function() {
|
||||
Warning.prototype.disposeBubble_ = function() {
|
||||
this.bubble_.dispose();
|
||||
this.bubble_ = null;
|
||||
this.paragraphElement_ = null;
|
||||
@@ -125,7 +128,7 @@ Blockly.Warning.prototype.disposeBubble_ = function() {
|
||||
* @param {string} id An ID for this text entry to be able to maintain
|
||||
* multiple warnings.
|
||||
*/
|
||||
Blockly.Warning.prototype.setText = function(text, id) {
|
||||
Warning.prototype.setText = function(text, id) {
|
||||
if (this.text_[id] == text) {
|
||||
return;
|
||||
}
|
||||
@@ -144,9 +147,9 @@ Blockly.Warning.prototype.setText = function(text, id) {
|
||||
* Get this warning's texts.
|
||||
* @return {string} All texts concatenated into one string.
|
||||
*/
|
||||
Blockly.Warning.prototype.getText = function() {
|
||||
var allWarnings = [];
|
||||
for (var id in this.text_) {
|
||||
Warning.prototype.getText = function() {
|
||||
const allWarnings = [];
|
||||
for (const id in this.text_) {
|
||||
allWarnings.push(this.text_[id]);
|
||||
}
|
||||
return allWarnings.join('\n');
|
||||
@@ -155,7 +158,9 @@ Blockly.Warning.prototype.getText = function() {
|
||||
/**
|
||||
* Dispose of this warning.
|
||||
*/
|
||||
Blockly.Warning.prototype.dispose = function() {
|
||||
Warning.prototype.dispose = function() {
|
||||
this.block_.warning = null;
|
||||
Blockly.Icon.prototype.dispose.call(this);
|
||||
Icon.prototype.dispose.call(this);
|
||||
};
|
||||
|
||||
exports = Warning;
|
||||
|
||||
@@ -11,28 +11,27 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.WorkspaceAudio');
|
||||
goog.module('Blockly.WorkspaceAudio');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.internalConstants');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.global');
|
||||
goog.require('Blockly.utils.userAgent');
|
||||
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const global = goog.require('Blockly.utils.global');
|
||||
const internalConstants = goog.require('Blockly.internalConstants');
|
||||
const userAgent = goog.require('Blockly.utils.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Class for loading, storing, and playing audio for a workspace.
|
||||
* @param {Blockly.WorkspaceSvg} parentWorkspace The parent of the workspace
|
||||
* @param {WorkspaceSvg} parentWorkspace The parent of the workspace
|
||||
* this audio object belongs to, or null.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.WorkspaceAudio = function(parentWorkspace) {
|
||||
|
||||
const WorkspaceAudio = function(parentWorkspace) {
|
||||
/**
|
||||
* The parent of the workspace this object belongs to, or null. May be
|
||||
* checked for sounds that this object can't find.
|
||||
* @type {Blockly.WorkspaceSvg}
|
||||
* @type {WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
this.parentWorkspace_ = parentWorkspace;
|
||||
@@ -49,13 +48,13 @@ Blockly.WorkspaceAudio = function(parentWorkspace) {
|
||||
* @type {Date}
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceAudio.prototype.lastSound_ = null;
|
||||
WorkspaceAudio.prototype.lastSound_ = null;
|
||||
|
||||
/**
|
||||
* Dispose of this audio manager.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceAudio.prototype.dispose = function() {
|
||||
WorkspaceAudio.prototype.dispose = function() {
|
||||
this.parentWorkspace_ = null;
|
||||
this.SOUNDS_ = null;
|
||||
};
|
||||
@@ -67,24 +66,25 @@ Blockly.WorkspaceAudio.prototype.dispose = function() {
|
||||
* Filenames include path from Blockly's root. File extensions matter.
|
||||
* @param {string} name Name of sound.
|
||||
*/
|
||||
Blockly.WorkspaceAudio.prototype.load = function(filenames, name) {
|
||||
WorkspaceAudio.prototype.load = function(filenames, name) {
|
||||
if (!filenames.length) {
|
||||
return;
|
||||
}
|
||||
let audioTest;
|
||||
try {
|
||||
var audioTest = new Blockly.utils.global['Audio']();
|
||||
audioTest = new global['Audio']();
|
||||
} catch (e) {
|
||||
// No browser support for Audio.
|
||||
// IE can throw an error even if the Audio object exists.
|
||||
return;
|
||||
}
|
||||
var sound;
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
var filename = filenames[i];
|
||||
var ext = filename.match(/\.(\w+)$/);
|
||||
let sound;
|
||||
for (let i = 0; i < filenames.length; i++) {
|
||||
const filename = filenames[i];
|
||||
const ext = filename.match(/\.(\w+)$/);
|
||||
if (ext && audioTest.canPlayType('audio/' + ext[1])) {
|
||||
// Found an audio format we can play.
|
||||
sound = new Blockly.utils.global['Audio'](filename);
|
||||
sound = new global['Audio'](filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -97,16 +97,17 @@ Blockly.WorkspaceAudio.prototype.load = function(filenames, name) {
|
||||
* Preload all the audio files so that they play quickly when asked for.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceAudio.prototype.preload = function() {
|
||||
for (var name in this.SOUNDS_) {
|
||||
var sound = this.SOUNDS_[name];
|
||||
WorkspaceAudio.prototype.preload = function() {
|
||||
for (const name in this.SOUNDS_) {
|
||||
const sound = this.SOUNDS_[name];
|
||||
sound.volume = 0.01;
|
||||
var playPromise = sound.play();
|
||||
const playPromise = sound.play();
|
||||
// Edge does not return a promise, so we need to check.
|
||||
if (playPromise !== undefined) {
|
||||
// If we don't wait for the play request to complete before calling pause()
|
||||
// we will get an exception: (DOMException: The play() request was interrupted)
|
||||
// See more: https://developers.google.com/web/updates/2017/06/play-request-was-interrupted
|
||||
// If we don't wait for the play request to complete before calling
|
||||
// pause() we will get an exception: (DOMException: The play() request was
|
||||
// interrupted) See more:
|
||||
// https://developers.google.com/web/updates/2017/06/play-request-was-interrupted
|
||||
playPromise.then(sound.pause).catch(function() {
|
||||
// Play without user interaction was prevented.
|
||||
});
|
||||
@@ -116,7 +117,7 @@ Blockly.WorkspaceAudio.prototype.preload = function() {
|
||||
|
||||
// iOS can only process one sound at a time. Trying to load more than one
|
||||
// corrupts the earlier ones. Just load one and leave the others uncached.
|
||||
if (Blockly.utils.userAgent.IPAD || Blockly.utils.userAgent.IPHONE) {
|
||||
if (userAgent.IPAD || userAgent.IPHONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -128,18 +129,18 @@ Blockly.WorkspaceAudio.prototype.preload = function() {
|
||||
* @param {string} name Name of sound.
|
||||
* @param {number=} opt_volume Volume of sound (0-1).
|
||||
*/
|
||||
Blockly.WorkspaceAudio.prototype.play = function(name, opt_volume) {
|
||||
var sound = this.SOUNDS_[name];
|
||||
WorkspaceAudio.prototype.play = function(name, opt_volume) {
|
||||
const sound = this.SOUNDS_[name];
|
||||
if (sound) {
|
||||
// Don't play one sound on top of another.
|
||||
var now = new Date;
|
||||
const now = new Date;
|
||||
if (this.lastSound_ != null &&
|
||||
now - this.lastSound_ < Blockly.internalConstants.SOUND_LIMIT) {
|
||||
now - this.lastSound_ < internalConstants.SOUND_LIMIT) {
|
||||
return;
|
||||
}
|
||||
this.lastSound_ = now;
|
||||
var mySound;
|
||||
if (Blockly.utils.userAgent.IPAD || Blockly.utils.userAgent.ANDROID) {
|
||||
let mySound;
|
||||
if (userAgent.IPAD || userAgent.ANDROID) {
|
||||
// Creating a new audio node causes lag in Android and iPad. Android
|
||||
// refetches the file from the server, iPad uses a singleton audio
|
||||
// node which must be deleted and recreated for each new audio tag.
|
||||
@@ -154,3 +155,5 @@ Blockly.WorkspaceAudio.prototype.play = function(name, opt_volume) {
|
||||
this.parentWorkspace_.getAudioManager().play(name, opt_volume);
|
||||
}
|
||||
};
|
||||
|
||||
exports = WorkspaceAudio;
|
||||
|
||||
@@ -10,9 +10,15 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.WorkspaceComment');
|
||||
goog.module('Blockly.WorkspaceComment');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Events');
|
||||
const Coordinate = goog.require('Blockly.utils.Coordinate');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
const utils = goog.require('Blockly.utils');
|
||||
const xml = goog.require('Blockly.utils.xml');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.CommentChange');
|
||||
/** @suppress {extraRequire} */
|
||||
@@ -21,14 +27,11 @@ goog.require('Blockly.Events.CommentCreate');
|
||||
goog.require('Blockly.Events.CommentDelete');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.CommentMove');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.xml');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a workspace comment.
|
||||
* @param {!Blockly.Workspace} workspace The block's workspace.
|
||||
* @param {!Workspace} workspace The block's workspace.
|
||||
* @param {string} content The content of this workspace comment.
|
||||
* @param {number} height Height of the comment.
|
||||
* @param {number} width Width of the comment.
|
||||
@@ -36,20 +39,20 @@ goog.require('Blockly.utils.xml');
|
||||
* create a new ID.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.WorkspaceComment = function(workspace, content, height, width, opt_id) {
|
||||
const WorkspaceComment = function(workspace, content, height, width, opt_id) {
|
||||
/** @type {string} */
|
||||
this.id = (opt_id && !workspace.getCommentById(opt_id)) ?
|
||||
opt_id : Blockly.utils.genUid();
|
||||
this.id =
|
||||
(opt_id && !workspace.getCommentById(opt_id)) ? opt_id : utils.genUid();
|
||||
|
||||
workspace.addTopComment(this);
|
||||
|
||||
/**
|
||||
* The comment's position in workspace units. (0, 0) is at the workspace's
|
||||
* origin; scale does not change this value.
|
||||
* @type {!Blockly.utils.Coordinate}
|
||||
* @type {!Coordinate}
|
||||
* @protected
|
||||
*/
|
||||
this.xy_ = new Blockly.utils.Coordinate(0, 0);
|
||||
this.xy_ = new Coordinate(0, 0);
|
||||
|
||||
/**
|
||||
* The comment's height in workspace units. Scale does not change this value.
|
||||
@@ -66,7 +69,7 @@ Blockly.WorkspaceComment = function(workspace, content, height, width, opt_id) {
|
||||
this.width_ = width;
|
||||
|
||||
/**
|
||||
* @type {!Blockly.Workspace}
|
||||
* @type {!Workspace}
|
||||
*/
|
||||
this.workspace = workspace;
|
||||
|
||||
@@ -106,22 +109,21 @@ Blockly.WorkspaceComment = function(workspace, content, height, width, opt_id) {
|
||||
*/
|
||||
this.isComment = true;
|
||||
|
||||
Blockly.WorkspaceComment.fireCreateEvent(this);
|
||||
WorkspaceComment.fireCreateEvent(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispose of this comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.dispose = function() {
|
||||
WorkspaceComment.prototype.dispose = function() {
|
||||
if (!this.workspace) {
|
||||
// The comment has already been deleted.
|
||||
return;
|
||||
}
|
||||
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
Blockly.Events.fire(
|
||||
new (Blockly.Events.get(Blockly.Events.COMMENT_DELETE))(this));
|
||||
if (Events.isEnabled()) {
|
||||
Events.fire(new (Events.get(Events.COMMENT_DELETE))(this));
|
||||
}
|
||||
|
||||
// Remove from the list of top comments and the comment database.
|
||||
@@ -137,7 +139,7 @@ Blockly.WorkspaceComment.prototype.dispose = function() {
|
||||
* @return {number} Comment height.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getHeight = function() {
|
||||
WorkspaceComment.prototype.getHeight = function() {
|
||||
return this.height_;
|
||||
};
|
||||
|
||||
@@ -146,7 +148,7 @@ Blockly.WorkspaceComment.prototype.getHeight = function() {
|
||||
* @param {number} height Comment height.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setHeight = function(height) {
|
||||
WorkspaceComment.prototype.setHeight = function(height) {
|
||||
this.height_ = height;
|
||||
};
|
||||
|
||||
@@ -155,7 +157,7 @@ Blockly.WorkspaceComment.prototype.setHeight = function(height) {
|
||||
* @return {number} Comment width.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getWidth = function() {
|
||||
WorkspaceComment.prototype.getWidth = function() {
|
||||
return this.width_;
|
||||
};
|
||||
|
||||
@@ -164,18 +166,18 @@ Blockly.WorkspaceComment.prototype.getWidth = function() {
|
||||
* @param {number} width comment width.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setWidth = function(width) {
|
||||
WorkspaceComment.prototype.setWidth = function(width) {
|
||||
this.width_ = width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get stored location.
|
||||
* @return {!Blockly.utils.Coordinate} The comment's stored location.
|
||||
* @return {!Coordinate} The comment's stored location.
|
||||
* This is not valid if the comment is currently being dragged.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getXY = function() {
|
||||
return new Blockly.utils.Coordinate(this.xy_.x, this.xy_.y);
|
||||
WorkspaceComment.prototype.getXY = function() {
|
||||
return new Coordinate(this.xy_.x, this.xy_.y);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -184,11 +186,11 @@ Blockly.WorkspaceComment.prototype.getXY = function() {
|
||||
* @param {number} dy Vertical offset, in workspace units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.moveBy = function(dx, dy) {
|
||||
var event = new (Blockly.Events.get(Blockly.Events.COMMENT_MOVE))(this);
|
||||
WorkspaceComment.prototype.moveBy = function(dx, dy) {
|
||||
const event = new (Events.get(Events.COMMENT_MOVE))(this);
|
||||
this.xy_.translate(dx, dy);
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
Events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -196,7 +198,7 @@ Blockly.WorkspaceComment.prototype.moveBy = function(dx, dy) {
|
||||
* @return {boolean} True if deletable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.isDeletable = function() {
|
||||
WorkspaceComment.prototype.isDeletable = function() {
|
||||
return this.deletable_ &&
|
||||
!(this.workspace && this.workspace.options.readOnly);
|
||||
};
|
||||
@@ -206,7 +208,7 @@ Blockly.WorkspaceComment.prototype.isDeletable = function() {
|
||||
* @param {boolean} deletable True if deletable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setDeletable = function(deletable) {
|
||||
WorkspaceComment.prototype.setDeletable = function(deletable) {
|
||||
this.deletable_ = deletable;
|
||||
};
|
||||
|
||||
@@ -215,9 +217,8 @@ Blockly.WorkspaceComment.prototype.setDeletable = function(deletable) {
|
||||
* @return {boolean} True if movable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.isMovable = function() {
|
||||
return this.movable_ &&
|
||||
!(this.workspace && this.workspace.options.readOnly);
|
||||
WorkspaceComment.prototype.isMovable = function() {
|
||||
return this.movable_ && !(this.workspace && this.workspace.options.readOnly);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -225,7 +226,7 @@ Blockly.WorkspaceComment.prototype.isMovable = function() {
|
||||
* @param {boolean} movable True if movable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setMovable = function(movable) {
|
||||
WorkspaceComment.prototype.setMovable = function(movable) {
|
||||
this.movable_ = movable;
|
||||
};
|
||||
|
||||
@@ -233,16 +234,15 @@ Blockly.WorkspaceComment.prototype.setMovable = function(movable) {
|
||||
* Get whether this comment is editable or not.
|
||||
* @return {boolean} True if editable.
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.isEditable = function() {
|
||||
return this.editable_ &&
|
||||
!(this.workspace && this.workspace.options.readOnly);
|
||||
WorkspaceComment.prototype.isEditable = function() {
|
||||
return this.editable_ && !(this.workspace && this.workspace.options.readOnly);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether this comment is editable or not.
|
||||
* @param {boolean} editable True if editable.
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setEditable = function(editable) {
|
||||
WorkspaceComment.prototype.setEditable = function(editable) {
|
||||
this.editable_ = editable;
|
||||
};
|
||||
|
||||
@@ -251,7 +251,7 @@ Blockly.WorkspaceComment.prototype.setEditable = function(editable) {
|
||||
* @return {string} Comment text.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getContent = function() {
|
||||
WorkspaceComment.prototype.getContent = function() {
|
||||
return this.content_;
|
||||
};
|
||||
|
||||
@@ -260,10 +260,10 @@ Blockly.WorkspaceComment.prototype.getContent = function() {
|
||||
* @param {string} content Comment content.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setContent = function(content) {
|
||||
WorkspaceComment.prototype.setContent = function(content) {
|
||||
if (this.content_ != content) {
|
||||
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.COMMENT_CHANGE))(
|
||||
this, this.content_, content));
|
||||
Events.fire(
|
||||
new (Events.get(Events.COMMENT_CHANGE))(this, this.content_, content));
|
||||
this.content_ = content;
|
||||
}
|
||||
};
|
||||
@@ -274,8 +274,8 @@ Blockly.WorkspaceComment.prototype.setContent = function(content) {
|
||||
* @return {!Element} Tree of XML elements.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.toXmlWithXY = function(opt_noId) {
|
||||
var element = this.toXml(opt_noId);
|
||||
WorkspaceComment.prototype.toXmlWithXY = function(opt_noId) {
|
||||
const element = this.toXml(opt_noId);
|
||||
element.setAttribute('x', Math.round(this.xy_.x));
|
||||
element.setAttribute('y', Math.round(this.xy_.y));
|
||||
element.setAttribute('h', this.height_);
|
||||
@@ -291,8 +291,8 @@ Blockly.WorkspaceComment.prototype.toXmlWithXY = function(opt_noId) {
|
||||
* @return {!Element} Tree of XML elements.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.toXml = function(opt_noId) {
|
||||
var commentElement = Blockly.utils.xml.createElement('comment');
|
||||
WorkspaceComment.prototype.toXml = function(opt_noId) {
|
||||
const commentElement = xml.createElement('comment');
|
||||
if (!opt_noId) {
|
||||
commentElement.id = this.id;
|
||||
}
|
||||
@@ -302,21 +302,20 @@ Blockly.WorkspaceComment.prototype.toXml = function(opt_noId) {
|
||||
|
||||
/**
|
||||
* Fire a create event for the given workspace comment, if comments are enabled.
|
||||
* @param {!Blockly.WorkspaceComment} comment The comment that was just created.
|
||||
* @param {!WorkspaceComment} comment The comment that was just created.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.fireCreateEvent = function(comment) {
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
var existingGroup = Blockly.Events.getGroup();
|
||||
WorkspaceComment.fireCreateEvent = function(comment) {
|
||||
if (Events.isEnabled()) {
|
||||
const existingGroup = Events.getGroup();
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(true);
|
||||
Events.setGroup(true);
|
||||
}
|
||||
try {
|
||||
Blockly.Events.fire(
|
||||
new (Blockly.Events.get(Blockly.Events.COMMENT_CREATE))(comment));
|
||||
Events.fire(new (Events.get(Events.COMMENT_CREATE))(comment));
|
||||
} finally {
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(false);
|
||||
Events.setGroup(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,23 +324,23 @@ Blockly.WorkspaceComment.fireCreateEvent = function(comment) {
|
||||
/**
|
||||
* Decode an XML comment tag and create a comment on the workspace.
|
||||
* @param {!Element} xmlComment XML comment element.
|
||||
* @param {!Blockly.Workspace} workspace The workspace.
|
||||
* @return {!Blockly.WorkspaceComment} The created workspace comment.
|
||||
* @param {!Workspace} workspace The workspace.
|
||||
* @return {!WorkspaceComment} The created workspace comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.fromXml = function(xmlComment, workspace) {
|
||||
var info = Blockly.WorkspaceComment.parseAttributes(xmlComment);
|
||||
WorkspaceComment.fromXml = function(xmlComment, workspace) {
|
||||
const info = WorkspaceComment.parseAttributes(xmlComment);
|
||||
|
||||
var comment = new Blockly.WorkspaceComment(
|
||||
workspace, info.content, info.h, info.w, info.id);
|
||||
const comment =
|
||||
new WorkspaceComment(workspace, info.content, info.h, info.w, info.id);
|
||||
|
||||
var commentX = parseInt(xmlComment.getAttribute('x'), 10);
|
||||
var commentY = parseInt(xmlComment.getAttribute('y'), 10);
|
||||
const commentX = parseInt(xmlComment.getAttribute('x'), 10);
|
||||
const commentY = parseInt(xmlComment.getAttribute('y'), 10);
|
||||
if (!isNaN(commentX) && !isNaN(commentY)) {
|
||||
comment.moveBy(commentX, commentY);
|
||||
}
|
||||
|
||||
Blockly.WorkspaceComment.fireCreateEvent(comment);
|
||||
WorkspaceComment.fireCreateEvent(comment);
|
||||
return comment;
|
||||
};
|
||||
|
||||
@@ -352,9 +351,9 @@ Blockly.WorkspaceComment.fromXml = function(xmlComment, workspace) {
|
||||
* object containing the id, size, position, and comment string.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.parseAttributes = function(xml) {
|
||||
var xmlH = xml.getAttribute('h');
|
||||
var xmlW = xml.getAttribute('w');
|
||||
WorkspaceComment.parseAttributes = function(xml) {
|
||||
const xmlH = xml.getAttribute('h');
|
||||
const xmlW = xml.getAttribute('w');
|
||||
|
||||
return {
|
||||
// @type {string}
|
||||
@@ -377,3 +376,5 @@ Blockly.WorkspaceComment.parseAttributes = function(xml) {
|
||||
content: xml.textContent
|
||||
};
|
||||
};
|
||||
|
||||
exports = WorkspaceComment;
|
||||
|
||||
@@ -1,463 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2017 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Methods for rendering a workspace comment as SVG
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.WorkspaceCommentSvg.render');
|
||||
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
|
||||
|
||||
/**
|
||||
* Size of the resize icon.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.RESIZE_SIZE = 8;
|
||||
|
||||
/**
|
||||
* Radius of the border around the comment.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.BORDER_RADIUS = 3;
|
||||
|
||||
/**
|
||||
* Offset from the foreignobject edge to the textarea edge.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET = 2;
|
||||
|
||||
/**
|
||||
* Offset from the top to make room for a top bar.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.TOP_OFFSET = 10;
|
||||
|
||||
/**
|
||||
* Returns a bounding box describing the dimensions of this comment.
|
||||
* @return {!{height: number, width: number}} Object with height and width
|
||||
* properties in workspace units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.getHeightWidth = function() {
|
||||
return { width: this.getWidth(), height: this.getHeight() };
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the workspace comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.render = function() {
|
||||
if (this.rendered_) {
|
||||
return;
|
||||
}
|
||||
|
||||
var size = this.getHeightWidth();
|
||||
|
||||
// Add text area
|
||||
this.createEditor_();
|
||||
this.svgGroup_.appendChild(this.foreignObject_);
|
||||
|
||||
this.svgHandleTarget_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
'class': 'blocklyCommentHandleTarget',
|
||||
'x': 0,
|
||||
'y': 0
|
||||
});
|
||||
this.svgGroup_.appendChild(this.svgHandleTarget_);
|
||||
this.svgRectTarget_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
'class': 'blocklyCommentTarget',
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
'rx': Blockly.WorkspaceCommentSvg.BORDER_RADIUS,
|
||||
'ry': Blockly.WorkspaceCommentSvg.BORDER_RADIUS
|
||||
});
|
||||
this.svgGroup_.appendChild(this.svgRectTarget_);
|
||||
|
||||
// Add the resize icon
|
||||
this.addResizeDom_();
|
||||
if (this.isDeletable()) {
|
||||
// Add the delete icon
|
||||
this.addDeleteDom_();
|
||||
}
|
||||
|
||||
this.setSize_(size.width, size.height);
|
||||
|
||||
// Set the content
|
||||
this.textarea_.value = this.content_;
|
||||
|
||||
this.rendered_ = true;
|
||||
|
||||
if (this.resizeGroup_) {
|
||||
Blockly.browserEvents.conditionalBind(
|
||||
this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_);
|
||||
}
|
||||
|
||||
if (this.isDeletable()) {
|
||||
Blockly.browserEvents.conditionalBind(
|
||||
this.deleteGroup_, 'mousedown', this, this.deleteMouseDown_);
|
||||
Blockly.browserEvents.conditionalBind(
|
||||
this.deleteGroup_, 'mouseout', this, this.deleteMouseOut_);
|
||||
Blockly.browserEvents.conditionalBind(
|
||||
this.deleteGroup_, 'mouseup', this, this.deleteMouseUp_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the text area for the comment.
|
||||
* @return {!Element} The top-level node of the editor.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.createEditor_ = function() {
|
||||
/* Create the editor. Here's the markup that will be generated:
|
||||
<foreignObject class="blocklyCommentForeignObject" x="0" y="10" width="164" height="164">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" class="blocklyMinimalBody">
|
||||
<textarea xmlns="http://www.w3.org/1999/xhtml"
|
||||
class="blocklyCommentTextarea"
|
||||
style="height: 164px; width: 164px;"></textarea>
|
||||
</body>
|
||||
</foreignObject>
|
||||
*/
|
||||
this.foreignObject_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.FOREIGNOBJECT,
|
||||
{
|
||||
'x': 0,
|
||||
'y': Blockly.WorkspaceCommentSvg.TOP_OFFSET,
|
||||
'class': 'blocklyCommentForeignObject'
|
||||
},
|
||||
null);
|
||||
var body = document.createElementNS(Blockly.utils.dom.HTML_NS, 'body');
|
||||
body.setAttribute('xmlns', Blockly.utils.dom.HTML_NS);
|
||||
body.className = 'blocklyMinimalBody';
|
||||
var textarea = document.createElementNS(Blockly.utils.dom.HTML_NS, 'textarea');
|
||||
textarea.className = 'blocklyCommentTextarea';
|
||||
textarea.setAttribute('dir', this.RTL ? 'RTL' : 'LTR');
|
||||
textarea.readOnly = !this.isEditable();
|
||||
body.appendChild(textarea);
|
||||
this.textarea_ = textarea;
|
||||
this.foreignObject_.appendChild(body);
|
||||
// Don't zoom with mousewheel.
|
||||
Blockly.browserEvents.conditionalBind(textarea, 'wheel', this, function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
Blockly.browserEvents.conditionalBind(
|
||||
textarea, 'change', this,
|
||||
function(
|
||||
/* eslint-disable no-unused-vars */ e
|
||||
/* eslint-enable no-unused-vars */) {
|
||||
this.setContent(textarea.value);
|
||||
});
|
||||
return this.foreignObject_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the resize icon to the DOM
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.addResizeDom_ = function() {
|
||||
this.resizeGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G,
|
||||
{
|
||||
'class': this.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE'
|
||||
},
|
||||
this.svgGroup_);
|
||||
var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE;
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.POLYGON,
|
||||
{'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())},
|
||||
this.resizeGroup_);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.LINE,
|
||||
{
|
||||
'class': 'blocklyResizeLine',
|
||||
'x1': resizeSize / 3, 'y1': resizeSize - 1,
|
||||
'x2': resizeSize - 1, 'y2': resizeSize / 3
|
||||
}, this.resizeGroup_);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.LINE,
|
||||
{
|
||||
'class': 'blocklyResizeLine',
|
||||
'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1,
|
||||
'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3
|
||||
}, this.resizeGroup_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the delete icon to the DOM
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.addDeleteDom_ = function() {
|
||||
this.deleteGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G,
|
||||
{
|
||||
'class': 'blocklyCommentDeleteIcon'
|
||||
},
|
||||
this.svgGroup_);
|
||||
this.deleteIconBorder_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.CIRCLE,
|
||||
{
|
||||
'class': 'blocklyDeleteIconShape',
|
||||
'r': '7',
|
||||
'cx': '7.5',
|
||||
'cy': '7.5'
|
||||
},
|
||||
this.deleteGroup_);
|
||||
// x icon.
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.LINE,
|
||||
{
|
||||
'x1': '5', 'y1': '10',
|
||||
'x2': '10', 'y2': '5',
|
||||
'stroke': '#fff',
|
||||
'stroke-width': '2'
|
||||
},
|
||||
this.deleteGroup_);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.LINE,
|
||||
{
|
||||
'x1': '5', 'y1': '5',
|
||||
'x2': '10', 'y2': '10',
|
||||
'stroke': '#fff',
|
||||
'stroke-width': '2'
|
||||
},
|
||||
this.deleteGroup_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-down on comment's resize corner.
|
||||
* @param {!Event} e Mouse down event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeMouseDown_ = function(e) {
|
||||
this.unbindDragEvents_();
|
||||
if (Blockly.utils.isRightButton(e)) {
|
||||
// No right-click.
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
// Left-click (or middle click)
|
||||
this.workspace.startDrag(e, new Blockly.utils.Coordinate(
|
||||
this.workspace.RTL ? -this.width_ : this.width_, this.height_));
|
||||
|
||||
this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
document, 'mouseup', this, this.resizeMouseUp_);
|
||||
this.onMouseMoveWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
document, 'mousemove', this, this.resizeMouseMove_);
|
||||
Blockly.hideChaff();
|
||||
// This event has been handled. No need to bubble up to the document.
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-down on comment's delete icon.
|
||||
* @param {!Event} e Mouse down event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.deleteMouseDown_ = function(e) {
|
||||
// Highlight the delete icon.
|
||||
Blockly.utils.dom.addClass(
|
||||
/** @type {!Element} */ (this.deleteIconBorder_),
|
||||
'blocklyDeleteIconHighlighted');
|
||||
// This event has been handled. No need to bubble up to the document.
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-out on comment's delete icon.
|
||||
* @param {!Event} _e Mouse out event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.deleteMouseOut_ = function(_e) {
|
||||
// Restore highlight on the delete icon.
|
||||
Blockly.utils.dom.removeClass(
|
||||
/** @type {!Element} */ (this.deleteIconBorder_),
|
||||
'blocklyDeleteIconHighlighted');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-up on comment's delete icon.
|
||||
* @param {!Event} e Mouse up event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.deleteMouseUp_ = function(e) {
|
||||
// Delete this comment.
|
||||
this.dispose(true, true);
|
||||
// This event has been handled. No need to bubble up to the document.
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop binding to the global mouseup and mousemove events.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.unbindDragEvents_ = function() {
|
||||
if (this.onMouseUpWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onMouseUpWrapper_);
|
||||
this.onMouseUpWrapper_ = null;
|
||||
}
|
||||
if (this.onMouseMoveWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onMouseMoveWrapper_);
|
||||
this.onMouseMoveWrapper_ = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-up event while dragging a comment's border or resize handle.
|
||||
* @param {!Event} e Mouse up event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeMouseUp_ = function(/* e */) {
|
||||
Blockly.Touch.clearTouchIdentifier();
|
||||
this.unbindDragEvents_();
|
||||
};
|
||||
|
||||
/**
|
||||
* Resize this comment to follow the mouse.
|
||||
* @param {!Event} e Mouse move event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeMouseMove_ = function(e) {
|
||||
this.autoLayout_ = false;
|
||||
var newXY = this.workspace.moveDrag(e);
|
||||
this.setSize_(this.RTL ? -newXY.x : newXY.x, newXY.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback function triggered when the comment has resized.
|
||||
* Resize the text area accordingly.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeComment_ = function() {
|
||||
var size = this.getHeightWidth();
|
||||
var topOffset = Blockly.WorkspaceCommentSvg.TOP_OFFSET;
|
||||
var textOffset = Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET * 2;
|
||||
|
||||
this.foreignObject_.setAttribute('width', size.width);
|
||||
this.foreignObject_.setAttribute('height', size.height - topOffset);
|
||||
if (this.RTL) {
|
||||
this.foreignObject_.setAttribute('x', -size.width);
|
||||
}
|
||||
this.textarea_.style.width = (size.width - textOffset) + 'px';
|
||||
this.textarea_.style.height = (size.height - textOffset - topOffset) + 'px';
|
||||
};
|
||||
|
||||
/**
|
||||
* Set size
|
||||
* @param {number} width width of the container
|
||||
* @param {number} height height of the container
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setSize_ = function(width, height) {
|
||||
// Minimum size of a comment.
|
||||
width = Math.max(width, 45);
|
||||
height = Math.max(height, 20 + Blockly.WorkspaceCommentSvg.TOP_OFFSET);
|
||||
this.width_ = width;
|
||||
this.height_ = height;
|
||||
this.svgRect_.setAttribute('width', width);
|
||||
this.svgRect_.setAttribute('height', height);
|
||||
this.svgRectTarget_.setAttribute('width', width);
|
||||
this.svgRectTarget_.setAttribute('height', height);
|
||||
this.svgHandleTarget_.setAttribute('width', width);
|
||||
this.svgHandleTarget_.setAttribute('height',
|
||||
Blockly.WorkspaceCommentSvg.TOP_OFFSET);
|
||||
if (this.RTL) {
|
||||
this.svgRect_.setAttribute('transform', 'scale(-1 1)');
|
||||
this.svgRectTarget_.setAttribute('transform', 'scale(-1 1)');
|
||||
}
|
||||
|
||||
var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE;
|
||||
if (this.resizeGroup_) {
|
||||
if (this.RTL) {
|
||||
// Mirror the resize group.
|
||||
this.resizeGroup_.setAttribute('transform', 'translate(' +
|
||||
(-width + resizeSize) + ',' + (height - resizeSize) + ') scale(-1 1)');
|
||||
this.deleteGroup_.setAttribute('transform', 'translate(' +
|
||||
(-width + resizeSize) + ',' + (-resizeSize) + ') scale(-1 1)');
|
||||
} else {
|
||||
this.resizeGroup_.setAttribute('transform', 'translate(' +
|
||||
(width - resizeSize) + ',' +
|
||||
(height - resizeSize) + ')');
|
||||
this.deleteGroup_.setAttribute('transform', 'translate(' +
|
||||
(width - resizeSize) + ',' +
|
||||
(-resizeSize) + ')');
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the contents to resize.
|
||||
this.resizeComment_();
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispose of any rendered comment components.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.disposeInternal_ = function() {
|
||||
this.textarea_ = null;
|
||||
this.foreignObject_ = null;
|
||||
this.svgRectTarget_ = null;
|
||||
this.svgHandleTarget_ = null;
|
||||
this.disposed_ = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the focus on the text area.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setFocus = function() {
|
||||
var comment = this;
|
||||
this.focused_ = true;
|
||||
// Defer CSS changes.
|
||||
setTimeout(function() {
|
||||
if (comment.disposed_) {
|
||||
return;
|
||||
}
|
||||
comment.textarea_.focus();
|
||||
comment.addFocus();
|
||||
Blockly.utils.dom.addClass(
|
||||
comment.svgRectTarget_, 'blocklyCommentTargetFocused');
|
||||
Blockly.utils.dom.addClass(
|
||||
comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused');
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove focus from the text area.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.blurFocus = function() {
|
||||
var comment = this;
|
||||
this.focused_ = false;
|
||||
// Defer CSS changes.
|
||||
setTimeout(function() {
|
||||
if (comment.disposed_) {
|
||||
return;
|
||||
}
|
||||
|
||||
comment.textarea_.blur();
|
||||
comment.removeFocus();
|
||||
Blockly.utils.dom.removeClass(
|
||||
comment.svgRectTarget_, 'blocklyCommentTargetFocused');
|
||||
Blockly.utils.dom.removeClass(
|
||||
comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused');
|
||||
}, 0);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,35 +10,37 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.ZoomControls');
|
||||
goog.module('Blockly.ZoomControls');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.browserEvents');
|
||||
goog.require('Blockly.ComponentManager');
|
||||
goog.require('Blockly.Css');
|
||||
goog.require('Blockly.Events');
|
||||
const ComponentManager = goog.require('Blockly.ComponentManager');
|
||||
const Css = goog.require('Blockly.Css');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const IPositionable = goog.require('Blockly.IPositionable');
|
||||
const Rect = goog.require('Blockly.utils.Rect');
|
||||
const Svg = goog.require('Blockly.utils.Svg');
|
||||
const Touch = goog.require('Blockly.Touch');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
|
||||
const browserEvents = goog.require('Blockly.browserEvents');
|
||||
const dom = goog.require('Blockly.utils.dom');
|
||||
const internalConstants = goog.require('Blockly.internalConstants');
|
||||
const uiPosition = goog.require('Blockly.uiPosition');
|
||||
const utils = goog.require('Blockly.utils');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.Click');
|
||||
goog.require('Blockly.IPositionable');
|
||||
goog.require('Blockly.internalConstants');
|
||||
goog.require('Blockly.Touch');
|
||||
goog.require('Blockly.uiPosition');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.Rect');
|
||||
goog.require('Blockly.utils.Svg');
|
||||
|
||||
goog.requireType('Blockly.WorkspaceSvg');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a zoom controls.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace to sit in.
|
||||
* @param {!WorkspaceSvg} workspace The workspace to sit in.
|
||||
* @constructor
|
||||
* @implements {Blockly.IPositionable}
|
||||
* @implements {IPositionable}
|
||||
*/
|
||||
Blockly.ZoomControls = function(workspace) {
|
||||
const ZoomControls = function(workspace) {
|
||||
/**
|
||||
* @type {!Blockly.WorkspaceSvg}
|
||||
* @type {!WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
this.workspace_ = workspace;
|
||||
@@ -52,24 +54,24 @@ Blockly.ZoomControls = function(workspace) {
|
||||
|
||||
/**
|
||||
* A handle to use to unbind the mouse down event handler for zoom reset
|
||||
* button. Opaque data returned from Blockly.bindEventWithChecks_.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* button. Opaque data returned from browserEvents.conditionalBind.
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.onZoomResetWrapper_ = null;
|
||||
|
||||
/**
|
||||
* A handle to use to unbind the mouse down event handler for zoom in button.
|
||||
* Opaque data returned from Blockly.bindEventWithChecks_.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* Opaque data returned from browserEvents.conditionalBind.
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.onZoomInWrapper_ = null;
|
||||
|
||||
/**
|
||||
* A handle to use to unbind the mouse down event handler for zoom out button.
|
||||
* Opaque data returned from Blockly.bindEventWithChecks_.
|
||||
* @type {?Blockly.browserEvents.Data}
|
||||
* Opaque data returned from browserEvents.conditionalBind.
|
||||
* @type {?browserEvents.Data}
|
||||
* @private
|
||||
*/
|
||||
this.onZoomOutWrapper_ = null;
|
||||
@@ -102,7 +104,7 @@ Blockly.ZoomControls = function(workspace) {
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.WIDTH_ = 32;
|
||||
ZoomControls.prototype.WIDTH_ = 32;
|
||||
|
||||
/**
|
||||
* Height of each zoom control.
|
||||
@@ -110,7 +112,7 @@ Blockly.ZoomControls.prototype.WIDTH_ = 32;
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.HEIGHT_ = 32;
|
||||
ZoomControls.prototype.HEIGHT_ = 32;
|
||||
|
||||
/**
|
||||
* Small spacing used between the zoom in and out control, in pixels.
|
||||
@@ -118,7 +120,7 @@ Blockly.ZoomControls.prototype.HEIGHT_ = 32;
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.SMALL_SPACING_ = 2;
|
||||
ZoomControls.prototype.SMALL_SPACING_ = 2;
|
||||
|
||||
/**
|
||||
* Large spacing used between the zoom in and reset control, in pixels.
|
||||
@@ -126,7 +128,7 @@ Blockly.ZoomControls.prototype.SMALL_SPACING_ = 2;
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.LARGE_SPACING_ = 11;
|
||||
ZoomControls.prototype.LARGE_SPACING_ = 11;
|
||||
|
||||
/**
|
||||
* Distance between zoom controls and bottom or top edge of workspace.
|
||||
@@ -134,55 +136,54 @@ Blockly.ZoomControls.prototype.LARGE_SPACING_ = 11;
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.MARGIN_VERTICAL_ = 20;
|
||||
ZoomControls.prototype.MARGIN_VERTICAL_ = 20;
|
||||
|
||||
/**
|
||||
* Distance between zoom controls and right or left edge of workspace.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.MARGIN_HORIZONTAL_ = 20;
|
||||
ZoomControls.prototype.MARGIN_HORIZONTAL_ = 20;
|
||||
|
||||
/**
|
||||
* The SVG group containing the zoom controls.
|
||||
* @type {SVGElement}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.svgGroup_ = null;
|
||||
ZoomControls.prototype.svgGroup_ = null;
|
||||
|
||||
/**
|
||||
* Left coordinate of the zoom controls.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.left_ = 0;
|
||||
ZoomControls.prototype.left_ = 0;
|
||||
|
||||
/**
|
||||
* Top coordinate of the zoom controls.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.top_ = 0;
|
||||
ZoomControls.prototype.top_ = 0;
|
||||
|
||||
/**
|
||||
* Whether this has been initialized.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.initialized_ = false;
|
||||
ZoomControls.prototype.initialized_ = false;
|
||||
|
||||
/**
|
||||
* Create the zoom controls.
|
||||
* @return {!SVGElement} The zoom controls SVG group.
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createDom = function() {
|
||||
this.svgGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G, {}, null);
|
||||
ZoomControls.prototype.createDom = function() {
|
||||
this.svgGroup_ = dom.createSvgElement(Svg.G, {}, null);
|
||||
|
||||
// Each filter/pattern needs a unique ID for the case of multiple Blockly
|
||||
// instances on a page. Browser behaviour becomes undefined otherwise.
|
||||
// https://neil.fraser.name/news/2015/11/01/
|
||||
var rnd = String(Math.random()).substring(2);
|
||||
const rnd = String(Math.random()).substring(2);
|
||||
this.createZoomOutSvg_(rnd);
|
||||
this.createZoomInSvg_(rnd);
|
||||
if (this.workspace_.isMovable()) {
|
||||
@@ -196,11 +197,11 @@ Blockly.ZoomControls.prototype.createDom = function() {
|
||||
/**
|
||||
* Initializes the zoom controls.
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.init = function() {
|
||||
ZoomControls.prototype.init = function() {
|
||||
this.workspace_.getComponentManager().addComponent({
|
||||
component: this,
|
||||
weight: 2,
|
||||
capabilities: [Blockly.ComponentManager.Capability.POSITIONABLE]
|
||||
capabilities: [ComponentManager.Capability.POSITIONABLE]
|
||||
});
|
||||
this.initialized_ = true;
|
||||
};
|
||||
@@ -209,36 +210,36 @@ Blockly.ZoomControls.prototype.init = function() {
|
||||
* Disposes of this zoom controls.
|
||||
* Unlink from all DOM elements to prevent memory leaks.
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.dispose = function() {
|
||||
ZoomControls.prototype.dispose = function() {
|
||||
this.workspace_.getComponentManager().removeComponent('zoomControls');
|
||||
if (this.svgGroup_) {
|
||||
Blockly.utils.dom.removeNode(this.svgGroup_);
|
||||
dom.removeNode(this.svgGroup_);
|
||||
}
|
||||
if (this.onZoomResetWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onZoomResetWrapper_);
|
||||
browserEvents.unbind(this.onZoomResetWrapper_);
|
||||
}
|
||||
if (this.onZoomInWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onZoomInWrapper_);
|
||||
browserEvents.unbind(this.onZoomInWrapper_);
|
||||
}
|
||||
if (this.onZoomOutWrapper_) {
|
||||
Blockly.browserEvents.unbind(this.onZoomOutWrapper_);
|
||||
browserEvents.unbind(this.onZoomOutWrapper_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.ZoomControls.prototype.getBoundingRectangle = function() {
|
||||
var height = this.SMALL_SPACING_ + 2 * this.HEIGHT_;
|
||||
ZoomControls.prototype.getBoundingRectangle = function() {
|
||||
let height = this.SMALL_SPACING_ + 2 * this.HEIGHT_;
|
||||
if (this.zoomResetGroup_) {
|
||||
height += this.LARGE_SPACING_ + this.HEIGHT_;
|
||||
}
|
||||
var bottom = this.top_ + height;
|
||||
var right = this.left_ + this.WIDTH_;
|
||||
return new Blockly.utils.Rect(this.top_, bottom, this.left_, right);
|
||||
const bottom = this.top_ + height;
|
||||
const right = this.left_ + this.WIDTH_;
|
||||
return new Rect(this.top_, bottom, this.left_, right);
|
||||
};
|
||||
|
||||
|
||||
@@ -247,59 +248,57 @@ Blockly.ZoomControls.prototype.getBoundingRectangle = function() {
|
||||
* It is positioned in the opposite corner to the corner the
|
||||
* categories/toolbox starts at.
|
||||
* @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace metrics.
|
||||
* @param {!Array<!Blockly.utils.Rect>} savedPositions List of rectangles that
|
||||
* @param {!Array<!Rect>} savedPositions List of rectangles that
|
||||
* are already on the workspace.
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.position = function(metrics, savedPositions) {
|
||||
ZoomControls.prototype.position = function(metrics, savedPositions) {
|
||||
// Not yet initialized.
|
||||
if (!this.initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cornerPosition =
|
||||
Blockly.uiPosition.getCornerOppositeToolbox(this.workspace_, metrics);
|
||||
var height = this.SMALL_SPACING_ + 2 * this.HEIGHT_;
|
||||
const cornerPosition =
|
||||
uiPosition.getCornerOppositeToolbox(this.workspace_, metrics);
|
||||
let height = this.SMALL_SPACING_ + 2 * this.HEIGHT_;
|
||||
if (this.zoomResetGroup_) {
|
||||
height += this.LARGE_SPACING_ + this.HEIGHT_;
|
||||
}
|
||||
var startRect = Blockly.uiPosition.getStartPositionRect(
|
||||
cornerPosition, new Blockly.utils.Size(this.WIDTH_, height),
|
||||
this.MARGIN_HORIZONTAL_, this.MARGIN_VERTICAL_, metrics,
|
||||
this.workspace_);
|
||||
const startRect = uiPosition.getStartPositionRect(
|
||||
cornerPosition, new utils.Size(this.WIDTH_, height),
|
||||
this.MARGIN_HORIZONTAL_, this.MARGIN_VERTICAL_, metrics, this.workspace_);
|
||||
|
||||
var verticalPosition = cornerPosition.vertical;
|
||||
var bumpDirection =
|
||||
verticalPosition === Blockly.uiPosition.verticalPosition.TOP ?
|
||||
Blockly.uiPosition.bumpDirection.DOWN :
|
||||
Blockly.uiPosition.bumpDirection.UP;
|
||||
var positionRect = Blockly.uiPosition.bumpPositionRect(
|
||||
const verticalPosition = cornerPosition.vertical;
|
||||
const bumpDirection = verticalPosition === uiPosition.verticalPosition.TOP ?
|
||||
uiPosition.bumpDirection.DOWN :
|
||||
uiPosition.bumpDirection.UP;
|
||||
const positionRect = uiPosition.bumpPositionRect(
|
||||
startRect, this.MARGIN_VERTICAL_, bumpDirection, savedPositions);
|
||||
|
||||
if (verticalPosition === Blockly.uiPosition.verticalPosition.TOP) {
|
||||
var zoomInTranslateY = this.SMALL_SPACING_ + this.HEIGHT_;
|
||||
this.zoomInGroup_.setAttribute('transform',
|
||||
'translate(0, ' + zoomInTranslateY + ')');
|
||||
if (verticalPosition === uiPosition.verticalPosition.TOP) {
|
||||
const zoomInTranslateY = this.SMALL_SPACING_ + this.HEIGHT_;
|
||||
this.zoomInGroup_.setAttribute(
|
||||
'transform', 'translate(0, ' + zoomInTranslateY + ')');
|
||||
if (this.zoomResetGroup_) {
|
||||
var zoomResetTranslateY =
|
||||
const zoomResetTranslateY =
|
||||
zoomInTranslateY + this.LARGE_SPACING_ + this.HEIGHT_;
|
||||
this.zoomResetGroup_.setAttribute('transform',
|
||||
'translate(0, ' + zoomResetTranslateY + ')');
|
||||
this.zoomResetGroup_.setAttribute(
|
||||
'transform', 'translate(0, ' + zoomResetTranslateY + ')');
|
||||
}
|
||||
} else {
|
||||
var zoomInTranslateY = this.zoomResetGroup_ ?
|
||||
this.LARGE_SPACING_ + this.HEIGHT_ : 0;
|
||||
this.zoomInGroup_.setAttribute('transform',
|
||||
'translate(0, ' + zoomInTranslateY + ')');
|
||||
var zoomOutTranslateY =
|
||||
const zoomInTranslateY =
|
||||
this.zoomResetGroup_ ? this.LARGE_SPACING_ + this.HEIGHT_ : 0;
|
||||
this.zoomInGroup_.setAttribute(
|
||||
'transform', 'translate(0, ' + zoomInTranslateY + ')');
|
||||
const zoomOutTranslateY =
|
||||
zoomInTranslateY + this.SMALL_SPACING_ + this.HEIGHT_;
|
||||
this.zoomOutGroup_.setAttribute('transform',
|
||||
'translate(0, ' + zoomOutTranslateY + ')');
|
||||
this.zoomOutGroup_.setAttribute(
|
||||
'transform', 'translate(0, ' + zoomOutTranslateY + ')');
|
||||
}
|
||||
|
||||
this.top_ = positionRect.top;
|
||||
this.left_ = positionRect.left;
|
||||
this.svgGroup_.setAttribute('transform',
|
||||
'translate(' + this.left_ + ',' + this.top_ + ')');
|
||||
this.svgGroup_.setAttribute(
|
||||
'transform', 'translate(' + this.left_ + ',' + this.top_ + ')');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -309,48 +308,42 @@ Blockly.ZoomControls.prototype.position = function(metrics, savedPositions) {
|
||||
* instances on the same page.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createZoomOutSvg_ = function(rnd) {
|
||||
ZoomControls.prototype.createZoomOutSvg_ = function(rnd) {
|
||||
/* This markup will be generated and added to the .svgGroup_:
|
||||
<g class="blocklyZoom">
|
||||
<clipPath id="blocklyZoomoutClipPath837493">
|
||||
<rect width="32" height="32></rect>
|
||||
</clipPath>
|
||||
<image width="96" height="124" x="-64" y="-92" xlink:href="media/sprites.png"
|
||||
<image width="96" height="124" x="-64" y="-92"
|
||||
xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomoutClipPath837493)"></image>
|
||||
</g>
|
||||
*/
|
||||
this.zoomOutGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G,
|
||||
{'class': 'blocklyZoom'}, this.svgGroup_);
|
||||
var clip = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.CLIPPATH,
|
||||
{
|
||||
'id': 'blocklyZoomoutClipPath' + rnd
|
||||
},
|
||||
this.zoomOutGroup_);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
this.zoomOutGroup_ =
|
||||
dom.createSvgElement(Svg.G, {'class': 'blocklyZoom'}, this.svgGroup_);
|
||||
const clip = dom.createSvgElement(
|
||||
Svg.CLIPPATH, {'id': 'blocklyZoomoutClipPath' + rnd}, this.zoomOutGroup_);
|
||||
dom.createSvgElement(
|
||||
Svg.RECT, {
|
||||
'width': 32,
|
||||
'height': 32,
|
||||
},
|
||||
clip);
|
||||
var zoomoutSvg = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.IMAGE, {
|
||||
'width': Blockly.internalConstants.SPRITE.width,
|
||||
'height': Blockly.internalConstants.SPRITE.height,
|
||||
const zoomoutSvg = dom.createSvgElement(
|
||||
Svg.IMAGE, {
|
||||
'width': internalConstants.SPRITE.width,
|
||||
'height': internalConstants.SPRITE.height,
|
||||
'x': -64,
|
||||
'y': -92,
|
||||
'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')'
|
||||
},
|
||||
this.zoomOutGroup_);
|
||||
zoomoutSvg.setAttributeNS(
|
||||
Blockly.utils.dom.XLINK_NS, 'xlink:href',
|
||||
this.workspace_.options.pathToMedia +
|
||||
Blockly.internalConstants.SPRITE.url);
|
||||
dom.XLINK_NS, 'xlink:href',
|
||||
this.workspace_.options.pathToMedia + internalConstants.SPRITE.url);
|
||||
|
||||
// Attach listener.
|
||||
this.onZoomOutWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
this.onZoomOutWrapper_ = browserEvents.conditionalBind(
|
||||
this.zoomOutGroup_, 'mousedown', null, this.zoom_.bind(this, -1));
|
||||
};
|
||||
|
||||
@@ -361,48 +354,42 @@ Blockly.ZoomControls.prototype.createZoomOutSvg_ = function(rnd) {
|
||||
* instances on the same page.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createZoomInSvg_ = function(rnd) {
|
||||
ZoomControls.prototype.createZoomInSvg_ = function(rnd) {
|
||||
/* This markup will be generated and added to the .svgGroup_:
|
||||
<g class="blocklyZoom">
|
||||
<clipPath id="blocklyZoominClipPath837493">
|
||||
<rect width="32" height="32"></rect>
|
||||
</clipPath>
|
||||
<image width="96" height="124" x="-32" y="-92" xlink:href="media/sprites.png"
|
||||
<image width="96" height="124" x="-32" y="-92"
|
||||
xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoominClipPath837493)"></image>
|
||||
</g>
|
||||
*/
|
||||
this.zoomInGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G,
|
||||
{'class': 'blocklyZoom'}, this.svgGroup_);
|
||||
var clip = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.CLIPPATH,
|
||||
{
|
||||
'id': 'blocklyZoominClipPath' + rnd
|
||||
},
|
||||
this.zoomInGroup_);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
this.zoomInGroup_ =
|
||||
dom.createSvgElement(Svg.G, {'class': 'blocklyZoom'}, this.svgGroup_);
|
||||
const clip = dom.createSvgElement(
|
||||
Svg.CLIPPATH, {'id': 'blocklyZoominClipPath' + rnd}, this.zoomInGroup_);
|
||||
dom.createSvgElement(
|
||||
Svg.RECT, {
|
||||
'width': 32,
|
||||
'height': 32,
|
||||
},
|
||||
clip);
|
||||
var zoominSvg = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.IMAGE, {
|
||||
'width': Blockly.internalConstants.SPRITE.width,
|
||||
'height': Blockly.internalConstants.SPRITE.height,
|
||||
const zoominSvg = dom.createSvgElement(
|
||||
Svg.IMAGE, {
|
||||
'width': internalConstants.SPRITE.width,
|
||||
'height': internalConstants.SPRITE.height,
|
||||
'x': -32,
|
||||
'y': -92,
|
||||
'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')'
|
||||
},
|
||||
this.zoomInGroup_);
|
||||
zoominSvg.setAttributeNS(
|
||||
Blockly.utils.dom.XLINK_NS, 'xlink:href',
|
||||
this.workspace_.options.pathToMedia +
|
||||
Blockly.internalConstants.SPRITE.url);
|
||||
dom.XLINK_NS, 'xlink:href',
|
||||
this.workspace_.options.pathToMedia + internalConstants.SPRITE.url);
|
||||
|
||||
// Attach listener.
|
||||
this.onZoomInWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
this.onZoomInWrapper_ = browserEvents.conditionalBind(
|
||||
this.zoomInGroup_, 'mousedown', null, this.zoom_.bind(this, 1));
|
||||
};
|
||||
|
||||
@@ -414,13 +401,13 @@ Blockly.ZoomControls.prototype.createZoomInSvg_ = function(rnd) {
|
||||
* @param {!Event} e A mouse down event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.zoom_ = function(amount, e) {
|
||||
ZoomControls.prototype.zoom_ = function(amount, e) {
|
||||
this.workspace_.markFocused();
|
||||
this.workspace_.zoomCenter(amount);
|
||||
this.fireZoomEvent_();
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -430,47 +417,37 @@ Blockly.ZoomControls.prototype.zoom_ = function(amount, e) {
|
||||
* instances on the same page.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createZoomResetSvg_ = function(rnd) {
|
||||
ZoomControls.prototype.createZoomResetSvg_ = function(rnd) {
|
||||
/* This markup will be generated and added to the .svgGroup_:
|
||||
<g class="blocklyZoom">
|
||||
<clipPath id="blocklyZoomresetClipPath837493">
|
||||
<rect width="32" height="32"></rect>
|
||||
</clipPath>
|
||||
<image width="96" height="124" x="-32" y="-92" xlink:href="media/sprites.png"
|
||||
<image width="96" height="124" x="-32" y="-92"
|
||||
xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomresetClipPath837493)"></image>
|
||||
</g>
|
||||
*/
|
||||
this.zoomResetGroup_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.G,
|
||||
{'class': 'blocklyZoom'}, this.svgGroup_);
|
||||
var clip = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.CLIPPATH,
|
||||
{
|
||||
'id': 'blocklyZoomresetClipPath' + rnd
|
||||
},
|
||||
this.zoomResetGroup_ =
|
||||
dom.createSvgElement(Svg.G, {'class': 'blocklyZoom'}, this.svgGroup_);
|
||||
const clip = dom.createSvgElement(
|
||||
Svg.CLIPPATH, {'id': 'blocklyZoomresetClipPath' + rnd},
|
||||
this.zoomResetGroup_);
|
||||
Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
'width': 32,
|
||||
'height': 32
|
||||
},
|
||||
clip);
|
||||
var zoomresetSvg = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.IMAGE, {
|
||||
'width': Blockly.internalConstants.SPRITE.width,
|
||||
'height': Blockly.internalConstants.SPRITE.height,
|
||||
dom.createSvgElement(Svg.RECT, {'width': 32, 'height': 32}, clip);
|
||||
const zoomresetSvg = dom.createSvgElement(
|
||||
Svg.IMAGE, {
|
||||
'width': internalConstants.SPRITE.width,
|
||||
'height': internalConstants.SPRITE.height,
|
||||
'y': -92,
|
||||
'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')'
|
||||
},
|
||||
this.zoomResetGroup_);
|
||||
zoomresetSvg.setAttributeNS(
|
||||
Blockly.utils.dom.XLINK_NS, 'xlink:href',
|
||||
this.workspace_.options.pathToMedia +
|
||||
Blockly.internalConstants.SPRITE.url);
|
||||
dom.XLINK_NS, 'xlink:href',
|
||||
this.workspace_.options.pathToMedia + internalConstants.SPRITE.url);
|
||||
|
||||
// Attach event listeners.
|
||||
this.onZoomResetWrapper_ = Blockly.browserEvents.conditionalBind(
|
||||
this.onZoomResetWrapper_ = browserEvents.conditionalBind(
|
||||
this.zoomResetGroup_, 'mousedown', null, this.resetZoom_.bind(this));
|
||||
};
|
||||
|
||||
@@ -479,55 +456,55 @@ Blockly.ZoomControls.prototype.createZoomResetSvg_ = function(rnd) {
|
||||
* @param {!Event} e A mouse down event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.resetZoom_ = function(e) {
|
||||
ZoomControls.prototype.resetZoom_ = function(e) {
|
||||
this.workspace_.markFocused();
|
||||
|
||||
// zoom is passed amount and computes the new scale using the formula:
|
||||
// targetScale = currentScale * Math.pow(speed, amount)
|
||||
var targetScale = this.workspace_.options.zoomOptions.startScale;
|
||||
var currentScale = this.workspace_.scale;
|
||||
var speed = this.workspace_.options.zoomOptions.scaleSpeed;
|
||||
const targetScale = this.workspace_.options.zoomOptions.startScale;
|
||||
const currentScale = this.workspace_.scale;
|
||||
const speed = this.workspace_.options.zoomOptions.scaleSpeed;
|
||||
// To compute amount:
|
||||
// amount = log(speed, (targetScale / currentScale))
|
||||
// Math.log computes natural logarithm (ln), to change the base, use formula:
|
||||
// log(base, value) = ln(value) / ln(base)
|
||||
var amount = Math.log(targetScale / currentScale) / Math.log(speed);
|
||||
const amount = Math.log(targetScale / currentScale) / Math.log(speed);
|
||||
this.workspace_.beginCanvasTransition();
|
||||
this.workspace_.zoomCenter(amount);
|
||||
this.workspace_.scrollCenter();
|
||||
|
||||
setTimeout(this.workspace_.endCanvasTransition.bind(this.workspace_), 500);
|
||||
this.fireZoomEvent_();
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
};
|
||||
|
||||
/**
|
||||
* Fires a zoom control UI event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.fireZoomEvent_ = function() {
|
||||
var uiEvent = new (Blockly.Events.get(Blockly.Events.CLICK))(
|
||||
null, this.workspace_.id, 'zoom_controls');
|
||||
Blockly.Events.fire(uiEvent);
|
||||
ZoomControls.prototype.fireZoomEvent_ = function() {
|
||||
const uiEvent =
|
||||
new (Events.get(Events.CLICK))(null, this.workspace_.id, 'zoom_controls');
|
||||
Events.fire(uiEvent);
|
||||
};
|
||||
|
||||
/**
|
||||
* CSS for zoom controls. See css.js for use.
|
||||
*/
|
||||
Blockly.Css.register([
|
||||
/* eslint-disable indent */
|
||||
'.blocklyZoom>image, .blocklyZoom>svg>image {',
|
||||
'opacity: .4;',
|
||||
'}',
|
||||
Css.register([
|
||||
`.blocklyZoom>image, .blocklyZoom>svg>image {
|
||||
opacity: .4;
|
||||
}`,
|
||||
|
||||
'.blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {',
|
||||
'opacity: .6;',
|
||||
'}',
|
||||
`.blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {
|
||||
opacity: .6;
|
||||
}`,
|
||||
|
||||
'.blocklyZoom>image:active, .blocklyZoom>svg>image:active {',
|
||||
'opacity: .8;',
|
||||
'}'
|
||||
/* eslint-enable indent */
|
||||
`.blocklyZoom>image:active, .blocklyZoom>svg>image:active {
|
||||
'opacity: .8;
|
||||
}`
|
||||
]);
|
||||
|
||||
exports = ZoomControls;
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This file makes extensive use of perl for the purpose of extracting and
|
||||
# replacing string (regex) patterns in a way that is both GNU and macOS
|
||||
# compatible.
|
||||
#
|
||||
# Common perl flags used (also described at https://perldoc.perl.org/perlrun):
|
||||
# -e : Used to execute perl programs on the command line
|
||||
# -p : Assumes an input loop around script. Prints every processed line.
|
||||
# -n : Assumes an input loop around script. Does not print every line.
|
||||
# -i : Used for in-place editing. Used in commands for find/replace.
|
||||
# -l[octnum] : Assigns the output record separator "$/" as an octal number. If
|
||||
# octnum is not present, sets output record separator to the current
|
||||
# value of the input record separator "$\".
|
||||
#
|
||||
# Common perl commands found:
|
||||
# 1. perl -pi -e 's/regex/replacement/modifiers'
|
||||
# This command does an in-place search-and-replace. The global ("/g") modifier
|
||||
# causes it to replace all occurrences, rather than only the first match.
|
||||
# 2. perl -ne 'print m/regex/modifiers'
|
||||
# This command returns a string containing the regex match (designated by the
|
||||
# capture group "()" in the regex). This will return the first match, unless
|
||||
# the global modifier is specified, in which case, it will return all matches.
|
||||
# If this command is used without a capture group it returns true or false (in
|
||||
# the form a truthy or falsy value).
|
||||
# 3. perl -nle 'print $& while m{regex}modifiers'
|
||||
# Similar to (2), but returns regex matches separated by newlines.
|
||||
# The "m{regex}modifiers" is equivalent to "m/regex/modifiers" syntax.
|
||||
#
|
||||
# Additional information on regex:
|
||||
# This script makes use of some advanced regex syntax such as "capture groups"
|
||||
# and "lookaround assertions".
|
||||
# Additionally, characters are escaped from regex with a backslash "\".
|
||||
# Single quotes need to be escaped in both regex and the string, resulting in
|
||||
# '\'' being used to represent a single quote character.
|
||||
# For a reference to syntax of regular expressions in Perl, see:
|
||||
# https://perldoc.perl.org/perlre
|
||||
|
||||
#######################################
|
||||
# Logging functions.
|
||||
#######################################
|
||||
@@ -89,6 +125,64 @@ commit-step() {
|
||||
success "created commit with message: \"${message}\""
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Extracts a list of properties that are accessed on the specified module name.
|
||||
# Excludes any matches
|
||||
# Arguments:
|
||||
# The module name to find properties accessed for.
|
||||
# The modules required by the specified module as a single string.
|
||||
# The filepath to extract requires from.
|
||||
# Optional: The top-level module.
|
||||
# Outputs:
|
||||
# Writes list of properties to stdout as items separated by spaces.
|
||||
#######################################
|
||||
getPropertiesAccessed() {
|
||||
local module_name="$1"
|
||||
local requires="$2"
|
||||
local filepath="$3"
|
||||
local top_module_name="$4"
|
||||
# Get any strings that follow "$module_name.", excluding matches for
|
||||
# "$module_name.prototype" and remove list item duplicates (sort -u).
|
||||
local properties_accessed=$(perl -nle 'print $& while m{(?<='"${module_name}"'\.)(?!prototype)\w+}g' "${filepath}" | sort -u)
|
||||
|
||||
# Get a list of any requires that are a child of $module_name.
|
||||
# Ex: Blockly.utils.dom is a child of Blockly.utils, this would return "dom"
|
||||
local requires_overlap=$(echo "${requires}" | perl -nle 'print $& while m{(?<='"${module_name}"'\.)\w+}g')
|
||||
# Detect if there was any overlap.
|
||||
if [[ -n "${requires_overlap}" ]]; then
|
||||
while read -r requires_overlap_prop; do
|
||||
# Removes any instances of $requires_overlap_prop. Includes regex
|
||||
# lookarounds so that it does not simply match string contains.
|
||||
# Ex: if $requires_overlap is "Svg", then it would update the list
|
||||
# "isTargetInput mouseToSvg noEvent Svg" to
|
||||
# "isTargetInput mouseToSvg noEvent " (note that mouseToSvg is unchanged).
|
||||
properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/(?<!\w)'"${requires_overlap_prop}"'(?!\w)//g')
|
||||
done <<<"${requires_overlap}"
|
||||
fi
|
||||
|
||||
# Fix formatting (remove extra whitespace) and delimit the list with spaces.
|
||||
properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/\s+/ /g' | xargs)
|
||||
|
||||
echo "${properties_accessed}"
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Extracts a list of requires defined in the file in the form of a single string
|
||||
# of items separated by newlines.
|
||||
# Arguments:
|
||||
# The filepath to extract requires from.
|
||||
# Outputs:
|
||||
# Writes list of requires to stdout as items separated by newlines.
|
||||
#######################################
|
||||
getRequires() {
|
||||
local filepath="$1"
|
||||
# Extracts all strings that start with goog.require(' or goog.requireType('
|
||||
# up until the ending single quote.
|
||||
# Ex: "goog.require('Blockly.utils')" would extract "Blockly.utils"
|
||||
local requires=$(perl -nle 'print $& while m{(?:(?<=^goog.require\('\'')|(?<=^goog.requireType\('\''))[^'\'']+}g' "${filepath}")
|
||||
echo "${requires}"
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Runs step 2 of the automated conversion.
|
||||
# Arguments:
|
||||
@@ -98,10 +192,10 @@ step2 () {
|
||||
local filepath="$1"
|
||||
|
||||
inf "Updating goog.provide declaration..."
|
||||
perl -pi -e 's/^goog\.provide(\([^\)]+\)\;)/goog\.module\1\ngoog.module.declareLegacyNamespace\(\)\;/g' "${filepath}"
|
||||
perl -pi -e 's/^goog\.provide(\([^\)]+\)\;)/goog\.module\1\ngoog.module.declareLegacyNamespace\(\)\;/' "${filepath}"
|
||||
|
||||
inf "Extracting module name..."
|
||||
local module_name=$(perl -nle'print $& while m{(?<=^goog\.module\('\'')([^'\'')]+)}g' "${filepath}")
|
||||
local module_name=$(perl -ne 'print m/(?<=^goog\.module\('\'')([^'\'']+)/' "${filepath}")
|
||||
if [[ -z "${module_name}" ]]; then
|
||||
err "Could not extract module name"
|
||||
return 1
|
||||
@@ -109,7 +203,7 @@ step2 () {
|
||||
inf "Extracted module name \"${module_name}\""
|
||||
|
||||
if [[ $(grep "${module_name} = " "${filepath}") ]]; then
|
||||
local class_name=$(echo "${module_name}" | perl -nle'print $& while m{(\w+)$}g')
|
||||
local class_name=$(echo "${module_name}" | perl -ne 'print m/(\w+)$/')
|
||||
inf "Found class \"${class_name}\" in file."
|
||||
inf "Updating class declaration..."
|
||||
perl -pi -e 's/^('"${module_name}"') =/const '"${class_name}"' =/g' "${filepath}"
|
||||
@@ -130,8 +224,18 @@ step2 () {
|
||||
# No top level class.
|
||||
inf 'Updating top-level property declarations...'
|
||||
perl -pi -e 's/^'"${module_name}"'\.([^ ]+) =/const \1 =/g' "${filepath}"
|
||||
|
||||
# Extract specific properties accessed so that properties from requires that
|
||||
# are children of the module aren't changed.
|
||||
# Ex: The module Blockly.utils shouldn't update Blockly.utils.dom (since it is
|
||||
# a require from another module.
|
||||
local requires=$(getRequires "${filepath}")
|
||||
local properties_accessed=$(getPropertiesAccessed "${module_name}" "${requires}" "${filepath}")
|
||||
inf "Updating local references to module..."
|
||||
perl -pi -e 's/'"${module_name}"'\.([^ ]+)/\1/g' "${filepath}"
|
||||
for property in $(echo "${properties_accessed}"); do
|
||||
inf "Updating references of ${module_name}.${property} to ${property}..."
|
||||
perl -pi -e 's/'"${module_name}"'\.'"${property}"'(?!\w)/'"${property}"'/g' "${filepath}"
|
||||
done
|
||||
|
||||
npm run build:deps
|
||||
success "Completed automation for step 2. Please manually review and add exports for non-private top-level functions."
|
||||
@@ -144,85 +248,68 @@ step2 () {
|
||||
#######################################
|
||||
step3() {
|
||||
inf "Extracting module name..."
|
||||
local module_name=$(perl -nle'print $& while m{(?<=^goog\.module\('\'')([^'\'')]+)}g' "${filepath}")
|
||||
local module_name=$(perl -ne 'print m/(?<=^goog\.module\('\'')([^'\'']+)/' "${filepath}")
|
||||
if [[ -z "${module_name}" ]]; then
|
||||
err "Could not extract module name"
|
||||
return 1
|
||||
fi
|
||||
inf "Extracted module name \"${module_name}\""
|
||||
|
||||
local requires=$(perl -nle'print $& while m{(?:(?<=^goog.require\('\'')|(?<=^goog.requireType\('\''))[^'\'']+}g' "${filepath}")
|
||||
local requires=$(getRequires "${filepath}")
|
||||
|
||||
# Process each require
|
||||
echo "${requires}" | while read -r require; do
|
||||
inf "Processing require \"${require}\""
|
||||
local usages=$(perl -nle'print $& while m{'"${require}"'(?!'\'')}g' "${filepath}" | wc -l)
|
||||
local usages=$(perl -nle 'print $& while m{'"${require}"'(?!'\'')}g' "${filepath}" | wc -l)
|
||||
|
||||
if [[ "${usages}" -eq "0" ]]; then
|
||||
warn "Unused require \"${require}\""
|
||||
continue
|
||||
fi
|
||||
|
||||
local direct_access_count=$(perl -nle'print $& while m{'"${require}"'[^\.'\'']}g' "${filepath}" | wc -l)
|
||||
local properties_accessed=$(perl -nle'print $& while m{(?<='"${require}"'\.)(?!prototype)\w+}g' "${filepath}" | tr ' ' '\n' | sort -u)
|
||||
# Detect requires overlap
|
||||
# (ex: Blockly.utils require and Blockly.utils.dom also in requires)
|
||||
local requires_overlap=$(echo "${requires}" | perl -nle'print $& while m{(?<='"${require}"'\.)\w+}g')
|
||||
if [[ -n "${requires_overlap}" ]]; then
|
||||
while read -r requires_overlap_prop; do
|
||||
properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/'"${requires_overlap_prop}"'//g')
|
||||
done <<<"${requires_overlap}"
|
||||
fi
|
||||
# Detect module name overlap
|
||||
# (ex: Blockly require and Blockly.ContextMenuItems module being converted)
|
||||
local module_overlap=$(echo "${module_name}" | perl -nle'print $& while m{(?<='"${require}"'\.)\w+}g')
|
||||
if [[ -n "${module_overlap}" ]]; then
|
||||
properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/'"${module_overlap}"'//g')
|
||||
fi
|
||||
properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/\s+/ /g' | xargs)
|
||||
|
||||
if [[ "${direct_access_count}" -eq "0" && -n "${properties_accessed}" ]]; then
|
||||
local deconstructed_comma=$(echo "${properties_accessed}" | perl -pe 's/\s+/, /g' | perl -pe 's/, $//')
|
||||
local confirm=''
|
||||
while true; do
|
||||
read -p "Would you like to deconstruct ${require} into \"{${deconstructed_comma}}\"? (y/n): " yn </dev/tty
|
||||
case $yn in
|
||||
[Yy]* )
|
||||
confirm='true'
|
||||
break
|
||||
;;
|
||||
[Nn]* )
|
||||
confirm='false'
|
||||
break
|
||||
;;
|
||||
* ) reenter_instructions "Please type y or n \"${yn}\"";;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "${confirm}" == 'true' ]]; then
|
||||
inf "Deconstructing ${require} into \"{${deconstructed_comma}}\"..."
|
||||
perl -pi -e 's/^(goog\.(require|requireType)\('\'"${require}"\''\);)/const \{'"${deconstructed_comma}"'\} = \1/' "${filepath}"
|
||||
|
||||
for require_prop in $(echo "${properties_accessed}"); do
|
||||
inf "Updating references of ${require}.${require_prop} to ${require_prop}..."
|
||||
perl -pi -e 's/'"${require}"'\.'"${require_prop}"'([^'\''\w])/'"${require_prop}"'\1/g' "${filepath}"
|
||||
done
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
local require_name=$(echo "${require}" | perl -pe 's/(\w+\.)+(\w+)/\2/g')
|
||||
inf "Updating require declaration for ${require}..."
|
||||
perl -pi -e 's/^(goog\.(require|requireType)\('\'"${require}"\''\);)/const '"${require_name}"' = \1/' "${filepath}"
|
||||
|
||||
inf "Updating references of ${require} to ${require_name}..."
|
||||
perl -pi -e 's/'"${require}"'([^'\''\w])/'"${require_name}"'\1/g' "${filepath}"
|
||||
# Parse property access of module
|
||||
local direct_access_count=$(perl -nle 'print $& while m{'"${require}"'[^\.'\'']}g' "${filepath}" | wc -l)
|
||||
local properties_accessed=$(getPropertiesAccessed "${require}" "${requires}" "${filepath}")
|
||||
|
||||
# Remove $module_name in case it is a child of $require.
|
||||
# Ex: Blockly.utils.dom would be a child of Blockly, module_overlap would be
|
||||
# "utils"
|
||||
local module_overlap=$(echo "${module_name}" | perl -nle 'print $& while m{(?<='"${require}"'\.)\w+}g')
|
||||
if [[ -n "${module_overlap}" ]]; then
|
||||
properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/'"${module_overlap}"'//g')
|
||||
# Trim any extra whitespace created.
|
||||
properties_accessed=$(echo "${properties_accessed}" | xargs)
|
||||
fi
|
||||
|
||||
if [[ -n "${properties_accessed}" ]]; then
|
||||
local comma_properties=$(echo "${properties_accessed}" | perl -pe 's/\s+/, /g' | perl -pe 's/, $//')
|
||||
inf "Detected references of ${require}: ${comma_properties}"
|
||||
|
||||
for require_prop in $(echo "${properties_accessed}"); do
|
||||
inf "Updating references of ${require}.${require_prop} to ${require_name}.${require_prop}..."
|
||||
perl -pi -e 's/'"${require}"'\.'"${require_prop}"'(?!\w)/'"${require_name}"'\.'"${require_prop}"'/g' "${filepath}"
|
||||
done
|
||||
fi
|
||||
|
||||
inf "Updating direct references of ${require} to ${require_name}..."
|
||||
perl -pi -e 's/'"${require}"'(?!['\''\w\.])/'"${require_name}"'/g' "${filepath}"
|
||||
done
|
||||
|
||||
local missing_requires=$(perl -nle'print $& while m{(?<!'\'')Blockly(\.\w+)+}g' "${filepath}")
|
||||
missing_requires=$(echo "${missing_requires}" | tr ' ' '\n' | sort -u)
|
||||
if [[ -n "${missing_requires}" ]]; then
|
||||
err "Missing requires for:\n${missing_requires}\nPlease manually fix."
|
||||
# Search for the string goog.require('Blockly') or goog.requireType('Blockly')
|
||||
local has_blockly_require=$(perl -ne 'print m/goog\.(?:require|requireType)\('\''Blockly'\''\)/' "${filepath}")
|
||||
if [[ -n "${has_blockly_require}" ]]; then
|
||||
warn 'Blockly detected as a require.'
|
||||
warn "Potentially missing requires for:\n${missing_requires}\nPlease manually review."
|
||||
else
|
||||
err "Missing requires for:\n${missing_requires}\nPlease manually fix."
|
||||
fi
|
||||
fi
|
||||
|
||||
success "Completed automation for step 3. Please manually review and reorder requires."
|
||||
@@ -287,8 +374,8 @@ help() {
|
||||
echo ""
|
||||
echo "Usage: $0 [-h] [-c <step> <filepath>|-s <step> <filepath>]"
|
||||
echo " -h Display help and exit"
|
||||
echo " -c <step> <filepath> Create a commit for the specified step [2-4]"
|
||||
echo " -s <step> <filepath> Run the specified step [1-4]"
|
||||
echo " -c <step> <filepath> Create a commit for the specified step [1-4]"
|
||||
echo " -s <step> <filepath> Run the specified step [2-4]"
|
||||
}
|
||||
|
||||
#######################################
|
||||
|
||||
@@ -10,7 +10,7 @@ goog.addDependency('../../blocks/variables_dynamic.js', ['Blockly.Constants.Vari
|
||||
goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.IASTNodeLocation', 'Blockly.IDeletable', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.Workspace', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.IASTNodeLocationSvg', 'Blockly.IBoundedElement', 'Blockly.ICopyable', 'Blockly.IDraggable', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
@@ -53,24 +53,24 @@ goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockl
|
||||
goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.IdGenerator', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.DropDownDiv', 'Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.fieldRegistry', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IFlyout', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml']);
|
||||
goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly', 'Blockly.Block', 'Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutButton', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IFlyout', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.internalConstants', 'Blockly.utils.deprecation']);
|
||||
goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate']);
|
||||
goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly', 'Blockly.internalConstants', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'});
|
||||
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.internalConstants'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/interfaces/i_ast_node_location.js', ['Blockly.IASTNodeLocation'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
@@ -91,7 +91,7 @@ goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarg
|
||||
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_metrics_manager.js', ['Blockly.IMetricsManager'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
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'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
@@ -102,31 +102,31 @@ goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'
|
||||
goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], ['Blockly.IRegistrable'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.IToolboxItem'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/internal_constants.js', ['Blockly.internalConstants'], ['Blockly.connectionTypes'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.utils.Coordinate'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'});
|
||||
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': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode']);
|
||||
goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker']);
|
||||
goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style']);
|
||||
goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.IdGenerator', 'Blockly.utils.aria', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/metrics_manager.js', ['Blockly.FlyoutMetricsManager', 'Blockly.MetricsManager'], ['Blockly.IMetricsManager', 'Blockly.registry', 'Blockly.utils.Size', 'Blockly.utils.toolbox'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global']);
|
||||
goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml']);
|
||||
goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.internalConstants']);
|
||||
goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.IdGenerator', 'Blockly.utils.Metrics', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/positionable_helpers.js', ['Blockly.uiPosition'], ['Blockly.Scrollbar', 'Blockly.utils.Rect', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils.xml']);
|
||||
goog.addDependency('../../core/registry.js', ['Blockly.registry'], []);
|
||||
goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.connectionTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/registry.js', ['Blockly.registry'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.Events', 'Blockly.connectionTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
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.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
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.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'});
|
||||
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.Icon', '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'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.IRegistrable', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.connectionTypes']);
|
||||
goog.addDependency('../../core/renderers/geras/constants.js', ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.geras.Highlighter', 'Blockly.geras.RenderInfo', 'Blockly.utils.object', 'Blockly.utils.svgPaths']);
|
||||
@@ -160,13 +160,13 @@ goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Ren
|
||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes']);
|
||||
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme']);
|
||||
goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme']);
|
||||
goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.Theme']);
|
||||
goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.ISelectableToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ICollapsibleToolboxItem', 'Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ICollapsibleToolboxItem', 'Blockly.ToolboxCategory', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.IToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.BlockSvg', 'Blockly.CollapsibleToolboxCategory', 'Blockly.ComponentManager', 'Blockly.Css', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.IAutoHideable', 'Blockly.IKeyboardAccessible', 'Blockly.IStyleable', 'Blockly.IToolbox', 'Blockly.Options', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], ['Blockly.IToolboxItem']);
|
||||
@@ -179,7 +179,7 @@ goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], []);
|
||||
goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], []);
|
||||
goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.IdGenerator'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
@@ -187,7 +187,7 @@ goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], [], {'lan
|
||||
goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
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/size.js', ['Blockly.utils.Size'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], []);
|
||||
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'], []);
|
||||
@@ -199,17 +199,16 @@ goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Bloc
|
||||
goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils']);
|
||||
goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.xml']);
|
||||
goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.utils.xml']);
|
||||
goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.IASTNodeLocation', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math']);
|
||||
goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml']);
|
||||
goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']);
|
||||
goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly', 'Blockly.ContextMenu', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.IBoundedElement', 'Blockly.IBubble', 'Blockly.ICopyable', 'Blockly.Touch', 'Blockly.WorkspaceComment', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate']);
|
||||
goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.IASTNodeLocationSvg', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml']);
|
||||
goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('base.js', [], []);
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
<script>
|
||||
// Custom requires for the playground.
|
||||
goog.require('Blockly.WorkspaceCommentSvg');
|
||||
goog.require('Blockly.WorkspaceCommentSvg.render');
|
||||
</script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
@@ -77,7 +77,6 @@ goog.require('Blockly.Themes.Zelos');
|
||||
|
||||
// Other.
|
||||
goog.require('Blockly.WorkspaceCommentSvg');
|
||||
goog.require('Blockly.WorkspaceCommentSvg.render');
|
||||
</script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
Reference in New Issue
Block a user