|
8 | 8 |
|
9 | 9 | import {BlockSvg} from './block_svg.js'; |
10 | 10 | import * as clipboard from './clipboard.js'; |
| 11 | +import { RenderedWorkspaceComment } from './comments.js'; |
11 | 12 | import * as eventUtils from './events/utils.js'; |
12 | 13 | import {getFocusManager} from './focus_manager.js'; |
13 | 14 | import {Gesture} from './gesture.js'; |
@@ -106,68 +107,44 @@ let copyCoords: Coordinate | null = null; |
106 | 107 | /** |
107 | 108 | * Determine if a focusable node can be copied. |
108 | 109 | * |
109 | | - * Unfortunately the ICopyable interface doesn't include an isCopyable |
110 | | - * method, so we must use some other criteria to make the decision. |
111 | | - * Specifically, |
112 | | - * |
113 | | - * - It must be an ICopyable. |
114 | | - * - So that a pasted copy can be manipluated and/or disposed of, it |
115 | | - * must be both an IDraggable and an IDeletable. |
116 | | - * - Additionally, both .isOwnMovable() and .isOwnDeletable() must return |
117 | | - * true (i.e., the copy could be moved and deleted). |
118 | | - * |
119 | | - * TODO(#9098): Revise these criteria. The latter criteria prevents |
120 | | - * shadow blocks from being copied; additionally, there are likely to |
121 | | - * be other circumstances were it is desirable to allow movable / |
122 | | - * copyable copies of a currently-unmovable / -copyable block to be |
123 | | - * made. |
| 110 | + * This will use the isCopyable method if the node implements it, otherwise |
| 111 | + * it will fall back to checking if the node is deletable and draggable not |
| 112 | + * considering the workspace's edit state. |
124 | 113 | * |
125 | 114 | * @param focused The focused object. |
126 | 115 | */ |
127 | | -function isCopyable( |
128 | | - focused: IFocusableNode, |
129 | | -): focused is ICopyable<ICopyData> & IDeletable & IDraggable { |
130 | | - if (!(focused instanceof BlockSvg)) return false; |
131 | | - return ( |
132 | | - isICopyable(focused) && |
133 | | - isIDeletable(focused) && |
134 | | - focused.isOwnDeletable() && |
135 | | - isDraggable(focused) && |
136 | | - focused.isOwnMovable() |
137 | | - ); |
| 116 | +function isCopyable(focused: IFocusableNode): boolean { |
| 117 | + if (!isICopyable(focused) || !isIDeletable(focused) || !isDraggable(focused)) |
| 118 | + return false; |
| 119 | + if (focused.isCopyable !== undefined) { |
| 120 | + return focused.isCopyable(); |
| 121 | + } else if ( |
| 122 | + focused instanceof BlockSvg || |
| 123 | + focused instanceof RenderedWorkspaceComment |
| 124 | + ) { |
| 125 | + return focused.isOwnDeletable() && focused.isOwnMovable(); |
| 126 | + } |
| 127 | + // This isn't a class Blockly knows about, so fall back to the stricter |
| 128 | + // checks for deletable and movable. |
| 129 | + return focused.isDeletable() && focused.isMovable(); |
138 | 130 | } |
139 | 131 |
|
140 | 132 | /** |
141 | 133 | * Determine if a focusable node can be cut. |
142 | 134 | * |
143 | | - * Unfortunately the ICopyable interface doesn't include an isCuttable |
144 | | - * method, so we must use some other criteria to make the decision. |
145 | | - * Specifically, |
146 | | - * |
147 | | - * - It must be an ICopyable. |
148 | | - * - So that a pasted copy can be manipluated and/or disposed of, it |
149 | | - * must be both an IDraggable and an IDeletable. |
150 | | - * - Additionally, both .isMovable() and .isDeletable() must return |
151 | | - * true (i.e., can currently be moved and deleted). This is the main |
152 | | - * difference with isCopyable. |
153 | | - * |
154 | | - * TODO(#9098): Revise these criteria. The latter criteria prevents |
155 | | - * shadow blocks from being copied; additionally, there are likely to |
156 | | - * be other circumstances were it is desirable to allow movable / |
157 | | - * copyable copies of a currently-unmovable / -copyable block to be |
158 | | - * made. |
| 135 | + * This will use the isCuttable method if the node implements it, otherwise |
| 136 | + * it will fall back to checking if the node can be moved and deleted in its |
| 137 | + * current workspace. |
159 | 138 | * |
160 | 139 | * @param focused The focused object. |
161 | 140 | */ |
162 | 141 | function isCuttable(focused: IFocusableNode): boolean { |
163 | | - if (!(focused instanceof BlockSvg)) return false; |
164 | | - return ( |
165 | | - isICopyable(focused) && |
166 | | - isIDeletable(focused) && |
167 | | - focused.isDeletable() && |
168 | | - isDraggable(focused) && |
169 | | - focused.isMovable() |
170 | | - ); |
| 142 | + if (!isICopyable(focused) || !isIDeletable(focused) || !isDraggable(focused)) |
| 143 | + return false; |
| 144 | + if (focused.isCuttable !== undefined) { |
| 145 | + return focused.isCuttable(); |
| 146 | + } |
| 147 | + return focused.isMovable() && focused.isDeletable(); |
171 | 148 | } |
172 | 149 |
|
173 | 150 | /** |
|
0 commit comments