aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/GestureOverlay.tsx4
-rw-r--r--src/client/views/InkControls.tsx10
-rw-r--r--src/client/views/InkHandles.tsx38
-rw-r--r--src/client/views/InkStrokeProperties.ts11
-rw-r--r--src/client/views/InkingStroke.tsx4
5 files changed, 39 insertions, 28 deletions
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 6ccbd3fd7..465e6b2df 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -708,7 +708,7 @@ export class GestureOverlay extends Touchable {
this._points.push({ X: left, Y: top });
break;
-
+
case "triangle":
this._points.push({ X: left, Y: bottom });
this._points.push({ X: left, Y: bottom });
@@ -851,7 +851,7 @@ export class GestureOverlay extends Touchable {
}),
this._points.length <= 1 ? (null) : <svg key="svg" width={B.width} height={B.height}
style={{ transform: `translate(${B.left}px, ${B.top}px)`, pointerEvents: "none", position: "absolute", zIndex: 30000, overflow: "visible" }}>
- {InteractionUtils.CreatePolyline(this._points.map(p => ({ X: p.X, Y: p.Y - (rect?.y || 0) })), B.left, B.top, ActiveInkColor(), width, width, ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", 1.0, false)}
+ {InteractionUtils.CreatePolyline(this._points.map(p => ({ X: p.X, Y: p.Y - (rect?.y || 0) })), B.left, B.top, ActiveInkColor(), width, width, "", ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", 1.0, false)}
</svg>]
];
}
diff --git a/src/client/views/InkControls.tsx b/src/client/views/InkControls.tsx
index 4df7ee813..7e685288d 100644
--- a/src/client/views/InkControls.tsx
+++ b/src/client/views/InkControls.tsx
@@ -37,8 +37,8 @@ export class InkControls extends React.Component<InkControlProps> {
const controlUndo = UndoManager.StartBatch("DocDecs set radius");
const screenScale = this.props.ScreenToLocalTransform().Scale;
const order = controlIndex % 4;
- const handleIndexA = order === 2 ? controlIndex - 1 : controlIndex - 2;
- const handleIndexB = order === 2 ? controlIndex + 2 : controlIndex + 1;
+ 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[]) => {
@@ -47,7 +47,11 @@ export class InkControls extends React.Component<InkControlProps> {
},
() => controlUndo?.end(),
action((e: PointerEvent, doubleTap: boolean | undefined) => {
- if (doubleTap && brokenIndices && brokenIndices.includes(controlIndex)) {
+ 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);
}
}));
diff --git a/src/client/views/InkHandles.tsx b/src/client/views/InkHandles.tsx
index afe94cdfb..1a514bdce 100644
--- a/src/client/views/InkHandles.tsx
+++ b/src/client/views/InkHandles.tsx
@@ -31,10 +31,11 @@ export class InkHandles extends React.Component<InkHandlesProps> {
const controlUndo = UndoManager.StartBatch("DocDecs set radius");
const screenScale = this.props.ScreenToLocalTransform().Scale;
const order = handleIndex % 4;
- const oppositeHandleIndex = order === 1 ? handleIndex - 3 : handleIndex + 3;
- const controlIndex = order === 1 ? handleIndex - 1 : handleIndex + 2;
- document.addEventListener("keydown", (e: KeyboardEvent) => this.onBreakTangent(e, controlIndex), true);
+ const oppositeHandleRawIndex = order === 1 ? handleIndex - 3 : handleIndex + 3;
+ const oppositeHandleIndex = (oppositeHandleRawIndex < 0 ? this.props.data.length + oppositeHandleRawIndex : oppositeHandleRawIndex) % this.props.data.length;
+ const controlIndex = (order === 1 ? handleIndex - 1 : handleIndex + 2) % this.props.data.length;
setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => {
+ if (e.altKey) this.onBreakTangent(controlIndex);
InkStrokeProperties.Instance?.moveHandle(-delta[0] * screenScale, -delta[1] * screenScale, handleIndex, oppositeHandleIndex, controlIndex);
return false;
}, () => controlUndo?.end(), emptyFunction
@@ -48,15 +49,14 @@ export class InkHandles extends React.Component<InkHandlesProps> {
* @param handleNum The index of the currently selected handle point.
*/
@action
- onBreakTangent = (e: KeyboardEvent, controlIndex: number) => {
- const doc: Doc = this.props.inkDoc;
- if (["Alt"].includes(e.key)) {
- e.stopPropagation();
- if (doc) {
- const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number")) || new List;
- if (brokenIndices && !brokenIndices.includes(controlIndex)) {
- brokenIndices.push(controlIndex);
- }
+ onBreakTangent = (controlIndex: number) => {
+ const doc = this.props.inkDoc;
+ if (doc) {
+ const closed = this.props.data.lastElement().X === this.props.data[0].X && this.props.data.lastElement().Y === this.props.data[0].Y;
+ const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number")) || new List;
+ if (!brokenIndices?.includes(controlIndex) &&
+ ((controlIndex > 0 && controlIndex < this.props.data.length - 1) || closed)) {
+ brokenIndices.push(controlIndex);
doc.brokenInkIndices = brokenIndices;
}
}
@@ -70,14 +70,20 @@ export class InkHandles extends React.Component<InkHandlesProps> {
const data = this.props.data;
const handlePoints: HandlePoint[] = [];
const handleLines: HandleLine[] = [];
+ const closed = data.lastElement().X === data[0].X && data.lastElement().Y === data[0].Y;
if (data.length >= 4) {
for (let 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 });
+ handlePoints.push({ X: data[i + 1].X, Y: data[i + 1].Y, I: i + 1, dot1: i, dot2: i === 0 ? (closed ? data.length - 1 : 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 ? (closed ? (i + 4) % data.length : i + 3) : i + 4 });
}
// Adding first and last (single) handle lines.
- handleLines.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 });
- handleLines.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 (closed) {
+ handleLines.push({ X1: data[data.length - 2].X, Y1: data[data.length - 2].Y, X2: data[0].X, Y2: data[0].Y, X3: data[1].X, Y3: data[1].Y, dot1: 0, dot2: data.length - 1 });
+ }
+ else {
+ handleLines.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 });
+ handleLines.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 });
+ }
for (let i = 2; i < data.length - 4; i += 4) {
handleLines.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 });
}
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 42190238e..2073497b9 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,14 +1,14 @@
import { action, computed, observable, reaction } from "mobx";
-import { Doc, DocListCast, Field, Opt } from "../../fields/Doc";
+import { Doc, Field, Opt } from "../../fields/Doc";
import { Document } from "../../fields/documentSchemas";
-import { InkField, InkData, PointData, ControlPoint, InkTool } from "../../fields/InkField";
+import { InkData, InkField, InkTool, PointData } 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 { CurrentUserUtils } from "../util/CurrentUserUtils";
import { SelectionManager } from "../util/SelectionManager";
import { undoBatch } from "../util/UndoManager";
-import { CurrentUserUtils } from "../util/CurrentUserUtils";
export class InkStrokeProperties {
static Instance: InkStrokeProperties | undefined;
@@ -241,6 +241,7 @@ export class InkStrokeProperties {
this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
const newPoints: { X: number, Y: number }[] = [];
const order = controlIndex % 4;
+ const closed = ink.lastElement().X === ink[0].X && ink.lastElement().Y === ink[0].Y;
for (var i = 0; i < ink.length; i++) {
const leftHandlePoint = order === 0 && i === controlIndex + 1;
const rightHandlePoint = order === 0 && controlIndex !== 0 && i === controlIndex - 2;
@@ -248,6 +249,7 @@ export class InkStrokeProperties {
leftHandlePoint ||
rightHandlePoint ||
(order === 0 && controlIndex !== 0 && i === controlIndex - 1) ||
+ ((order === 0 || order === 3) && (controlIndex === 0 || controlIndex === ink.length - 1) && (i === 1 || i === ink.length - 2) && closed) ||
(order === 3 && i === controlIndex - 1) ||
(order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 1) ||
(order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 2) ||
@@ -335,6 +337,7 @@ export class InkStrokeProperties {
@action
moveHandle = (deltaX: number, deltaY: number, handleIndex: number, oppositeHandleIndex: number, controlIndex: number) =>
this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
+ const closed = ink.lastElement().X === ink[0].X && ink.lastElement().Y === ink[0].Y;
const oldHandlePoint = ink[handleIndex];
let oppositeHandlePoint = ink[oppositeHandleIndex];
const controlPoint = ink[controlIndex];
@@ -342,7 +345,7 @@ export class InkStrokeProperties {
ink[handleIndex] = newHandlePoint;
const 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 ((!brokenIndices || !brokenIndices?.includes(controlIndex)) && handleIndex !== 1 && handleIndex !== ink.length - 2) {
+ if ((!brokenIndices || !brokenIndices?.includes(controlIndex)) && (closed || (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 ca39bdaa1..a518bf07b 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -11,14 +11,11 @@ import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../Utils";
import { CognitiveServices } from "../cognitive_services/CognitiveServices";
import { CurrentUserUtils } from "../util/CurrentUserUtils";
import { InteractionUtils } from "../util/InteractionUtils";
-import { Scripting } from "../util/Scripting";
import { ContextMenu } from "./ContextMenu";
import { ViewBoxBaseComponent } from "./DocComponent";
import { Colors } from "./global/globalEnums";
import { InkControls } from "./InkControls";
import { InkHandles } from "./InkHandles";
-import { GestureOverlay } from "./GestureOverlay";
-import { isThisTypeNode } from "typescript";
import "./InkStroke.scss";
import { InkStrokeProperties } from "./InkStrokeProperties";
import { FieldView, FieldViewProps } from "./nodes/FieldView";
@@ -83,6 +80,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
doubleTap = doubleTap || this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick;
if (doubleTap && this._properties) {
this._properties._controlButton = true;
+ InkStrokeProperties.Instance && (InkStrokeProperties.Instance._currentPoint = -1);
this._handledClick = true; // mark the double-click pseudo pointerevent so we can block the real mouse event from propagating to DocumentView
}
}), this._properties?._controlButton, this._properties?._controlButton