Skip to content

Commit

Permalink
#261 zindex visible when multiple selection and fix zindex methods
Browse files Browse the repository at this point in the history
  • Loading branch information
oleojake committed Sep 4, 2024
1 parent e8bf1c2 commit 26ecc96
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 195 deletions.
8 changes: 4 additions & 4 deletions src/core/providers/canvas/use-selection.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react';
import Konva from 'konva';
import { OtherProps, ShapeModel, ShapeRefs, ShapeType } from '@/core/model';
import { DocumentModel, SelectionInfo, ZIndexAction } from './canvas.model';
import { performZIndexActionMultiple } from './zindex.util';
import { performZIndexAction } from './zindex.util';

export const useSelection = (
document: DocumentModel,
Expand Down Expand Up @@ -82,11 +82,11 @@ export const useSelection = (
};

const handleClearSelection = (
mouseEvent:
mouseEvent?:
| Konva.KonvaEventObject<MouseEvent>
| Konva.KonvaEventObject<TouchEvent>
) => {
if (mouseEvent.target === mouseEvent.target.getStage()) {
if (!mouseEvent || mouseEvent.target === mouseEvent.target.getStage()) {
transformerRef.current?.nodes([]);
selectedShapesRefs.current = [];
setSelectedShapesIds([]);
Expand All @@ -96,7 +96,7 @@ export const useSelection = (

const setZIndexOnSelected = (action: ZIndexAction) => {
setDocument(prevDocument => ({
shapes: performZIndexActionMultiple(
shapes: performZIndexAction(
selectedShapesIds,
action,
prevDocument.shapes
Expand Down
32 changes: 16 additions & 16 deletions src/core/providers/canvas/zindex.util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('moveZIndexToTop', () => {
},
];
// Act
const result = moveZIndexToTop(selectedShapeId, shapes);
const result = moveZIndexToTop([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([
{
Expand Down Expand Up @@ -145,7 +145,7 @@ describe('moveZIndexToTop', () => {
},
];
// Act
const result = moveZIndexToTop(selectedShapeId, shapes);
const result = moveZIndexToTop([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand All @@ -155,7 +155,7 @@ describe('moveZIndexToTop', () => {
const selectedShapeId: string = '2';
const shapes: ShapeModel[] = [];
// Act
const result = moveZIndexToTop(selectedShapeId, shapes);
const result = moveZIndexToTop([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([]);
});
Expand Down Expand Up @@ -206,7 +206,7 @@ describe('moveZIndexToTop', () => {
},
];
// Act
const result = moveZIndexToTop(selectedShapeId, shapes);
const result = moveZIndexToTop([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand Down Expand Up @@ -259,7 +259,7 @@ describe('moveZIndexToBottom', () => {
},
];
// Act
const result = moveZIndexToBottom(selectedShapeId, shapes);
const result = moveZIndexToBottom([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([
{
Expand Down Expand Up @@ -351,7 +351,7 @@ describe('moveZIndexToBottom', () => {
},
];
// Act
const result = moveZIndexToBottom(selectedShapeId, shapes);
const result = moveZIndexToBottom([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand All @@ -361,7 +361,7 @@ describe('moveZIndexToBottom', () => {
const selectedShapeId: string = '2';
const shapes: ShapeModel[] = [];
// Act
const result = moveZIndexToBottom(selectedShapeId, shapes);
const result = moveZIndexToBottom([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([]);
});
Expand Down Expand Up @@ -412,7 +412,7 @@ describe('moveZIndexToBottom', () => {
},
];
// Act
const result = moveZIndexToBottom(selectedShapeId, shapes);
const result = moveZIndexToBottom([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand Down Expand Up @@ -465,7 +465,7 @@ describe('moveZIndexDownOneLevel', () => {
},
];
// Act
const result = moveZIndexDownOneLevel(selectedShapeId, shapes);
const result = moveZIndexDownOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([
{
Expand Down Expand Up @@ -557,7 +557,7 @@ describe('moveZIndexDownOneLevel', () => {
},
];
// Act
const result = moveZIndexDownOneLevel(selectedShapeId, shapes);
const result = moveZIndexDownOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand All @@ -567,7 +567,7 @@ describe('moveZIndexDownOneLevel', () => {
const selectedShapeId: string = '2';
const shapes: ShapeModel[] = [];
// Act
const result = moveZIndexDownOneLevel(selectedShapeId, shapes);
const result = moveZIndexDownOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([]);
});
Expand Down Expand Up @@ -618,7 +618,7 @@ describe('moveZIndexDownOneLevel', () => {
},
];
// Act
const result = moveZIndexDownOneLevel(selectedShapeId, shapes);
const result = moveZIndexDownOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand Down Expand Up @@ -671,7 +671,7 @@ describe('moveZIndexTopOneLevel', () => {
},
];
// Act
const result = moveZIndexTopOneLevel(selectedShapeId, shapes);
const result = moveZIndexTopOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([
{
Expand Down Expand Up @@ -763,7 +763,7 @@ describe('moveZIndexTopOneLevel', () => {
},
];
// Act
const result = moveZIndexTopOneLevel(selectedShapeId, shapes);
const result = moveZIndexTopOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand All @@ -773,7 +773,7 @@ describe('moveZIndexTopOneLevel', () => {
const selectedShapeId: string = '2';
const shapes: ShapeModel[] = [];
// Act
const result = moveZIndexTopOneLevel(selectedShapeId, shapes);
const result = moveZIndexTopOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual<ShapeModel[]>([]);
});
Expand Down Expand Up @@ -824,7 +824,7 @@ describe('moveZIndexTopOneLevel', () => {
},
];
// Act
const result = moveZIndexTopOneLevel(selectedShapeId, shapes);
const result = moveZIndexTopOneLevel([selectedShapeId], shapes);
// Assert
expect(result).toStrictEqual(shapes);
});
Expand Down
129 changes: 50 additions & 79 deletions src/core/providers/canvas/zindex.util.ts
Original file line number Diff line number Diff line change
@@ -1,114 +1,85 @@
import { ShapeModel } from '@/core/model';
import { ZIndexAction } from './canvas.model';

// TOO Add Unit tests to all these methods: #65
export const moveZIndexToTop = (
selectedShapeId: string,
selectedShapesIds: string[],
shapeCollection: ShapeModel[]
): ShapeModel[] => {
const selectedShape = shapeCollection.find(
shape => shape.id === selectedShapeId
const selectedShapes = shapeCollection.filter(shape =>
selectedShapesIds.includes(shape.id)
);
return selectedShape
? [
...shapeCollection.filter(shape => shape.id !== selectedShapeId),
selectedShape,
]
: shapeCollection;
const remainingShapes = shapeCollection.filter(
shape => !selectedShapesIds.includes(shape.id)
);
return [...remainingShapes, ...selectedShapes];
};

export const moveZIndexToBottom = (
selectedShapeId: string,
selectedShapesIds: string[],
shapeCollection: ShapeModel[]
): ShapeModel[] => {
const selectedShape = shapeCollection.find(
shape => shape.id === selectedShapeId
const selectedShapes = shapeCollection.filter(shape =>
selectedShapesIds.includes(shape.id)
);
const remainingShapes = shapeCollection.filter(
shape => !selectedShapesIds.includes(shape.id)
);
return selectedShape
? [
selectedShape,
...shapeCollection.filter(shape => shape.id !== selectedShapeId),
]
: shapeCollection;
return [...selectedShapes, ...remainingShapes];
};

export const moveZIndexDownOneLevel = (
selectedShapeId: string,
selectedShapesIds: string[],
shapeCollection: ShapeModel[]
): ShapeModel[] => {
const selectedShapeIndex = shapeCollection.findIndex(
shape => shape.id === selectedShapeId
);
const selectedShape = shapeCollection.find(
shape => shape.id === selectedShapeId
);

return selectedShape &&
selectedShapeIndex > 0 &&
selectedShapeIndex < shapeCollection.length
? [
...shapeCollection.slice(0, selectedShapeIndex - 1),
selectedShape,
shapeCollection[selectedShapeIndex - 1],
...shapeCollection.slice(selectedShapeIndex + 1),
]
: shapeCollection;
let newCollection = [...shapeCollection];
for (let i = 0; i < newCollection.length; i++) {
const shape = newCollection[i];
if (selectedShapesIds.includes(shape.id) && i > 0) {
const previousShape = newCollection[i - 1];
if (!selectedShapesIds.includes(previousShape.id)) {
// Swap positions if previous shape is not part of the selection
newCollection[i - 1] = shape;
newCollection[i] = previousShape;
}
}
}
return newCollection;
};

export const moveZIndexTopOneLevel = (
selectedShapeId: string,
selectedShapesIds: string[],
shapeCollection: ShapeModel[]
): ShapeModel[] => {
const selectedShapeIndex = shapeCollection.findIndex(
shape => shape.id === selectedShapeId
);
const selectedShape = shapeCollection.find(
shape => shape.id === selectedShapeId
);

return selectedShape &&
selectedShapeIndex >= 0 &&
selectedShapeIndex < shapeCollection.length - 1
? [
...shapeCollection.slice(0, selectedShapeIndex),
shapeCollection[selectedShapeIndex + 1],
selectedShape,
...shapeCollection.slice(selectedShapeIndex + 2),
]
: shapeCollection;
let newCollection = [...shapeCollection];
for (let i = newCollection.length - 1; i >= 0; i--) {
const shape = newCollection[i];
if (selectedShapesIds.includes(shape.id) && i < newCollection.length - 1) {
const nextShape = newCollection[i + 1];
if (!selectedShapesIds.includes(nextShape.id)) {
// Swap positions if next shape is not part of the selection
newCollection[i + 1] = shape;
newCollection[i] = nextShape;
}
}
}
return newCollection;
};

const performZIndexAction = (
selectedShapeId: string,
export const performZIndexAction = (
selectedShapesIds: string[],
action: ZIndexAction,
shapes: ShapeModel[]
): ShapeModel[] => {
switch (action) {
case 'top':
return moveZIndexToTop(selectedShapeId, shapes);
break;
return moveZIndexToTop(selectedShapesIds, shapes);
case 'bottom':
return moveZIndexToBottom(selectedShapeId, shapes);
break;
return moveZIndexToBottom(selectedShapesIds, shapes);
case 'up':
return moveZIndexTopOneLevel(selectedShapeId, shapes);
break;
return moveZIndexTopOneLevel(selectedShapesIds, shapes);
case 'down':
return moveZIndexDownOneLevel(selectedShapeId, shapes);
return moveZIndexDownOneLevel(selectedShapesIds, shapes);
default:
return shapes;
}
};

export const performZIndexActionMultiple = (
selectedShapesId: string[],
action: ZIndexAction,
shapes: ShapeModel[]
): ShapeModel[] => {
// TODO: Enhance this, this won't perform well
let workShapes = [...shapes];

selectedShapesId.forEach(selectedShapeId => {
workShapes = performZIndexAction(selectedShapeId, action, workShapes);
});

return workShapes;
};
Loading

0 comments on commit 26ecc96

Please sign in to comment.