fix!: various drag-adjacent interfaces (#7975)

* fix: ISelectable and IDeletable interfaces

* fix: switch everything over to use new draggable interface

* fix: exports
This commit is contained in:
Beka Westberg
2024-03-29 21:00:56 +00:00
committed by GitHub
parent 59f589c32a
commit abfbbbc299
14 changed files with 78 additions and 39 deletions

View File

@@ -33,7 +33,6 @@ import * as fieldRegistry from './field_registry.js';
import {Input} from './inputs/input.js';
import {Align} from './inputs/align.js';
import type {IASTNodeLocation} from './interfaces/i_ast_node_location.js';
import type {IDeletable} from './interfaces/i_deletable.js';
import {type IIcon} from './interfaces/i_icon.js';
import {isCommentIcon} from './interfaces/i_comment_icon.js';
import type {MutatorIcon} from './icons/mutator_icon.js';
@@ -56,7 +55,7 @@ import {IconType} from './icons/icon_types.js';
* Class for one block.
* Not normally called directly, workspace.newBlock() is preferred.
*/
export class Block implements IASTNodeLocation, IDeletable {
export class Block implements IASTNodeLocation {
/**
* An optional callback method to use whenever the block's parent workspace
* changes. This is usually only called from the constructor, the block type
@@ -318,7 +317,7 @@ export class Block implements IASTNodeLocation, IDeletable {
* statement with the previous statement. Otherwise, dispose of all
* children of this block.
*/
dispose(healStack: boolean) {
dispose(healStack = false) {
this.disposing = true;
// Dispose of this change listener before unplugging.

View File

@@ -61,6 +61,7 @@ import * as renderManagement from './render_management.js';
import {IconType} from './icons/icon_types.js';
import {BlockCopyData, BlockPaster} from './clipboard/block_paster.js';
import {BlockDragStrategy} from './dragging/block_drag_strategy.js';
import {IDeletable} from './blockly.js';
/**
* Class for a block's SVG representation.
@@ -72,7 +73,8 @@ export class BlockSvg
IASTNodeLocationSvg,
IBoundedElement,
ICopyable<BlockCopyData>,
IDraggable
IDraggable,
IDeletable
{
/**
* Constant for identifying rows that are to be rendered inline.

View File

@@ -122,10 +122,10 @@ import {IConnectionChecker} from './interfaces/i_connection_checker.js';
import {IConnectionPreviewer} from './interfaces/i_connection_previewer.js';
import {IContextMenu} from './interfaces/i_contextmenu.js';
import {ICopyable, isCopyable} from './interfaces/i_copyable.js';
import {IDeletable} from './interfaces/i_deletable.js';
import {IDeletable, isDeletable} from './interfaces/i_deletable.js';
import {IDeleteArea} from './interfaces/i_delete_area.js';
import {IDragTarget} from './interfaces/i_drag_target.js';
import {IDraggable} from './interfaces/i_draggable.old.js';
import {IDraggable, isDraggable} from './interfaces/i_draggable.js';
import {IFlyout} from './interfaces/i_flyout.js';
import {IHasBubble, hasBubble} from './interfaces/i_has_bubble.js';
import {IIcon, isIcon} from './interfaces/i_icon.js';
@@ -136,7 +136,7 @@ import {IObservable, isObservable} from './interfaces/i_observable.js';
import {IPaster, isPaster} from './interfaces/i_paster.js';
import {IPositionable} from './interfaces/i_positionable.js';
import {IRegistrable} from './interfaces/i_registrable.js';
import {ISelectable} from './interfaces/i_selectable.js';
import {ISelectable, isSelectable} from './interfaces/i_selectable.js';
import {ISelectableToolboxItem} from './interfaces/i_selectable_toolbox_item.js';
import {ISerializable, isSerializable} from './interfaces/i_serializable.js';
import {IStyleable} from './interfaces/i_styleable.js';
@@ -527,10 +527,10 @@ export {IConnectionPreviewer};
export {IContextMenu};
export {icons};
export {ICopyable, isCopyable};
export {IDeletable};
export {IDeletable, isDeletable};
export {IDeleteArea};
export {IDragTarget};
export {IDraggable};
export {IDraggable, isDraggable};
export {IFlyout};
export {IHasBubble, hasBubble};
export {IIcon, isIcon};
@@ -545,7 +545,7 @@ export {IObservable, isObservable};
export {IPaster, isPaster};
export {IPositionable};
export {IRegistrable};
export {ISelectable};
export {ISelectable, isSelectable};
export {ISelectableToolboxItem};
export {ISerializable, isSerializable};
export {IStyleable};

View File

@@ -15,7 +15,8 @@
import {BlockSvg} from './block_svg.js';
import {DragTarget} from './drag_target.js';
import type {IDeleteArea} from './interfaces/i_delete_area.js';
import type {IDraggable} from './interfaces/i_draggable.old.js';
import type {IDraggable} from './interfaces/i_draggable.js';
import {isDeletable} from './interfaces/i_deletable.js';
/**
* Abstract class for a component that can delete a block or bubble that is
@@ -60,7 +61,7 @@ export class DeleteArea extends DragTarget implements IDeleteArea {
const couldDeleteBlock = !block.getParent() && block.isDeletable();
this.updateWouldDelete_(couldDeleteBlock);
} else {
this.updateWouldDelete_(element.isDeletable());
this.updateWouldDelete_(isDeletable(element) && element.isDeletable());
}
return this.wouldDelete_;
}

View File

@@ -13,7 +13,7 @@
// Former goog.module ID: Blockly.DragTarget
import type {IDragTarget} from './interfaces/i_drag_target.js';
import type {IDraggable} from './interfaces/i_draggable.old.js';
import type {IDraggable} from './interfaces/i_draggable.js';
import type {Rect} from './utils/rect.js';
/**
@@ -39,8 +39,9 @@ export class DragTarget implements IDragTarget {
*
* @param _dragElement The block or bubble currently being dragged.
*/
onDragEnter(_dragElement: IDraggable) {}
// no-op
onDragEnter(_dragElement: IDraggable) {
// no-op
}
/**
* Handles when a cursor with a block or bubble is dragged over this drag
@@ -48,24 +49,27 @@ export class DragTarget implements IDragTarget {
*
* @param _dragElement The block or bubble currently being dragged.
*/
onDragOver(_dragElement: IDraggable) {}
// no-op
onDragOver(_dragElement: IDraggable) {
// no-op
}
/**
* Handles when a cursor with a block or bubble exits this drag target.
*
* @param _dragElement The block or bubble currently being dragged.
*/
onDragExit(_dragElement: IDraggable) {}
// no-op
onDragExit(_dragElement: IDraggable) {
// no-op
}
/**
* Handles when a block or bubble is dropped on this component.
* Should not handle delete here.
*
* @param _dragElement The block or bubble currently being dragged.
*/
onDrop(_dragElement: IDraggable) {}
// no-op
onDrop(_dragElement: IDraggable) {
// no-op
}
/**
* Returns the bounding rectangle of the drag target area in pixel units

View File

@@ -43,7 +43,7 @@ export class Dragger implements IDragger {
// Must check `wouldDelete` before calling other hooks on drag targets
// since we have documented that we would do so.
if (isDeletable(this.draggable)) {
(this.draggable as AnyDuringMigration).setDeleteStyle(
this.draggable.setDeleteStyle(
this.wouldDeleteDraggable(e, this.draggable),
);
}
@@ -54,10 +54,10 @@ export class Dragger implements IDragger {
protected updateDragTarget(e: PointerEvent) {
const newDragTarget = this.workspace.getDragTarget(e);
if (this.dragTarget !== newDragTarget) {
this.dragTarget?.onDragExit(this.draggable as AnyDuringMigration);
newDragTarget?.onDragEnter(this.draggable as AnyDuringMigration);
this.dragTarget?.onDragExit(this.draggable);
newDragTarget?.onDragEnter(this.draggable);
}
newDragTarget?.onDragOver(this.draggable as AnyDuringMigration);
newDragTarget?.onDragOver(this.draggable);
this.dragTarget = newDragTarget;
}
@@ -96,7 +96,7 @@ export class Dragger implements IDragger {
onDragEnd(e: PointerEvent) {
const dragTarget = this.workspace.getDragTarget(e);
if (dragTarget) {
this.dragTarget?.onDrop(this.draggable as AnyDuringMigration);
this.dragTarget?.onDrop(this.draggable);
}
if (this.shouldReturnToStart(e, this.draggable)) {
@@ -109,7 +109,7 @@ export class Dragger implements IDragger {
isDeletable(this.draggable) &&
this.wouldDeleteDraggable(e, this.draggable)
) {
(this.draggable as AnyDuringMigration).dispose();
this.draggable.dispose();
}
}
@@ -120,7 +120,7 @@ export class Dragger implements IDragger {
protected shouldReturnToStart(e: PointerEvent, draggable: IDraggable) {
const dragTarget = this.workspace.getDragTarget(e);
if (!dragTarget) return false;
return dragTarget.shouldPreventMove(draggable as AnyDuringMigration);
return dragTarget.shouldPreventMove(draggable);
}
protected pixelsToWorkspaceUnits(pixelCoord: Coordinate): Coordinate {

View File

@@ -16,9 +16,19 @@ export interface IDeletable {
* @returns True if deletable.
*/
isDeletable(): boolean;
/** Disposes of this object, cleaning up any references or DOM elements. */
dispose(): void;
/** Visually indicates that the object is pending deletion. */
setDeleteStyle(wouldDelete: boolean): void;
}
/** Returns whether the given object is an IDeletable. */
export function isDeletable(obj: any): obj is IDeletable {
return obj['isDeletable'] !== undefined;
return (
obj['isDeletable'] !== undefined &&
obj['dispose'] !== undefined &&
obj['setDeleteStyle'] !== undefined
);
}

View File

@@ -7,7 +7,7 @@
// Former goog.module ID: Blockly.IDeleteArea
import type {IDragTarget} from './i_drag_target.js';
import type {IDraggable} from './i_draggable.old.js';
import type {IDraggable} from './i_draggable.js';
/**
* Interface for a component that can delete a block or bubble that is dropped

View File

@@ -6,7 +6,7 @@
import {Rect} from '../utils/rect.js';
import {IDraggable} from './i_draggable.old.js';
import {IDraggable} from './i_draggable.js';
// Former goog.module ID: Blockly.IDragTarget

View File

@@ -58,3 +58,15 @@ export interface IDragStrategy {
/** Moves the draggable back to where it was at the start of the drag. */
revertDrag(): void;
}
/** Returns whether the given object is an IDraggable or not. */
export function isDraggable(obj: any): obj is IDraggable {
return (
obj.getRelativeToSurfaceXY !== undefined &&
obj.isMovable !== undefined &&
obj.startDrag !== undefined &&
obj.drag !== undefined &&
obj.endDrag !== undefined &&
obj.revertDrag !== undefined
);
}

View File

@@ -6,13 +6,10 @@
// Former goog.module ID: Blockly.ISelectable
import type {IDeletable} from './i_deletable.js';
import type {IMovable} from './i_movable.js';
/**
* The interface for an object that is selectable.
*/
export interface ISelectable extends IDeletable, IMovable {
export interface ISelectable {
id: string;
/** Select this. Highlight it visually. */
@@ -21,3 +18,12 @@ export interface ISelectable extends IDeletable, IMovable {
/** Unselect this. Unhighlight it visually. */
unselect(): void;
}
/** Checks whether the given object is an ISelectable. */
export function isSelectable(obj: Object): obj is ISelectable {
return (
typeof (obj as any).id === 'string' &&
(obj as any).select !== undefined &&
(obj as any).unselect !== undefined
);
}

View File

@@ -11,9 +11,11 @@ import * as clipboard from './clipboard.js';
import * as common from './common.js';
import {Gesture} from './gesture.js';
import {ICopyData, isCopyable} from './interfaces/i_copyable.js';
import {isDeletable} from './interfaces/i_deletable.js';
import {KeyboardShortcut, ShortcutRegistry} from './shortcut_registry.js';
import {KeyCodes} from './utils/keycodes.js';
import type {WorkspaceSvg} from './workspace_svg.js';
import {isDraggable} from './interfaces/i_draggable.js';
/**
* Object holding the names of the default shortcut items.
@@ -59,6 +61,7 @@ export function registerDelete() {
return (
!workspace.options.readOnly &&
selected != null &&
isDeletable(selected) &&
selected.isDeletable()
);
},
@@ -105,7 +108,9 @@ export function registerCopy() {
!workspace.options.readOnly &&
!Gesture.inProgress() &&
selected != null &&
isDeletable(selected) &&
selected.isDeletable() &&
isDraggable(selected) &&
selected.isMovable() &&
isCopyable(selected)
);

View File

@@ -24,7 +24,7 @@ import {DeleteArea} from '../delete_area.js';
import * as eventUtils from '../events/utils.js';
import type {IAutoHideable} from '../interfaces/i_autohideable.js';
import type {ICollapsibleToolboxItem} from '../interfaces/i_collapsible_toolbox_item.js';
import type {IDraggable} from '../interfaces/i_draggable.old.js';
import type {IDraggable} from '../interfaces/i_draggable.js';
import type {IFlyout} from '../interfaces/i_flyout.js';
import type {IKeyboardAccessible} from '../interfaces/i_keyboard_accessible.js';
import type {ISelectableToolboxItem} from '../interfaces/i_selectable_toolbox_item.js';
@@ -41,9 +41,9 @@ import * as dom from '../utils/dom.js';
import {Rect} from '../utils/rect.js';
import * as toolbox from '../utils/toolbox.js';
import type {WorkspaceSvg} from '../workspace_svg.js';
import type {ToolboxCategory} from './category.js';
import {CollapsibleToolboxCategory} from './collapsible_category.js';
import {isDeletable} from '../interfaces/i_deletable.js';
/**
* Class for a Toolbox.
@@ -540,7 +540,7 @@ export class Toolbox
const block = element;
this.updateWouldDelete_(!block.getParent() && block.isDeletable());
} else {
this.updateWouldDelete_(element.isDeletable());
this.updateWouldDelete_(isDeletable(element) && element.isDeletable());
}
return this.wouldDelete_;
}

View File

@@ -22,7 +22,7 @@ import type {Abstract} from './events/events_abstract.js';
import type {BlockDelete} from './events/events_block_delete.js';
import * as eventUtils from './events/utils.js';
import type {IAutoHideable} from './interfaces/i_autohideable.js';
import type {IDraggable} from './interfaces/i_draggable.old.js';
import type {IDraggable} from './interfaces/i_draggable.js';
import type {IFlyout} from './interfaces/i_flyout.js';
import type {IPositionable} from './interfaces/i_positionable.js';
import type {UiMetrics} from './metrics_manager.js';