From 1e2840c12af0d21bc2cd5f3d3e9a1733ce7dcfd6 Mon Sep 17 00:00:00 2001 From: John Nesky Date: Fri, 31 May 2024 23:42:50 -0700 Subject: [PATCH 1/5] feat: Added a comment_drag event. --- core/dragging/comment_drag_strategy.ts | 21 +++++ core/events/events.ts | 4 + core/events/events_comment_drag.ts | 101 +++++++++++++++++++++++++ core/events/utils.ts | 9 ++- tests/mocha/event_comment_drag_test.js | 34 +++++++++ tests/mocha/event_test.js | 22 ++++++ tests/mocha/index.html | 1 + 7 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 core/events/events_comment_drag.ts create mode 100644 tests/mocha/event_comment_drag_test.js diff --git a/core/dragging/comment_drag_strategy.ts b/core/dragging/comment_drag_strategy.ts index 804ad2e9c9e..2ad5fa144fe 100644 --- a/core/dragging/comment_drag_strategy.ts +++ b/core/dragging/comment_drag_strategy.ts @@ -29,6 +29,7 @@ export class CommentDragStrategy implements IDragStrategy { if (!eventUtils.getGroup()) { eventUtils.setGroup(true); } + this.fireDragStartEvent(); this.startLoc = this.comment.getRelativeToSurfaceXY(); this.workspace.setResizesEnabled(false); this.workspace.getLayerManager()?.moveToDragLayer(this.comment); @@ -40,6 +41,7 @@ export class CommentDragStrategy implements IDragStrategy { } endDrag(): void { + this.fireDragEndEvent(); this.fireMoveEvent(); this.workspace @@ -53,6 +55,25 @@ export class CommentDragStrategy implements IDragStrategy { eventUtils.setGroup(false); } + /** Fire a UI event at the start of a comment drag. */ + private fireDragStartEvent() { + const event = new (eventUtils.get(eventUtils.COMMENT_DRAG))( + this.comment, + true, + ); + eventUtils.fire(event); + } + + /** Fire a UI event at the end of a comment drag. */ + private fireDragEndEvent() { + const event = new (eventUtils.get(eventUtils.COMMENT_DRAG))( + this.comment, + false, + ); + eventUtils.fire(event); + } + + /** Fire a move event at the end of a comment drag. */ private fireMoveEvent() { if (this.comment.isDeadOrDying()) return; const event = new (eventUtils.get(eventUtils.COMMENT_MOVE))( diff --git a/core/events/events.ts b/core/events/events.ts index bb8011755fc..2187e24aeee 100644 --- a/core/events/events.ts +++ b/core/events/events.ts @@ -24,6 +24,7 @@ import {CommentChange, CommentChangeJson} from './events_comment_change.js'; import {CommentCreate, CommentCreateJson} from './events_comment_create.js'; import {CommentDelete} from './events_comment_delete.js'; import {CommentMove, CommentMoveJson} from './events_comment_move.js'; +import {CommentDrag, CommentDragJson} from './events_comment_drag.js'; import { CommentCollapse, CommentCollapseJson, @@ -77,6 +78,8 @@ export {CommentCreateJson}; export {CommentDelete}; export {CommentMove}; export {CommentMoveJson}; +export {CommentDrag}; +export {CommentDragJson}; export {CommentCollapse}; export {CommentCollapseJson}; export {FinishedLoading}; @@ -119,6 +122,7 @@ export const COMMENT_CHANGE = eventUtils.COMMENT_CHANGE; export const COMMENT_CREATE = eventUtils.COMMENT_CREATE; export const COMMENT_DELETE = eventUtils.COMMENT_DELETE; export const COMMENT_MOVE = eventUtils.COMMENT_MOVE; +export const COMMENT_DRAG = eventUtils.COMMENT_DRAG; export const CREATE = eventUtils.CREATE; export const DELETE = eventUtils.DELETE; export const FINISHED_LOADING = eventUtils.FINISHED_LOADING; diff --git a/core/events/events_comment_drag.ts b/core/events/events_comment_drag.ts new file mode 100644 index 00000000000..b65ae211183 --- /dev/null +++ b/core/events/events_comment_drag.ts @@ -0,0 +1,101 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Events fired when a workspace comment is dragged. + * + * @class + */ + +import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as registry from '../registry.js'; +import {AbstractEventJson} from './events_abstract.js'; +import {UiBase} from './events_ui_base.js'; +import * as eventUtils from './utils.js'; +import {Workspace} from '../workspace.js'; + +/** + * Notifies listeners when a comment is being manually dragged/dropped. + */ +export class CommentDrag extends UiBase { + /** The ID of the top-level comment being dragged. */ + commentId?: string; + + /** True if this is the start of a drag, false if this is the end of one. */ + isStart?: boolean; + + override type = eventUtils.COMMENT_DRAG; + + /** + * @param opt_comment The comment that is being dragged. + * Undefined for a blank event. + * @param opt_isStart Whether this is the start of a comment drag. + * Undefined for a blank event. + */ + constructor(opt_comment?: WorkspaceComment, opt_isStart?: boolean) { + const workspaceId = opt_comment ? opt_comment.workspace.id : undefined; + super(workspaceId); + if (!opt_comment) return; + + this.commentId = opt_comment.id; + this.isStart = opt_isStart; + } + + /** + * Encode the event as JSON. + * + * @returns JSON representation. + */ + override toJson(): CommentDragJson { + const json = super.toJson() as CommentDragJson; + if (this.isStart === undefined) { + throw new Error( + 'Whether this event is the start of a drag is undefined. ' + + 'Either pass the value to the constructor, or call fromJson', + ); + } + if (this.commentId === undefined) { + throw new Error( + 'The comment ID is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + json['isStart'] = this.isStart; + json['commentId'] = this.commentId; + return json; + } + + /** + * Deserializes the JSON event. + * + * @param event The event to append new properties to. Should be a subclass + * of CommentDrag, but we can't specify that due to the fact that parameters + * to static methods in subclasses must be supertypes of parameters to + * static methods in superclasses.. + * @internal + */ + static fromJson( + json: CommentDragJson, + workspace: Workspace, + event?: any, + ): CommentDrag { + const newEvent = super.fromJson( + json, + workspace, + event ?? new CommentDrag(), + ) as CommentDrag; + newEvent.isStart = json['isStart']; + newEvent.commentId = json['commentId']; + return newEvent; + } +} + +export interface CommentDragJson extends AbstractEventJson { + isStart: boolean; + commentId: string; +} + +registry.register(registry.Type.EVENT, eventUtils.COMMENT_DRAG, CommentDrag); diff --git a/core/events/utils.ts b/core/events/utils.ts index eacf0490673..65d36a7a619 100644 --- a/core/events/utils.ts +++ b/core/events/utils.ts @@ -116,7 +116,7 @@ export const VAR_RENAME = 'var_rename'; export const UI = 'ui'; /** - * Name of event that record a block drags a block. + * Name of event that drags a block. */ export const BLOCK_DRAG = 'drag'; @@ -180,7 +180,12 @@ export const COMMENT_CHANGE = 'comment_change'; */ export const COMMENT_MOVE = 'comment_move'; -/** Type of event that moves a comment. */ +/** + * Name of event that drags a comment. + */ +export const COMMENT_DRAG = 'comment_drag'; + +/** Type of event that collapses a comment. */ export const COMMENT_COLLAPSE = 'comment_collapse'; /** diff --git a/tests/mocha/event_comment_drag_test.js b/tests/mocha/event_comment_drag_test.js new file mode 100644 index 00000000000..194e2394118 --- /dev/null +++ b/tests/mocha/event_comment_drag_test.js @@ -0,0 +1,34 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + sharedTestSetup, + sharedTestTeardown, +} from './test_helpers/setup_teardown.js'; + +suite('Comment Drag Event', function () { + setup(function () { + sharedTestSetup.call(this); + this.workspace = new Blockly.Workspace(); + }); + + teardown(function () { + sharedTestTeardown.call(this); + }); + + suite('Serialization', function () { + test('events round-trip through JSON', function () { + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('test text'); + + const origEvent = new Blockly.Events.CommentDrag(comment, true); + const json = origEvent.toJson(); + const newEvent = new Blockly.Events.fromJson(json, this.workspace); + + chai.assert.deepEqual(newEvent, origEvent); + }); + }); +}); diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index 75688c6547e..cf88df91550 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -862,6 +862,28 @@ suite('Events', function () { }), }, // TODO(#4577) Test serialization of move event coordinate properties. + { + title: 'Comment drag start', + class: Blockly.Events.CommentDrag, + getArgs: (thisObj) => [thisObj.comment, true], + getExpectedJson: (thisObj) => ({ + type: 'comment_drag', + group: '', + isStart: true, + blockId: thisObj.block.id, + }), + }, + { + title: 'Comment drag end', + class: Blockly.Events.CommentDrag, + getArgs: (thisObj) => [thisObj.comment, false], + getExpectedJson: (thisObj) => ({ + type: 'comment_drag', + group: '', + isStart: false, + blockId: thisObj.block.id, + }), + }, ]; const testSuites = [ { diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 9c7b10cabe2..581a02ad4db 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -67,6 +67,7 @@ import './event_comment_create_test.js'; import './event_comment_delete_test.js'; import './event_comment_move_test.js'; + import './event_comment_drag_test.js'; import './event_marker_move_test.js'; import './event_selected_test.js'; import './event_theme_change_test.js'; From f358a88459c2085555a8a44e077e1ad2e46198c7 Mon Sep 17 00:00:00 2001 From: John Nesky Date: Fri, 14 Jun 2024 21:58:41 -0700 Subject: [PATCH 2/5] Add workspace comment resize events. --- core/bump_objects.ts | 4 +- core/comments/comment_view.ts | 27 ++-- core/comments/workspace_comment.ts | 10 ++ core/events/events.ts | 4 + core/events/events_comment_resize.ts | 176 +++++++++++++++++++++++ core/events/utils.ts | 15 +- core/utils/size.ts | 2 +- tests/mocha/event_comment_resize_test.js | 37 +++++ tests/mocha/event_test.js | 7 +- tests/mocha/index.html | 1 + tests/mocha/workspace_comment_test.js | 22 +++ 11 files changed, 288 insertions(+), 17 deletions(-) create mode 100644 core/events/events_comment_resize.ts create mode 100644 tests/mocha/event_comment_resize_test.js diff --git a/core/bump_objects.ts b/core/bump_objects.ts index 3ceae2dbcfd..f9495b3d822 100644 --- a/core/bump_objects.ts +++ b/core/bump_objects.ts @@ -12,6 +12,7 @@ import type {BlockCreate} from './events/events_block_create.js'; import type {BlockMove} from './events/events_block_move.js'; import type {CommentCreate} from './events/events_comment_create.js'; import type {CommentMove} from './events/events_comment_move.js'; +import type {CommentResize} from './events/events_comment_resize.js'; import type {ViewportChange} from './events/events_viewport.js'; import * as eventUtils from './events/utils.js'; import type {IBoundedElement} from './interfaces/i_bounded_element.js'; @@ -163,8 +164,9 @@ function extractObjectFromEvent( break; case eventUtils.COMMENT_CREATE: case eventUtils.COMMENT_MOVE: + case eventUtils.COMMENT_RESIZE: object = workspace.getCommentById( - (e as CommentCreate | CommentMove).commentId!, + (e as CommentCreate | CommentMove | CommentResize).commentId!, ) as RenderedWorkspaceComment; break; } diff --git a/core/comments/comment_view.ts b/core/comments/comment_view.ts index 52f92b56776..006238db9d6 100644 --- a/core/comments/comment_view.ts +++ b/core/comments/comment_view.ts @@ -125,7 +125,7 @@ export class CommentView implements IRenderedElement { workspace.getLayerManager()?.append(this, layers.BLOCK); // Set size to the default size. - this.setSize(this.size); + this.setSizeWithoutFiringEvents(this.size); // Set default transform (including inverted scale for RTL). this.moveTo(new Coordinate(0, 0)); @@ -298,7 +298,7 @@ export class CommentView implements IRenderedElement { * Sets the size of the comment in workspace units, and updates the view * elements to reflect the new size. */ - setSize(size: Size) { + setSizeWithoutFiringEvents(size: Size) { const topBarSize = this.topBarBackground.getBBox(); const deleteSize = this.deleteIcon.getBBox(); const foldoutSize = this.foldoutIcon.getBBox(); @@ -309,7 +309,6 @@ export class CommentView implements IRenderedElement { size, this.calcMinSize(topBarSize, foldoutSize, deleteSize), ); - const oldSize = this.size; this.size = size; this.svgRoot.setAttribute('height', `${size.height}`); @@ -328,7 +327,15 @@ export class CommentView implements IRenderedElement { resizeSize, ); this.updateResizeHandlePosition(size, resizeSize); + } + /** + * Sets the size of the comment in workspace units, updates the view + * elements to reflect the new size, and triggers size change listeners. + */ + setSize(size: Size) { + const oldSize = this.size; + this.setSizeWithoutFiringEvents(size); this.onSizeChange(oldSize, this.size); } @@ -472,7 +479,7 @@ export class CommentView implements IRenderedElement { /** * Triggers listeners when the size of the comment changes, either - * progrmatically or manually by the user. + * programmatically or manually by the user. */ private onSizeChange(oldSize: Size, newSize: Size) { // Loop through listeners backwards in case they remove themselves. @@ -550,13 +557,17 @@ export class CommentView implements IRenderedElement { browserEvents.unbind(this.resizePointerMoveListener); this.resizePointerMoveListener = null; } + // When ending a resize drag, notify size change listeners to fire an event. + this.setSize(this.size); } /** Resizes the comment in response to a drag on the resize handle. */ private onResizePointerMove(e: PointerEvent) { // TODO(#7926): Move this into a utils file. - const delta = this.workspace.moveDrag(e); - this.setSize(new Size(this.workspace.RTL ? -delta.x : delta.x, delta.y)); + const size = this.workspace.moveDrag(e); + this.setSizeWithoutFiringEvents( + new Size(this.workspace.RTL ? -size.x : size.x, size.y), + ); } /** Returns true if the comment is currently collapsed. */ @@ -573,7 +584,7 @@ export class CommentView implements IRenderedElement { dom.removeClass(this.svgRoot, 'blocklyCollapsed'); } // Repositions resize handle and such. - this.setSize(this.size); + this.setSizeWithoutFiringEvents(this.size); this.onCollapse(); } @@ -682,7 +693,7 @@ export class CommentView implements IRenderedElement { /** * Triggers listeners when the text of the comment changes, either - * progrmatically or manually by the user. + * programmatically or manually by the user. */ private onTextChange() { const oldText = this.text; diff --git a/core/comments/workspace_comment.ts b/core/comments/workspace_comment.ts index 3c23aba86a2..8453a56f63e 100644 --- a/core/comments/workspace_comment.ts +++ b/core/comments/workspace_comment.ts @@ -10,6 +10,7 @@ import {Coordinate} from '../utils/coordinate.js'; import * as idGenerator from '../utils/idgenerator.js'; import * as eventUtils from '../events/utils.js'; import {CommentMove} from '../events/events_comment_move.js'; +import {CommentResize} from '../events/events_comment_resize.js'; export class WorkspaceComment { /** The unique identifier for this comment. */ @@ -104,7 +105,16 @@ export class WorkspaceComment { /** Sets the comment's size in workspace units. */ setSize(size: Size) { + const event = new (eventUtils.get(eventUtils.COMMENT_RESIZE))( + this, + ) as CommentResize; + this.size = size; + + if (eventUtils.isEnabled()) { + event.recordNew(); + eventUtils.fire(event); + } } /** Returns the comment's size in workspace units. */ diff --git a/core/events/events.ts b/core/events/events.ts index 2187e24aeee..b31cf7dc788 100644 --- a/core/events/events.ts +++ b/core/events/events.ts @@ -24,6 +24,7 @@ import {CommentChange, CommentChangeJson} from './events_comment_change.js'; import {CommentCreate, CommentCreateJson} from './events_comment_create.js'; import {CommentDelete} from './events_comment_delete.js'; import {CommentMove, CommentMoveJson} from './events_comment_move.js'; +import {CommentResize, CommentResizeJson} from './events_comment_resize.js'; import {CommentDrag, CommentDragJson} from './events_comment_drag.js'; import { CommentCollapse, @@ -78,6 +79,8 @@ export {CommentCreateJson}; export {CommentDelete}; export {CommentMove}; export {CommentMoveJson}; +export {CommentResize}; +export {CommentResizeJson}; export {CommentDrag}; export {CommentDragJson}; export {CommentCollapse}; @@ -122,6 +125,7 @@ export const COMMENT_CHANGE = eventUtils.COMMENT_CHANGE; export const COMMENT_CREATE = eventUtils.COMMENT_CREATE; export const COMMENT_DELETE = eventUtils.COMMENT_DELETE; export const COMMENT_MOVE = eventUtils.COMMENT_MOVE; +export const COMMENT_RESIZE = eventUtils.COMMENT_RESIZE; export const COMMENT_DRAG = eventUtils.COMMENT_DRAG; export const CREATE = eventUtils.CREATE; export const DELETE = eventUtils.DELETE; diff --git a/core/events/events_comment_resize.ts b/core/events/events_comment_resize.ts new file mode 100644 index 00000000000..e56bc84df4a --- /dev/null +++ b/core/events/events_comment_resize.ts @@ -0,0 +1,176 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Class for comment resize event. + * + * @class + */ + +import * as registry from '../registry.js'; +import {Size} from '../utils/size.js'; +import type {WorkspaceComment} from '../comments/workspace_comment.js'; + +import {CommentBase, CommentBaseJson} from './events_comment_base.js'; +import * as eventUtils from './utils.js'; +import type {Workspace} from '../workspace.js'; + +/** + * Notifies listeners that a workspace comment has resized. + */ +export class CommentResize extends CommentBase { + override type = eventUtils.COMMENT_RESIZE; + + /** The size of the comment before the resize. */ + oldSize?: Size; + + /** The size of the comment after the resize. */ + newSize?: Size; + + /** + * @param opt_comment The comment that is being resized. Undefined for a blank + * event. + */ + constructor(opt_comment?: WorkspaceComment) { + super(opt_comment); + + if (!opt_comment) { + return; // Blank event to be populated by fromJson. + } + + this.oldSize = opt_comment.getSize(); + } + + /** + * Record the comment's new size. Called after the resize. Can only be + * called once. + */ + recordNew() { + if (this.newSize) { + throw Error( + 'Tried to record the new size of a comment on the ' + + 'same event twice.', + ); + } + const workspace = this.getEventWorkspace_(); + if (!this.commentId) { + throw new Error( + 'The comment ID is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + const comment = workspace.getCommentById(this.commentId); + if (!comment) { + throw new Error( + 'The comment associated with the comment resize event ' + + 'could not be found', + ); + } + this.newSize = comment.getSize(); + } + + /** + * Encode the event as JSON. + * + * @returns JSON representation. + */ + override toJson(): CommentResizeJson { + const json = super.toJson() as CommentResizeJson; + if (!this.oldSize) { + throw new Error( + 'The old comment size is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + if (!this.newSize) { + throw new Error( + 'The new comment size is undefined. Either call recordNew, or ' + + 'call fromJson', + ); + } + json['oldSize'] = + `${Math.round(this.oldSize.width)}, ${Math.round(this.oldSize.height)}`; + json['newSize'] = + `${Math.round(this.newSize.width)}, ${Math.round(this.newSize.height)}`; + return json; + } + + /** + * Deserializes the JSON event. + * + * @param event The event to append new properties to. Should be a subclass + * of CommentResize, but we can't specify that due to the fact that + * parameters to static methods in subclasses must be supertypes of + * parameters to static methods in superclasses. + * @internal + */ + static fromJson( + json: CommentResizeJson, + workspace: Workspace, + event?: any, + ): CommentResize { + const newEvent = super.fromJson( + json, + workspace, + event ?? new CommentResize(), + ) as CommentResize; + let dimensions = json['oldSize'].split(','); + newEvent.oldSize = new Size(Number(dimensions[0]), Number(dimensions[1])); + dimensions = json['newSize'].split(','); + newEvent.newSize = new Size(Number(dimensions[0]), Number(dimensions[1])); + return newEvent; + } + + /** + * Does this event record any change of state? + * + * @returns False if something changed. + */ + override isNull(): boolean { + return Size.equals(this.oldSize, this.newSize); + } + + /** + * Run a resize event. + * + * @param forward True if run forward, false if run backward (undo). + */ + override run(forward: boolean) { + const workspace = this.getEventWorkspace_(); + if (!this.commentId) { + throw new Error( + 'The comment ID is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + const comment = workspace.getCommentById(this.commentId); + if (!comment) { + console.warn("Can't resize non-existent comment: " + this.commentId); + return; + } + + const size = forward ? this.newSize : this.oldSize; + if (!size) { + throw new Error( + 'Either oldSize or newSize is undefined. ' + + 'Either pass a comment to the constructor and call recordNew, ' + + 'or call fromJson', + ); + } + comment.setSize(size); + } +} + +export interface CommentResizeJson extends CommentBaseJson { + oldSize: string; + newSize: string; +} + +registry.register( + registry.Type.EVENT, + eventUtils.COMMENT_RESIZE, + CommentResize, +); diff --git a/core/events/utils.ts b/core/events/utils.ts index 65d36a7a619..2d434594b19 100644 --- a/core/events/utils.ts +++ b/core/events/utils.ts @@ -19,6 +19,7 @@ import type {BlockCreate} from './events_block_create.js'; import type {BlockMove} from './events_block_move.js'; import type {CommentCreate} from './events_comment_create.js'; import type {CommentMove} from './events_comment_move.js'; +import type {CommentResize} from './events_comment_resize.js'; import type {ViewportChange} from './events_viewport.js'; /** Group ID for new events. Grouped events are indivisible. */ @@ -180,9 +181,10 @@ export const COMMENT_CHANGE = 'comment_change'; */ export const COMMENT_MOVE = 'comment_move'; -/** - * Name of event that drags a comment. - */ +/** Name of event that resizes a comment. */ +export const COMMENT_RESIZE = 'comment_resize'; + +/** Name of event that drags a comment. */ export const COMMENT_DRAG = 'comment_drag'; /** Type of event that collapses a comment. */ @@ -206,7 +208,12 @@ const ORPHANED_BLOCK_DISABLED_REASON = 'ORPHANED_BLOCK'; * Not to be confused with bumping so that disconnected connections do not * appear connected. */ -export type BumpEvent = BlockCreate | BlockMove | CommentCreate | CommentMove; +export type BumpEvent = + | BlockCreate + | BlockMove + | CommentCreate + | CommentMove + | CommentResize; /** * List of events that cause objects to be bumped back into the visible diff --git a/core/utils/size.ts b/core/utils/size.ts index 705dc2c2897..4b5eede751b 100644 --- a/core/utils/size.ts +++ b/core/utils/size.ts @@ -34,7 +34,7 @@ export class Size { * @returns True iff the sizes have equal widths and equal heights, or if both * are null. */ - static equals(a: Size | null, b: Size | null): boolean { + static equals(a?: Size | null, b?: Size | null): boolean { if (a === b) { return true; } diff --git a/tests/mocha/event_comment_resize_test.js b/tests/mocha/event_comment_resize_test.js new file mode 100644 index 00000000000..84f5b45c410 --- /dev/null +++ b/tests/mocha/event_comment_resize_test.js @@ -0,0 +1,37 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + sharedTestSetup, + sharedTestTeardown, +} from './test_helpers/setup_teardown.js'; + +suite('Comment Resize Event', function () { + setup(function () { + sharedTestSetup.call(this); + this.workspace = new Blockly.Workspace(); + }); + + teardown(function () { + sharedTestTeardown.call(this); + }); + + suite('Serialization', function () { + test('events round-trip through JSON', function () { + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('test text'); + comment.setSize(new Blockly.utils.Size(100, 100)); + const origEvent = new Blockly.Events.CommentResize(comment); + comment.setSize(new Blockly.utils.Size(200, 200)); + origEvent.recordNew(); + + const json = origEvent.toJson(); + const newEvent = new Blockly.Events.fromJson(json, this.workspace); + + chai.assert.deepEqual(newEvent, origEvent); + }); + }); +}); diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index cf88df91550..e54d8d3794a 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -861,7 +861,6 @@ suite('Events', function () { }, }), }, - // TODO(#4577) Test serialization of move event coordinate properties. { title: 'Comment drag start', class: Blockly.Events.CommentDrag, @@ -870,7 +869,7 @@ suite('Events', function () { type: 'comment_drag', group: '', isStart: true, - blockId: thisObj.block.id, + commentId: thisObj.comment.id, }), }, { @@ -881,9 +880,11 @@ suite('Events', function () { type: 'comment_drag', group: '', isStart: false, - blockId: thisObj.block.id, + commentId: thisObj.comment.id, }), }, + // TODO(#4577) Test serialization of move event coordinate properties. + // TODO(#4577) Test serialization of comment resize event properties. ]; const testSuites = [ { diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 581a02ad4db..71a08a5fd9a 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -68,6 +68,7 @@ import './event_comment_delete_test.js'; import './event_comment_move_test.js'; import './event_comment_drag_test.js'; + import './event_comment_resize_test.js'; import './event_marker_move_test.js'; import './event_selected_test.js'; import './event_theme_change_test.js'; diff --git a/tests/mocha/workspace_comment_test.js b/tests/mocha/workspace_comment_test.js index aa42cfbe2ac..ece1819e434 100644 --- a/tests/mocha/workspace_comment_test.js +++ b/tests/mocha/workspace_comment_test.js @@ -81,6 +81,28 @@ suite('Workspace comment', function () { ); }); + test('resize events are fired when a comment is resized', function () { + this.renderedComment = new Blockly.comments.RenderedWorkspaceComment( + this.workspace, + ); + const spy = createChangeListenerSpy(this.workspace); + + this.renderedComment.setSize(new Blockly.utils.Size(300, 200)); + + this.clock.runAll(); + + assertEventFired( + spy, + Blockly.Events.CommentResize, + { + commentId: this.renderedComment.id, + oldSize: {width: 120, height: 100}, + newSize: {width: 300, height: 200}, + }, + this.workspace.id, + ); + }); + test('change events are fired when a comments text is edited', function () { this.renderedComment = new Blockly.comments.RenderedWorkspaceComment( this.workspace, From 301d81e47977bd477646dcf2440f40a1d05d4657 Mon Sep 17 00:00:00 2001 From: John Nesky Date: Fri, 21 Jun 2024 19:27:43 -0700 Subject: [PATCH 3/5] Addressing PR feedback. --- core/comments/workspace_comment.ts | 6 ++--- core/events/events_comment_drag.ts | 2 +- core/events/events_comment_resize.ts | 30 ++++++++++++------------ tests/mocha/event_comment_resize_test.js | 2 +- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/core/comments/workspace_comment.ts b/core/comments/workspace_comment.ts index 8453a56f63e..e9e7a1bdd47 100644 --- a/core/comments/workspace_comment.ts +++ b/core/comments/workspace_comment.ts @@ -111,10 +111,8 @@ export class WorkspaceComment { this.size = size; - if (eventUtils.isEnabled()) { - event.recordNew(); - eventUtils.fire(event); - } + event.recordCurrentSizeAsNewSize(); + eventUtils.fire(event); } /** Returns the comment's size in workspace units. */ diff --git a/core/events/events_comment_drag.ts b/core/events/events_comment_drag.ts index b65ae211183..f8ea1f841a0 100644 --- a/core/events/events_comment_drag.ts +++ b/core/events/events_comment_drag.ts @@ -74,7 +74,7 @@ export class CommentDrag extends UiBase { * @param event The event to append new properties to. Should be a subclass * of CommentDrag, but we can't specify that due to the fact that parameters * to static methods in subclasses must be supertypes of parameters to - * static methods in superclasses.. + * static methods in superclasses. * @internal */ static fromJson( diff --git a/core/events/events_comment_resize.ts b/core/events/events_comment_resize.ts index e56bc84df4a..357030f2cf0 100644 --- a/core/events/events_comment_resize.ts +++ b/core/events/events_comment_resize.ts @@ -48,7 +48,7 @@ export class CommentResize extends CommentBase { * Record the comment's new size. Called after the resize. Can only be * called once. */ - recordNew() { + recordCurrentSizeAsNewSize() { if (this.newSize) { throw Error( 'Tried to record the new size of a comment on the ' + @@ -87,14 +87,14 @@ export class CommentResize extends CommentBase { } if (!this.newSize) { throw new Error( - 'The new comment size is undefined. Either call recordNew, or ' + - 'call fromJson', + 'The new comment size is undefined. Either call ' + + 'recordCurrentSizeAsNewSize, or call fromJson', ); } - json['oldSize'] = - `${Math.round(this.oldSize.width)}, ${Math.round(this.oldSize.height)}`; - json['newSize'] = - `${Math.round(this.newSize.width)}, ${Math.round(this.newSize.height)}`; + json['oldWidth'] = Math.round(this.oldSize.width); + json['oldHeight'] = Math.round(this.oldSize.height); + json['newWidth'] = Math.round(this.newSize.width); + json['newHeight'] = Math.round(this.newSize.height); return json; } @@ -117,10 +117,8 @@ export class CommentResize extends CommentBase { workspace, event ?? new CommentResize(), ) as CommentResize; - let dimensions = json['oldSize'].split(','); - newEvent.oldSize = new Size(Number(dimensions[0]), Number(dimensions[1])); - dimensions = json['newSize'].split(','); - newEvent.newSize = new Size(Number(dimensions[0]), Number(dimensions[1])); + newEvent.oldSize = new Size(json['oldWidth'], json['oldHeight']); + newEvent.newSize = new Size(json['newWidth'], json['newHeight']); return newEvent; } @@ -156,8 +154,8 @@ export class CommentResize extends CommentBase { if (!size) { throw new Error( 'Either oldSize or newSize is undefined. ' + - 'Either pass a comment to the constructor and call recordNew, ' + - 'or call fromJson', + 'Either pass a comment to the constructor and call ' + + 'recordCurrentSizeAsNewSize, or call fromJson', ); } comment.setSize(size); @@ -165,8 +163,10 @@ export class CommentResize extends CommentBase { } export interface CommentResizeJson extends CommentBaseJson { - oldSize: string; - newSize: string; + oldWidth: number; + oldHeight: number; + newWidth: number; + newHeight: number; } registry.register( diff --git a/tests/mocha/event_comment_resize_test.js b/tests/mocha/event_comment_resize_test.js index 84f5b45c410..6a55fc2d861 100644 --- a/tests/mocha/event_comment_resize_test.js +++ b/tests/mocha/event_comment_resize_test.js @@ -26,7 +26,7 @@ suite('Comment Resize Event', function () { comment.setSize(new Blockly.utils.Size(100, 100)); const origEvent = new Blockly.Events.CommentResize(comment); comment.setSize(new Blockly.utils.Size(200, 200)); - origEvent.recordNew(); + origEvent.recordCurrentSizeAsNewSize(); const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); From 31692604df5e4e042d2a8c844b845114a430d4d2 Mon Sep 17 00:00:00 2001 From: John Nesky Date: Fri, 21 Jun 2024 19:50:19 -0700 Subject: [PATCH 4/5] Fixed chai imports in new test files. --- tests/mocha/event_comment_drag_test.js | 3 ++- tests/mocha/event_comment_resize_test.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/mocha/event_comment_drag_test.js b/tests/mocha/event_comment_drag_test.js index 194e2394118..d214e0adba1 100644 --- a/tests/mocha/event_comment_drag_test.js +++ b/tests/mocha/event_comment_drag_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -28,7 +29,7 @@ suite('Comment Drag Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_comment_resize_test.js b/tests/mocha/event_comment_resize_test.js index 6a55fc2d861..b74e1abb2bf 100644 --- a/tests/mocha/event_comment_resize_test.js +++ b/tests/mocha/event_comment_resize_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -31,7 +32,7 @@ suite('Comment Resize Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); From 044b5bc012388ff20ff904193e2d3a05f81b8343 Mon Sep 17 00:00:00 2001 From: John Nesky Date: Mon, 24 Jun 2024 12:37:56 -0700 Subject: [PATCH 5/5] Addressing more PR feedback. --- core/comments/workspace_comment.ts | 2 +- core/events/events_comment_drag.ts | 2 -- core/events/events_comment_resize.ts | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/core/comments/workspace_comment.ts b/core/comments/workspace_comment.ts index e9e7a1bdd47..0764b5168d2 100644 --- a/core/comments/workspace_comment.ts +++ b/core/comments/workspace_comment.ts @@ -204,7 +204,7 @@ export class WorkspaceComment { this.location = location; event.recordNew(); - if (eventUtils.isEnabled()) eventUtils.fire(event); + eventUtils.fire(event); } /** Returns the position of the comment in workspace coordinates. */ diff --git a/core/events/events_comment_drag.ts b/core/events/events_comment_drag.ts index f8ea1f841a0..80caeea52ff 100644 --- a/core/events/events_comment_drag.ts +++ b/core/events/events_comment_drag.ts @@ -6,8 +6,6 @@ /** * Events fired when a workspace comment is dragged. - * - * @class */ import type {WorkspaceComment} from '../comments/workspace_comment.js'; diff --git a/core/events/events_comment_resize.ts b/core/events/events_comment_resize.ts index 357030f2cf0..dfc785832f4 100644 --- a/core/events/events_comment_resize.ts +++ b/core/events/events_comment_resize.ts @@ -6,8 +6,6 @@ /** * Class for comment resize event. - * - * @class */ import * as registry from '../registry.js';