選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

command.ts 2.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { Data } from "types"
  2. /* ------------------ Command Class ----------------- */
  3. export type CommandFn<T> = (data: T, initial?: boolean) => void
  4. export enum CommandType {
  5. ChangeBounds,
  6. CreateGlob,
  7. CreateNode,
  8. Delete,
  9. Split,
  10. Move,
  11. MoveAnchor,
  12. ReorderGlobs,
  13. ReorderNodes,
  14. Paste,
  15. ToggleCap,
  16. ToggleLocked,
  17. SetProperty,
  18. SetItems,
  19. Transform,
  20. }
  21. /**
  22. * A command makes changes to some applicate state. Every command has an "undo"
  23. * method to reverse its changes. The apps history is a series of commands.
  24. */
  25. export class BaseCommand<T extends any> {
  26. timestamp = Date.now()
  27. private undoFn: CommandFn<T>
  28. private doFn: CommandFn<T>
  29. protected restoreBeforeSelectionState: (data: T) => void
  30. protected restoreAfterSelectionState: (data: T) => void
  31. protected saveSelectionState: (data: T) => (data: T) => void
  32. protected manualSelection: boolean
  33. constructor(options: {
  34. type: CommandType
  35. do: CommandFn<T>
  36. undo: CommandFn<T>
  37. manualSelection?: boolean
  38. }) {
  39. this.doFn = options.do
  40. this.undoFn = options.undo
  41. this.manualSelection = options.manualSelection || false
  42. this.restoreBeforeSelectionState = () => () => {
  43. null
  44. }
  45. this.restoreAfterSelectionState = () => () => {
  46. null
  47. }
  48. }
  49. undo = (data: T) => {
  50. if (this.manualSelection) {
  51. this.undoFn(data)
  52. return
  53. }
  54. // We need to set the selection state to what it was before we after we did the command
  55. this.restoreAfterSelectionState(data)
  56. this.undoFn(data)
  57. this.restoreBeforeSelectionState(data)
  58. }
  59. redo = (data: T, initial = false) => {
  60. if (initial) {
  61. this.restoreBeforeSelectionState = this.saveSelectionState(data)
  62. } else {
  63. this.restoreBeforeSelectionState(data)
  64. }
  65. // We need to set the selection state to what it was before we did the command
  66. this.doFn(data, initial)
  67. if (initial) {
  68. this.restoreAfterSelectionState = this.saveSelectionState(data)
  69. }
  70. }
  71. }
  72. /* ---------------- Project Specific ---------------- */
  73. /**
  74. * A subclass of BaseCommand that sends events to our state. In our case, we want our actions
  75. * to mutate the state's data. Actions do not effect the "active states" in
  76. * the app.
  77. */
  78. export class Command extends BaseCommand<Data> {
  79. saveSelectionState = (data: Data) => {
  80. return (data: Data) => {}
  81. }
  82. }