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

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