mirror of
https://github.com/google/blockly.git
synced 2026-01-10 18:37:09 +01:00
* feat: add empty implementations of events * chore: register all events * chore: change assertions to shallow match properties * feat: add firing events from the observable procedure map * fix: make event not fired assertions actually fail * chore: fixup typos in tests * feat: add firing procedure model events * feat: add firing parameter create and parameter delete events * chore: reorganize event tests into suites * feat: add firing parameter rename events * chore: format * chore: use tripple equals
195 lines
5.6 KiB
TypeScript
195 lines
5.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2022 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import * as eventUtils from '../events/utils.js';
|
|
import {genUid} from '../utils/idgenerator.js';
|
|
import type {IParameterModel} from '../interfaces/i_parameter_model.js';
|
|
import type {IProcedureModel} from '../interfaces/i_procedure_model.js';
|
|
import {isObservable} from '../interfaces/i_observable.js';
|
|
import {triggerProceduresUpdate} from './update_procedures.js';
|
|
import type {Workspace} from '../workspace.js';
|
|
|
|
|
|
export class ObservableProcedureModel implements IProcedureModel {
|
|
private id: string;
|
|
private name: string;
|
|
private parameters: IParameterModel[] = [];
|
|
private returnTypes: string[]|null = null;
|
|
private enabled = true;
|
|
private shouldFireEvents = false;
|
|
|
|
constructor(
|
|
private readonly workspace: Workspace, name: string, id?: string) {
|
|
this.id = id ?? genUid();
|
|
this.name = name;
|
|
}
|
|
|
|
/** Sets the human-readable name of the procedure. */
|
|
setName(name: string): this {
|
|
if (name === this.name) return this;
|
|
const prevName = this.name;
|
|
this.name = name;
|
|
triggerProceduresUpdate(this.workspace);
|
|
if (this.shouldFireEvents) {
|
|
eventUtils.fire(new (eventUtils.get(eventUtils.PROCEDURE_RENAME))(
|
|
this.workspace, this, prevName));
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Inserts a parameter into the list of parameters.
|
|
*
|
|
* To move a parameter, first delete it, and then re-insert.
|
|
*/
|
|
insertParameter(parameterModel: IParameterModel, index: number): this {
|
|
if (this.parameters[index] &&
|
|
this.parameters[index].getId() === parameterModel.getId()) {
|
|
return this;
|
|
}
|
|
|
|
this.parameters.splice(index, 0, parameterModel);
|
|
parameterModel.setProcedureModel(this);
|
|
if (isObservable(parameterModel)) {
|
|
if (this.shouldFireEvents) {
|
|
parameterModel.startPublishing();
|
|
} else {
|
|
parameterModel.stopPublishing();
|
|
}
|
|
}
|
|
|
|
triggerProceduresUpdate(this.workspace);
|
|
if (this.shouldFireEvents) {
|
|
eventUtils.fire(
|
|
new (eventUtils.get(eventUtils.PROCEDURE_PARAMETER_CREATE))(
|
|
this.workspace, this, parameterModel, index));
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/** Removes the parameter at the given index from the parameter list. */
|
|
deleteParameter(index: number): this {
|
|
if (!this.parameters[index]) return this;
|
|
const oldParam = this.parameters[index];
|
|
|
|
this.parameters.splice(index, 1);
|
|
triggerProceduresUpdate(this.workspace);
|
|
if (isObservable(oldParam)) {
|
|
oldParam.stopPublishing();
|
|
}
|
|
|
|
if (this.shouldFireEvents) {
|
|
eventUtils.fire(
|
|
new (eventUtils.get(eventUtils.PROCEDURE_PARAMETER_DELETE))(
|
|
this.workspace, this, oldParam, index));
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets whether the procedure has a return value (empty array) or no return
|
|
* value (null).
|
|
*
|
|
* The built-in procedure model does not support procedures that have actual
|
|
* return types (i.e. non-empty arrays, e.g. ['number']). If you want your
|
|
* procedure block to have return types, you need to implement your own
|
|
* procedure model.
|
|
*/
|
|
setReturnTypes(types: string[]|null): this {
|
|
if (types && types.length) {
|
|
throw new Error(
|
|
'The built-in ProcedureModel does not support typing. You need to ' +
|
|
'implement your own custom ProcedureModel.');
|
|
}
|
|
// Either they're both an empty array, or both null. Noop either way.
|
|
if (!!types === !!this.returnTypes) return this;
|
|
const oldReturnTypes = this.returnTypes;
|
|
this.returnTypes = types;
|
|
triggerProceduresUpdate(this.workspace);
|
|
if (this.shouldFireEvents) {
|
|
eventUtils.fire(new (eventUtils.get(eventUtils.PROCEDURE_CHANGE_RETURN))(
|
|
this.workspace, this, oldReturnTypes));
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets whether this procedure is enabled/disabled. If a procedure is disabled
|
|
* all procedure caller blocks should be disabled as well.
|
|
*/
|
|
setEnabled(enabled: boolean): this {
|
|
if (enabled === this.enabled) return this;
|
|
this.enabled = enabled;
|
|
triggerProceduresUpdate(this.workspace);
|
|
if (this.shouldFireEvents) {
|
|
eventUtils.fire(new (eventUtils.get(eventUtils.PROCEDURE_ENABLE))(
|
|
this.workspace, this));
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/** Returns the unique language-neutral ID for the procedure. */
|
|
getId(): string {
|
|
return this.id;
|
|
}
|
|
|
|
/** Returns the human-readable name of the procedure. */
|
|
getName(): string {
|
|
return this.name;
|
|
}
|
|
|
|
/** Returns the parameter at the given index in the parameter list. */
|
|
getParameter(index: number): IParameterModel {
|
|
return this.parameters[index];
|
|
}
|
|
|
|
/** Returns an array of all of the parameters in the parameter list. */
|
|
getParameters(): IParameterModel[] {
|
|
return [...this.parameters];
|
|
}
|
|
|
|
/**
|
|
* Returns the return type of the procedure.
|
|
*
|
|
* Null represents a procedure that does not return a value.
|
|
*/
|
|
getReturnTypes(): string[]|null {
|
|
return this.returnTypes;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the procedure is enabled/disabled. If a procedure is
|
|
* disabled, all procedure caller blocks should be disabled as well.
|
|
*/
|
|
getEnabled(): boolean {
|
|
return this.enabled;
|
|
}
|
|
|
|
/**
|
|
* Tells the procedure model it should fire events.
|
|
*
|
|
* @internal
|
|
*/
|
|
startPublishing() {
|
|
this.shouldFireEvents = true;
|
|
for (const param of this.parameters) {
|
|
if (isObservable(param)) param.startPublishing();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tells the procedure model it should not fire events.
|
|
*
|
|
* @internal
|
|
*/
|
|
stopPublishing() {
|
|
this.shouldFireEvents = false;
|
|
for (const param of this.parameters) {
|
|
if (isObservable(param)) param.stopPublishing();
|
|
}
|
|
}
|
|
}
|