@eclipse-emfcloud/model-manager
Version:
Command-based model editing with undo/redo.
109 lines • 4.13 kB
JavaScript
"use strict";
// *****************************************************************************
// Copyright (C) 2023-2024 STMicroelectronics.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: MIT License which is
// available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: EPL-2.0 OR MIT
// *****************************************************************************
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandStackImpl = void 0;
/** Default values of all command-stack options. */
const commandStackOptionsDefaults = {
keepHistory: true,
};
/**
* Complete the incoming `options` with defaults for any not specified.
*
* @param [options] the options, if any, to complete
* @returns the completed `options`, filled out with defaults where necessary
*/
const defaultCommandStackOptions = (options) => ({ ...commandStackOptionsDefaults, ...options });
/**
* The implementation of the command stack wraps a {@link CoreCommandStack} and adds a private
* {@link EditingContext} to all operation delegation.
*
* @template K the type of model ID used by the Model Manager
*/
class CommandStackImpl {
/**
* Initializes me with the core command stack to which I `delegate` my implementation
* and my unique `id` that I use as my editing context in the core command stack.
*
* @param delegate the core command stack to which I delegate my API with my editing context
* @param id my identifier, which I use as my editing context
*/
constructor(delegate, options) {
this.delegate = delegate;
const { id, ...otherOptions } = defaultCommandStackOptions(options);
this.editingContext = id;
this.options = otherOptions;
}
execute(command) {
const result = this.delegate.execute(command, this.editingContext);
if (!this.options.keepHistory) {
// Discard the history on completion or failure
return result.finally(() => this.flush());
}
return result;
}
executeAndAppend(command) {
// If we don't keep history, this will fail because there's no undo command
// to append to, which is all correct.
return this.delegate.executeAndAppend(this.editingContext, command);
}
undo() {
return this.delegate.undo(this.editingContext);
}
redo() {
return this.delegate.redo(this.editingContext);
}
canExecute(command) {
return this.delegate.canExecute(command, this.editingContext);
}
canUndo() {
return this.delegate.canUndo(this.editingContext);
}
canRedo() {
return this.delegate.canRedo(this.editingContext);
}
getUndoCommand() {
return this.delegate.getUndoCommand(this.editingContext);
}
getRedoCommand() {
return this.delegate.getRedoCommand(this.editingContext);
}
flush() {
return this.delegate.flush(this.editingContext);
}
markSaved() {
this.delegate.markSaved(this.editingContext);
}
isDirty() {
return this.delegate.isDirty(this.editingContext);
}
getDirtyModelIds() {
return this.delegate.getDirtyModelIds(this.editingContext);
}
subscribe() {
const sub = this.delegate.subscribe(this.editingContext);
const result = {
close: sub.close.bind(sub),
};
sub.onContextChanged = (_, eventType, command) => result.onCommandStackChanged?.(eventType, command);
sub.onDirtyStateChanged = (_, dirtyStateChanges) => result.onDirtyStateChanged?.(dirtyStateChanges);
return result;
}
getCoreCommandStack() {
return this.delegate;
}
}
exports.CommandStackImpl = CommandStackImpl;
//# sourceMappingURL=command-stack.js.map