From c253c0b635d734d96e78cc7c8f3be466bba3f089 Mon Sep 17 00:00:00 2001 From: Timur Khazamov Date: Sat, 11 Jan 2020 02:45:58 +0500 Subject: [PATCH] Command clicking should "xor" selection (#300) * Command clicking should "xor" selection * Only shift key should play a role * Get rid of `isDraggingElements` * Renamed someElementIsDragged to draggingOccured --- src/index.tsx | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 0c61158b..53b48cd4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -20,7 +20,6 @@ import { deleteSelectedElements, setSelection, isOverScrollBars, - someElementIsSelected, restoreFromLocalStorage, saveToLocalStorage, getElementAtPosition, @@ -542,8 +541,10 @@ export class App extends React.Component<{}, AppState> { ); type ResizeTestType = ReturnType; let resizeHandle: ResizeTestType = false; - let isDraggingElements = false; let isResizingElements = false; + let draggingOccured = false; + let hitElement: ExcalidrawElement | null = null; + let elementIsAddedToSelection = false; if (this.state.elementType === "selection") { const resizeElement = getElementWithResizeHandler( elements, @@ -569,7 +570,7 @@ export class App extends React.Component<{}, AppState> { if (!selected && !e.shiftKey) { elements = clearSelection(elements); } - const hitElement = getElementAtPosition(elements, x, y); + hitElement = getElementAtPosition(elements, x, y); // If we click on something if (hitElement) { @@ -577,7 +578,10 @@ export class App extends React.Component<{}, AppState> { // if shift is not clicked, this will always return true // otherwise, it will trigger selection based on current // state of the box - hitElement.isSelected = true; + if (!hitElement.isSelected) { + hitElement.isSelected = true; + elementIsAddedToSelection = true; + } // No matter what, we select it // We duplicate the selected element if alt is pressed on Mouse down @@ -596,13 +600,9 @@ export class App extends React.Component<{}, AppState> { ]; } } - - isDraggingElements = someElementIsSelected(elements); - - if (isDraggingElements) { - document.documentElement.style.cursor = "move"; - } } + } else { + elements = clearSelection(elements); } if (isTextElement(element)) { @@ -754,7 +754,10 @@ export class App extends React.Component<{}, AppState> { } } - if (isDraggingElements) { + if (hitElement?.isSelected) { + // Marking that click was used for dragging to check + // if elements should be deselected on mouseup + draggingOccured = true; const selectedElements = elements.filter(el => el.isSelected); if (selectedElements.length) { const { x, y } = viewportCoordsToSceneCoords(e, this.state); @@ -809,17 +812,35 @@ export class App extends React.Component<{}, AppState> { resetCursor(); - // if no element is clicked, clear the selection and redraw + // If click occured on already selected element + // it is needed to remove selection from other elements + // or if SHIFT or META key pressed remove selection + // from hitted element + // + // If click occured and elements were dragged or some element + // was added to selection (on mousedown phase) we need to keep + // selection unchanged + if ( + hitElement && + !draggingOccured && + !elementIsAddedToSelection + ) { + if (e.shiftKey) { + hitElement.isSelected = false; + } else { + elements = clearSelection(elements); + hitElement.isSelected = true; + } + } + if (draggingElement === null) { + // if no element is clicked, clear the selection and redraw elements = clearSelection(elements); this.forceUpdate(); return; } if (elementType === "selection") { - if (isDraggingElements) { - isDraggingElements = false; - } elements = elements.slice(0, -1); } else { draggingElement.isSelected = true;