From fcb11f19e343763df96c3a2aa0dd649e101e17fb Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Fri, 4 Jun 2021 18:56:46 +0100 Subject: [PATCH] Fixes selection for shapes in a group --- state/commands/delete-selected.ts | 20 +++++++++------ state/commands/style.ts | 15 +++++++---- state/history.ts | 2 +- state/sessions/brush-session.ts | 41 +++++++++---------------------- state/state.ts | 4 ++- utils/utils.ts | 12 +++++++++ 6 files changed, 51 insertions(+), 43 deletions(-) diff --git a/state/commands/delete-selected.ts b/state/commands/delete-selected.ts index d873b91c1..5720e07e3 100644 --- a/state/commands/delete-selected.ts +++ b/state/commands/delete-selected.ts @@ -1,8 +1,8 @@ import Command from './command' import history from '../history' import { TranslateSnapshot } from 'state/sessions/translate-session' -import { Data } from 'types' -import { getPage, updateParents } from 'utils/utils' +import { Data, ShapeType } from 'types' +import { getDocumentBranch, getPage, updateParents } from 'utils/utils' import { current } from 'immer' import { getShapeUtils } from 'lib/shape-utils' @@ -13,7 +13,9 @@ export default function deleteSelected(data: Data) { const page = getPage(current(data)) - const shapes = selectedIds.map((id) => page.shapes[id]) + const childrenToDelete = selectedIds + .flatMap((id) => getDocumentBranch(data, id)) + .map((id) => page.shapes[id]) data.selectedIds.clear() @@ -41,18 +43,22 @@ export default function deleteSelected(data: Data) { parent.children.map((id) => page.shapes[id]) ) } - delete page.shapes[id] + + for (let shape of childrenToDelete) { + delete page.shapes[shape.id] + } } data.selectedIds.clear() }, undo(data) { const page = getPage(data, currentPageId) - data.selectedIds.clear() - for (let shape of shapes) { + + for (let shape of childrenToDelete) { page.shapes[shape.id] = shape - data.selectedIds.add(shape.id) } + + data.selectedIds = new Set(selectedIds) }, }) ) diff --git a/state/commands/style.ts b/state/commands/style.ts index be9c5c997..0d1c71c5f 100644 --- a/state/commands/style.ts +++ b/state/commands/style.ts @@ -1,13 +1,18 @@ import Command from './command' import history from '../history' import { Data, ShapeStyles } from 'types' -import { getPage, getSelectedShapes } from 'utils/utils' +import { getDocumentBranch, getPage, getSelectedShapes } from 'utils/utils' import { getShapeUtils } from 'lib/shape-utils' import { current } from 'immer' export default function styleCommand(data: Data, styles: Partial) { - const { currentPageId } = data - const initialShapes = getSelectedShapes(current(data)) + const cData = current(data) + const page = getPage(cData) + const { currentPageId } = cData + + const shapesToStyle = Array.from(data.selectedIds.values()) + .flatMap((id) => getDocumentBranch(data, id)) + .map((id) => page.shapes[id]) history.execute( data, @@ -18,7 +23,7 @@ export default function styleCommand(data: Data, styles: Partial) { do(data) { const { shapes } = getPage(data, currentPageId) - for (const { id } of initialShapes) { + for (const { id } of shapesToStyle) { const shape = shapes[id] getShapeUtils(shape).applyStyles(shape, styles) } @@ -26,7 +31,7 @@ export default function styleCommand(data: Data, styles: Partial) { undo(data) { const { shapes } = getPage(data, currentPageId) - for (const { id, style } of initialShapes) { + for (const { id, style } of shapesToStyle) { const shape = shapes[id] getShapeUtils(shape).applyStyles(shape, style) } diff --git a/state/history.ts b/state/history.ts index 5214432d0..e586ca628 100644 --- a/state/history.ts +++ b/state/history.ts @@ -1,7 +1,7 @@ import { Data } from 'types' import { BaseCommand } from './commands/command' -const CURRENT_VERSION = 'code_slate_0.0.2' +const CURRENT_VERSION = 'code_slate_0.0.3' // A singleton to manage history changes. diff --git a/state/sessions/brush-session.ts b/state/sessions/brush-session.ts index 2decde220..d94b8dbed 100644 --- a/state/sessions/brush-session.ts +++ b/state/sessions/brush-session.ts @@ -22,25 +22,21 @@ export default class BrushSession extends BaseSession { const brushBounds = getBoundsFromPoints([origin, point]) + const hits = new Set([]) + for (let id in snapshot.shapeHitTests) { const { test, selectId } = snapshot.shapeHitTests[id] - if (test(brushBounds)) { - // When brushing a shape, select its top group parent. - if (!data.selectedIds.has(selectId)) { - data.selectedIds.add(selectId) + if (!hits.has(selectId)) { + if (test(brushBounds)) { + hits.add(selectId) + + // When brushing a shape, select its top group parent. + if (!data.selectedIds.has(selectId)) { + data.selectedIds.add(selectId) + } + } else if (data.selectedIds.has(selectId)) { + data.selectedIds.delete(selectId) } - - // Possibly... select all of the top group parent's children too? - // const selectedId = getTopParentId(data, id) - // const idsToSelect = collectChildIds(data, selectedId) - - // for (let id in idsToSelect) { - // if (!data.selectedIds.has(id)) { - // data.selectedIds.add(id) - // } - // } - } else if (data.selectedIds.has(selectId)) { - data.selectedIds.delete(selectId) } } @@ -89,16 +85,3 @@ function getTopParentId(data: Data, id: string): string { ? id : getTopParentId(data, shape.parentId) } - -function collectChildIds(data: Data, id: string): string[] { - const shape = getPage(data).shapes[id] - - if (shape.type === ShapeType.Group) { - return [ - id, - ...shape.children.flatMap((childId) => collectChildIds(data, childId)), - ] - } - - return [id] -} diff --git a/state/state.ts b/state/state.ts index eba7459e5..7d99dcd9d 100644 --- a/state/state.ts +++ b/state/state.ts @@ -1027,7 +1027,9 @@ const state = createState({ const page = getPage(data) selectedIds.clear() for (let id in page.shapes) { - selectedIds.add(id) + if (page.shapes[id].parentId === data.currentPageId) { + selectedIds.add(id) + } } }, setHoveredId(data, payload: PointerInfo) { diff --git a/utils/utils.ts b/utils/utils.ts index 11be0623a..906293100 100644 --- a/utils/utils.ts +++ b/utils/utils.ts @@ -1610,6 +1610,8 @@ export function getCurrentCamera(data: Data) { // }) // } +/* --------------------- Groups --------------------- */ + export function updateParents(data: Data, changedShapeIds: string[]) { if (changedShapeIds.length === 0) return @@ -1647,3 +1649,13 @@ export function getParentRotation( ? rotation + shape.rotation : getParentRotation(data, shape.parentId, rotation + shape.rotation) } + +export function getDocumentBranch(data: Data, id: string): string[] { + const shape = getPage(data).shapes[id] + if (shape.type !== ShapeType.Group) return [id] + + return [ + id, + ...shape.children.flatMap((childId) => getDocumentBranch(data, childId)), + ] +}