aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/InkHandles.tsx60
-rw-r--r--src/client/views/InkStrokeProperties.ts31
-rw-r--r--src/client/views/InkingStroke.tsx60
3 files changed, 86 insertions, 65 deletions
diff --git a/src/client/views/InkHandles.tsx b/src/client/views/InkHandles.tsx
index ba3fdf9db..ffb6986f1 100644
--- a/src/client/views/InkHandles.tsx
+++ b/src/client/views/InkHandles.tsx
@@ -6,8 +6,12 @@ import { setupMoveUpEvents, emptyFunction } from "../../Utils";
import { UndoManager } from "../util/UndoManager";
import { InkData, HandlePoint, HandleLine } from "../../fields/InkField";
import { Transform } from "../util/Transform";
+import { Doc } from "../../fields/Doc";
+import { listSpec } from "../../fields/Schema";
+import { Cast } from "../../fields/Types";
export interface InkControlProps {
+ inkDoc: Doc;
data: InkData;
format: number[];
ScreenToLocalTransform: () => Transform;
@@ -19,7 +23,7 @@ export class InkHandles extends React.Component<InkControlProps> {
* Handles the movement of a selected handle point when the user clicks and drags.
* @param handleNum The index of the currently selected handle point.
*/
- onHandleDown = (e: React.PointerEvent, handleIndex: number): void => {
+ onHandleDown = (e: React.PointerEvent, handleIndex: number): void => {
if (InkStrokeProperties.Instance) {
InkStrokeProperties.Instance.moveControl(0, 0, 1);
const controlUndo = UndoManager.StartBatch("DocDecs set radius");
@@ -29,9 +33,9 @@ export class InkHandles extends React.Component<InkControlProps> {
const controlIndex = order === 1 ? handleIndex - 1 : handleIndex + 2;
document.addEventListener("keydown", (e: KeyboardEvent) => this.onBreakTangent(e, controlIndex), true);
setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => {
- InkStrokeProperties.Instance?.moveHandle(-delta[0] * screenScale, -delta[1] * screenScale, handleIndex, oppositeHandleIndex, controlIndex);
- return false;
- }, () => controlUndo?.end(), emptyFunction
+ InkStrokeProperties.Instance?.moveHandle(-delta[0] * screenScale, -delta[1] * screenScale, handleIndex, oppositeHandleIndex, controlIndex);
+ return false;
+ }, () => controlUndo?.end(), emptyFunction
);
}
}
@@ -43,13 +47,19 @@ export class InkHandles extends React.Component<InkControlProps> {
*/
@action
onBreakTangent = (e: KeyboardEvent, controlIndex: number) => {
+ const doc: Doc = this.props.inkDoc;
if (["Alt"].includes(e.key)) {
- if (!InkStrokeProperties.Instance?._brokenIndices.includes(controlIndex)) {
- InkStrokeProperties.Instance?._brokenIndices.push(controlIndex);
+ if (doc) {
+ let brokenIndices = Cast(doc.brokenInkIndices, listSpec("number"));
+ if (brokenIndices && brokenIndices.includes(controlIndex)) {
+ brokenIndices.push(controlIndex);
+ }
+
+ doc.brokenInkIndices = brokenIndices;
}
}
}
-
+
render() {
const formatInstance = InkStrokeProperties.Instance;
if (!formatInstance) return (null);
@@ -76,33 +86,33 @@ export class InkHandles extends React.Component<InkControlProps> {
<>
{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}
+ <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"
+ onPointerDown={(e) => this.onHandleDown(e, pts.I)}
+ pointerEvents="all"
+ cursor="default"
display={(pts.dot1 === formatInstance._currentPoint || pts.dot2 === formatInstance._currentPoint) ? "inherit" : "none"} />
</svg>)}
{handleLines.map((pts, i) =>
<svg height="100" width="100" key={`line${i}`}>
- <line
- x1={(pts.X1 - left - strokeWidth / 2) * scaleX + strokeWidth / 2}
+ <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"
+ x2={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2}
+ y2={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2}
+ stroke="#1F85DE"
strokeWidth={dotsize / 8}
display={(pts.dot1 === formatInstance._currentPoint || pts.dot2 === formatInstance._currentPoint) ? "inherit" : "none"} />
- <line
- x1={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2}
+ <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="#1F85DE"
+ x2={(pts.X3 - left - strokeWidth / 2) * scaleX + strokeWidth / 2}
+ y2={(pts.Y3 - top - strokeWidth / 2) * scaleY + strokeWidth / 2}
+ stroke="#1F85DE"
strokeWidth={dotsize / 8}
display={(pts.dot1 === formatInstance._currentPoint || pts.dot2 === formatInstance._currentPoint) ? "inherit" : "none"} />
</svg>)}
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index a3f7562e0..4c225210e 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,7 +1,9 @@
import { action, computed, observable } from "mobx";
-import { Doc, Field, Opt } from "../../fields/Doc";
+import { Doc, DocListCast, Field, Opt } from "../../fields/Doc";
import { Document } from "../../fields/documentSchemas";
import { InkField, InkData, PointData, ControlPoint } from "../../fields/InkField";
+import { List } from "../../fields/List";
+import { listSpec } from "../../fields/Schema";
import { Cast, NumCast } from "../../fields/Types";
import { DocumentType } from "../documents/DocumentTypes";
import { SelectionManager } from "../util/SelectionManager";
@@ -13,7 +15,7 @@ export class InkStrokeProperties {
@observable _lock = false;
@observable _controlButton = false;
@observable _currentPoint = -1;
- @observable _brokenIndices: number[] = [];
+ // @observable _brokenIndices: List<number> = new List<number>();
constructor() {
InkStrokeProperties.Instance = this;
@@ -110,14 +112,20 @@ export class InkStrokeProperties {
}
}
+
+ let brokenIndices = Cast(doc.brokenInkIndices, listSpec("number"));
+
// Updating the indices of the control points whose handle tangency has been broken.
- this._brokenIndices = this._brokenIndices.map((control) => {
- if (control >= newIndex) {
- return control + 4;
- } else {
- return control;
- }
- });
+ if(brokenIndices){
+ brokenIndices = new List(brokenIndices.map((control) => {
+ if (control >= newIndex) {
+ return control + 4;
+ } else {
+ return control;
+ }
+ }));
+ }
+ doc.brokenInkIndices = brokenIndices;
this._currentPoint = -1;
return newPoints;
});
@@ -250,7 +258,7 @@ export class InkStrokeProperties {
snapHandleTangent = (controlIndex: number, handleIndexA: number, handleIndexB: number) => {
this.applyFunction((doc: Doc, ink: InkData) => {
- this._brokenIndices.splice(this._brokenIndices.indexOf(controlIndex), 1);
+ // doc.brokenIndices.splice(this._brokenIndices.indexOf(controlIndex), 1);
const [controlPoint, handleA, handleB] = [ink[controlIndex], ink[handleIndexA], ink[handleIndexB]];
const oppositeHandleA = this.rotatePoint(handleA, controlPoint, Math.PI);
const angleDifference = this.angleChange(handleB, oppositeHandleA, controlPoint);
@@ -315,8 +323,9 @@ export class InkStrokeProperties {
const controlPoint = ink[controlIndex];
const newHandlePoint = { X: ink[handleIndex].X - deltaX / xScale, Y: ink[handleIndex].Y - deltaY / yScale };
ink[handleIndex] = newHandlePoint;
+ let brokenIndices = Cast(doc.brokenInkIndices, listSpec("number"));
// Rotate opposite handle if user hasn't held 'Alt' key or not first/final control (which have only 1 handle).
- if (!this._brokenIndices.includes(controlIndex) && handleIndex !== 1 && handleIndex !== ink.length - 2) {
+ if (brokenIndices && !brokenIndices.includes(controlIndex) && handleIndex !== 1 && handleIndex !== ink.length - 2) {
const angle = this.angleChange(oldHandlePoint, newHandlePoint, controlPoint);
oppositeHandlePoint = this.rotatePoint(oppositeHandlePoint, controlPoint, angle);
ink[oppositeHandleIndex] = oppositeHandlePoint;
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index b630c20cc..bd71aaf19 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -34,8 +34,8 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
this._properties = InkStrokeProperties.Instance;
}
- public static LayoutString(fieldStr: string) {
- return FieldView.LayoutString(InkingStroke, fieldStr);
+ public static LayoutString(fieldStr: string) {
+ return FieldView.LayoutString(InkingStroke, fieldStr);
}
analyzeStrokes() {
@@ -57,9 +57,9 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
*/
onPointerDown = (e: React.PointerEvent) => {
if (this.props.isSelected(true)) {
- setupMoveUpEvents(this, e, returnFalse, emptyFunction,
+ setupMoveUpEvents(this, e, returnFalse, emptyFunction,
action((e: PointerEvent, doubleTap: boolean | undefined) =>
- doubleTap && this._properties && (this._properties._controlButton = true))
+ doubleTap && this._properties && (this._properties._controlButton = true))
);
}
}
@@ -68,6 +68,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
TraceMobx();
// Extracting the ink data and formatting information of the current ink stroke.
const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
+ const inkDoc: Doc = this.layoutDoc;
const strokeWidth = Number(this.layoutDoc.strokeWidth);
const lineTop = Math.min(...data.map(p => p.Y));
const lineBottom = Math.max(...data.map(p => p.Y));
@@ -85,31 +86,31 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const dotsize = Math.max(width * scaleX, height * scaleY) / 40;
// Visually renders the polygonal line made by the user.
- const inkLine = 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 && lineBottom - lineTop > 1 && lineRight - lineLeft > 1,
+ const inkLine = 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 && lineBottom - lineTop > 1 && lineRight - lineLeft > 1,
false);
// Thin blue line indicating that the current ink stroke is selected.
const selectedLine = InteractionUtils.CreatePolyline(
- data, lineLeft - strokeWidth * 3, lineTop - strokeWidth * 3, "#1F85DE", strokeWidth / 6,
- strokeWidth / 6,StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"),
+ data, lineLeft - 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 && lineBottom - lineTop > 1 && lineRight - lineLeft > 1,
+ StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none",
+ this.props.isSelected() && strokeWidth <= 5 && lineBottom - lineTop > 1 && lineRight - lineLeft > 1,
false);
// Invisible polygonal line that enables the ink to be selected by the user.
- const clickableLine = 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, "",
+ const clickableLine = 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);
// Set of points rendered upon the ink that can be added if a user clicks on one.
const addedPoints = 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",
+ StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none",
this.props.isSelected() && strokeWidth <= 5, false);
return (
@@ -126,25 +127,26 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
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(() => {if (this._properties) { this._properties._controlButton = !this._properties._controlButton; }} ), icon: "paint-brush" });
+ cm.addItem({ description: "Edit Points", event: action(() => { if (this._properties) { this._properties._controlButton = !this._properties._controlButton; } }), icon: "paint-brush" });
}
}}
>
-
+
{clickableLine}
{inkLine}
{this.props.isSelected() ? selectedLine : ""}
- {this.props.isSelected() && this._properties?._controlButton ?
+ {this.props.isSelected() && this._properties?._controlButton ?
<>
- <InkControls
- data={data}
- addedPoints={addedPoints}
- format={[left, top, scaleX, scaleY, strokeWidth, dotsize]}
+ <InkControls
+ data={data}
+ addedPoints={addedPoints}
+ format={[left, top, scaleX, scaleY, strokeWidth, dotsize]}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform} />
+ <InkHandles
+ inkDoc={inkDoc}
+ data={data}
+ format={[left, top, scaleX, scaleY, strokeWidth, dotsize]}
ScreenToLocalTransform={this.props.ScreenToLocalTransform} />
- <InkHandles
- data={data}
- format={[left, top, scaleX, scaleY, strokeWidth, dotsize]}
- ScreenToLocalTransform={this.props.ScreenToLocalTransform} />
</> : ""}
</svg>
);