aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkingStroke.tsx
diff options
context:
space:
mode:
authorAndy Rickert <andrew_rickert@brown.edu>2020-07-31 19:04:32 -0400
committerAndy Rickert <andrew_rickert@brown.edu>2020-07-31 19:04:32 -0400
commitcfa39673564b6cd12d61ebbf3778cea8c3d0eff2 (patch)
treefd43d10a62c5d8f15057af7f1d788f263194ee0d /src/client/views/InkingStroke.tsx
parenta1950ec49c56f5f9e2612da7e60a1e2615209386 (diff)
parentc71d7fa4f84149bcb62246d50e06bfd1481365bc (diff)
merge
Diffstat (limited to 'src/client/views/InkingStroke.tsx')
-rw-r--r--src/client/views/InkingStroke.tsx134
1 files changed, 122 insertions, 12 deletions
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index c32e76cec..5892e8346 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -15,6 +15,9 @@ import { FieldView, FieldViewProps } from "./nodes/FieldView";
import React = require("react");
import { Scripting } from "../util/Scripting";
import { Doc } from "../../fields/Doc";
+import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane";
+import { action } from "mobx";
+import { setupMoveUpEvents } from "../../Utils";
library.add(faPaintBrush);
@@ -38,10 +41,49 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
this.props.Document.isInkMask = true;
}
+ @action
+ private formatShape = () => {
+ FormatShapePane.Instance.Pinned = true;
+ }
+
+ private _prevX = 0;
+ private _prevY = 0;
+ private _controlNum = 0;
+ @action
+ onControlDown = (e: React.PointerEvent, i: number): void => {
+ setupMoveUpEvents(this, e, this.onControlMove, this.onControlup, (e) => { });
+ this._prevX = e.clientX;
+ this._prevY = e.clientY;
+ this._controlNum = i;
+ }
+
+ @action
+ changeCurrPoint = (i: number) => {
+ FormatShapePane.Instance._currPoint = i;
+ }
+
+ @action
+ onControlMove = (e: PointerEvent, down: number[]): boolean => {
+ const xDiff = this._prevX - e.clientX;
+ const yDiff = this._prevY - e.clientY;
+ FormatShapePane.Instance.control(xDiff, yDiff, this._controlNum);
+ this._prevX = e.clientX;
+ this._prevY = e.clientY;
+ return false;
+ }
+
+ onControlup = (e: PointerEvent) => {
+ this._prevX = 0;
+ this._prevY = 0;
+ this._controlNum = 0;
+ }
+
+ public static MaskDim = 50000;
render() {
TraceMobx();
const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
- const strokeWidth = Number(StrCast(this.layoutDoc.strokeWidth, ActiveInkWidth()));
+ // const strokeWidth = Number(StrCast(this.layoutDoc.strokeWidth, ActiveInkWidth()));
+ const strokeWidth = Number(this.layoutDoc.strokeWidth);
const xs = data.map(p => p.X);
const ys = data.map(p => p.Y);
const left = Math.min(...xs) - strokeWidth / 2;
@@ -52,33 +94,101 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const height = bottom - top;
const scaleX = (this.props.PanelWidth() - strokeWidth) / (width - strokeWidth);
const scaleY = (this.props.PanelHeight() - strokeWidth) / (height - strokeWidth);
- const strokeColor = StrCast(this.layoutDoc.color, ActiveInkColor());
+ const strokeColor = StrCast(this.layoutDoc.color, "");
+
const points = InteractionUtils.CreatePolyline(data, left, top, strokeColor, strokeWidth, strokeWidth,
- StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), StrCast(this.layoutDoc.fillColor, ActiveFillColor()),
- StrCast(this.layoutDoc.arrowStart, ActiveArrowStart()), StrCast(this.layoutDoc.arrowEnd, ActiveArrowEnd()),
- StrCast(this.layoutDoc.dash, ActiveDash()), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false);
+ StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"),
+ StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
+ StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false);
+
const hpoints = InteractionUtils.CreatePolyline(data, left, top,
this.props.isSelected() && strokeWidth > 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15),
- StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), StrCast(this.layoutDoc.fillColor, ActiveFillColor()),
+ StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"),
"none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblepainted" : "none", false, true);
+
+ var controlPoints: { X: number, Y: number, I: number }[] = [];
+ var handlePoints: { X: number, Y: number, I: number, dot1: number, dot2: number }[] = [];
+ var handleLine: { X1: number, Y1: number, X2: number, Y2: number, X3: number, Y3: number, dot1: number, dot2: number }[] = [];
+ if (data.length >= 4) {
+ 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 });
+ }
+
+ handleLine.push({ X1: data[0].X, Y1: data[0].Y, X2: data[0].X, Y2: data[0].Y, X3: data[1].X, Y3: 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 + 1].X, Y2: data[i + 1].Y, X3: data[i + 3].X, Y3: data[i + 3].Y, dot1: i + 1, dot2: i + 2 });
+
+ }
+ 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, X3: data[data.length - 1].X, Y3: data[data.length - 1].Y, dot1: data.length - 1, dot2: data.length - 1 });
+
+
+ }
+ if (data.length <= 4) {
+ handlePoints = [];
+ handleLine = [];
+ controlPoints = [];
+ for (var i = 0; i < data.length; i++) {
+ controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
+ }
+
+ }
+ const dotsize = String(Math.min(width * scaleX, height * scaleY) / 40);
+
+ const controls = controlPoints.map((pts, i) =>
+
+ <svg height="10" width="10">
+ <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={dotsize} stroke="black" stroke-width={String(Number(dotsize) / 2)} fill="red"
+ onPointerDown={(e) => { this.changeCurrPoint(pts.I); this.onControlDown(e, pts.I); }} pointerEvents="all" cursor="all-scroll" />
+ </svg>);
+ const handles = handlePoints.map((pts, i) =>
+
+ <svg height="10" width="10">
+ <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={dotsize} stroke="black" stroke-width={String(Number(dotsize) / 2)} fill="green"
+ onPointerDown={(e) => this.onControlDown(e, pts.I)} pointerEvents="all" cursor="all-scroll" display={(pts.dot1 === FormatShapePane.Instance._currPoint || pts.dot2 === FormatShapePane.Instance._currPoint) ? "inherit" : "none"} />
+ </svg>);
+ const handleLines = handleLine.map((pts, i) =>
+
+ <svg height="100" width="100">
+ <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="green" stroke-width={String(Number(dotsize) / 2)}
+ display={(pts.dot1 === FormatShapePane.Instance._currPoint || pts.dot2 === FormatShapePane.Instance._currPoint) ? "inherit" : "none"} />
+ <line x1={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y1={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2}
+ x2={(pts.X3 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y2={(pts.Y3 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} stroke="green" stroke-width={String(Number(dotsize) / 2)}
+ display={(pts.dot1 === FormatShapePane.Instance._currPoint || pts.dot2 === FormatShapePane.Instance._currPoint) ? "inherit" : "none"} />
+
+ </svg>);
+
+
return (
<svg className="inkingStroke"
width={width}
height={height}
style={{
pointerEvents: this.props.Document.isInkMask ? "all" : "none",
- transform: this.props.Document.isInkMask ? "translate(2500px, 2500px)" : undefined,
+ 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",
}}
onContextMenu={() => {
- ContextMenu.Instance.addItem({ description: "Analyze Stroke", event: this.analyzeStrokes, icon: "paint-brush" });
- ContextMenu.Instance.addItem({ description: "Make Mask", event: this.makeMask, icon: "paint-brush" });
+ const cm = ContextMenu.Instance;
+ if (cm) {
+ !Doc.UserDoc().noviceMode && cm.addItem({ description: "Recognize Writing", event: this.analyzeStrokes, icon: "paint-brush" });
+ cm.addItem({ description: "Make Mask", event: this.makeMask, icon: "paint-brush" });
+ cm.addItem({ description: "Format Shape...", event: this.formatShape, icon: "paint-brush" });
+ }
}}
><defs>
</defs>
{hpoints}
{points}
+ {FormatShapePane.Instance._controlBtn && this.props.isSelected() ? controls : ""}
+ {FormatShapePane.Instance._controlBtn && this.props.isSelected() ? handles : ""}
+ {FormatShapePane.Instance._controlBtn && this.props.isSelected() ? handleLines : ""}
+
</svg>
);
}
@@ -94,9 +204,9 @@ export function SetActiveArrowEnd(value: string) { ActiveInkPen() && (ActiveInkP
export function SetActiveDash(dash: string): void { !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); }
export function ActiveInkPen(): Doc { return Cast(Doc.UserDoc().activeInkPen, Doc, null); }
export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, "black"); }
-export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, "none"); }
-export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, "none"); }
-export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, "none"); }
+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); }