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.7KB

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