From 72f4da5db7d3d68faee04f16bc55bc39692f9b0b Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Thu, 4 May 2023 23:18:16 +0000 Subject: [PATCH 1/5] feat: add IIcon interface --- core/interfaces/i_icon.ts | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 core/interfaces/i_icon.ts diff --git a/core/interfaces/i_icon.ts b/core/interfaces/i_icon.ts new file mode 100644 index 00000000000..d5fec788f3c --- /dev/null +++ b/core/interfaces/i_icon.ts @@ -0,0 +1,82 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {Coordinate} from '../utils/coordinate.js'; +import {Size} from '../utils/size.js'; + + +export interface IIcon { + /** + * @return the string representing the type of the icon. + * E.g. 'comment', 'warning', etc. This string should also be used when + * registering the icon class. + */ + getType(): string; + + /** + * Creates the SVG elements for the icon that will live on the block. + * + * @param pointerdownListener The listener to be attached to the root svg + * element. This passes off the pointer down to Blockly's gesture system + * so that clicks and drags can be properly handled. + */ + initView(pointerdownListener: (e: PointerEvent) => void): void; + + /** + * Disposes of any elements of the icon. + * + * @remarks + * + * In particular, if this icon is currently showing a bubble, this should be + * used to hide it. + */ + dispose(): void; + + /** + * @return the "weight" of the icon, which determines the static order which + * icons should be rendered in. + * + * More positive numbers are rendered farther toward the end of the block. + */ + getWeight(): number; + + /** @return The dimensions of the icon for use in rendering. */ + getSize(): Size; + + /** Notifies the icon that the block's colour has changed. */ + applyColour(): void; + + /** Notifies the icon that the block's editability has changed. */ + updateEditable(): void; + + /** Notifies the icon that the block's collapsed-ness has changed. */ + updateCollapsed(): void; + + /** + * @return Whether this icon is shown when the block is collapsed. Used + * to allow renderers to account for padding. + */ + isShownWhenCollapsed(): boolean; + + /** + * Notifies the icon where it is relative to its block's top-start, in + * workspace units. + */ + setOffsetInBlock(offset: Coordinate): void; + + /** + * Notifies the icon that it has changed locations. + * + * @param blockOrigin The location of this icon's block's top-start corner + * in workspace coordinates. + */ + onLocationChange(blockOrigin: Coordinate): void; + + /** + * Notifies the icon that it has been clicked. + */ + onClick(): void; +} From e3a685b6e4c419f85a34bfb3f719a04bbda8b681 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Thu, 4 May 2023 23:22:32 +0000 Subject: [PATCH 2/5] feat: add ISerializable interface --- core/field.ts | 3 ++- core/interfaces/i_serializable.ts | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 core/interfaces/i_serializable.ts diff --git a/core/field.ts b/core/field.ts index 43558ce4090..391ab5ac84a 100644 --- a/core/field.ts +++ b/core/field.ts @@ -42,6 +42,7 @@ import * as userAgent from './utils/useragent.js'; import * as utilsXml from './utils/xml.js'; import * as WidgetDiv from './widgetdiv.js'; import type {WorkspaceSvg} from './workspace_svg.js'; +import {ISerializable} from './interfaces/i_serializable.js'; /** * A function that is called to validate changes to the field's value before @@ -68,7 +69,7 @@ export type FieldValidator = (newValue: T) => T|null|undefined; export abstract class Field implements IASTNodeLocationSvg, IASTNodeLocationWithBlock, IKeyboardAccessible, - IRegistrable { + IRegistrable, ISerializable { /** * To overwrite the default value which is set in **Field**, directly update * the prototype. diff --git a/core/interfaces/i_serializable.ts b/core/interfaces/i_serializable.ts new file mode 100644 index 00000000000..341df788b8a --- /dev/null +++ b/core/interfaces/i_serializable.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + + +export interface ISerializable { + /** + * @param doFullSerialization If true, this signals that any backing data + * structures used by this ISerializable should also be serialized. This + * is used for copy-paste. + * @return a JSON serializable value that records the icon's state. + */ + saveState(doFullSerialization: boolean): any; + + /** + * Takes in a JSON serializable value and sets the ISerializable's state + * based on that. + * + * @param state The state to apply to the ISerializable. + */ + loadState(state: any): void; +} From a5977476d8d652a2fd9d5093b0ffad5ca2a65e74 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Thu, 4 May 2023 23:26:28 +0000 Subject: [PATCH 3/5] feat: add IHasBubble interface --- core/interfaces/i_has_bubble.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 core/interfaces/i_has_bubble.ts diff --git a/core/interfaces/i_has_bubble.ts b/core/interfaces/i_has_bubble.ts new file mode 100644 index 00000000000..74dcc83f49b --- /dev/null +++ b/core/interfaces/i_has_bubble.ts @@ -0,0 +1,14 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + + +export interface IHasBubble { + /** @return True if the bubble is currently open, false otherwise. */ + isBubbleVisible(): boolean; + + /** Sets whether the bubble is open or not. */ + setBubbleVisible(visible: boolean): void; +} From 77a6b8273f871e42a6e6bc847208455c021187d1 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Fri, 5 May 2023 22:48:17 +0000 Subject: [PATCH 4/5] feat: add type guards for icon interfaces --- core/interfaces/i_has_bubble.ts | 6 ++++++ core/interfaces/i_icon.ts | 11 +++++++++++ core/interfaces/i_serializable.ts | 5 +++++ 3 files changed, 22 insertions(+) diff --git a/core/interfaces/i_has_bubble.ts b/core/interfaces/i_has_bubble.ts index 74dcc83f49b..f82f1a9dccb 100644 --- a/core/interfaces/i_has_bubble.ts +++ b/core/interfaces/i_has_bubble.ts @@ -12,3 +12,9 @@ export interface IHasBubble { /** Sets whether the bubble is open or not. */ setBubbleVisible(visible: boolean): void; } + +/** Type guard that checks whether the given object is a IHasBubble. */ +export function hasBubble(obj: any): obj is IHasBubble { + return obj.isBubbleVisible !== undefined && + obj.setBubbleVisible !== undefined; +} diff --git a/core/interfaces/i_icon.ts b/core/interfaces/i_icon.ts index d5fec788f3c..f75422696ab 100644 --- a/core/interfaces/i_icon.ts +++ b/core/interfaces/i_icon.ts @@ -80,3 +80,14 @@ export interface IIcon { */ onClick(): void; } + +/** Type guard that checks whether the given object is an IIcon. */ +export function isIcon(obj: any): obj is IIcon { + return obj.getType !== undefined && obj.initView !== undefined && + obj.dispose !== undefined && obj.getWeight !== undefined && + obj.getSize !== undefined && obj.applyColour !== undefined && + obj.updateEditable !== undefined && obj.updateCollapsed !== undefined && + obj.isShownWhenCollapsed !== undefined && + obj.setOffsetInBlock !== undefined && + obj.onLocationChange !== undefined && obj.onClick !== undefined; +} diff --git a/core/interfaces/i_serializable.ts b/core/interfaces/i_serializable.ts index 341df788b8a..ad65cb3f026 100644 --- a/core/interfaces/i_serializable.ts +++ b/core/interfaces/i_serializable.ts @@ -22,3 +22,8 @@ export interface ISerializable { */ loadState(state: any): void; } + +/** Type guard that checks whether the given object is a ISerializable. */ +export function isSerializable(obj: any): obj is ISerializable { + return obj.saveState !== undefined && obj.loadState !== undefined; +} From 3d5ec4daaf87118850061ef5c22e631398de7011 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Mon, 8 May 2023 21:04:53 +0000 Subject: [PATCH 5/5] chore: PR comments --- core/interfaces/i_icon.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/interfaces/i_icon.ts b/core/interfaces/i_icon.ts index f75422696ab..fa7dc345d20 100644 --- a/core/interfaces/i_icon.ts +++ b/core/interfaces/i_icon.ts @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Coordinate} from '../utils/coordinate.js'; -import {Size} from '../utils/size.js'; +import type {Coordinate} from '../utils/coordinate.js'; +import type {Size} from '../utils/size.js'; export interface IIcon { @@ -19,9 +19,9 @@ export interface IIcon { /** * Creates the SVG elements for the icon that will live on the block. * - * @param pointerdownListener The listener to be attached to the root svg - * element. This passes off the pointer down to Blockly's gesture system - * so that clicks and drags can be properly handled. + * @param pointerdownListener An event listener that must be attached to the + * root SVG element by the implementation of `initView`. Used by Blockly's + * gesture system to properly handle clicks and drags. */ initView(pointerdownListener: (e: PointerEvent) => void): void; @@ -37,9 +37,8 @@ export interface IIcon { /** * @return the "weight" of the icon, which determines the static order which - * icons should be rendered in. - * - * More positive numbers are rendered farther toward the end of the block. + * icons should be rendered in. More positive numbers are rendered farther + * toward the end of the block. */ getWeight(): number;