aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DragManager.ts10
-rw-r--r--src/client/views/DocumentDecorations.scss8
-rw-r--r--src/client/views/DocumentDecorations.tsx10
-rw-r--r--src/client/views/collections/CollectionMapView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx14
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx53
6 files changed, 75 insertions, 22 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 66c7ecf7d..2a9c1633a 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -263,16 +263,16 @@ export namespace DragManager {
const denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
if (denominator === 0) return undefined; // Lines are parallel
- let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
+ const ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
// let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator;
//if (ua < 0 || ua > 1 || ub < 0 || ub > 1) return undefined; // is the intersection along the segments
// Return a object with the x and y coordinates of the intersection
- let x = x1 + ua * (x2 - x1)
- let y = y1 + ua * (y2 - y1)
+ const x = x1 + ua * (x2 - x1);
+ const y = y1 + ua * (y2 - y1);
const dist = Math.sqrt((dragx - x) * (dragx - x) + (dragy - y) * (dragy - y));
- return { pt: [x, y], dist }
- }
+ return { pt: [x, y], dist };
+ };
SnappingManager.vertSnapLines().forEach((xCoord, i) => {
const pt = intersect(dragPt[0], dragPt[1], dragPt[0] + snapAspect, dragPt[1] + 1, xCoord, -1, xCoord, 1, dragPt[0], dragPt[1]);
if (pt && pt.dist < closest) {
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 15eb537da..a4d4af2f0 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -138,9 +138,10 @@ $linkGap : 3px;
.documentDecorations-contextMenu {
width: 25px;
height: calc(100% + 8px); // 8px for the height of the top resizer bar
- grid-column-start: 1;
+ grid-column-start: 2;
grid-column-end : 2;
pointer-events: all;
+ padding-left: 5px;
}
.documentDecorations-title {
opacity: 1;
@@ -185,9 +186,12 @@ $linkGap : 3px;
position: absolute;
left: 0px;
top: 0px;
- width: $MINIMIZED_ICON_SIZE;
+ width: 8px;
height: $MINIMIZED_ICON_SIZE;
max-height: 20px;
+ > svg {
+ margin:0;
+ }
}
.documentDecorations-background {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 1f4f45f0e..fc7c16296 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -476,12 +476,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
<FontAwesomeIcon size="lg" color={SelectionManager.SelectedDocuments()[0].props.Document.title === SelectionManager.SelectedDocuments()[0].props.Document[Id] ? "green" : undefined} icon="sticky-note"></FontAwesomeIcon>
</div>}
</> :
- <div className="documentDecorations-title" onPointerDown={this.onTitleDown} >
- {minimal ? (null) : <div className="documentDecorations-contextMenu" title="Show context menu" onPointerDown={this.onSettingsDown}>
+ <>
+ {minimal ? (null) : <div className="documentDecorations-contextMenu" key="menu" title="Show context menu" onPointerDown={this.onSettingsDown}>
<FontAwesomeIcon size="lg" icon="cog" />
</div>}
- <span style={{ width: "calc(100% - 25px)", display: "inline-block" }}>{`${this.selectionTitle}`}</span>
- </div>;
+ <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
+ <span style={{ width: "calc(100% - 25px)", display: "inline-block" }}>{`${this.selectionTitle}`}</span>
+ </div>
+ </>
bounds.x = Math.max(0, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
bounds.y = Math.max(0, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight;
diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx
index da902cecd..d91337ce9 100644
--- a/src/client/views/collections/CollectionMapView.tsx
+++ b/src/client/views/collections/CollectionMapView.tsx
@@ -1,4 +1,4 @@
-import { GoogleApiWrapper, Map as GeoMap, MapProps as IMapProps, Marker } from "google-maps-react";
+import { GoogleApiWrapper, Map as GeoMap, IMapProps, Marker } from "google-maps-react";
import { observer } from "mobx-react";
import { Doc, Opt, DocListCast, FieldResult, Field } from "../../../fields/Doc";
import { documentSchema } from "../../../fields/documentSchemas";
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a4e843c8e..c9eb08b45 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -206,6 +206,8 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
}
}
+ addDocument = (doc: Doc | Doc[]) => this.props.addDocument(doc);
+
@undoBatch
@action
protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
@@ -214,21 +216,21 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
if (docDragData) {
let added = false;
if (docDragData.dropAction || docDragData.userDropAction) {
- added = this.props.addDocument(docDragData.droppedDocuments);
+ added = this.addDocument(docDragData.droppedDocuments);
} else if (docDragData.moveDocument) {
const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
- const res = addedDocs.length ? this.props.addDocument(addedDocs) : true;
- added = movedDocs.length ? docDragData.moveDocument(movedDocs, this.props.Document, this.props.addDocument) : res;
+ const res = addedDocs.length ? this.addDocument(addedDocs) : true;
+ added = movedDocs.length ? docDragData.moveDocument(movedDocs, this.props.Document, this.addDocument) : res;
} else {
- added = this.props.addDocument(docDragData.droppedDocuments);
+ added = this.addDocument(docDragData.droppedDocuments);
}
e.stopPropagation();
return added;
}
else if (de.complete.annoDragData) {
e.stopPropagation();
- return this.props.addDocument(de.complete.annoDragData.dropDocument);
+ return this.addDocument(de.complete.annoDragData.dropDocument);
}
return false;
}
@@ -265,7 +267,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
e.stopPropagation();
e.preventDefault();
- const { addDocument } = this.props;
+ const { addDocument } = this;
if (!addDocument) {
alert("this.props.addDocument does not exist. Aborting drop operation.");
return;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index af78fbe34..bf679309c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -11,11 +11,11 @@ import { InkData, InkField, InkTool, PointData } from "../../../../fields/InkFie
import { List } from "../../../../fields/List";
import { RichTextField } from "../../../../fields/RichTextField";
import { createSchema, listSpec, makeInterface } from "../../../../fields/Schema";
-import { ScriptField } from "../../../../fields/ScriptField";
+import { ScriptField, ComputedField } from "../../../../fields/ScriptField";
import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
import { TraceMobx } from "../../../../fields/util";
import { GestureUtils } from "../../../../pen-gestures/GestureUtils";
-import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse } from "../../../../Utils";
+import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse, numberRange } from "../../../../Utils";
import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
import { DocServer } from "../../../DocServer";
import { Docs } from "../../../documents/Documents";
@@ -46,7 +46,6 @@ import React = require("react");
import { CollectionViewType } from "../CollectionView";
import { Timeline } from "../../animationtimeline/Timeline";
import { SnappingManager } from "../../../util/SnappingManager";
-import GestureOverlay from "../../GestureOverlay";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
@@ -124,7 +123,18 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
this.addDocument(newBox);
}
- private addDocument = (newBox: Doc | Doc[]) => {
+ addDocument = (newBox: Doc | Doc[]) => {
+ const timecode = Cast(this.props.Document.timecode, "number", null);
+ if (timecode !== undefined) {
+ ((newBox instanceof Doc) ? [newBox] : newBox).map(doc => {
+ doc["x-indexed"] = new List<number>(numberRange(timecode + 1).map(i => NumCast(doc.x)));
+ doc["y-indexed"] = new List<number>(numberRange(timecode + 1).map(i => NumCast(doc.y)));
+ doc.timecode = ComputedField.MakeFunction("collection.timecode", {}, { collection: this.props.Document });
+ doc.x = ComputedField.MakeInterpolated("x", "timecode");
+ doc.y = ComputedField.MakeInterpolated("y", "timecode");
+ });
+ }
+
if (newBox instanceof Doc) {
const added = this.props.addDocument(newBox);
added && this.bringToFront(newBox);
@@ -1132,6 +1142,39 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth(), this.props.NativeHeight());
}
+ @undoBatch
+ @action
+ snaphsotInterpolated = (): void => {
+ if (this.props.Document.timecode === undefined) {
+ this.childDocs.map(doc => {
+ this.props.Document.timecode = 0;
+ doc["x-indexed"] = new List<number>([NumCast(doc.x)]);
+ doc["y-indexed"] = new List<number>([NumCast(doc.y)]);
+ doc.timecode = ComputedField.MakeFunction("collection.timecode", {}, { collection: this.props.Document });
+ doc.x = ComputedField.MakeInterpolated("x", "timecode");
+ doc.y = ComputedField.MakeInterpolated("y", "timecode");
+ });
+ }
+ const timecode = NumCast(this.props.Document.timecode);
+ this.childDocs.map(doc => {
+ const xindexed = Cast(doc['x-indexed'], listSpec("number"), null);
+ const yindexed = Cast(doc['y-indexed'], listSpec("number"), null);
+ xindexed.length <= timecode + 1 && xindexed.push(NumCast(doc.x));
+ yindexed.length <= timecode + 1 && yindexed.push(NumCast(doc.y));
+ });
+ this.childDocs.map(doc => doc.transition = "transform 1s");
+ this.props.Document.timecode = Math.max(0, timecode + 1);
+ setTimeout(() => this.childDocs.map(doc => doc.transition = undefined), 1010);
+ }
+ @undoBatch
+ @action
+ backupInterpolated = (): void => {
+ this.childDocs.map(doc => doc.transition = "transform 1s");
+ this.props.Document.timecode = Math.max(0, NumCast(this.props.Document.timecode) - 1);
+ setTimeout(() => this.childDocs.map(doc => doc.transition = undefined), 1010);
+ }
+
+
private thumbIdentifier?: number;
onContextMenu = (e: React.MouseEvent) => {
@@ -1142,6 +1185,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this._timelineVisible = !this._timelineVisible;
}), icon: this._timelineVisible ? faEyeSlash : faEye
});
+ ContextMenu.Instance.addItem({ description: "Advance", event: this.snaphsotInterpolated, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" });
+ ContextMenu.Instance.addItem({ description: "Backup ", event: this.backupInterpolated, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" });
const options = ContextMenu.Instance.findByDescription("Options...");
const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];