mirror of
https://github.com/google/blockly.git
synced 2026-01-30 12:10:12 +01:00
Add isCopyable and isCuttable as optional methods on ICopyable
This commit is contained in:
@@ -1721,6 +1721,16 @@ export class BlockSvg
|
||||
this.dragStrategy = dragStrategy;
|
||||
}
|
||||
|
||||
/** Returns whether this block is copyable or not. */
|
||||
isCopyable(): boolean {
|
||||
return this.isOwnDeletable() && this.isOwnMovable();
|
||||
}
|
||||
|
||||
/** Returns whether this block is cuttable or not. */
|
||||
isCuttable(): boolean {
|
||||
return this.isDeletable() && this.isMovable();
|
||||
}
|
||||
|
||||
/** Returns whether this block is movable or not. */
|
||||
override isMovable(): boolean {
|
||||
return this.dragStrategy.isMovable();
|
||||
|
||||
@@ -244,6 +244,16 @@ export class RenderedWorkspaceComment
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether this comment is copyable or not */
|
||||
isCopyable(): boolean {
|
||||
return this.isOwnMovable() && this.isOwnDeletable();
|
||||
}
|
||||
|
||||
/** Returns whether this comment is cuttable or not */
|
||||
isCuttable(): boolean {
|
||||
return this.isMovable() && this.isDeletable();
|
||||
}
|
||||
|
||||
/** Returns whether this comment is movable or not. */
|
||||
isMovable(): boolean {
|
||||
return this.dragStrategy.isMovable();
|
||||
|
||||
@@ -15,6 +15,20 @@ export interface ICopyable<T extends ICopyData> extends ISelectable {
|
||||
* @returns Copy metadata.
|
||||
*/
|
||||
toCopyData(): T | null;
|
||||
|
||||
/**
|
||||
* Whether this instance is currently copyable.
|
||||
*
|
||||
* @returns True if it can currently be copied.
|
||||
*/
|
||||
isCopyable?(): boolean;
|
||||
|
||||
/**
|
||||
* Whether this instance is currently cuttable.
|
||||
*
|
||||
* @returns True if it can currently be cut.
|
||||
*/
|
||||
isCuttable?(): boolean;
|
||||
}
|
||||
|
||||
export namespace ICopyable {
|
||||
@@ -25,7 +39,7 @@ export namespace ICopyable {
|
||||
|
||||
export type ICopyData = ICopyable.ICopyData;
|
||||
|
||||
/** @returns true if the given object is copyable. */
|
||||
/** @returns true if the given object is an ICopyable. */
|
||||
export function isCopyable(obj: any): obj is ICopyable<ICopyData> {
|
||||
return obj.toCopyData !== undefined;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import {BlockSvg} from './block_svg.js';
|
||||
import * as clipboard from './clipboard.js';
|
||||
import { RenderedWorkspaceComment } from './comments.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import {getFocusManager} from './focus_manager.js';
|
||||
import {Gesture} from './gesture.js';
|
||||
@@ -106,68 +107,44 @@ let copyCoords: Coordinate | null = null;
|
||||
/**
|
||||
* Determine if a focusable node can be copied.
|
||||
*
|
||||
* Unfortunately the ICopyable interface doesn't include an isCopyable
|
||||
* method, so we must use some other criteria to make the decision.
|
||||
* Specifically,
|
||||
*
|
||||
* - It must be an ICopyable.
|
||||
* - So that a pasted copy can be manipluated and/or disposed of, it
|
||||
* must be both an IDraggable and an IDeletable.
|
||||
* - Additionally, both .isOwnMovable() and .isOwnDeletable() must return
|
||||
* true (i.e., the copy could be moved and deleted).
|
||||
*
|
||||
* TODO(#9098): Revise these criteria. The latter criteria prevents
|
||||
* shadow blocks from being copied; additionally, there are likely to
|
||||
* be other circumstances were it is desirable to allow movable /
|
||||
* copyable copies of a currently-unmovable / -copyable block to be
|
||||
* made.
|
||||
* This will use the isCopyable method if the node implements it, otherwise
|
||||
* it will fall back to checking if the node is deletable and draggable not
|
||||
* considering the workspace's edit state.
|
||||
*
|
||||
* @param focused The focused object.
|
||||
*/
|
||||
function isCopyable(
|
||||
focused: IFocusableNode,
|
||||
): focused is ICopyable<ICopyData> & IDeletable & IDraggable {
|
||||
if (!(focused instanceof BlockSvg)) return false;
|
||||
return (
|
||||
isICopyable(focused) &&
|
||||
isIDeletable(focused) &&
|
||||
focused.isOwnDeletable() &&
|
||||
isDraggable(focused) &&
|
||||
focused.isOwnMovable()
|
||||
);
|
||||
function isCopyable(focused: IFocusableNode): boolean {
|
||||
if (!isICopyable(focused) || !isIDeletable(focused) || !isDraggable(focused))
|
||||
return false;
|
||||
if (focused.isCopyable !== undefined) {
|
||||
return focused.isCopyable();
|
||||
} else if (
|
||||
focused instanceof BlockSvg ||
|
||||
focused instanceof RenderedWorkspaceComment
|
||||
) {
|
||||
return focused.isOwnDeletable() && focused.isOwnMovable();
|
||||
}
|
||||
// This isn't a class Blockly knows about, so fall back to the stricter
|
||||
// checks for deletable and movable.
|
||||
return focused.isDeletable() && focused.isMovable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a focusable node can be cut.
|
||||
*
|
||||
* Unfortunately the ICopyable interface doesn't include an isCuttable
|
||||
* method, so we must use some other criteria to make the decision.
|
||||
* Specifically,
|
||||
*
|
||||
* - It must be an ICopyable.
|
||||
* - So that a pasted copy can be manipluated and/or disposed of, it
|
||||
* must be both an IDraggable and an IDeletable.
|
||||
* - Additionally, both .isMovable() and .isDeletable() must return
|
||||
* true (i.e., can currently be moved and deleted). This is the main
|
||||
* difference with isCopyable.
|
||||
*
|
||||
* TODO(#9098): Revise these criteria. The latter criteria prevents
|
||||
* shadow blocks from being copied; additionally, there are likely to
|
||||
* be other circumstances were it is desirable to allow movable /
|
||||
* copyable copies of a currently-unmovable / -copyable block to be
|
||||
* made.
|
||||
* This will use the isCuttable method if the node implements it, otherwise
|
||||
* it will fall back to checking if the node can be moved and deleted in its
|
||||
* current workspace.
|
||||
*
|
||||
* @param focused The focused object.
|
||||
*/
|
||||
function isCuttable(focused: IFocusableNode): boolean {
|
||||
if (!(focused instanceof BlockSvg)) return false;
|
||||
return (
|
||||
isICopyable(focused) &&
|
||||
isIDeletable(focused) &&
|
||||
focused.isDeletable() &&
|
||||
isDraggable(focused) &&
|
||||
focused.isMovable()
|
||||
);
|
||||
if (!isICopyable(focused) || !isIDeletable(focused) || !isDraggable(focused))
|
||||
return false;
|
||||
if (focused.isCuttable !== undefined) {
|
||||
return focused.isCuttable();
|
||||
}
|
||||
return focused.isMovable() && focused.isDeletable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user