Adding IDragTarget support. (#4852)

This commit is contained in:
Monica Kozbial
2021-06-09 13:59:22 -07:00
committed by GitHub
parent 861a981cb6
commit 11390341b1
18 changed files with 505 additions and 204 deletions

View File

@@ -42,6 +42,8 @@ goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Block
goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'});
goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es5'});
goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es5'});
goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.DragTarget', 'Blockly.IDeleteArea']);
goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], ['Blockly.IDragTarget']);
goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style']);
goog.addDependency('../../core/events/block_events.js', ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']);
goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.registry', 'Blockly.utils']);
@@ -73,11 +75,11 @@ goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Bloc
goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry']);
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_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object']);
goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IDeleteArea', '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.Block', '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_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es5'});
goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['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/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.constants']);
goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.constants', '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.constants', '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']);
@@ -94,7 +96,8 @@ goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IC
goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], []);
goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], []);
goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], []);
goog.addDependency('../../core/interfaces/i_deletearea.js', ['Blockly.IDeleteArea'], []);
goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget']);
goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent']);
goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], []);
goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], []);
goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], []);
@@ -174,12 +177,12 @@ goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Bl
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/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.IToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'});
goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.CollapsibleToolboxCategory', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.IAutoHideable', 'Blockly.IDeleteArea', '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.js', ['Blockly.Toolbox'], ['Blockly.CollapsibleToolboxCategory', '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']);
goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.utils.string']);
goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string']);
goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object']);
goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IAutoHideable', 'Blockly.IDeleteArea', 'Blockly.IPositionable', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IAutoHideable', 'Blockly.IPositionable', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], []);
goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], []);

View File

