aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkingStroke.tsx
diff options
context:
space:
mode:
authorvkalev <vjk1883@gmail.com>2021-07-06 12:45:37 -0500
committervkalev <vjk1883@gmail.com>2021-07-06 12:45:37 -0500
commita0207bf861908da9235a1752a723e69ecdbba734 (patch)
tree1ee49e73d1204a4379be7da52d1bb6275a637646 /src/client/views/InkingStroke.tsx
parent89c8891e9def96a871d36ab7772e453b8d8c21c1 (diff)
refactoring
Diffstat (limited to 'src/client/views/InkingStroke.tsx')
-rw-r--r--src/client/views/InkingStroke.tsx271
1 files changed, 0 insertions, 271 deletions
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
deleted file mode 100644
index b2ef76882..000000000
--- a/src/client/views/InkingStroke.tsx
+++ /dev/null
@@ -1,271 +0,0 @@
-import { action, observable } from "mobx";
-import { observer } from "mobx-react";
-import { Doc } from "../../fields/Doc";
-import { documentSchema } from "../../fields/documentSchemas";
-import { InkData, InkField, InkTool, ControlPoint, HandlePoint, HandleLine } from "../../fields/InkField";
-import { makeInterface } from "../../fields/Schema";
-import { Cast, StrCast } from "../../fields/Types";
-import { TraceMobx } from "../../fields/util";
-import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../Utils";
-import { CognitiveServices } from "../cognitive_services/CognitiveServices";
-import { InteractionUtils } from "../util/InteractionUtils";
-import { Scripting } from "../util/Scripting";
-import { UndoManager } from "../util/UndoManager";
-import { ContextMenu } from "./ContextMenu";
-import { ViewBoxBaseComponent } from "./DocComponent";
-import "./InkingStroke.scss";
-import { FieldView, FieldViewProps } from "./nodes/FieldView";
-import React = require("react");
-import { InkStrokeProperties } from "./InkStrokeProperties";
-import { CurrentUserUtils } from "../util/CurrentUserUtils";
-import { InkControl } from "./InkControl";
-
-type InkDocument = makeInterface<[typeof documentSchema]>;
-const InkDocument = makeInterface(documentSchema);
-
-@observer
-export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocument>(InkDocument) {
- private _controlUndo?: UndoManager.Batch;
- @observable private _overAddPoint = -1;
-
- static readonly MaskDim = 50000;
-
- public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); }
-
- analyzeStrokes = () => {
- const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
- CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]);
- }
-
- @action
- onPointerEnter = (i: number) => {
- this._overAddPoint = i;
- }
-
- @action
- onPointerLeave = () => {
- this._overAddPoint = -1;
- }
-
-
- @action
- public static toggleMask = (inkDoc: Doc) => {
- inkDoc.isInkMask = !inkDoc.isInkMask;
- inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined;
- inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined;
- inkDoc.color = "#9b9b9bff";
- inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined;
- };
-
- /**
- * Handles the movement of a selected control point when the user clicks and drags.
- * @param controlNum The index of the currently selected control point.
- */
- @action
- onControlDown = (e: React.PointerEvent, controlNum: number): void => {
- if (InkStrokeProperties.Instance) {
- InkStrokeProperties.Instance.moveControl(0, 0, 1);
- const controlUndo = UndoManager.StartBatch("DocDecs set radius");
- const screenScale = this.props.ScreenToLocalTransform().Scale;
- setupMoveUpEvents(this, e,
- (e: PointerEvent, down: number[], delta: number[]) => {
- InkStrokeProperties.Instance?.moveControl(-delta[0] * screenScale, -delta[1] * screenScale, controlNum);
- return false;
- },
- () => controlUndo?.end(), emptyFunction);
- }
- }
-
- /**
- * Handles the movement of a selected handle point when the user clicks and drags.
- * @param controlNum The index of the currently selected handle point.
- */
- onHandleDown = (e: React.PointerEvent, handleNum: number): void => {
- if (InkStrokeProperties.Instance) {
- InkStrokeProperties.Instance.moveControl(0, 0, 1);
- const controlUndo = UndoManager.StartBatch("DocDecs set radius");
- const screenScale = this.props.ScreenToLocalTransform().Scale;
- setupMoveUpEvents(this, e,
- (e: PointerEvent, down: number[], delta: number[]) => {
- InkStrokeProperties.Instance?.moveHandle(-delta[0] * screenScale, -delta[1] * screenScale, handleNum);
- return false;
- },
- () => controlUndo?.end(), emptyFunction);
- }
- }
-
- /**
- * Handles the movement of the entire ink object when the user clicks and drags.
- * @param e React Pointer Event.
- */
- onPointerDown = (e: React.PointerEvent) => {
- if (this.props.isSelected(true)) {
- setupMoveUpEvents(this, e, returnFalse, emptyFunction, action((e: PointerEvent, doubleTap: boolean | undefined) =>
- doubleTap && InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlBtn = true)));
- }
- }
-
- render() {
- TraceMobx();
- const formatInstance = InkStrokeProperties.Instance;
- if (!formatInstance) return (null);
- const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
- const strokeWidth = Number(this.layoutDoc.strokeWidth);
- const xs = data.map(p => p.X);
- const ys = data.map(p => p.Y);
- const lineTop = Math.min(...ys);
- const lineBot = Math.max(...ys);
- const lineLft = Math.min(...xs);
- const lineRgt = Math.max(...xs);
- const left = lineLft - strokeWidth / 2;
- const top = lineTop - strokeWidth / 2;
- const right = lineRgt + strokeWidth / 2;
- const bottom = lineBot + strokeWidth / 2;
- const width = Math.max(1, right - left);
- const height = Math.max(1, bottom - top);
- const scaleX = width === strokeWidth ? 1 : (this.props.PanelWidth() - strokeWidth) / (width - strokeWidth);
- const scaleY = height === strokeWidth ? 1 : (this.props.PanelHeight() - strokeWidth) / (height - strokeWidth);
- const strokeColor = StrCast(this.layoutDoc.color, "");
- const dotsize = Math.max(width * scaleX, height * scaleY) / 40;
-
- // Visually renders the polygonal line made by the user.
- const points = InteractionUtils.CreatePolyline(data, left, top, strokeColor, strokeWidth, strokeWidth,
- StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"),
- StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
- StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5 && lineBot - lineTop > 1 && lineRgt - lineLft > 1, false);
-
- const selectedLine = InteractionUtils.CreatePolyline(data, lineLft - strokeWidth * 3, lineTop - strokeWidth * 3, "#1F85DE", strokeWidth / 6, strokeWidth / 6,
- StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"),
- StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
- StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5 && lineBot - lineTop > 1 && lineRgt - lineLft > 1, false);
-
- // Invisible polygonal line that enables the ink to be selected by the user.
- const hpoints = InteractionUtils.CreatePolyline(data, left, top,
- this.props.isSelected() && strokeWidth > 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15),
- StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"),
- "none", "none", undefined, scaleX, scaleY, "", this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted", false, true);
-
- const apoints = InteractionUtils.CreatePoints(data, left, top, strokeColor, strokeWidth, strokeWidth,
- StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"),
- StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
- StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false);
-
- const controlPoints: ControlPoint[] = [];
- const handlePoints: HandlePoint[] = [];
- const handleLine: HandleLine[] = [];
- // check the purpose of this conditional
- if (data.length >= 4) {
-
- // create separate functions for these
- for (var i = 0; i <= data.length - 4; i += 4) {
- controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
- controlPoints.push({ X: data[i + 3].X, Y: data[i + 3].Y, I: i + 3 });
- handlePoints.push({ X: data[i + 1].X, Y: data[i + 1].Y, I: i + 1, dot1: i, dot2: i === 0 ? i : i - 1 });
- handlePoints.push({ X: data[i + 2].X, Y: data[i + 2].Y, I: i + 2, dot1: i + 3, dot2: i === data.length ? i + 3 : i + 4 });
- }
-
- // first (single) handle line
- handleLine.push({ X1: data[0].X, Y1: data[0].Y, X2: data[1].X, Y2: data[1].Y, dot1: 0, dot2: 0 });
- for (var i = 2; i < data.length - 4; i += 4) {
-
- handleLine.push({ X1: data[i].X, Y1: data[i].Y, X2: data[i + 3].X, Y2: data[i + 3].Y, dot1: i + 1, dot2: i + 2 });
-
- }
- // last (single) handle line
- handleLine.push({ X1: data[data.length - 2].X, Y1: data[data.length - 2].Y, X2: data[data.length - 1].X, Y2: data[data.length - 1].Y, dot1: data.length - 1, dot2: data.length - 1 });
-
- for (var i = 0; i <= data.length - 4; i += 4) {
- handlePoints.push({ X: data[i + 1].X, Y: data[i + 1].Y, I: i + 1, dot1: i, dot2: i === 0 ? i : i - 1 });
- handlePoints.push({ X: data[i + 2].X, Y: data[i + 2].Y, I: i + 2, dot1: i + 3, dot2: i === data.length ? i + 3 : i + 4 });
- }
- }
-
- // Additional points (controls) added by the user via click when editing the ink's format.
- const addpoints = apoints.map((pts, i) =>
- <svg height="10" width="10" key={`add${i}`}>
- <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth / 2} stroke={this._overAddPoint === i ? "#1F85DE" : "invisible"} strokeWidth={dotsize / 4} fill={this._overAddPoint === i ? "#1F85DE" : "invisible"}
- onPointerDown={(e) => { formatInstance.addPoints(pts.X, pts.Y, apoints, i, controlPoints); }} onMouseEnter={() => this.onPointerEnter(i)} onMouseLeave={this.onPointerLeave} pointerEvents="all" cursor="all-scroll"
- />
- </svg>);
- // Blue circles that allow the user to edit the curvature of the line using the selected control point as the anchor.
- const handles = handlePoints.map((pts, i) =>
- <svg height="10" width="10" key={`hdl${i}`}>
- <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth / 2} strokeWidth={0} fill="#1F85DE"
- onPointerDown={(e) => this.onHandleDown(e, pts.I)} pointerEvents="all" cursor="default" display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} />
- </svg>);
- // Control points of the ink (blue outlined squares) that are made visible to user when editing its format.
- const controls = controlPoints.map((pts, i) => <InkControl control={pts} left={left} top={top} scaleX={scaleX} scaleY={scaleY} strokeWidth={strokeWidth} ScreenToLocalTransform={this.props.ScreenToLocalTransform} /> );
- // Set of two blue lines (each with a handle at the end) that are rendered perpendicular to the current selected point while editing.
- const handleLines = handleLine.map((pts, i) =>
- <svg height="100" width="100" key={`line${i}`}>
- <line x1={(pts.X1 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y1={(pts.Y1 - top - strokeWidth / 2) * scaleY + strokeWidth / 2}
- x2={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y2={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} stroke="#1F85DE" strokeWidth={dotsize / 10}
- display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} />
- </svg>);
-
- return (
- <svg className="inkingStroke"
- style={{
- pointerEvents: this.props.Document.isInkMask && this.props.layerProvider?.(this.props.Document) !== false ? "all" : "none",
- transform: this.props.Document.isInkMask ? `translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined,
- mixBlendMode: this.layoutDoc.tool === InkTool.Highlighter ? "multiply" : "unset",
- overflow: "visible",
- }}
- onPointerDown={this.onPointerDown}
- onContextMenu={() => {
- const cm = ContextMenu.Instance;
- if (cm) {
- !Doc.UserDoc().noviceMode && cm.addItem({ description: "Recognize Writing", event: this.analyzeStrokes, icon: "paint-brush" });
- cm.addItem({ description: "Toggle Mask", event: () => InkingStroke.toggleMask(this.rootDoc), icon: "paint-brush" });
- cm.addItem({ description: "Edit Points", event: action(() => formatInstance._controlBtn = !formatInstance._controlBtn), icon: "paint-brush" });
- //cm.addItem({ description: "Format Shape...", event: this.formatShape, icon: "paint-brush" });
- }
- }}
- ><defs>
- </defs>
- {hpoints}
- {points}
- {formatInstance._controlBtn && this.props.isSelected() ? addpoints : ""}
- {formatInstance._controlBtn && this.props.isSelected() ? handleLines : ""}
- {formatInstance._controlBtn && this.props.isSelected() ? handles : ""}
- {this.props.isSelected() ? selectedLine : ""}
- {formatInstance._controlBtn && this.props.isSelected() ? controls : ""}
- </svg>
- );
- }
-}
-
-
-export function SetActiveInkWidth(width: string): void { !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width); }
-export function SetActiveBezierApprox(bezier: string): void { ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? "" : bezier); }
-export function SetActiveInkColor(value: string) { ActiveInkPen() && (ActiveInkPen().activeInkColor = value); }
-export function SetActiveFillColor(value: string) { ActiveInkPen() && (ActiveInkPen().activeFillColor = value); }
-export function SetActiveArrowStart(value: string) { ActiveInkPen() && (ActiveInkPen().activeArrowStart = value); }
-export function SetActiveArrowEnd(value: string) { ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value); }
-export function SetActiveDash(dash: string): void { !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); }
-export function ActiveInkPen(): Doc { return Doc.UserDoc(); }
-export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, "black"); }
-export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ""); }
-export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ""); }
-export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ""); }
-export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, "0"); }
-export function ActiveInkWidth(): string { return StrCast(ActiveInkPen()?.activeInkWidth, "1"); }
-export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); }
-Scripting.addGlobal(function activateBrush(pen: any, width: any, color: any, fill: any, arrowStart: any, arrowEnd: any, dash: any) {
- CurrentUserUtils.SelectedTool = pen ? InkTool.Highlighter : InkTool.None;
- SetActiveInkWidth(width);
- SetActiveInkColor(color);
- SetActiveFillColor(fill);
- SetActiveArrowStart(arrowStart);
- SetActiveArrowEnd(arrowEnd);
- SetActiveDash(dash);
-});
-Scripting.addGlobal(function activateEraser(pen: any) { return CurrentUserUtils.SelectedTool = pen ? InkTool.Eraser : InkTool.None; });
-Scripting.addGlobal(function activateStamp(pen: any) { return CurrentUserUtils.SelectedTool = pen ? InkTool.Stamp : InkTool.None; });
-Scripting.addGlobal(function deactivateInk() { return CurrentUserUtils.SelectedTool = InkTool.None; });
-Scripting.addGlobal(function setInkWidth(width: any) { return SetActiveInkWidth(width); });
-Scripting.addGlobal(function setInkColor(color: any) { return SetActiveInkColor(color); });
-Scripting.addGlobal(function setFillColor(fill: any) { return SetActiveFillColor(fill); });
-Scripting.addGlobal(function setActiveArrowStart(arrowStart: any) { return SetActiveArrowStart(arrowStart); });
-Scripting.addGlobal(function setActiveArrowEnd(arrowEnd: any) { return SetActiveArrowStart(arrowEnd); });
-Scripting.addGlobal(function setActiveDash(dash: any) { return SetActiveDash(dash); });