aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/DocumentDecorations.tsx31
-rw-r--r--src/client/views/InkStrokeProperties.ts176
-rw-r--r--src/client/views/InkingStroke.tsx4
3 files changed, 75 insertions, 136 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 959b44f98..bf939d57c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -197,8 +197,15 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
@action
onRotateDown = (e: React.PointerEvent): void => {
this._rotateUndo = UndoManager.StartBatch("rotatedown");
-
- setupMoveUpEvents(this, e, this.onRotateMove, () => this._rotateUndo?.end(), emptyFunction);
+ setupMoveUpEvents(this, e,
+ (e: PointerEvent, down: number[], delta: number[]) => {
+ const movement = { X: delta[0], Y: e.clientY - down[1] };
+ const angle = Math.max(1, Math.abs(movement.Y / 10));
+ InkStrokeProperties.Instance?.rotate(2 * movement.X / angle * (Math.PI / 180));
+ return false;
+ },
+ () => this._rotateUndo?.end(),
+ emptyFunction);
this._prevY = e.clientY;
this._inkCenterPts = SelectionManager.Views()
.filter(dv => dv.rootDoc.type === DocumentType.INK)
@@ -207,26 +214,6 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
}
@action
- onRotateMove = (e: PointerEvent, down: number[]): boolean => {
- const distance = Math.abs(this._prevY - e.clientY);
- const angle = e.clientY > this._prevY ? distance * (Math.PI / 180) : e.clientY < this._prevY ? - distance * (Math.PI / 180) : 0;
- this._prevY = e.clientY;
- this._inkCenterPts.map(({ doc, X, Y }) => ({ doc, X, Y, inkData: Cast(doc.data, InkField)?.inkData }))
- .forEach(pair => {
- const newPoints = pair.inkData?.map(ink => ({
- X: Math.cos(angle) * (ink.X - pair.X) - Math.sin(angle) * (ink.Y - pair.Y) + pair.X,
- Y: Math.sin(angle) * (ink.X - pair.X) + Math.cos(angle) * (ink.Y - pair.Y) + pair.Y
- })) || [];
- Doc.GetProto(pair.doc).data = new InkField(newPoints);
-
- pair.doc._width = ((xs) => (Math.max(...xs) - Math.min(...xs)))(newPoints.map(p => p.X) || [0]);
- pair.doc._height = ((ys) => (Math.max(...ys) - Math.min(...ys)))(newPoints.map(p => p.Y) || [0]);
- pair.doc.rotation = NumCast(pair.doc.rotation) + angle;
- });
- return false;
- }
-
- @action
onPointerDown = (e: React.PointerEvent): void => {
DragManager.docsBeingDragged = SelectionManager.Views().map(dv => dv.rootDoc);
this._inkDragDocs = DragManager.docsBeingDragged
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index f400eb863..1261921ba 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -2,11 +2,12 @@ import { action, computed, observable } from "mobx";
import { ColorState } from 'react-color';
import { Doc, Field, Opt } from "../../fields/Doc";
import { Document } from "../../fields/documentSchemas";
-import { InkField } from "../../fields/InkField";
+import { InkField, InkData } from "../../fields/InkField";
import { Cast, NumCast } from "../../fields/Types";
import { DocumentType } from "../documents/DocumentTypes";
import { SelectionManager } from "../util/SelectionManager";
import { undoBatch } from "../util/UndoManager";
+import { bool } from "sharp";
export class InkStrokeProperties {
static Instance: InkStrokeProperties | undefined;
@@ -114,146 +115,97 @@ export class InkStrokeProperties {
}));
}
- @undoBatch
- @action
- deletePoints = () => {
- var deleted = false;
+ applyFunction = (func: (doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => { X: number, Y: number }[], requireCurrPoint: boolean = false) => {
+ var appliedFunc = false;
this.selectedInk?.forEach(action(inkView => {
- if (this.selectedInk?.length === 1 && this._currPoint !== -1) {
+ if (this.selectedInk?.length === 1 && (!requireCurrPoint || this._currPoint !== -1)) {
const doc = Document(inkView.rootDoc);
if (doc.type === DocumentType.INK && doc.width && doc.height) {
const ink = Cast(doc.data, InkField)?.inkData;
- if (ink && ink.length > 4) {
+ if (ink) {
const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X));
const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y));
const ptsXscale = NumCast(doc._width) / (oldXrange.max - oldXrange.min);
const ptsYscale = NumCast(doc._height) / (oldYrange.max - oldYrange.min);
- const newPoints: { X: number, Y: number }[] = [];
- const toRemove = Math.floor(((this._currPoint + 2) / 4));
- for (var i = 0; i < ink.length; i++) {
- if (Math.floor((i + 2) / 4) !== toRemove && (toRemove !== 0 || i > 3)) {
- newPoints.push({ X: ink[i].X, Y: ink[i].Y });
- }
- }
- this._currPoint = -1;
- Doc.GetProto(doc).data = new InkField(newPoints);
- if (newPoints.length === 4) {
- const newerPoints: { X: number, Y: number }[] = [];
- newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
- newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
- newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
- newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
- Doc.GetProto(doc).data = new InkField(newerPoints);
-
- }
+ const newPoints = func(doc, ink, ptsXscale, ptsYscale);
const newXrange = (xs => ({ min: Math.min(...xs), max: Math.max(...xs) }))(newPoints.map(p => p.X));
const newYrange = (ys => ({ min: Math.min(...ys), max: Math.max(...ys) }))(newPoints.map(p => p.Y));
doc._width = (newXrange.max - newXrange.min) * ptsXscale;
doc._height = (newYrange.max - newYrange.min) * ptsYscale;
doc.x = (oldXrange.coord + (newXrange.min - oldXrange.min) * ptsXscale);
doc.y = (oldYrange.coord + (newYrange.min - oldYrange.min) * ptsYscale);
- deleted = true;
+ Doc.GetProto(doc).data = new InkField(newPoints);
+ appliedFunc = true;
}
}
}
}));
- return deleted;
+ return appliedFunc;
}
@undoBatch
@action
- rotate = (angle: number) => {
- const _centerPoints: { X: number, Y: number }[] = [];
- SelectionManager.Views().forEach(action(inkView => {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const xs = ink.map(p => p.X);
- const ys = ink.map(p => p.Y);
- const left = Math.min(...xs);
- const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
- _centerPoints.push({ X: left, Y: top });
- }
+ deletePoints = () => this.applyFunction((doc: Doc, ink: InkData) => {
+ var newPoints: { X: number, Y: number }[] = [];
+ const toRemove = Math.floor(((this._currPoint + 2) / 4));
+ for (var i = 0; i < ink.length; i++) {
+ if (Math.floor((i + 2) / 4) !== toRemove && (toRemove !== 0 || i > 3)) {
+ newPoints.push({ X: ink[i].X, Y: ink[i].Y });
}
- }));
-
- var index = 0;
- SelectionManager.Views().forEach(action(inkView => {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
- doc.rotation = NumCast(doc.rotation) + angle;
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
-
- const newPoints: { X: number, Y: number }[] = [];
- ink.forEach(i => {
- const newX = Math.cos(angle) * (i.X - _centerPoints[index].X) - Math.sin(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].X;
- const newY = Math.sin(angle) * (i.X - _centerPoints[index].X) + Math.cos(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].Y;
- newPoints.push({ X: newX, Y: newY });
- });
- Doc.GetProto(doc).data = new InkField(newPoints);
- const xs = newPoints.map(p => p.X);
- const ys = newPoints.map(p => p.Y);
- const left = Math.min(...xs);
- const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
+ }
+ this._currPoint = -1;
+ Doc.GetProto(doc).data = new InkField(newPoints);
+ if (newPoints.length === 4) {
+ const newerPoints: { X: number, Y: number }[] = [];
+ newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
+ newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
+ newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
+ newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
+ return newerPoints;
+ }
+ return newPoints;
+ }, true);
- doc._height = (bottom - top);
- doc._width = (right - left);
- }
- index++;
- }
- }));
+ @undoBatch
+ @action
+ rotate = (angle: number) => {
+ this.applyFunction((doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => {
+ const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X));
+ const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y));
+ const centerPoint = { X: (oldXrange.min + oldXrange.max) / 2, Y: (oldYrange.min + oldYrange.max) / 2 };
+ const newPoints: { X: number, Y: number }[] = [];
+ ink.map(i => ({ X: i.X - centerPoint.X, Y: i.Y - centerPoint.Y })).forEach(i => {
+ const newX = Math.cos(angle) * i.X - Math.sin(angle) * i.Y;
+ const newY = Math.sin(angle) * i.X + Math.cos(angle) * i.Y;
+ newPoints.push({ X: newX + centerPoint.X, Y: newY + centerPoint.Y });
+ });
+ doc.rotation = NumCast(doc.rotation) + angle;
+ return newPoints;
+ });
}
@undoBatch
@action
- control = (xDiff: number, yDiff: number, controlNum: number) => {
- this.selectedInk?.forEach(action(inkView => {
- if (this.selectedInk?.length === 1) {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK && doc._width && doc._height) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X));
- const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y));
- const ptsXscale = NumCast(doc._width) / (oldXrange.max - oldXrange.min);
- const ptsYscale = NumCast(doc._height) / (oldYrange.max - oldYrange.min);
- const newPoints: { X: number, Y: number }[] = [];
- const order = controlNum % 4;
- for (var i = 0; i < ink.length; i++) {
- newPoints.push(
- (controlNum === i ||
- (order === 0 && i === controlNum + 1) ||
- (order === 0 && controlNum !== 0 && i === controlNum - 2) ||
- (order === 0 && controlNum !== 0 && i === controlNum - 1) ||
- (order === 3 && i === controlNum - 1) ||
- (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) ||
- (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2) ||
- ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1))
- ) ?
- { X: ink[i].X - xDiff / ptsXscale, Y: ink[i].Y - yDiff / ptsYscale } :
- { X: ink[i].X, Y: ink[i].Y });
- }
-
- const newXrange = (xs => ({ min: Math.min(...xs), max: Math.max(...xs) }))(newPoints.map(p => p.X));
- const newYrange = (ys => ({ min: Math.min(...ys), max: Math.max(...ys) }))(newPoints.map(p => p.Y));
-
- //if points move out of bounds
- doc._width = (newXrange.max - newXrange.min) * ptsXscale;
- doc._height = (newYrange.max - newYrange.min) * ptsYscale;
- doc.x = (oldXrange.coord + (newXrange.min - oldXrange.min) * ptsXscale);
- doc.y = (oldYrange.coord + (newYrange.min - oldYrange.min) * ptsYscale);
- Doc.GetProto(doc).data = new InkField(newPoints);
- }
- }
+ control = (xDiff: number, yDiff: number, controlNum: number) =>
+ this.applyFunction((doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => {
+ const newPoints: { X: number, Y: number }[] = [];
+ const order = controlNum % 4;
+ for (var i = 0; i < ink.length; i++) {
+ newPoints.push(
+ (controlNum === i ||
+ (order === 0 && i === controlNum + 1) ||
+ (order === 0 && controlNum !== 0 && i === controlNum - 2) ||
+ (order === 0 && controlNum !== 0 && i === controlNum - 1) ||
+ (order === 3 && i === controlNum - 1) ||
+ (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) ||
+ (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2) ||
+ ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1))
+ ) ?
+ { X: ink[i].X - xDiff / ptsXscale, Y: ink[i].Y - yDiff / ptsYscale } :
+ { X: ink[i].X, Y: ink[i].Y });
}
- }));
- }
+ return newPoints;
+ });
@undoBatch
@action
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 6a4afbb5c..449019ca8 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -161,13 +161,13 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
</svg>);
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="green"
+ <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth} strokeWidth={0} fill="green"
onPointerDown={(e) => this.onControlDown(e, pts.I)} pointerEvents="all" cursor="default" display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} />
</svg>);
const controls = controlPoints.map((pts, i) =>
<svg height="10" width="10" key={`ctrl${i}`}>
- <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth / 3} strokeWidth={0} fill="red"
+ <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="red"
onPointerDown={(e) => { this.changeCurrPoint(pts.I); this.onControlDown(e, pts.I); }} pointerEvents="all" cursor="default"
/>
</svg>);