@@ -25,6 +25,7 @@ goog.require('Blockly.utils.Coordinate');
goog.require('Blockly.utils.dom');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.IDragTarget');
goog.requireType('Blockly.WorkspaceSvg');
@@ -59,13 +60,11 @@ Blockly.BlockDragger = function(block, workspace) {
this.draggingBlock_);
/**
* Which delete area the mouse pointer is over, if any.
* One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @type {?number}
* Which drag area the mouse pointer is over, if any.
* @type {?Blockly.IDragTarget}
* @private
*/
this.deleteArea_ = null;
this.dragTarget_ = null;
/**
* Whether the block would be deleted if dropped immediately.
@@ -210,8 +209,15 @@ Blockly.BlockDragger.prototype.dragBlock = function(e, currentDragDeltaXY) {
this.draggingBlock_.moveDuringDrag(newLoc);
this.dragIcons_(delta);
this.deleteArea_ = this.workspace_.isDeleteArea(e);
this.draggedConnectionManager_.update(delta, this.deleteArea_);
var oldDragTarget = this.dragTarget_;
this.dragTarget_ = this.workspace_.getDragTarget(e);
if (this.dragTarget_ !== oldDragTarget) {
oldDragTarget && oldDragTarget.onDragExit();
this.dragTarget_ && this.dragTarget_.onDragEnter();
}
this.draggedConnectionManager_.update(delta, this.dragTarget_);
this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock();
this.updateCursorDuringBlockDrag_();
};
@@ -237,8 +243,16 @@ Blockly.BlockDragger.prototype.endBlockDrag = function(e, currentDragDeltaXY) {
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
this.draggingBlock_.moveOffDragSurface(newLoc);
var deleted = this.maybeDeleteBlock_();
if (!deleted) {
if (this.dragTarget_) {
this.dragTarget_.onBlockDrop(this.draggingBlock_);
}
if (this.wouldDeleteBlock_) {
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBlock_.dispose(false, true);
Blockly.draggingConnections = [];
} else {
// These are expensive and don't need to be done if we're deleting.
this.draggingBlock_.moveConnections(delta.x, delta.y);
this.draggingBlock_.setDragging(false);
@@ -284,49 +298,13 @@ Blockly.BlockDragger.prototype.fireMoveEvent_ = function() {
Blockly.Events.fire(event);
};
/**
* Shut the trash can and, if necessary, delete the dragging block.
* Should be called at the end of a block drag.
* @return {boolean} Whether the block was deleted.
* @private
*/
Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() {
var trashcan = this.workspace_.trashcan;
if (this.wouldDeleteBlock_) {
if (trashcan) {
setTimeout(trashcan.closeLid.bind(trashcan), 100);
}
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBlock_.dispose(false, true);
Blockly.draggingConnections = [];
} else if (trashcan) {
// Make sure the trash can lid is closed.
trashcan.closeLid();
}
return this.wouldDeleteBlock_;
};
/**
* Update the cursor (and possibly the trash can lid) to reflect whether the
* dragging block would be deleted if released immediately.
* @private
*/
Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() {
this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock();
var trashcan = this.workspace_.trashcan;
if (this.wouldDeleteBlock_) {
this.draggingBlock_.setDeleteStyle(true);
if (this.deleteArea_ == Blockly.DELETE_AREA_TRASH && trashcan) {
trashcan.setLidOpen(true);
}
} else {
this.draggingBlock_.setDeleteStyle(false);
if (trashcan) {
trashcan.setLidOpen(false);
}
}
this.draggingBlock_.setDeleteStyle(this.wouldDeleteBlock_);
};
/**

View File

@@ -51,13 +51,11 @@ Blockly.BubbleDragger = function(bubble, workspace) {
this.workspace_ = workspace;
/**
* Which delete area the mouse pointer is over, if any.
* One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @type {?number}
* Which drag target the mouse pointer is over, if any.
* @type {?Blockly.IDragTarget}
* @private
*/
this.deleteArea_ = null;
this.dragTarget_ = null;
/**
* Whether the bubble would be deleted if dropped immediately.
@@ -136,33 +134,41 @@ Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) {
this.draggingBubble_.moveDuringDrag(this.dragSurface_, newLoc);
if (this.draggingBubble_.isDeletable()) {
this.deleteArea_ = this.workspace_.isDeleteArea(e);
this.updateCursorDuringBubbleDrag_();
var oldDragTarget = this.dragTarget_;
this.dragTarget_ = this.workspace_.getDragTarget(e);
if (this.dragTarget_ !== oldDragTarget) {
oldDragTarget && oldDragTarget.onDragExit();
this.dragTarget_ && this.dragTarget_.onDragEnter();
}
this.wouldDeleteBubble_ = this.shouldDelete_(this.dragTarget_);
this.updateCursorDuringBubbleDrag_();
};
/**
* Shut the trash can and, if necessary, delete the dragging bubble.
* Should be called at the end of a bubble drag.
* @return {boolean} Whether the bubble was deleted.
* Whether ending the drag would delete the bubble.
* @param {?Blockly.IDragTarget} dragTarget The drag target that the bubblee is
* currently over.
* @return {boolean} Whether dropping the bubble immediately would delete the
* block.
* @private
*/
Blockly.BubbleDragger.prototype.maybeDeleteBubble_ = function() {
var trashcan = this.workspace_.trashcan;
Blockly.BubbleDragger.prototype.shouldDelete_ = function(dragTarget) {
var couldDeleteBubble = this.draggingBubble_.isDeletable();
if (this.wouldDeleteBubble_) {
if (trashcan) {
setTimeout(trashcan.closeLid.bind(trashcan), 100);
if (couldDeleteBubble && dragTarget) {
// TODO(#4881) use hasCapability instead of getComponents
var deleteAreas = this.workspace_.getComponentManager().getComponents(
Blockly.ComponentManager.Capability.DELETE_AREA, false);
var isDeleteArea = deleteAreas.some(function(deleteArea) {
return dragTarget === deleteArea;
});
if (isDeleteArea) {
return (/** @type {!Blockly.IDeleteArea} */ (dragTarget))
.wouldDeleteBubble(this.draggingBubble_);
}
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBubble_.dispose(false, true);
} else if (trashcan) {
// Make sure the trash can lid is closed.
trashcan.closeLid();
}
return this.wouldDeleteBubble_;
return false;
};
/**
@@ -171,18 +177,10 @@ Blockly.BubbleDragger.prototype.maybeDeleteBubble_ = function() {
* @private
*/
Blockly.BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() {
this.wouldDeleteBubble_ = this.deleteArea_ != Blockly.DELETE_AREA_NONE;
var trashcan = this.workspace_.trashcan;
if (this.wouldDeleteBubble_) {
this.draggingBubble_.setDeleteStyle(true);
if (this.deleteArea_ == Blockly.DELETE_AREA_TRASH && trashcan) {
trashcan.setLidOpen(true);
}
} else {
this.draggingBubble_.setDeleteStyle(false);
if (trashcan) {
trashcan.setLidOpen(false);
}
}
};
@@ -200,12 +198,18 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function(
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
// Move the bubble to its final location.
this.draggingBubble_.moveTo(newLoc.x, newLoc.y);
var deleted = this.maybeDeleteBubble_();
if (!deleted) {
if (this.dragTarget_) {
this.dragTarget_.onBubbleDrop(this.draggingBubble_);
}
if (this.wouldDeleteBubble_) {
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBubble_.dispose(false, true);
} else {
// Put everything back onto the bubble canvas.
if (this.dragSurface_) {
this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas());

View File

@@ -15,6 +15,8 @@ goog.provide('Blockly.ComponentManager');
goog.requireType('Blockly.IAutoHideable');
goog.requireType('Blockly.IComponent');
goog.requireType('Blockly.IDeleteArea');
goog.requireType('Blockly.IDragTarget');
goog.requireType('Blockly.IPositionable');
@@ -206,6 +208,15 @@ Blockly.ComponentManager.Capability.prototype.toString = function() {
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IPositionable>} */
Blockly.ComponentManager.Capability.POSITIONABLE =
new Blockly.ComponentManager.Capability('positionable');
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IDragTarget>} */
Blockly.ComponentManager.Capability.DRAG_TARGET =
new Blockly.ComponentManager.Capability('drag_target');
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IDeleteArea>} */
Blockly.ComponentManager.Capability.DELETE_AREA =
new Blockly.ComponentManager.Capability('delete_area');
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IAutoHideable>} */
Blockly.ComponentManager.Capability.AUTOHIDEABLE =
new Blockly.ComponentManager.Capability('autohideable');

View File

@@ -161,26 +161,6 @@ Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.NEXT_STATEMENT] =
Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.PREVIOUS_STATEMENT] =
Blockly.connectionTypes.NEXT_STATEMENT;
/**
* ENUM representing that an event is not in any delete areas.
* Null for backwards compatibility reasons.
* @const
*/
Blockly.DELETE_AREA_NONE = null;
/**
* ENUM representing that an event is in the delete area of the trash can.
* @const
*/
Blockly.DELETE_AREA_TRASH = 1;
/**
* ENUM representing that an event is in the delete area of the toolbox or
* flyout.
* @const
*/
Blockly.DELETE_AREA_TOOLBOX = 2;
/**
* String for use in the "custom" attribute of a category in toolbox XML.
* This string indicates that the category should be dynamically populated with

53
core/delete_area.js Normal file
View File

@@ -0,0 +1,53 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The abstract class for a component that can delete a block or
* bubble that is dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.DeleteArea');
goog.require('Blockly.DragTarget');
goog.require('Blockly.IDeleteArea');
/**
* Abstract class for a component that can delete a block or bubble that is
* dropped on top of it.
* @extends {Blockly.DragTarget}
* @implements {Blockly.IDeleteArea}
* @constructor
*/
Blockly.DeleteArea = function() {
Blockly.DeleteArea.superClass_.constructor.call(this);
};
Blockly.utils.object.inherits(Blockly.DeleteArea, Blockly.DragTarget);
/**
* Returns whether the provided block would be deleted if dropped on this area.
* @param {!Blockly.BlockSvg} _block The block.
* @param {boolean} couldConnect Whether the block could could connect to
* another.
* @return {boolean} Whether the block provided would be deleted if dropped on
* this area.
*/
Blockly.DeleteArea.prototype.wouldDeleteBlock = function(_block, couldConnect) {
return !couldConnect;
};
/**
* Returns whether the provided bubble would be deleted if dropped on this area.
* @param {!Blockly.IBubble} _bubble The bubble.
* @return {boolean} Whether the bubble provided would be deleted if dropped on
* this area.
*/
Blockly.DeleteArea.prototype.wouldDeleteBubble = function(_bubble) {
return true;
};

70
core/drag_target.js Normal file
View File

@@ -0,0 +1,70 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The abstract class for a component with custom behaviour when a
* block or bubble is dragged over or dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.DragTarget');
goog.require('Blockly.IDragTarget');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.IBubble');
goog.requireType('Blockly.utils.Rect');
/**
* Abstract class for a component with custom behaviour when a block or bubble
* is dragged over or dropped on top of it.
* @implements {Blockly.IDragTarget}
* @constructor
*/
Blockly.DragTarget = function() {};
/**
* Returns the bounding rectangle of the drag target area in pixel units
* relative to the Blockly injection div.
* @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
* target area should be ignored.
*/
Blockly.DragTarget.prototype.getClientRect;
/**
* Handles when a cursor with a block or bubble enters this drag target.
*/
Blockly.DragTarget.prototype.onDragEnter = function() {
// no-op
};
/**
* Handles when a cursor with a block or bubble exits this drag target.
*/
Blockly.DragTarget.prototype.onDragExit = function() {
// no-op
};
/**
* Handles when a block is dropped on this component. Should not handle delete
* here.
* @param {!Blockly.BlockSvg} _block The block.
*/
Blockly.DragTarget.prototype.onBlockDrop = function(_block) {
// no-op
};
/**
* Handles when a bubble is dropped on this component. Should not handle delete
* here.
* @param {!Blockly.IBubble} _bubble The bubble.
*/
Blockly.DragTarget.prototype.onBubbleDrop = function(_bubble) {
// no-op
};

View File

@@ -16,6 +16,7 @@ goog.require('Blockly.Block');
/** @suppress {extraRequire} */
goog.require('Blockly.blockRendering');
goog.require('Blockly.browserEvents');
goog.require('Blockly.DeleteArea');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BlockCreate');
@@ -24,7 +25,6 @@ goog.require('Blockly.Events.VarCreate');
goog.require('Blockly.FlyoutMetricsManager');
/** @suppress {extraRequire} */
goog.require('Blockly.Gesture');
goog.require('Blockly.IDeleteArea');
goog.require('Blockly.IFlyout');
goog.require('Blockly.ScrollbarPair');
goog.require('Blockly.Tooltip');
@@ -51,10 +51,11 @@ goog.requireType('Blockly.utils.Rect');
* workspace.
* @constructor
* @abstract
* @implements {Blockly.IDeleteArea}
* @implements {Blockly.IFlyout}
* @extends {Blockly.DeleteArea}
*/
Blockly.Flyout = function(workspaceOptions) {
Blockly.Flyout.superClass_.constructor.call(this);
workspaceOptions.setMetrics = this.setMetrics_.bind(this);
/**
@@ -140,6 +141,7 @@ Blockly.Flyout = function(workspaceOptions) {
*/
this.targetWorkspace = null;
};
Blockly.utils.object.inherits(Blockly.Flyout, Blockly.DeleteArea);
/**
* Does the flyout automatically close when a block is created?
@@ -300,6 +302,16 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) {
this.workspace_.setVariableMap(this.targetWorkspace.getVariableMap());
this.workspace_.createPotentialVariableMap();
targetWorkspace.getComponentManager().addComponent({
id: 'flyout' + this.workspace_.id,
component: this,
weight: 1,
capabilities: [
Blockly.ComponentManager.Capability.DELETE_AREA,
Blockly.ComponentManager.Capability.DRAG_TARGET
]
});
};
/**
@@ -380,6 +392,11 @@ Blockly.Flyout.prototype.setVisible = function(visible) {
this.isVisible_ = visible;
if (visibilityChanged) {
if (!this.autoClose) {
// Auto-close flyouts are ignored as drag targets, so only non auto-close
// flyouts need to have their drag target updated.
this.workspace_.recordDragTargets();
}
this.updateDisplay_();
}
};
@@ -1018,8 +1035,9 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) {
};
/**
* Return the deletion rectangle for this flyout in viewport coordinates.
* @return {?Blockly.utils.Rect} Rectangle in which to delete.
* Returns the bounding rectangle of the drag target area in pixel units
* relative to viewport.
* @return {Blockly.utils.Rect} The component's bounding box.
*/
Blockly.Flyout.prototype.getClientRect;

View File

@@ -304,11 +304,15 @@ Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function(
};
/**
* Return the deletion rectangle for this flyout in viewport coordinates.
* @return {?Blockly.utils.Rect} Rectangle in which to delete.
* 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
* target area should be ignored.
*/
Blockly.HorizontalFlyout.prototype.getClientRect = function() {
if (!this.svgGroup_) {
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;
}

View File

@@ -287,11 +287,15 @@ Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = function(
};
/**
* Return the deletion rectangle for this flyout in viewport coordinates.
* @return {?Blockly.utils.Rect} Rectangle in which to delete.
* 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
* target area should be ignored.
*/
Blockly.VerticalFlyout.prototype.getClientRect = function() {
if (!this.svgGroup_) {
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;
}

View File

@@ -240,14 +240,15 @@ Blockly.InsertionMarkerManager.prototype.applyConnections = function() {
* Update connections based on the most recent move location.
* @param {!Blockly.utils.Coordinate} dxy Position relative to drag start,
* in workspace units.
* @param {?number} deleteArea One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @param {?Blockly.IDragTarget} dragTarget The drag target that the block is
* currently over.
* @package
*/
Blockly.InsertionMarkerManager.prototype.update = function(dxy, deleteArea) {
Blockly.InsertionMarkerManager.prototype.update = function(dxy, dragTarget) {
var candidate = this.getCandidate_(dxy);
this.wouldDeleteBlock_ = this.shouldDelete_(candidate, deleteArea);
this.wouldDeleteBlock_ = this.shouldDelete_(candidate, dragTarget);
var shouldUpdate = this.wouldDeleteBlock_ ||
this.shouldUpdatePreviews_(candidate, dxy);
@@ -445,23 +446,32 @@ Blockly.InsertionMarkerManager.prototype.getStartRadius_ = function() {
/**
* Whether ending the drag would delete the block.
* @param {!Object} candidate An object containing a local connection, a closest
* connection, and a radius.
* @param {?number} deleteArea One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @return {boolean} True if dropping the block immediately would replace
* delete the block. False otherwise.
* connection, and a radius.
* @param {?Blockly.IDragTarget} dragTarget The drag target that the block is
* currently over.
* @return {boolean} Whether dropping the block immediately would delete the
* block.
* @private
*/
Blockly.InsertionMarkerManager.prototype.shouldDelete_ = function(candidate,
deleteArea) {
// Prefer connecting over dropping into the trash can, but prefer dragging to
// the toolbox over connecting to other blocks.
var wouldConnect = candidate && !!candidate.closest &&
deleteArea != Blockly.DELETE_AREA_TOOLBOX;
var wouldDelete = !!deleteArea && !this.topBlock_.getParent() &&
this.topBlock_.isDeletable();
Blockly.InsertionMarkerManager.prototype.shouldDelete_ = function(
candidate, dragTarget) {
var couldDeleteBlock =
!this.topBlock_.getParent() && this.topBlock_.isDeletable();
return wouldDelete && !wouldConnect;
if (couldDeleteBlock && dragTarget) {
// TODO(#4881) use hasCapability instead of getComponents
var deleteAreas = this.workspace_.getComponentManager().getComponents(
Blockly.ComponentManager.Capability.DELETE_AREA, false);
var isDeleteArea = deleteAreas.some(function(deleteArea) {
return dragTarget === deleteArea;
});
if (isDeleteArea) {
return (
/** @type {!Blockly.IDeleteArea} */ (dragTarget))
.wouldDeleteBlock(this.topBlock_, candidate && !!candidate.closest);
}
}
return false;
};
/**

View File

@@ -0,0 +1,44 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a component that can delete a block or bubble
* that is dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IDeleteArea');
goog.require('Blockly.IDragTarget');
/**
* Interface for a component that can delete a block or bubble that is dropped
* on top of it.
* @extends {Blockly.IDragTarget}
* @interface
*/
Blockly.IDeleteArea = function() {};
/**
* Returns whether the provided block would be deleted if dropped on this area.
* @param {!Blockly.BlockSvg} block The block.
* @param {boolean} couldConnect Whether the block could could connect to
* another.
* @return {boolean} Whether the block provided would be deleted if dropped on
* this area.
*/
Blockly.IDeleteArea.prototype.wouldDeleteBlock;
/**
* Returns whether the provided bubble would be deleted if dropped on this area.
* @param {!Blockly.IBubble} bubble The bubble.
* @return {boolean} Whether the bubble provided would be deleted if dropped on
* this area.
*/
Blockly.IDeleteArea.prototype.wouldDeleteBubble;

View File

@@ -1,30 +0,0 @@
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a component that can delete a block that is
* dropped on top of it.
* @author aschmiedt@google.com (Abby Schmiedt)
*/
'use strict';
goog.provide('Blockly.IDeleteArea');
goog.requireType('Blockly.utils.Rect');
/**
* Interface for a component that can delete a block that is dropped on top of it.
* @interface
*/
Blockly.IDeleteArea = function() {};
/**
* Return the deletion rectangle.
* @return {Blockly.utils.Rect} Rectangle in which to delete.
*/
Blockly.IDeleteArea.prototype.getClientRect;

View File

@@ -0,0 +1,60 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a component that has a handler for when a
* block is dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IDragTarget');
goog.require('Blockly.IComponent');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.IBubble');
goog.requireType('Blockly.utils.Rect');
/**
* Interface for a component with custom behaviour when a block or bubble is
* dragged over or dropped on top of it.
* @extends {Blockly.IComponent}
* @interface
*/
Blockly.IDragTarget = function() {};
/**
* Returns the bounding rectangle of the drag target area in pixel units
* relative to viewport.
* @return {Blockly.utils.Rect} The component's bounding box.
*/
Blockly.IDragTarget.prototype.getClientRect;
/**
* Handles when a cursor with a block or bubble enters this drag target.
*/
Blockly.IDragTarget.prototype.onDragEnter;
/**
* Handles when a cursor with a block or bubble exits this drag target.
*/
Blockly.IDragTarget.prototype.onDragExit;
/**
* Handles when a block is dropped on this component. Should not handle delete
* here.
* @param {!Blockly.BlockSvg} block The block.
*/
Blockly.IDragTarget.prototype.onBlockDrop;
/**
* Handles when a bubble is dropped on this component. Should not handle delete
* here.
* @param {!Blockly.IBubble} bubble The bubble.
*/
Blockly.IDragTarget.prototype.onBubbleDrop;

View File

@@ -287,7 +287,7 @@ Blockly.Mutator.prototype.resizeBubble_ = function() {
*/
Blockly.Mutator.prototype.onBubbleMove_ = function() {
if (this.workspace_) {
this.workspace_.recordDeleteAreas();
this.workspace_.recordDragTargets();
}
};

View File

@@ -17,11 +17,11 @@ goog.require('Blockly.CollapsibleToolboxCategory');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.Css');
goog.require('Blockly.DeleteArea');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.ToolboxItemSelect');
goog.require('Blockly.IAutoHideable');
goog.require('Blockly.IDeleteArea');
goog.require('Blockly.IKeyboardAccessible');
goog.require('Blockly.IStyleable');
goog.require('Blockly.IToolbox');
@@ -50,11 +50,12 @@ goog.requireType('Blockly.WorkspaceSvg');
* @constructor
* @implements {Blockly.IAutoHideable}
* @implements {Blockly.IKeyboardAccessible}
* @implements {Blockly.IDeleteArea}
* @implements {Blockly.IStyleable}
* @implements {Blockly.IToolbox}
* @extends {Blockly.DeleteArea}
*/
Blockly.Toolbox = function(workspace) {
Blockly.Toolbox.superClass_.constructor.call(this);
/**
* The workspace this toolbox is on.
* @type {!Blockly.WorkspaceSvg}
@@ -159,6 +160,7 @@ Blockly.Toolbox = function(workspace) {
*/
this.boundEvents_ = [];
};
Blockly.utils.object.inherits(Blockly.Toolbox, Blockly.DeleteArea);
/**
* Handles the given keyboard shortcut.
@@ -189,13 +191,14 @@ Blockly.Toolbox.prototype.init = function() {
themeManager.subscribe(this.HtmlDiv, 'toolboxBackgroundColour',
'background-color');
themeManager.subscribe(this.HtmlDiv, 'toolboxForegroundColour', 'color');
this.workspace_.getComponentManager().addComponent({
id: 'toolbox',
component: this,
weight: 1,
capabilities: [
Blockly.ComponentManager.Capability.AUTOHIDEABLE
Blockly.ComponentManager.Capability.AUTOHIDEABLE,
Blockly.ComponentManager.Capability.DELETE_AREA,
Blockly.ComponentManager.Capability.DRAG_TARGET
]
});
};
@@ -496,9 +499,10 @@ Blockly.Toolbox.prototype.removeStyle = function(style) {
};
/**
* Return the deletion rectangle for this toolbox.
* @return {?Blockly.utils.Rect} Rectangle in which to delete.
* @public
* 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
* target area should be ignored.
*/
Blockly.Toolbox.prototype.getClientRect = function() {
if (!this.HtmlDiv) {
@@ -529,6 +533,19 @@ Blockly.Toolbox.prototype.getClientRect = function() {
}
};
/**
* Returns whether the provided block would be deleted if dropped on this area.
* @param {!Blockly.BlockSvg} _block The block.
* @param {boolean} _couldConnect Whether the block could could connect to
* another.
* @return {boolean} Whether the block provided would be deleted if dropped on
* this area.
*/
Blockly.Toolbox.prototype.wouldDeleteBlock = function(_block, _couldConnect) {
// Prefer dragging to the toolbox over connecting to other blocks.
return true;
};
/**
* Gets the toolbox item with the given ID.
* @param {string} id The ID of the toolbox item.

View File

@@ -15,11 +15,11 @@ goog.provide('Blockly.Trashcan');
goog.require('Blockly.browserEvents');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.DeleteArea');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.TrashcanOpen');
goog.require('Blockly.IAutoHideable');
goog.require('Blockly.IDeleteArea');
goog.require('Blockly.IPositionable');
goog.require('Blockly.Options');
goog.require('Blockly.registry');
@@ -40,10 +40,11 @@ goog.requireType('Blockly.WorkspaceSvg');
* @param {!Blockly.WorkspaceSvg} workspace The workspace to sit in.
* @constructor
* @implements {Blockly.IAutoHideable}
* @implements {Blockly.IDeleteArea}
* @implements {Blockly.IPositionable}
* @extends {Blockly.DeleteArea}
*/
Blockly.Trashcan = function(workspace) {
Blockly.Trashcan.superClass_.constructor.call(this);
/**
* The workspace the trashcan sits in.
* @type {!Blockly.WorkspaceSvg}
@@ -102,6 +103,7 @@ Blockly.Trashcan = function(workspace) {
}
this.workspace_.addChangeListener(this.onDelete_.bind(this));
};
Blockly.utils.object.inherits(Blockly.Trashcan, Blockly.DeleteArea);
/**
* Width of both the trash can and lid images.
@@ -364,8 +366,10 @@ Blockly.Trashcan.prototype.init = function() {
component: this,
weight: 1,
capabilities: [
Blockly.ComponentManager.Capability.POSITIONABLE,
Blockly.ComponentManager.Capability.AUTOHIDEABLE
Blockly.ComponentManager.Capability.AUTOHIDEABLE,
Blockly.ComponentManager.Capability.DELETE_AREA,
Blockly.ComponentManager.Capability.DRAG_TARGET,
Blockly.ComponentManager.Capability.POSITIONABLE
]
});
this.initialized_ = true;
@@ -501,8 +505,10 @@ Blockly.Trashcan.prototype.getBoundingRectangle = function() {
};
/**
* Return the deletion rectangle for this trash can.
* @return {?Blockly.utils.Rect} Rectangle in which to delete.
* 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
* target area should be ignored.
*/
Blockly.Trashcan.prototype.getClientRect = function() {
if (!this.svgGroup_) {
@@ -518,6 +524,51 @@ Blockly.Trashcan.prototype.getClientRect = function() {
return new Blockly.utils.Rect(top, bottom, left, right);
};
/**
* Handles when a cursor with a block or bubble enters this drag target.
* @override
*/
Blockly.Trashcan.prototype.onDragEnter = function() {
this.setLidOpen(true);
};
/**
* Handles when a cursor with a block or bubble exits this drag target.
* @override
*/
Blockly.Trashcan.prototype.onDragExit = function() {
this.setLidOpen(false);
};
/**
* Handles when a block is dropped on this component. Should not handle delete
* here.
* @param {!Blockly.BlockSvg} _block The block.
* @override
*/
Blockly.Trashcan.prototype.onBlockDrop = function(_block) {
this.onDrop_();
};
/**
* Handles when a bubble is dropped on this component. Should not handle delete
* here.
* @param {!Blockly.IBubble} _bubble The bubble.
* @override
*/
Blockly.Trashcan.prototype.onBubbleDrop = function(_bubble) {
this.onDrop_();
};
/**
* Handles when a block or bubble is dropped on this component.
* @private
*/
Blockly.Trashcan.prototype.onDrop_ = function() {
setTimeout(this.closeLid.bind(this), 100);
};
/**
* Flip the lid open or shut.
* @param {boolean} state True if open.

View File

@@ -61,6 +61,7 @@ goog.requireType('Blockly.blockRendering.Renderer');
goog.requireType('Blockly.Cursor');
goog.requireType('Blockly.FlyoutButton');
goog.requireType('Blockly.IBoundedElement');
goog.requireType('Blockly.IDragTarget');
goog.requireType('Blockly.IFlyout');
goog.requireType('Blockly.IMetricsManager');
goog.requireType('Blockly.IToolbox');
@@ -232,6 +233,17 @@ Blockly.WorkspaceSvg = function(
*/
this.topBoundedElements_ = [];
/**
* The recorded drag targets.
* @type {!Array<
* {
* component: !Blockly.IDragTarget,
* clientRect: !Blockly.utils.Rect,
* }>}
* @private
*/
this.dragTargetAreas_ = [];
/**
* The cached size of the parent svg element.
* Used to compute svg metrics.
@@ -879,7 +891,7 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) {
if (this.grid_) {
this.grid_.update(this.scale);
}
this.recordDeleteAreas();
this.recordDragTargets();
var CursorClass = Blockly.registry.getClassFromOptions(
Blockly.registry.Type.CURSOR, this.options);
@@ -1096,7 +1108,7 @@ Blockly.WorkspaceSvg.prototype.getToolbox = function() {
*/
Blockly.WorkspaceSvg.prototype.updateScreenCalculations_ = function() {
this.updateInverseScreenCTM();
this.recordDeleteAreas();
this.recordDragTargets();
};
/**
@@ -1617,38 +1629,50 @@ Blockly.WorkspaceSvg.prototype.createVariable = function(name,
/**
* Make a list of all the delete areas for this workspace.
* @deprecated Use workspace.recordDragTargets. (2021 June)
*/
Blockly.WorkspaceSvg.prototype.recordDeleteAreas = function() {
if (this.trashcan && this.svgGroup_.parentNode) {
this.deleteAreaTrash_ = this.trashcan.getClientRect();
} else {
this.deleteAreaTrash_ = null;
}
if (this.flyout_) {
this.deleteAreaToolbox_ = this.flyout_.getClientRect();
} else if (this.toolbox_ && typeof this.toolbox_.getClientRect == 'function') {
this.deleteAreaToolbox_ = this.toolbox_.getClientRect();
} else {
this.deleteAreaToolbox_ = null;
}
Blockly.utils.deprecation.warn(
'WorkspaceSvg.prototype.recordDeleteAreas',
'June 2021',
'June 2022',
'WorkspaceSvg.prototype.recordDragTargets');
this.recordDragTargets();
};
/**
* Is the mouse event over a delete area (toolbox or non-closing flyout)?
* @param {!Event} e Mouse move event.
* @return {?number} Null if not over a delete area, or an enum representing
* which delete area the event is over.
* Make a list of all the delete areas for this workspace.
*/
Blockly.WorkspaceSvg.prototype.isDeleteArea = function(e) {
if (this.deleteAreaTrash_ &&
this.deleteAreaTrash_.contains(e.clientX, e.clientY)) {
return Blockly.DELETE_AREA_TRASH;
Blockly.WorkspaceSvg.prototype.recordDragTargets = function() {
var dragTargets = this.componentManager_.getComponents(
Blockly.ComponentManager.Capability.DRAG_TARGET, true);
this.dragTargetAreas_ = [];
for (var i = 0, targetArea; (targetArea = dragTargets[i]); i++) {
var rect = targetArea.getClientRect();
if (rect) {
this.dragTargetAreas_.push({
component: targetArea,
clientRect: rect,
});
}
}
if (this.deleteAreaToolbox_ &&
this.deleteAreaToolbox_.contains(e.clientX, e.clientY)) {
return Blockly.DELETE_AREA_TOOLBOX;
};
/**
* Returns the drag target the mouse event is over.
* @param {!Event} e Mouse move event.
* @return {?Blockly.IDragTarget} Null if not over a drag target, or the drag
* target the event is over.
*/
Blockly.WorkspaceSvg.prototype.getDragTarget = function(e) {
for (var i = 0, targetArea; (targetArea = this.dragTargetAreas_[i]); i++) {
if (targetArea.clientRect.contains(e.clientX, e.clientY)) {
return targetArea.component;
}
}
return Blockly.DELETE_AREA_NONE;
return null;
};
/**
@@ -2200,7 +2224,7 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) {
if (this.flyout_) {
// No toolbox, resize flyout.
this.flyout_.reflow();
this.recordDeleteAreas();
this.recordDragTargets();
}
if (this.grid_) {
this.grid_.update(this.scale);