From 93acb624561f43d63ef181dca8608c15ee6faf84 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Tue, 19 Mar 2024 17:52:27 +0000 Subject: [PATCH] feat: rendered workspace comment (#7918) * feat: add basic rendered workspace comment * feat: add updating the view and model * feat: add support for setting editability * feat: add moveTo support * feat: add disposing * chore: add tsdoc * fix: disposing of the comment when the delete icon is clicked * feat: add isDeadOrDying --- core/comments.ts | 1 + core/comments/rendered_workspace_comment.ts | 87 +++++++++++++++++++++ core/comments/workspace_comment.ts | 14 +++- 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 core/comments/rendered_workspace_comment.ts diff --git a/core/comments.ts b/core/comments.ts index 9487d45f2..368db0e77 100644 --- a/core/comments.ts +++ b/core/comments.ts @@ -6,3 +6,4 @@ export {CommentView} from './comments/comment_view.js'; export {WorkspaceComment} from './comments/workspace_comment.js'; +export {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js'; diff --git a/core/comments/rendered_workspace_comment.ts b/core/comments/rendered_workspace_comment.ts new file mode 100644 index 000000000..61a1e24d4 --- /dev/null +++ b/core/comments/rendered_workspace_comment.ts @@ -0,0 +1,87 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {WorkspaceComment} from './workspace_comment.js'; +import {WorkspaceSvg} from '../workspace_svg.js'; +import {CommentView} from './comment_view.js'; +import {Coordinate, Size} from '../utils.js'; + +export class RenderedWorkspaceComment extends WorkspaceComment { + /** The class encompassing the svg elements making up the workspace comment. */ + private view: CommentView; + + /** Constructs the workspace comment, including the view. */ + constructor(workspace: WorkspaceSvg, id?: string) { + super(workspace, id); + + this.view = new CommentView(workspace); + // Set the size to the default size as defined in the superclass. + this.view.setSize(this.getSize()); + this.view.setEditable(this.isEditable()); + + this.addModelUpdateBindings(); + } + + /** + * Adds listeners to the view that updates the model (i.e. the superclass) + * when changes are made to the view. + */ + private addModelUpdateBindings() { + this.view.addTextChangeListener( + (_, newText: string) => void super.setText(newText), + ); + this.view.addSizeChangeListener( + (_, newSize: Size) => void super.setSize(newSize), + ); + this.view.addOnCollapseListener( + () => void super.setCollapsed(this.view.isCollapsed()), + ); + this.view.addDisposeListener(() => { + if (!this.isDeadOrDying()) this.dispose(); + }); + } + + /** Sets the text of the comment. */ + override setText(text: string): void { + // setText will trigger the change listener that updates + // the model aka superclass. + this.view.setText(text); + } + + /** Sets the size of the comment. */ + override setSize(size: Size) { + // setSize will trigger the change listener that updates + // the model aka superclass. + this.view.setSize(size); + } + + /** Sets whether the comment is collapsed or not. */ + override setCollapsed(collapsed: boolean) { + // setCollapsed will trigger the change listener that updates + // the model aka superclass. + this.view.setCollapsed(collapsed); + } + + /** Sets whether the comment is editable or not. */ + override setEditable(editable: boolean): void { + super.setEditable(editable); + // Use isEditable rather than isOwnEditable to account for workspace state. + this.view.setEditable(this.isEditable()); + } + + /** Moves the comment to the given location in workspace coordinates. */ + override moveTo(location: Coordinate): void { + super.moveTo(location); + this.view.moveTo(location); + } + + /** Disposes of the view. */ + override dispose() { + this.disposing = true; + if (!this.view.isDeadOrDying()) this.view.dispose(); + super.dispose(); + } +} diff --git a/core/comments/workspace_comment.ts b/core/comments/workspace_comment.ts index 4a563c544..ebe0606e9 100644 --- a/core/comments/workspace_comment.ts +++ b/core/comments/workspace_comment.ts @@ -35,7 +35,10 @@ export class WorkspaceComment { private location = new Coordinate(0, 0); /** Whether this comment has been disposed or not. */ - private disposed = false; + protected disposed = false; + + /** Whether this comment is being disposed or not. */ + protected disposing = false; /** * Constructs the comment. @@ -158,6 +161,7 @@ export class WorkspaceComment { /** Disposes of this comment. */ dispose() { + this.disposing = true; this.disposed = true; } @@ -165,4 +169,12 @@ export class WorkspaceComment { isDisposed() { return this.disposed; } + + /** + * Returns true if this comment view is currently being disposed or has + * already been disposed. + */ + isDeadOrDying(): boolean { + return this.disposing || this.disposed; + } }