switch different types altogether

This commit is contained in:
Ryan Di 2025-03-24 12:07:57 +11:00
parent 41a4dadaaf
commit aa9139ad78
3 changed files with 53 additions and 38 deletions

View file

@ -193,9 +193,9 @@ import {
isElbowArrow, isElbowArrow,
isFlowchartNodeElement, isFlowchartNodeElement,
isBindableElement, isBindableElement,
isGenericSwitchableElement, areGenericSwitchableElements,
isGenericSwitchableToolType, isGenericSwitchableToolType,
isLinearSwitchableElement, areLinearSwitchableElements,
isLinearSwitchableToolType, isLinearSwitchableToolType,
} from "../element/typeChecks"; } from "../element/typeChecks";
import { getCenter, getDistance } from "../gesture"; import { getCenter, getDistance } from "../gesture";
@ -4110,8 +4110,9 @@ class App extends React.Component<AppProps, AppState> {
return; return;
} }
const genericSwitchable = isGenericSwitchableElement(selectedElements); const genericSwitchable =
const linearSwitchable = isLinearSwitchableElement(selectedElements); areGenericSwitchableElements(selectedElements);
const linearSwitchable = areLinearSwitchableElements(selectedElements);
if (genericSwitchable || linearSwitchable) { if (genericSwitchable || linearSwitchable) {
const firstElement = selectedElements[0]; const firstElement = selectedElements[0];
@ -4122,21 +4123,31 @@ class App extends React.Component<AppProps, AppState> {
event.preventDefault(); event.preventDefault();
if (editorJotaiStore.get(shapeSwitchAtom)?.type === "panel") { if (editorJotaiStore.get(shapeSwitchAtom)?.type === "panel") {
const index = genericSwitchable const sameType = selectedElements.every(
(element) => element.type === selectedElements[0].type,
);
let nextType;
if (genericSwitchable) {
const index = sameType
? GENERIC_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type) ? GENERIC_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type)
: LINEAR_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type); : -1;
const nextType = ( nextType = GENERIC_SWITCHABLE_SHAPES[
genericSwitchable
? GENERIC_SWITCHABLE_SHAPES[
(index + 1) % GENERIC_SWITCHABLE_SHAPES.length (index + 1) % GENERIC_SWITCHABLE_SHAPES.length
] ] as ToolType;
: LINEAR_SWITCHABLE_SHAPES[
(index + 1) % LINEAR_SWITCHABLE_SHAPES.length
]
) as ToolType;
this.setActiveTool({ type: nextType }); this.setActiveTool({ type: nextType });
} else if (linearSwitchable) {
const index = sameType
? LINEAR_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type)
: -1;
nextType = LINEAR_SWITCHABLE_SHAPES[
(index + 1) % LINEAR_SWITCHABLE_SHAPES.length
] as ToolType;
this.setActiveTool({ type: nextType });
}
} }
editorJotaiStore.set(shapeSwitchAtom, { editorJotaiStore.set(shapeSwitchAtom, {
@ -4827,7 +4838,7 @@ class App extends React.Component<AppProps, AppState> {
); );
if ( if (
isGenericSwitchableElement(selectedElements) && areGenericSwitchableElements(selectedElements) &&
isGenericSwitchableToolType(tool.type) isGenericSwitchableToolType(tool.type)
) { ) {
selectedElements.forEach((element) => { selectedElements.forEach((element) => {
@ -4889,7 +4900,7 @@ class App extends React.Component<AppProps, AppState> {
} }
if ( if (
isLinearSwitchableElement(selectedElements) && areLinearSwitchableElements(selectedElements) &&
isLinearSwitchableToolType(tool.type) isLinearSwitchableToolType(tool.type)
) { ) {
selectedElements.forEach((element) => { selectedElements.forEach((element) => {

View file

@ -192,6 +192,10 @@ const Panel = ({
let [x1, y2, cx, cy] = [0, 0, 0, 0]; let [x1, y2, cx, cy] = [0, 0, 0, 0];
let rotatedBottomLeft = [0, 0]; let rotatedBottomLeft = [0, 0];
const sameType = elements.every(
(element) => element.type === elements[0].type,
);
if (elements.length === 1) { if (elements.length === 1) {
[x1, , , y2, cx, cy] = getElementAbsoluteCoords( [x1, , , y2, cx, cy] = getElementAbsoluteCoords(
elements[0], elements[0],
@ -245,7 +249,8 @@ const Panel = ({
> >
{SHAPES.map(([type, shortcut, icon]) => { {SHAPES.map(([type, shortcut, icon]) => {
const isSelected = const isSelected =
type === elements[0].type || sameType &&
(type === elements[0].type ||
(isArrowElement(elements[0]) && (isArrowElement(elements[0]) &&
elements[0].elbowed && elements[0].elbowed &&
type === "elbow") || type === "elbow") ||
@ -255,7 +260,7 @@ const Panel = ({
(isArrowElement(elements[0]) && (isArrowElement(elements[0]) &&
!elements[0].elbowed && !elements[0].elbowed &&
!elements[0].roundness && !elements[0].roundness &&
type === "straight"); type === "straight"));
return ( return (
<ToolButton <ToolButton

View file

@ -350,18 +350,17 @@ type ExcalidrawGenericSwitchableElement =
| ExcalidrawEllipseElement | ExcalidrawEllipseElement
| ExcalidrawDiamondElement; | ExcalidrawDiamondElement;
export const isGenericSwitchableElement = ( export const areGenericSwitchableElements = (
elements: ExcalidrawElement[], elements: ExcalidrawElement[],
): elements is NonEmptyArray<ExcalidrawGenericSwitchableElement> => { ): elements is NonEmptyArray<ExcalidrawGenericSwitchableElement> => {
if (elements.length === 0) { if (elements.length === 0) {
return false; return false;
} }
const firstType = elements[0].type; return elements.every(
return ( (element) =>
(firstType === "rectangle" || element.type === "rectangle" ||
firstType === "ellipse" || element.type === "ellipse" ||
firstType === "diamond") && element.type === "diamond",
elements.every((element) => element.type === firstType)
); );
}; };
@ -371,7 +370,7 @@ export const isGenericSwitchableToolType = (
return type === "rectangle" || type === "ellipse" || type === "diamond"; return type === "rectangle" || type === "ellipse" || type === "diamond";
}; };
export const isLinearSwitchableElement = ( export const areLinearSwitchableElements = (
elements: ExcalidrawElement[], elements: ExcalidrawElement[],
): elements is NonEmptyArray<ExcalidrawLinearElement> => { ): elements is NonEmptyArray<ExcalidrawLinearElement> => {
if (elements.length === 0) { if (elements.length === 0) {