Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Drag and Resize events for workspace comments #8217

Merged
merged 7 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion core/bump_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}
Expand Down
27 changes: 19 additions & 8 deletions core/comments/comment_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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();
Expand All @@ -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}`);
Expand All @@ -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);
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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. */
Expand All @@ -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();
}

Expand Down Expand Up @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion core/comments/workspace_comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -104,7 +105,14 @@ 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;

event.recordCurrentSizeAsNewSize();
eventUtils.fire(event);
}

/** Returns the comment's size in workspace units. */
Expand Down Expand Up @@ -196,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. */
Expand Down
21 changes: 21 additions & 0 deletions core/dragging/comment_drag_strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -40,6 +41,7 @@ export class CommentDragStrategy implements IDragStrategy {
}

endDrag(): void {
this.fireDragEndEvent();
this.fireMoveEvent();

this.workspace
Expand All @@ -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))(
Expand Down
8 changes: 8 additions & 0 deletions core/events/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ 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,
CommentCollapseJson,
Expand Down Expand Up @@ -77,6 +79,10 @@ export {CommentCreateJson};
export {CommentDelete};
export {CommentMove};
export {CommentMoveJson};
export {CommentResize};
export {CommentResizeJson};
export {CommentDrag};
export {CommentDragJson};
export {CommentCollapse};
export {CommentCollapseJson};
export {FinishedLoading};
Expand Down Expand Up @@ -119,6 +125,8 @@ 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;
export const FINISHED_LOADING = eventUtils.FINISHED_LOADING;
Expand Down
99 changes: 99 additions & 0 deletions core/events/events_comment_drag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

/**
* Events fired when a workspace comment is dragged.
*/

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);
Loading