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

feat(react-components): Undo in architecture + implemented it in cropping, slicing, measurement etc #4629

Merged
merged 21 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
23 changes: 23 additions & 0 deletions react-components/src/architecture/base/commands/BaseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ export abstract class BaseCommand {
return undefined;
}

public get shortCutKeyOnCtrl(): boolean {
return false;
}

public get shortCutKeyOnShift(): boolean {
return false;
}

public get tooltip(): TranslateKey {
return { fallback: '' };
}
Expand Down Expand Up @@ -136,4 +144,19 @@ export abstract class BaseCommand {
}
return translate(key, fallback);
}

public getShortCutKeys(): string | undefined {
const key = this.shortCutKey;
if (key === undefined) {
return undefined;
}
let result = '';
if (this.shortCutKeyOnCtrl) {
result += 'Ctrl+';
}
if (this.shortCutKeyOnShift) {
result += 'Shift+';
}
return result + key;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export abstract class BaseEditTool extends NavigationTool {
await super.onLeftPointerUp(event);
} else {
this._dragger.onPointerUp(event);
this.addTransaction(this._dragger.transaction);
this._dragger = undefined;
}
}
Expand Down
23 changes: 18 additions & 5 deletions react-components/src/architecture/base/commands/BaseTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ import { type BaseCommand } from './BaseCommand';
import { ActiveToolUpdater } from '../reactUpdaters/ActiveToolUpdater';
import { PopupStyle } from '../domainObjectsHelpers/PopupStyle';
import { ThreeView } from '../views/ThreeView';
import { UndoManager } from '../undo/UndoManager';

