From a72a143c84ec7815522ec38a1a4bc8d77959ac4e Mon Sep 17 00:00:00 2001 From: Jilles Soeters Date: Mon, 20 Jan 2020 15:52:19 -0800 Subject: [PATCH] Introduce Shapelock (#480) * Introduce shape lock * Format code with prettier * Do not reset elementLocked on selection change * Don't set isSelected to true if element is locked * Don't reset the cursor * Move reset cursor call to better spot * Run prettier + lint --- src/appState.ts | 1 + src/components/LockIcon.tsx | 59 ++++++++++++++++++++++++++++++++++++ src/components/ToolIcon.scss | 3 +- src/index.tsx | 31 ++++++++++++++----- src/types.ts | 1 + 5 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 src/components/LockIcon.tsx diff --git a/src/appState.ts b/src/appState.ts index 36eb4a47..7ad0e7ad 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -9,6 +9,7 @@ export function getDefaultAppState(): AppState { resizingElement: null, editingElement: null, elementType: "selection", + elementLocked: false, exportBackground: true, currentItemStrokeColor: "#000000", currentItemBackgroundColor: "transparent", diff --git a/src/components/LockIcon.tsx b/src/components/LockIcon.tsx new file mode 100644 index 00000000..7a3977c6 --- /dev/null +++ b/src/components/LockIcon.tsx @@ -0,0 +1,59 @@ +import "./ToolIcon.scss"; + +import React from "react"; + +type LockIconSize = "s" | "m"; + +type LockIconProps = { + title?: string; + name?: string; + id?: string; + checked: boolean; + onChange?(): void; + size?: LockIconSize; +}; + +const DEFAULT_SIZE: LockIconSize = "m"; + +const ICONS = { + CHECKED: ( + + + + ), + UNCHECKED: ( + + + + ) +}; + +export function LockIcon(props: LockIconProps) { + const sizeCn = `ToolIcon_size_${props.size || DEFAULT_SIZE}`; + + return ( + + ); +} diff --git a/src/components/ToolIcon.scss b/src/components/ToolIcon.scss index bd25d91d..3fc72249 100644 --- a/src/components/ToolIcon.scss +++ b/src/components/ToolIcon.scss @@ -43,7 +43,8 @@ } } -.ToolIcon_type_radio { +.ToolIcon_type_radio, +.ToolIcon_type_checkbox { position: absolute; opacity: 0; diff --git a/src/index.tsx b/src/index.tsx index aafd7ed6..3431cb31 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -77,6 +77,7 @@ import { Island } from "./components/Island"; import Stack from "./components/Stack"; import { FixedSideContainer } from "./components/FixedSideContainer"; import { ToolIcon } from "./components/ToolIcon"; +import { LockIcon } from "./components/LockIcon"; import { ExportDialog } from "./components/ExportDialog"; import { withTranslation } from "react-i18next"; import "./i18n"; @@ -451,6 +452,16 @@ export class App extends React.Component { ); } + private renderShapeLock() { + const { elementLocked } = this.state; + return ( + this.setState({ elementLocked: !elementLocked })} + /> + ); + } + private renderShapesSwitcher() { const { t } = this.props; @@ -478,6 +489,7 @@ export class App extends React.Component { > ); })} + {this.renderShapeLock()} ); } @@ -1043,7 +1055,8 @@ export class App extends React.Component { const { draggingElement, resizingElement, - elementType + elementType, + elementLocked } = this.state; lastMouseUp = null; @@ -1068,8 +1081,6 @@ export class App extends React.Component { elements = elements.filter(el => el.id !== resizingElement.id); } - resetCursor(); - // 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 @@ -1100,14 +1111,18 @@ export class App extends React.Component { if (elementType === "selection") { elements = elements.slice(0, -1); - } else { + } else if (!elementLocked) { draggingElement.isSelected = true; } - this.setState({ - draggingElement: null, - elementType: "selection" - }); + if (!elementLocked) { + resetCursor(); + + this.setState({ + draggingElement: null, + elementType: "selection" + }); + } history.resumeRecording(); this.forceUpdate(); diff --git a/src/types.ts b/src/types.ts index e9e3558c..3634dacd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,6 +7,7 @@ export type AppState = { // (e.g. text element when typing into the input) editingElement: ExcalidrawElement | null; elementType: string; + elementLocked: boolean; exportBackground: boolean; currentItemStrokeColor: string; currentItemBackgroundColor: string;