Browse Source

feat: holding down CMD/CTRL will disable snap to grid when grid is active (#6983)

Co-authored-by: dwelle <[email protected]>
zsviczian 1 year ago
parent
commit
e3f4f567b8
4 changed files with 56 additions and 32 deletions
  1. 25 12
      src/components/App.tsx
  2. 20 11
      src/components/HintViewer.tsx
  3. 9 8
      src/element/linearElementEditor.ts
  4. 2 1
      src/locales/en.json

+ 25 - 12
src/components/App.tsx

@@ -3944,7 +3944,7 @@ class App extends React.Component<AppProps, AppState> {
         const [gridX, gridY] = getGridPoint(
         const [gridX, gridY] = getGridPoint(
           scenePointerX,
           scenePointerX,
           scenePointerY,
           scenePointerY,
-          this.state.gridSize,
+          event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
         );
         );
 
 
         const [lastCommittedX, lastCommittedY] =
         const [lastCommittedX, lastCommittedY] =
@@ -4761,7 +4761,11 @@ class App extends React.Component<AppProps, AppState> {
       origin,
       origin,
       withCmdOrCtrl: event[KEYS.CTRL_OR_CMD],
       withCmdOrCtrl: event[KEYS.CTRL_OR_CMD],
       originInGrid: tupleToCoors(
       originInGrid: tupleToCoors(
-        getGridPoint(origin.x, origin.y, this.state.gridSize),
+        getGridPoint(
+          origin.x,
+          origin.y,
+          event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
+        ),
       ),
       ),
       scrollbars: isOverScrollBars(
       scrollbars: isOverScrollBars(
         currentScrollBars,
         currentScrollBars,
@@ -5285,7 +5289,11 @@ class App extends React.Component<AppProps, AppState> {
     sceneY: number;
     sceneY: number;
     link: string;
     link: string;
   }) => {
   }) => {
-    const [gridX, gridY] = getGridPoint(sceneX, sceneY, this.state.gridSize);
+    const [gridX, gridY] = getGridPoint(
+      sceneX,
+      sceneY,
+      this.lastPointerDown?.[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
+    );
 
 
     const embedLink = getEmbedLink(link);
     const embedLink = getEmbedLink(link);
 
 
@@ -5331,7 +5339,11 @@ class App extends React.Component<AppProps, AppState> {
     sceneX: number;
     sceneX: number;
     sceneY: number;
     sceneY: number;
   }) => {
   }) => {
-    const [gridX, gridY] = getGridPoint(sceneX, sceneY, this.state.gridSize);
+    const [gridX, gridY] = getGridPoint(
+      sceneX,
+      sceneY,
+      this.lastPointerDown?.[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
+    );
 
 
     const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
     const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
       x: gridX,
       x: gridX,
@@ -5414,7 +5426,7 @@ class App extends React.Component<AppProps, AppState> {
       const [gridX, gridY] = getGridPoint(
       const [gridX, gridY] = getGridPoint(
         pointerDownState.origin.x,
         pointerDownState.origin.x,
         pointerDownState.origin.y,
         pointerDownState.origin.y,
-        this.state.gridSize,
+        event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
       );
       );
 
 
       const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
       const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
@@ -5507,7 +5519,7 @@ class App extends React.Component<AppProps, AppState> {
     const [gridX, gridY] = getGridPoint(
     const [gridX, gridY] = getGridPoint(
       pointerDownState.origin.x,
       pointerDownState.origin.x,
       pointerDownState.origin.y,
       pointerDownState.origin.y,
-      this.state.gridSize,
+      this.lastPointerDown?.[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
     );
     );
 
 
     const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
     const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
@@ -5565,7 +5577,7 @@ class App extends React.Component<AppProps, AppState> {
     const [gridX, gridY] = getGridPoint(
     const [gridX, gridY] = getGridPoint(
       pointerDownState.origin.x,
       pointerDownState.origin.x,
       pointerDownState.origin.y,
       pointerDownState.origin.y,
-      this.state.gridSize,
+      this.lastPointerDown?.[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
     );
     );
 
 
     const frame = newFrameElement({
     const frame = newFrameElement({
@@ -5648,7 +5660,7 @@ class App extends React.Component<AppProps, AppState> {
       const [gridX, gridY] = getGridPoint(
       const [gridX, gridY] = getGridPoint(
         pointerCoords.x,
         pointerCoords.x,
         pointerCoords.y,
         pointerCoords.y,
-        this.state.gridSize,
+        event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
       );
       );
 
 
       // for arrows/lines, don't start dragging until a given threshold
       // for arrows/lines, don't start dragging until a given threshold
@@ -5694,6 +5706,7 @@ class App extends React.Component<AppProps, AppState> {
             this.state.selectedLinearElement,
             this.state.selectedLinearElement,
             pointerCoords,
             pointerCoords,
             this.state,
             this.state,
+            !event[KEYS.CTRL_OR_CMD],
           );
           );
           if (!ret) {
           if (!ret) {
             return;
             return;
@@ -5819,7 +5832,7 @@ class App extends React.Component<AppProps, AppState> {
           const [dragX, dragY] = getGridPoint(
           const [dragX, dragY] = getGridPoint(
             pointerCoords.x - pointerDownState.drag.offset.x,
             pointerCoords.x - pointerDownState.drag.offset.x,
             pointerCoords.y - pointerDownState.drag.offset.y,
             pointerCoords.y - pointerDownState.drag.offset.y,
-            this.state.gridSize,
+            event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
           );
           );
 
 
           const [dragDistanceX, dragDistanceY] = [
           const [dragDistanceX, dragDistanceY] = [
@@ -5886,7 +5899,7 @@ class App extends React.Component<AppProps, AppState> {
                 const [originDragX, originDragY] = getGridPoint(
                 const [originDragX, originDragY] = getGridPoint(
                   pointerDownState.origin.x - pointerDownState.drag.offset.x,
                   pointerDownState.origin.x - pointerDownState.drag.offset.x,
                   pointerDownState.origin.y - pointerDownState.drag.offset.y,
                   pointerDownState.origin.y - pointerDownState.drag.offset.y,
-                  this.state.gridSize,
+                  event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
                 );
                 );
                 mutateElement(duplicatedElement, {
                 mutateElement(duplicatedElement, {
                   x: duplicatedElement.x + (originDragX - dragX),
                   x: duplicatedElement.x + (originDragX - dragX),
@@ -7679,7 +7692,7 @@ class App extends React.Component<AppProps, AppState> {
       const [gridX, gridY] = getGridPoint(
       const [gridX, gridY] = getGridPoint(
         pointerCoords.x,
         pointerCoords.x,
         pointerCoords.y,
         pointerCoords.y,
-        this.state.gridSize,
+        event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
       );
       );
 
 
       const image =
       const image =
@@ -7748,7 +7761,7 @@ class App extends React.Component<AppProps, AppState> {
     const [resizeX, resizeY] = getGridPoint(
     const [resizeX, resizeY] = getGridPoint(
       pointerCoords.x - pointerDownState.resize.offset.x,
       pointerCoords.x - pointerDownState.resize.offset.x,
       pointerCoords.y - pointerDownState.resize.offset.y,
       pointerCoords.y - pointerDownState.resize.offset.y,
-      this.state.gridSize,
+      event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize,
     );
     );
 
 
     const frameElementsOffsetsMap = new Map<
     const frameElementsOffsetsMap = new Map<

+ 20 - 11
src/components/HintViewer.tsx

@@ -83,27 +83,36 @@ const getHints = ({ appState, isMobile, device, app }: HintViewerProps) => {
   if (activeTool.type === "selection") {
   if (activeTool.type === "selection") {
     if (
     if (
       appState.draggingElement?.type === "selection" &&
       appState.draggingElement?.type === "selection" &&
+      !selectedElements.length &&
       !appState.editingElement &&
       !appState.editingElement &&
       !appState.editingLinearElement
       !appState.editingLinearElement
     ) {
     ) {
       return t("hints.deepBoxSelect");
       return t("hints.deepBoxSelect");
     }
     }
+
+    if (appState.gridSize && appState.draggingElement) {
+      return t("hints.disableSnapping");
+    }
+
     if (!selectedElements.length && !isMobile) {
     if (!selectedElements.length && !isMobile) {
       return t("hints.canvasPanning");
       return t("hints.canvasPanning");
     }
     }
-  }
 
 
-  if (selectedElements.length === 1) {
-    if (isLinearElement(selectedElements[0])) {
-      if (appState.editingLinearElement) {
-        return appState.editingLinearElement.selectedPointsIndices
-          ? t("hints.lineEditor_pointSelected")
-          : t("hints.lineEditor_nothingSelected");
+    if (selectedElements.length === 1) {
+      if (isLinearElement(selectedElements[0])) {
+        if (appState.editingLinearElement) {
+          return appState.editingLinearElement.selectedPointsIndices
+            ? t("hints.lineEditor_pointSelected")
+            : t("hints.lineEditor_nothingSelected");
+        }
+        return t("hints.lineEditor_info");
+      }
+      if (
+        !appState.draggingElement &&
+        isTextBindableContainer(selectedElements[0])
+      ) {
+        return t("hints.bindTextToElement");
       }
       }
-      return t("hints.lineEditor_info");
-    }
-    if (isTextBindableContainer(selectedElements[0])) {
-      return t("hints.bindTextToElement");
     }
     }
   }
   }
 
 

+ 9 - 8
src/element/linearElementEditor.ts

@@ -42,7 +42,7 @@ import {
 } from "./binding";
 } from "./binding";
 import { tupleToCoors } from "../utils";
 import { tupleToCoors } from "../utils";
 import { isBindingElement } from "./typeChecks";
 import { isBindingElement } from "./typeChecks";
-import { shouldRotateWithDiscreteAngle } from "../keys";
+import { KEYS, shouldRotateWithDiscreteAngle } from "../keys";
 import { getBoundTextElement, handleBindTextResize } from "./textElement";
 import { getBoundTextElement, handleBindTextResize } from "./textElement";
 import { DRAGGING_THRESHOLD } from "../constants";
 import { DRAGGING_THRESHOLD } from "../constants";
 import { Mutable } from "../utility-types";
 import { Mutable } from "../utility-types";
@@ -221,7 +221,7 @@ export class LinearElementEditor {
           element,
           element,
           referencePoint,
           referencePoint,
           [scenePointerX, scenePointerY],
           [scenePointerX, scenePointerY],
-          appState.gridSize,
+          event[KEYS.CTRL_OR_CMD] ? null : appState.gridSize,
         );
         );
 
 
         LinearElementEditor.movePoints(element, [
         LinearElementEditor.movePoints(element, [
@@ -238,7 +238,7 @@ export class LinearElementEditor {
           element,
           element,
           scenePointerX - linearElementEditor.pointerOffset.x,
           scenePointerX - linearElementEditor.pointerOffset.x,
           scenePointerY - linearElementEditor.pointerOffset.y,
           scenePointerY - linearElementEditor.pointerOffset.y,
-          appState.gridSize,
+          event[KEYS.CTRL_OR_CMD] ? null : appState.gridSize,
         );
         );
 
 
         const deltaX = newDraggingPointPosition[0] - draggingPoint[0];
         const deltaX = newDraggingPointPosition[0] - draggingPoint[0];
@@ -254,7 +254,7 @@ export class LinearElementEditor {
                     element,
                     element,
                     scenePointerX - linearElementEditor.pointerOffset.x,
                     scenePointerX - linearElementEditor.pointerOffset.x,
                     scenePointerY - linearElementEditor.pointerOffset.y,
                     scenePointerY - linearElementEditor.pointerOffset.y,
-                    appState.gridSize,
+                    event[KEYS.CTRL_OR_CMD] ? null : appState.gridSize,
                   )
                   )
                 : ([
                 : ([
                     element.points[pointIndex][0] + deltaX,
                     element.points[pointIndex][0] + deltaX,
@@ -647,7 +647,7 @@ export class LinearElementEditor {
               element,
               element,
               scenePointer.x,
               scenePointer.x,
               scenePointer.y,
               scenePointer.y,
-              appState.gridSize,
+              event[KEYS.CTRL_OR_CMD] ? null : appState.gridSize,
             ),
             ),
           ],
           ],
         });
         });
@@ -798,7 +798,7 @@ export class LinearElementEditor {
         element,
         element,
         lastCommittedPoint,
         lastCommittedPoint,
         [scenePointerX, scenePointerY],
         [scenePointerX, scenePointerY],
-        appState.gridSize,
+        event[KEYS.CTRL_OR_CMD] ? null : appState.gridSize,
       );
       );
 
 
       newPoint = [
       newPoint = [
@@ -810,7 +810,7 @@ export class LinearElementEditor {
         element,
         element,
         scenePointerX - appState.editingLinearElement.pointerOffset.x,
         scenePointerX - appState.editingLinearElement.pointerOffset.x,
         scenePointerY - appState.editingLinearElement.pointerOffset.y,
         scenePointerY - appState.editingLinearElement.pointerOffset.y,
-        appState.gridSize,
+        event[KEYS.CTRL_OR_CMD] ? null : appState.gridSize,
       );
       );
     }
     }
 
 
@@ -1176,6 +1176,7 @@ export class LinearElementEditor {
     linearElementEditor: LinearElementEditor,
     linearElementEditor: LinearElementEditor,
     pointerCoords: PointerCoords,
     pointerCoords: PointerCoords,
     appState: AppState,
     appState: AppState,
+    snapToGrid: boolean,
   ) {
   ) {
     const element = LinearElementEditor.getElement(
     const element = LinearElementEditor.getElement(
       linearElementEditor.elementId,
       linearElementEditor.elementId,
@@ -1196,7 +1197,7 @@ export class LinearElementEditor {
       element,
       element,
       pointerCoords.x,
       pointerCoords.x,
       pointerCoords.y,
       pointerCoords.y,
-      appState.gridSize,
+      snapToGrid ? appState.gridSize : null,
     );
     );
     const points = [
     const points = [
       ...element.points.slice(0, segmentMidpoint.index!),
       ...element.points.slice(0, segmentMidpoint.index!),

+ 2 - 1
src/locales/en.json

@@ -264,7 +264,8 @@
     "bindTextToElement": "Press enter to add text",
     "bindTextToElement": "Press enter to add text",
     "deepBoxSelect": "Hold CtrlOrCmd to deep select, and to prevent dragging",
     "deepBoxSelect": "Hold CtrlOrCmd to deep select, and to prevent dragging",
     "eraserRevert": "Hold Alt to revert the elements marked for deletion",
     "eraserRevert": "Hold Alt to revert the elements marked for deletion",
-    "firefox_clipboard_write": "This feature can likely be enabled by setting the \"dom.events.asyncClipboard.clipboardItem\" flag to \"true\". To change the browser flags in Firefox, visit the \"about:config\" page."
+    "firefox_clipboard_write": "This feature can likely be enabled by setting the \"dom.events.asyncClipboard.clipboardItem\" flag to \"true\". To change the browser flags in Firefox, visit the \"about:config\" page.",
+    "disableSnapping": "Hold CtrlOrCmd to disable snapping"
   },
   },
   "canvasError": {
   "canvasError": {
     "cannotShowPreview": "Cannot show preview",
     "cannotShowPreview": "Cannot show preview",