diff --git a/examples/x6-example-features/src/pages/history/index.tsx b/examples/x6-example-features/src/pages/history/index.tsx new file mode 100644 index 00000000000..df309e750c5 --- /dev/null +++ b/examples/x6-example-features/src/pages/history/index.tsx @@ -0,0 +1,104 @@ +import React from 'react' +import { Graph } from '@antv/x6' +import { Keyboard } from '@antv/x6-plugin-keyboard' +import { Selection } from '@antv/x6-plugin-selection' +import { History } from '@antv/x6-plugin-history' +import '../index.less' + +export default class Example extends React.Component< + {}, + { graph: Graph | undefined } +> { + private container: HTMLDivElement + + componentDidMount() { + const graph = new Graph({ + container: this.container, + width: 800, + height: 600, + grid: true, + }) + + this.setState({ graph }) + + const selection = new Selection({ enabled: true }) + const keyboard = new Keyboard({ enabled: true }) + const history = new History({ enabled: true, stackSize: 5 }) + + graph.use(selection) + graph.use(keyboard) + graph.use(history) + + graph.addNode({ + x: 50, + y: 50, + width: 100, + height: 40, + attrs: { label: { text: 'A' } }, + }) + + graph.addNode({ + x: 250, + y: 50, + width: 100, + height: 40, + attrs: { label: { text: 'B' } }, + }) + + graph.addNode({ + x: 350, + y: 150, + width: 100, + height: 40, + attrs: { label: { text: 'C' } }, + }) + + keyboard.bindKey('backspace', () => { + graph.removeCells(selection.getSelectedCells()) + }) + keyboard.bindKey('command+z', () => { + this.undo() + }) + keyboard.bindKey('command+shift+z', () => { + this.redo() + }) + } + + refContainer = (container: HTMLDivElement) => { + this.container = container + } + + enablePlugins = () => { + const { graph } = this.state + graph?.enablePlugins('keyboard') + } + + disablePlugins = () => { + const { graph } = this.state + graph?.disablePlugins('keyboard') + } + + undo = () => { + const { graph } = this.state + const history = graph?.getPlugin('history') as History + history?.undo() + } + + redo = () => { + const { graph } = this.state + const history = graph?.getPlugin('history') as History + history?.redo() + } + + render() { + return ( +
+
+ + + + +
+ ) + } +} diff --git a/examples/x6-example-features/src/pages/index.tsx b/examples/x6-example-features/src/pages/index.tsx index 4ae0449ee03..d218d81cedc 100755 --- a/examples/x6-example-features/src/pages/index.tsx +++ b/examples/x6-example-features/src/pages/index.tsx @@ -179,6 +179,10 @@ const dataSource = [ example: 'animation/transition', description: '动画', }, + { + example: 'history', + description: '时光回溯', + }, ].map((item, index) => ({ key: index, ...item })) const columns = [ diff --git a/packages/x6-plugin-history/src/index.ts b/packages/x6-plugin-history/src/index.ts index 84ea02b662d..a3faa0a8289 100644 --- a/packages/x6-plugin-history/src/index.ts +++ b/packages/x6-plugin-history/src/index.ts @@ -25,6 +25,7 @@ export class History protected batchLevel = 0 protected lastBatchIndex = -1 protected freezed = false + protected stackSize = 0 // 0: not limit protected readonly handlers: (( event: T, @@ -33,6 +34,8 @@ export class History constructor(options: History.Options) { super() + const { stackSize = 0 } = options + this.stackSize = stackSize this.options = Util.getOptions(options) this.validator = new History.Validator({ history: this, @@ -101,7 +104,7 @@ export class History const cmd = this.redoStack.pop() if (cmd) { this.applyCommand(cmd, options) - this.undoStack.push(cmd) + this.undoStackPush(cmd) this.notify('redo', cmd, options) } } @@ -424,7 +427,7 @@ export class History const cmds = this.filterBatchCommand(this.batchCommands) if (cmds.length > 0) { this.redoStack = [] - this.undoStack.push(cmds) + this.undoStackPush(cmds) this.consolidateCommands() this.notify('add', cmds, options) } @@ -498,7 +501,7 @@ export class History this.lastBatchIndex = Math.max(this.lastBatchIndex, 0) this.emit('batch', { cmd, options }) } else { - this.undoStack.push(cmd) + this.undoStackPush(cmd) this.consolidateCommands() this.notify('add', cmd, options) } @@ -560,6 +563,17 @@ export class History this.undoStack.pop() } + protected undoStackPush(cmd: History.Commands) { + if (this.stackSize === 0) { + this.undoStack.push(cmd) + return + } + if (this.undoStack.length >= this.stackSize) { + this.undoStack.shift() + } + this.undoStack.push(cmd) + } + @Basecoat.dispose() dispose() { this.validator.dispose() @@ -614,7 +628,9 @@ export namespace History { cancelInvalid?: boolean } - export interface Options extends Partial {} + export interface Options extends Partial { + stackSize?: number + } interface Data { id?: string