This commit is contained in:
Panayiotis Lipiridis 2020-12-24 17:51:26 +02:00
parent 40cd4caeec
commit 1d7c5705b2
6 changed files with 174 additions and 266 deletions

View File

@ -18,6 +18,7 @@ import { getNewZoom } from "../scene/zoom";
import { centerScrollOn } from "../scene/scroll";
import { EVENT_ACTION, EVENT_CHANGE, trackEvent } from "../analytics";
import colors from "../colors";
import { GRID_SIZE } from "../constants";
export const actionChangeViewBackgroundColor = register({
name: "changeViewBackgroundColor",
@ -64,7 +65,7 @@ export const actionClearCanvas = register({
elementLocked: appState.elementLocked,
exportBackground: appState.exportBackground,
exportEmbedScene: appState.exportEmbedScene,
gridSize: appState.gridSize,
gridSize: appState.gridSize || GRID_SIZE,
shouldAddWatermark: appState.shouldAddWatermark,
showStats: appState.showStats,
},

View File

@ -1,181 +1,167 @@
import { Point, simplify } from "points-on-curve";
import React from "react";
import rough from "roughjs/bin/rough";
import { RoughCanvas } from "roughjs/bin/canvas";
import { simplify, Point } from "points-on-curve";
import {
newElement,
newTextElement,
duplicateElement,
isInvisiblySmallElement,
isTextElement,
textWysiwyg,
getCommonBounds,
getCursorForResizingElement,
getPerfectElementSize,
getNormalizedDimensions,
newLinearElement,
transformElements,
getElementWithTransformHandleType,
getResizeOffsetXY,
getResizeArrowDirection,
getTransformHandleTypeFromCoords,
isNonDeletedElement,
updateTextElement,
dragSelectedElements,
getDragOffsetXY,
dragNewElement,
hitTest,
isHittingElementBoundingBoxWithoutHittingElement,
getNonDeletedElements,
} from "../element";
import {
getElementsWithinSelection,
isOverScrollBars,
getElementsAtPosition,
getElementContainingPosition,
getNormalizedZoom,
getSelectedElements,
isSomeElementSelected,
calculateScrollCenter,
} from "../scene";
import { loadFromBlob, exportCanvas } from "../data";
import { renderScene } from "../renderer";
import {
AppState,
GestureEvent,
Gesture,
ExcalidrawProps,
SceneData,
} from "../types";
import {
ExcalidrawElement,
ExcalidrawTextElement,
NonDeleted,
ExcalidrawGenericElement,
ExcalidrawLinearElement,
ExcalidrawBindableElement,
} from "../element/types";
import { distance2d, isPathALoop, getGridPoint } from "../math";
import {
isWritableElement,
isInputLike,
isToolIcon,
debounce,
distance,
resetCursor,
viewportCoordsToSceneCoords,
sceneCoordsToViewportCoords,
setCursorForShape,
tupleToCoors,
ResolvablePromise,
resolvablePromise,
withBatchedUpdates,
} from "../utils";
import {
KEYS,
isArrowKey,
getResizeCenterPointKey,
getResizeWithSidesSameLengthKey,
getRotateWithDiscreteAngleKey,
CODES,
} from "../keys";
import { findShapeByKey } from "../shapes";
import { createHistory, SceneHistory } from "../history";
import ContextMenu from "./ContextMenu";
import { ActionManager } from "../actions/manager";
import rough from "roughjs/bin/rough";
import "../actions";
import { actionDeleteSelected, actionFinalize } from "../actions";
import { createRedoAction, createUndoAction } from "../actions/actionHistory";
import { ActionManager } from "../actions/manager";
import { actions } from "../actions/register";
import { ActionResult } from "../actions/types";
import { getDefaultAppState } from "../appState";
import { t, getLanguage } from "../i18n";
import {
copyToClipboard,
parseClipboard,
probablySupportsClipboardBlob,
probablySupportsClipboardWriteText,
} from "../clipboard";
import { normalizeScroll } from "../scene";
import { getCenter, getDistance } from "../gesture";
import { createUndoAction, createRedoAction } from "../actions/actionHistory";
import {
CURSOR_TYPE,
ELEMENT_SHIFT_TRANSLATE_AMOUNT,
ELEMENT_TRANSLATE_AMOUNT,
POINTER_BUTTON,
DRAGGING_THRESHOLD,
TEXT_TO_CENTER_SNAP_THRESHOLD,
LINE_CONFIRM_THRESHOLD,
EVENT,
ENV,
CANVAS_ONLY_ACTIONS,
DEFAULT_VERTICAL_ALIGN,
GRID_SIZE,
MIME_TYPES,
TAP_TWICE_TIMEOUT,
TOUCH_CTX_MENU_TIMEOUT,
APP_NAME,
} from "../constants";
import LayerUI from "./LayerUI";
import { ScrollBars, SceneState } from "../scene/types";
import { mutateElement } from "../element/mutateElement";
import { invalidateShapeForElement } from "../renderer/renderElement";
import {
isLinearElement,
isLinearElementType,
isBindingElement,
isBindingElementType,
} from "../element/typeChecks";
import { actionFinalize, actionDeleteSelected } from "../actions";
import { LinearElementEditor } from "../element/linearElementEditor";
import {
getSelectedGroupIds,
isSelectedViaGroup,
selectGroupsForSelectedElements,
isElementInGroup,
getSelectedGroupIdForElement,
getElementsInGroup,
editGroupForSelectedElement,
} from "../groups";
import { Library } from "../data/library";
import Scene from "../scene/Scene";
import {
getHoveredElementForBinding,
maybeBindLinearElement,
getEligibleElementsForBinding,
bindOrUnbindSelectedElements,
unbindLinearElements,
fixBindingsAfterDuplication,
fixBindingsAfterDeletion,
isLinearElementSimpleAndAlreadyBound,
isBindingEnabled,
updateBoundElements,
shouldEnableBindingForPointerEvent,
} from "../element/binding";
import { MaybeTransformHandleType } from "../element/transformHandles";
import { deepCopyElement } from "../element/newElement";
import { renderSpreadsheet } from "../charts";
import { isValidLibrary } from "../data/json";
import { getNewZoom } from "../scene/zoom";
import { restore } from "../data/restore";
import {
EVENT_DIALOG,
EVENT_LIBRARY,
EVENT_SHAPE,
trackEvent,
} from "../analytics";
import { getDefaultAppState } from "../appState";
import { renderSpreadsheet } from "../charts";
import {
copyToClipboard,
parseClipboard,
probablySupportsClipboardBlob,
probablySupportsClipboardWriteText,
} from "../clipboard";
import {
APP_NAME,
CANVAS_ONLY_ACTIONS,
CURSOR_TYPE,
DEFAULT_VERTICAL_ALIGN,
DRAGGING_THRESHOLD,
ELEMENT_SHIFT_TRANSLATE_AMOUNT,
ELEMENT_TRANSLATE_AMOUNT,
ENV,
EVENT,
LINE_CONFIRM_THRESHOLD,
MIME_TYPES,
POINTER_BUTTON,
TAP_TWICE_TIMEOUT,
TEXT_TO_CENTER_SNAP_THRESHOLD,
TOUCH_CTX_MENU_TIMEOUT,
} from "../constants";
import { exportCanvas, loadFromBlob } from "../data";
import { isValidLibrary } from "../data/json";
import { Library } from "../data/library";
import { restore } from "../data/restore";
import {
dragNewElement,
dragSelectedElements,
duplicateElement,
getCommonBounds,
getCursorForResizingElement,
getDragOffsetXY,
getElementWithTransformHandleType,
getNonDeletedElements,
getNormalizedDimensions,
getPerfectElementSize,
getResizeArrowDirection,
getResizeOffsetXY,
getTransformHandleTypeFromCoords,
hitTest,
isHittingElementBoundingBoxWithoutHittingElement,
isInvisiblySmallElement,
isNonDeletedElement,
isTextElement,
newElement,
newLinearElement,
newTextElement,
textWysiwyg,
transformElements,
updateTextElement,
} from "../element";
import {
bindOrUnbindSelectedElements,
fixBindingsAfterDeletion,
fixBindingsAfterDuplication,
getEligibleElementsForBinding,
getHoveredElementForBinding,
isBindingEnabled,
isLinearElementSimpleAndAlreadyBound,
maybeBindLinearElement,
shouldEnableBindingForPointerEvent,
unbindLinearElements,
updateBoundElements,
} from "../element/binding";
import { LinearElementEditor } from "../element/linearElementEditor";
import { mutateElement } from "../element/mutateElement";
import { deepCopyElement } from "../element/newElement";
import { MaybeTransformHandleType } from "../element/transformHandles";
import {
isBindingElement,
isBindingElementType,
isLinearElement,
isLinearElementType,
} from "../element/typeChecks";
import {
ExcalidrawBindableElement,
ExcalidrawElement,
ExcalidrawGenericElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
NonDeleted,
} from "../element/types";
import { getCenter, getDistance } from "../gesture";
import {
editGroupForSelectedElement,
getElementsInGroup,
getSelectedGroupIdForElement,
getSelectedGroupIds,
isElementInGroup,
isSelectedViaGroup,
selectGroupsForSelectedElements,
} from "../groups";
import { createHistory, SceneHistory } from "../history";
import { getLanguage, t } from "../i18n";
import {
CODES,
getResizeCenterPointKey,
getResizeWithSidesSameLengthKey,
getRotateWithDiscreteAngleKey,
isArrowKey,
KEYS,
} from "../keys";
import { distance2d, getGridPoint, isPathALoop } from "../math";
import { renderScene } from "../renderer";
import { invalidateShapeForElement } from "../renderer/renderElement";
import {
calculateScrollCenter,
getElementContainingPosition,
getElementsAtPosition,
getElementsWithinSelection,
getNormalizedZoom,
getSelectedElements,
isOverScrollBars,
isSomeElementSelected,
normalizeScroll,
} from "../scene";
import Scene from "../scene/Scene";
import { SceneState, ScrollBars } from "../scene/types";
import { getNewZoom } from "../scene/zoom";
import { findShapeByKey } from "../shapes";
import {
AppState,
ExcalidrawProps,
Gesture,
GestureEvent,
SceneData,
} from "../types";
import {
debounce,
distance,
isInputLike,
isToolIcon,
isWritableElement,
resetCursor,
ResolvablePromise,
resolvablePromise,
sceneCoordsToViewportCoords,
setCursorForShape,
tupleToCoors,
viewportCoordsToSceneCoords,
withBatchedUpdates,
} from "../utils";
import ContextMenu from "./ContextMenu";
import LayerUI from "./LayerUI";
import { Stats } from "./Stats";
const { history } = createHistory();
@ -3662,7 +3648,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
CANVAS_ONLY_ACTIONS.includes(action.name),
),
{
checked: this.state.gridSize !== null,
checked: this.state.showGrid,
shortcutName: "gridMode",
label: t("labels.gridMode"),
action: this.toggleGridMode,

View File

@ -1,68 +0,0 @@
import React, { CSSProperties, useEffect, useState } from "react";
import classes from "./SlidableInput.module.css";
import { throttle } from "./utils/throttle";
interface SlidableInputProps {
value: number;
prefix?: string;
suffix?: string;
minValue?: number;
maxValue?: number;
style?: CSSProperties;
onChange?: (value: number) => void;
}
export const SlidableInput: React.FC<SlidableInputProps> = ({
value,
style,
prefix,
suffix,
onChange,
minValue,
maxValue,
}) => {
const [isLocked, setIsLocked] = useState<boolean>(true);
const previousX = React.useRef(0);
useEffect(() => {
const onMouseMoveHandler = throttle((event: MouseEvent) => {
if (isLocked) return;
const nextX = event.screenX;
if (nextX === previousX.current) return;
const nextValue = value + (nextX > previousX.current ? 1 : -1);
onChange &&
nextValue <= (maxValue || Infinity) &&
nextValue >= (typeof minValue === "number" ? minValue : -Infinity) &&
onChange(nextValue);
previousX.current = nextX;
}, 250) as EventListenerOrEventListenerObject;
window.addEventListener("mousemove", onMouseMoveHandler);
return () => {
window.removeEventListener("mousemove", onMouseMoveHandler);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLocked, value]);
const onMouseDown = () => setIsLocked(false);
useEffect(() => {
const onMouseUp = () => setIsLocked(true);
window.addEventListener("mouseup", onMouseUp);
return () => {
window.removeEventListener("mouseup", onMouseUp);
};
}, []);
return (
<span className={classes.input} style={style} onMouseDown={onMouseDown}>
{prefix}
{value}
{suffix}
</span>
);
};

View File

@ -12,7 +12,6 @@ import { AppState } from "../types";
import { debounce, nFormatter } from "../utils";
import { close } from "./icons";
import { Island } from "./Island";
import { SlidableInput } from "./SlidableInput";
import "./Stats.scss";
type StorageSizes = { scene: number; total: number };
@ -158,19 +157,23 @@ export const Stats = (props: {
</td>
</tr>
)}
<tr>
<th colSpan={2}>{"Misc"}</th>
</tr>
<tr>
<td>{"Grid size"}</td>
<td>
<SlidableInput
value={props.appState.gridSize || 8}
minValue={8}
/>
</td>
</tr>
{props.appState.showGrid && (
<>
<tr>
<th colSpan={2}>{"Misc"}</th>
</tr>
<tr
onClick={() => {
// TODO: better way to update the gridSize and re-render the scene
props.appState.gridSize =
((props.appState.gridSize - 5) % 50) + 10;
}}
>
<td>{"Grid size"}</td>
<td>{props.appState.gridSize}</td>
</tr>
</>
)}
</tbody>
</table>
</Island>

View File

@ -1,14 +0,0 @@
export const throttle = (func: Function, limit: number): Function => {
let inThrottle: boolean;
return function (this: any): any {
const args = arguments;
const context = this;
if (!inThrottle) {
inThrottle = true;
func.apply(context, args);
setTimeout(() => (inThrottle = false), limit);
}
};
};

View File

@ -233,7 +233,7 @@ export const renderScene = (
context.scale(sceneState.zoom.value, sceneState.zoom.value);
// Grid
if (renderGrid && appState.gridSize) {
if (renderGrid && appState.showGrid) {
strokeGrid(
context,
appState.gridSize,