You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

delete-selected.ts 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import Command from './command'
  2. import history from '../history'
  3. import { Data, Shape } from 'types'
  4. import {
  5. deepClone,
  6. getDocumentBranch,
  7. getPage,
  8. getSelectedShapes,
  9. setSelectedIds,
  10. } from 'utils'
  11. import { getShapeUtils } from 'state/shape-utils'
  12. export default function deleteSelected(data: Data): void {
  13. const selectedShapes = getSelectedShapes(data)
  14. const selectedIdsArr = selectedShapes
  15. .filter((shape) => !shape.isLocked)
  16. .map((shape) => shape.id)
  17. const shapeIdsToDelete = selectedIdsArr.flatMap((id) =>
  18. getDocumentBranch(data, id)
  19. )
  20. const remainingIds = selectedShapes
  21. .filter((shape) => shape.isLocked)
  22. .map((shape) => shape.id)
  23. let deletedShapes: Shape[] = []
  24. history.execute(
  25. data,
  26. new Command({
  27. name: 'delete_selection',
  28. category: 'canvas',
  29. manualSelection: true,
  30. do(data) {
  31. // Update selected ids
  32. setSelectedIds(data, remainingIds)
  33. // Recursively delete shapes (and maybe their parents too)
  34. deletedShapes = deleteShapes(data, shapeIdsToDelete)
  35. },
  36. undo(data) {
  37. const page = getPage(data)
  38. // Update selected ids
  39. setSelectedIds(data, selectedIdsArr)
  40. // Restore deleted shapes
  41. deletedShapes.forEach((shape) => (page.shapes[shape.id] = shape))
  42. // Update parents
  43. deletedShapes.forEach((shape) => {
  44. if (shape.parentId === data.currentPageId) return
  45. const parent = page.shapes[shape.parentId]
  46. getShapeUtils(parent)
  47. .setProperty(parent, 'children', [...parent.children, shape.id])
  48. .onChildrenChange(
  49. parent,
  50. parent.children.map((id) => page.shapes[id])
  51. )
  52. })
  53. },
  54. })
  55. )
  56. }
  57. /** Recursively delete shapes and their parents */
  58. function deleteShapes(
  59. data: Data,
  60. shapeIds: string[],
  61. shapesDeleted: Shape[] = []
  62. ): Shape[] {
  63. const parentsToDelete: string[] = []
  64. const page = getPage(data)
  65. const parentIds = new Set(shapeIds.map((id) => page.shapes[id].parentId))
  66. // Delete shapes
  67. shapeIds.forEach((id) => {
  68. shapesDeleted.push(deepClone(page.shapes[id]))
  69. delete page.shapes[id]
  70. })
  71. // Update parents
  72. parentIds.forEach((id) => {
  73. const parent = page.shapes[id]
  74. if (!parent || id === page.id) return
  75. getShapeUtils(parent)
  76. .setProperty(
  77. parent,
  78. 'children',
  79. parent.children.filter((childId) => !shapeIds.includes(childId))
  80. )
  81. .onChildrenChange(
  82. parent,
  83. parent.children.map((id) => page.shapes[id])
  84. )
  85. if (getShapeUtils(parent).shouldDelete(parent)) {
  86. parentsToDelete.push(parent.id)
  87. }
  88. })
  89. if (parentsToDelete.length > 0) {
  90. return deleteShapes(data, parentsToDelete, shapesDeleted)
  91. }
  92. return shapesDeleted
  93. }