/**
* Base class for interactions in the 3D viewer
* Provides common functionality and virtual methods to be overridden by derived classes.
*/
export abstract class BaseTool extends RenderTargetCommand {
private readonly _undoManager = new UndoManager();

// ==================================================
// OVERRIDES
// =================================================

public override get isChecked(): boolean {
return this.renderTarget.commandsController.activeTool === this;
return this.activeTool === this;
}

protected override invokeCore(): boolean {
Expand All @@ -44,6 +47,10 @@ export abstract class BaseTool extends RenderTargetCommand {
return true;
}

public override get undoManager(): UndoManager | undefined {
return this._undoManager;
}

// ==================================================
// VIRTUAL METHODS: To be overridden
// ==================================================
Expand Down Expand Up @@ -121,14 +128,12 @@ export abstract class BaseTool extends RenderTargetCommand {

public onKey(_event: KeyboardEvent, _down: boolean): void {}

public onUndo(): void {}

// ==================================================
// INSTANCE METHODS: Intersections
// ==================================================

public setDefaultCursor(): void {
this.renderTarget.cursor = this.defaultCursor;
}

protected async getIntersection(
event: PointerEvent | WheelEvent,
domainObjectPredicate?: (domainObject: DomainObject) => boolean
Expand Down Expand Up @@ -213,4 +218,12 @@ export abstract class BaseTool extends RenderTargetCommand {
const point = viewer.getPixelCoordinatesFromEvent(event);
return viewer.getNormalizedPixelCoordinates(point);
}

// ==================================================
// INSTANCE METHODS: Misc
// ==================================================

public setDefaultCursor(): void {
this.renderTarget.cursor = this.defaultCursor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
*/

import { type DomainObject } from '../domainObjects/DomainObject';
import { BaseCommand } from './BaseCommand';
import { RenderTargetCommand } from './RenderTargetCommand';

export abstract class DomainObjectCommand<Type extends DomainObject> extends BaseCommand {
export abstract class DomainObjectCommand<Type extends DomainObject> extends RenderTargetCommand {
// ==================================================
// INSTANCE FIELDS
// ==================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,44 @@ import { BaseCommand } from './BaseCommand';
import { type RevealRenderTarget } from '../renderTarget/RevealRenderTarget';
import { type RootDomainObject } from '../domainObjects/RootDomainObject';
import { CommandsUpdater } from '../reactUpdaters/CommandsUpdater';
import { type UndoManager } from '../undo/UndoManager';
import { type Transaction } from '../undo/Transaction';
import { type BaseTool } from './BaseTool';

/**
* Represents a base class where the render target is known.
* Subclasses of this class is used to interact with the render target
*/
export abstract class RenderTargetCommand extends BaseCommand {
// ==================================================
// INSTANCE FIELDS
// ==================================================

public _renderTarget: RevealRenderTarget | undefined = undefined;

// ==================================================
// INSTANCE PROPERTIES
// ==================================================

public get renderTarget(): RevealRenderTarget {
if (this._renderTarget === undefined) {
throw new Error('Render target is not set');
}
return this._renderTarget;
}

public get rootDomainObject(): RootDomainObject {
protected get rootDomainObject(): RootDomainObject {
return this.renderTarget.rootDomainObject;
}

protected get activeTool(): BaseTool | undefined {
return this.renderTarget.commandsController.activeTool;
}

// ==================================================
// OVERRIDES
// ==================================================

public override invoke(): boolean {
const success = this.invokeCore();
if (success) {
Expand All @@ -33,7 +52,39 @@ export abstract class RenderTargetCommand extends BaseCommand {
return success;
}

// ==================================================
// VIRTUAL METHODS
// ==================================================

public get undoManager(): UndoManager | undefined {
// This method is overridden on BaseTool only!
const { activeTool } = this;
if (activeTool === undefined) {
return undefined;
}
return activeTool.undoManager;
}

// ==================================================
// INSTANCE METHODS
// ==================================================

public attach(renderTarget: RevealRenderTarget): void {
this._renderTarget = renderTarget;
}

public addTransaction(transaction: Transaction | undefined): void {
if (transaction === undefined) {
return;
}
const undoManager = this.undoManager;
if (undoManager === undefined) {
return;
}
const couldUndo = undoManager.canUndo;
undoManager.addTransaction(transaction);
if (couldUndo !== undoManager.canUndo) {
CommandsUpdater.update(this.renderTarget); // This refresh the undo button!
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export abstract class ShowDomainObjectsOnTopCommand extends InstanceCommand {
if (!(renderStyle instanceof CommonRenderStyle)) {
continue;
}
this.addTransaction(domainObject.createTransaction(Changes.renderStyle));
renderStyle.depthTest = !depthTest;
domainObject.notify(Changes.renderStyle);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
import { type TranslateKey } from '../utilities/TranslateKey';
import { type DomainObject } from '../domainObjects/DomainObject';
import { DomainObjectCommand } from '../commands/DomainObjectCommand';
import { Changes } from '../domainObjectsHelpers/Changes';

export class DeleteDomainObjectCommand extends DomainObjectCommand<DomainObject> {
// ==================================================
// INSTANCE PROPERTIES
// ==================================================

// ==================================================
// OVERRIDES
// ==================================================
Expand All @@ -28,6 +33,7 @@ export class DeleteDomainObjectCommand extends DomainObjectCommand<DomainObject>
}

protected override invokeCore(): boolean {
this.addTransaction(this._domainObject.createTransaction(Changes.deleted));
return this._domainObject.removeInteractive();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ export class NavigationTool extends BaseTool {
// OVERRIDES
// ==================================================

public override get shortCutKey(): string | undefined {
return 'N';
}

public override get icon(): string {
return 'Grab';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class SetFlexibleControlsTypeCommand extends RenderTargetCommand {
// OVERRIDES
// ==================================================

public override get shortCutKey(): string | undefined {
return this._controlsType === FlexibleControlsType.Orbit ? '1' : '2';
}

public override equals(other: BaseCommand): boolean {
if (!(other instanceof SetFlexibleControlsTypeCommand)) {
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*!
* Copyright 2024 Cognite AS
*/

import { RenderTargetCommand } from '../commands/RenderTargetCommand';
import { CommandsUpdater } from '../reactUpdaters/CommandsUpdater';
import { type TranslateKey } from '../utilities/TranslateKey';

export class UndoCommand extends RenderTargetCommand {
// ==================================================
// OVERRIDES
// ==================================================

public override get icon(): string {
return 'Refresh'; // Should be 'Restore ' but it doesn't exist
}

public override get tooltip(): TranslateKey {
return { key: 'UNDO', fallback: 'Undo' };
}

public override get isEnabled(): boolean {
const undoManager = this.undoManager;
if (undoManager === undefined) {
return false;
}
return undoManager.canUndo;
}

public override get shortCutKey(): string | undefined {
return 'Z';
}

public override get shortCutKeyOnCtrl(): boolean {
return true;
}

public override get isVisible(): boolean {
return true; // Let it always be there in case many clicks
}

protected override invokeCore(): boolean {
const undoManager = this.undoManager;
if (undoManager === undefined) {
return false;
}
const couldUndo = undoManager.canUndo;
const undone = undoManager.undo(this.renderTarget);
if (couldUndo !== undoManager.canUndo) {
CommandsUpdater.update(this.renderTarget);
}
this.activeTool?.onUndo();
return undone;
}
}
Loading
Loading