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.

ungroup.ts 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import Command from './command'
  2. import history from '../history'
  3. import { Data, GroupShape, Shape, ShapeType } from 'types'
  4. import {
  5. getCommonBounds,
  6. getPage,
  7. getSelectedShapes,
  8. getShape,
  9. setSelectedIds,
  10. } from 'utils/utils'
  11. import { current } from 'immer'
  12. import { createShape, getShapeUtils } from 'lib/shape-utils'
  13. import { PropsOfType } from 'types'
  14. import { v4 as uuid } from 'uuid'
  15. export default function ungroupCommand(data: Data) {
  16. const cData = current(data)
  17. const { currentPageId } = cData
  18. const selectedGroups = getSelectedShapes(cData)
  19. .filter((shape) => shape.type === ShapeType.Group)
  20. .sort((a, b) => a.childIndex - b.childIndex)
  21. // Are all of the shapes already in the same group?
  22. // - ungroup the shapes
  23. // Otherwise...
  24. // - remove the shapes from any existing group and add them to a new one
  25. history.execute(
  26. data,
  27. new Command({
  28. name: 'ungroup_shapes',
  29. category: 'canvas',
  30. do(data) {
  31. const { shapes } = getPage(data)
  32. // Remove shapes from old parents
  33. for (const oldGroupShape of selectedGroups) {
  34. const siblings = (
  35. oldGroupShape.parentId === currentPageId
  36. ? Object.values(shapes).filter(
  37. (shape) => shape.parentId === currentPageId
  38. )
  39. : shapes[oldGroupShape.parentId].children.map((id) => shapes[id])
  40. ).sort((a, b) => a.childIndex - b.childIndex)
  41. const trueIndex = siblings.findIndex((s) => s.id === oldGroupShape.id)
  42. let step: number
  43. if (trueIndex === siblings.length - 1) {
  44. step = 1
  45. } else {
  46. step =
  47. (siblings[trueIndex + 1].childIndex - oldGroupShape.childIndex) /
  48. (oldGroupShape.children.length + 1)
  49. }
  50. // Move shapes to page
  51. oldGroupShape.children
  52. .map((id) => shapes[id])
  53. .forEach(({ id }, i) => {
  54. const shape = shapes[id]
  55. getShapeUtils(shape)
  56. .setProperty(shape, 'parentId', oldGroupShape.parentId)
  57. .setProperty(
  58. shape,
  59. 'childIndex',
  60. oldGroupShape.childIndex + step * i
  61. )
  62. })
  63. setSelectedIds(data, oldGroupShape.children)
  64. delete shapes[oldGroupShape.id]
  65. }
  66. },
  67. undo(data) {
  68. const { shapes } = getPage(data, currentPageId)
  69. selectedGroups.forEach((group) => {
  70. shapes[group.id] = group
  71. group.children.forEach((id, i) => {
  72. const shape = shapes[id]
  73. getShapeUtils(shape)
  74. .setProperty(shape, 'parentId', group.id)
  75. .setProperty(shape, 'childIndex', i)
  76. })
  77. })
  78. setSelectedIds(
  79. data,
  80. selectedGroups.map((g) => g.id)
  81. )
  82. },
  83. })
  84. )
  85. }
  86. function getShapeDepth(data: Data, id: string, depth = 0) {
  87. if (id === data.currentPageId) {
  88. return depth
  89. }
  90. return getShapeDepth(data, getShape(data, id).parentId, depth + 1)
  91. }