diff options
| author | bobzel <zzzman@gmail.com> | 2021-09-28 18:10:26 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2021-09-28 18:10:26 -0400 |
| commit | 244e06ec9873888dcef3cd08322880d73848fe69 (patch) | |
| tree | 3bc49ecabef65cc1ccb701d72a0f9816b65f7722 /src/client/views/InkControlPtHandles.tsx | |
| parent | bc654229325e8bbd30c0b3e464c7e66fa0fbc609 (diff) | |
renamed some ink files
Diffstat (limited to 'src/client/views/InkControlPtHandles.tsx')
| -rw-r--r-- | src/client/views/InkControlPtHandles.tsx | 147 |
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 |
