aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkControlPtHandles.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-09-28 18:10:26 -0400
committerbobzel <zzzman@gmail.com>2021-09-28 18:10:26 -0400
commit244e06ec9873888dcef3cd08322880d73848fe69 (patch)
tree3bc49ecabef65cc1ccb701d72a0f9816b65f7722 /src/client/views/InkControlPtHandles.tsx
parentbc654229325e8bbd30c0b3e464c7e66fa0fbc609 (diff)
renamed some ink files
Diffstat (limited to 'src/client/views/InkControlPtHandles.tsx')
-rw-r--r--src/client/views/InkControlPtHandles.tsx147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
new file mode 100644
index 000000000..eb0eebcdf
--- /dev/null
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -0,0 +1,147 @@
+import React = require("react");
+import { action, observable } from "mobx";
+import { observer } from "mobx-react";
+import { Doc } from "../../fields/Doc";
+import { ControlPoint, InkData, PointData } from "../../fields/InkField";
+import { listSpec } from "../../fields/Schema";
+import { Cast } from "../../fields/Types";
+import { setupMoveUpEvents } from "../../Utils";
+import { Transform } from "../util/Transform";
+import { UndoManager } from "../util/UndoManager";
+import { Colors } from "./global/globalEnums";
+import { InkStrokeProperties } from "./InkStrokeProperties";
+
+export interface InkControlProps {
+ inkDoc: Doc;
+ inkCtrlPoints: InkData;
+ screenCtrlPoints: InkData;
+ screenSpaceLineWidth: number;
+ ScreenToLocalTransform: () => Transform;
+ nearestScreenPt: () => PointData | undefined;
+}
+
+@observer
+export class InkControlPtHandles extends React.Component<InkControlProps> {
+
+ @observable private _overControl = -1;
+ @observable private _overAddPoint = -1;
+ /**
+ * Handles the movement of a selected control point when the user clicks and drags.
+ * @param controlIndex The index of the currently selected control point.
+ */
+ @action
+ onControlDown = (e: React.PointerEvent, controlIndex: number): void => {
+ if (InkStrokeProperties.Instance) {
+ InkStrokeProperties.Instance.moveControl(0, 0, 1);
+ const controlUndo = UndoManager.StartBatch("DocDecs set radius");
+ const screenScale = this.props.ScreenToLocalTransform().Scale;
+ const order = controlIndex % 4;
+ const handleIndexA = ((order === 3 ? controlIndex - 1 : controlIndex - 2) + this.props.inkCtrlPoints.length) % this.props.inkCtrlPoints.length;
+ const handleIndexB = (order === 3 ? controlIndex + 2 : controlIndex + 1) % this.props.inkCtrlPoints.length;
+ const brokenIndices = Cast(this.props.inkDoc.brokenInkIndices, listSpec("number"));
+ setupMoveUpEvents(this, e,
+ (e: PointerEvent, down: number[], delta: number[]) => {
+ InkStrokeProperties.Instance?.moveControl(-delta[0] * screenScale, -delta[1] * screenScale, controlIndex);
+ return false;
+ },
+ () => controlUndo?.end(),
+ action((e: PointerEvent, doubleTap: boolean | undefined) => {
+ const equivIndex = controlIndex === 0 ? this.props.inkCtrlPoints.length - 1 : controlIndex === this.props.inkCtrlPoints.length - 1 ? 0 : controlIndex;
+ if (doubleTap && brokenIndices?.includes(equivIndex)) {
+ InkStrokeProperties.Instance?.snapHandleTangent(equivIndex, handleIndexA, handleIndexB);
+ }
+ if (doubleTap && brokenIndices?.includes(controlIndex)) {
+ InkStrokeProperties.Instance?.snapHandleTangent(controlIndex, handleIndexA, handleIndexB);
+ }
+ }));
+ }
+ }
+ /**
+ * Updates whether a user has hovered over a particular control point or point that could be added
+ * on click.
+ */
+ @action onEnterControl = (i: number) => { this._overControl = i; };
+ @action onLeaveControl = () => { this._overControl = -1; };
+ @action onEnterAddPoint = (i: number) => { this._overAddPoint = i; };
+ @action onLeaveAddPoint = () => { this._overAddPoint = -1; };
+
+ /**
+ * Deletes the currently selected point.
+ */
+ @action
+ onDelete = (e: KeyboardEvent) => {
+ if (["-", "Backspace", "Delete"].includes(e.key)) {
+ if (InkStrokeProperties.Instance?.deletePoints()) e.stopPropagation();
+ }
+ }
+
+ /**
+ * Changes the current selected control point.
+ */
+ @action
+ changeCurrPoint = (i: number) => {
+ if (InkStrokeProperties.Instance) {
+ InkStrokeProperties.Instance._currentPoint = i;
+ document.addEventListener("keydown", this.onDelete, true);
+ }
+ }
+
+ render() {
+ const formatInstance = InkStrokeProperties.Instance;
+ if (!formatInstance) return (null);
+
+ // Accessing the current ink's data and extracting all control points.
+ const scrData = this.props.screenCtrlPoints;
+ const sreenCtrlPoints: ControlPoint[] = [];
+ for (let i = 0; i <= scrData.length - 4; i += 4) {
+ sreenCtrlPoints.push({ ...scrData[i], I: i });
+ sreenCtrlPoints.push({ ...scrData[i + 3], I: i + 3 });
+ }
+
+ const inkData = this.props.inkCtrlPoints;
+ const inkCtrlPts: ControlPoint[] = [];
+ for (let i = 0; i <= inkData.length - 4; i += 4) {
+ inkCtrlPts.push({ ...inkData[i], I: i });
+ inkCtrlPts.push({ ...inkData[i + 3], I: i + 3 });
+ }
+
+ const screenSpaceLineWidth = this.props.screenSpaceLineWidth;
+ const rectHdlSize = (i: number) => this._overControl === i ? screenSpaceLineWidth * 6 : screenSpaceLineWidth * 4;
+
+ const nearestScreenPt = this.props.nearestScreenPt();
+ return (<svg>
+ {!nearestScreenPt ? (null) :
+ <circle key={"npt"}
+ cx={nearestScreenPt.X}
+ cy={nearestScreenPt.Y}
+ r={screenSpaceLineWidth * 4}
+ fill={"#00007777"}
+ stroke={"#00007777"}
+ strokeWidth={0}
+ pointerEvents="none"
+ cursor="all-scroll"
+ />
+ }
+ {sreenCtrlPoints.map((control, i) =>
+ <rect key={i}
+ x={control.X - rectHdlSize(i) / 2}
+ y={control.Y - rectHdlSize(i) / 2}
+ height={rectHdlSize(i)}
+ width={rectHdlSize(i)}
+ strokeWidth={screenSpaceLineWidth / 2}
+ stroke={Colors.MEDIUM_BLUE}
+ fill={formatInstance?._currentPoint === control.I ? Colors.MEDIUM_BLUE : Colors.WHITE}
+ onPointerDown={e => {
+ this.changeCurrPoint(control.I);
+ this.onControlDown(e, control.I);
+ }}
+ onMouseEnter={e => this.onEnterControl(i)}
+ onMouseLeave={this.onLeaveControl}
+ pointerEvents="all"
+ cursor="default"
+ />
+ )}
+ </svg>
+ );
+ }
+} \ No newline at end of file