diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-04-26 17:08:38 -0400 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-04-26 17:08:38 -0400 |
commit | f01b842a5d6ef6b9deb9807fa0c3a8cd2c81a25a (patch) | |
tree | c9e3b3c18dc35f4a3fa3083b69b985821041c879 /src | |
parent | c318c6cb44b26b780e94e0f0854e5ec4c14634a9 (diff) |
TreeView and others
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 3 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 9 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 80 | ||||
-rw-r--r-- | src/client/views/nodes/LinkBox.tsx | 77 | ||||
-rw-r--r-- | src/new_fields/Doc.ts | 2 | ||||
-rw-r--r-- | src/new_fields/InkField.ts | 7 | ||||
-rw-r--r-- | src/new_fields/Types.ts | 4 |
7 files changed, 91 insertions, 91 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ed76f32ff..9511027d3 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -29,11 +29,12 @@ import { Cast } from "../../new_fields/Types"; import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; +import { StrokeData, InkField } from "../../new_fields/InkField"; export interface DocumentOptions { x?: number; y?: number; - // ink?: Map<string, StrokeData>; + ink?: InkField; width?: number; height?: number; nativeWidth?: number; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 675e720e2..e7bf1e121 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -7,7 +7,6 @@ import { CollectionDockingView } from './CollectionDockingView'; import { CollectionTreeView } from './CollectionTreeView'; import { ContextMenu } from '../ContextMenu'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; -import { KeyStore } from '../../../fields/KeyStore'; import { observer } from 'mobx-react'; import { undoBatch } from '../../util/UndoManager'; import { trace } from 'mobx'; @@ -29,13 +28,13 @@ export class CollectionView extends React.Component<FieldViewProps> { return (null); } - get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's? + get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's? onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) }); - ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) }); - ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) }); + ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform) }); + ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema) }); + ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree) }); } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index c6681e014..644a8784c 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,10 +1,6 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { FieldWaiting } from "../../../../fields/Field"; -import { InkField, StrokeData } from "../../../../fields/InkField"; -import { KeyStore } from "../../../../fields/KeyStore"; -import { Documents } from "../../../documents/Documents"; +import { Docs } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; @@ -14,16 +10,19 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; import React = require("react"); import { Utils } from "../../../../Utils"; +import { Doc } from "../../../../new_fields/Doc"; +import { NumCast, Cast } from "../../../../new_fields/Types"; +import { InkField, StrokeData } from "../../../../new_fields/InkField"; interface MarqueeViewProps { getContainerTransform: () => Transform; getTransform: () => Transform; container: CollectionFreeFormView; - addDocument: (doc: Document, allowDuplicates: false) => boolean; - activeDocuments: () => Document[]; - selectDocuments: (docs: Document[]) => void; - removeDocument: (doc: Document) => boolean; - addLiveTextDocument: (doc: Document) => void; + addDocument: (doc: Doc, allowDuplicates: false) => boolean; + activeDocuments: () => Doc[]; + selectDocuments: (docs: Doc[]) => void; + removeDocument: (doc: Doc) => boolean; + addLiveTextDocument: (doc: Doc) => void; } @observer @@ -49,7 +48,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps> onKeyPress = (e: KeyboardEvent) => { //make textbox and add it to this collection let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY); - let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); + let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); this.props.addLiveTextDocument(newBox); e.stopPropagation(); } @@ -64,8 +63,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); } - if (e.altKey) + if (e.altKey) { e.preventDefault(); + } } @action @@ -80,8 +80,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> e.preventDefault(); } } - if (e.altKey) + if (e.altKey) { e.preventDefault(); + } } @action @@ -94,8 +95,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]); } this.cleanupInteractions(true); - if (e.altKey) + if (e.altKey) { e.preventDefault(); + } } @action @@ -127,11 +129,11 @@ export class MarqueeView extends React.Component<MarqueeViewProps> @undoBatch @action marqueeCommand = (e: KeyboardEvent) => { - if (e.key === "Backspace" || e.key === "Delete" || e.key == "d") { + if (e.key === "Backspace" || e.key === "Delete" || e.key === "d") { this.marqueeSelect().map(d => this.props.removeDocument(d)); - let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); - if (ink && ink !== FieldWaiting) { - this.marqueeInkDelete(ink.Data); + let ink = Cast(this.props.container.props.Document.ink, InkField); + if (ink) { + this.marqueeInkDelete(ink.inkData); } this.cleanupInteractions(true); e.stopPropagation(); @@ -141,33 +143,33 @@ export class MarqueeView extends React.Component<MarqueeViewProps> let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { this.props.removeDocument(d); - d.SetNumber(KeyStore.X, d.GetNumber(KeyStore.X, 0) - bounds.left - bounds.width / 2); - d.SetNumber(KeyStore.Y, d.GetNumber(KeyStore.Y, 0) - bounds.top - bounds.height / 2); - d.SetNumber(KeyStore.Page, -1); + d.x = NumCast(d.X) - bounds.left - bounds.width / 2; + d.y = NumCast(d.Y) - bounds.top - bounds.height / 2; + d.page = -1; return d; }); - let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); - let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined; - let zoomBasis = this.props.container.props.Document.GetNumber(KeyStore.Scale, 1); - let newCollection = Documents.FreeformDocument(selected, { + let ink = Cast(this.props.container.props.Document.ink, InkField); + let inkData = ink ? ink.inkData : undefined; + let zoomBasis = NumCast(this.props.container.props.Document.scale, 1); + let newCollection = Docs.FreeformDocument(selected, { x: bounds.left, y: bounds.top, - panx: 0, - pany: 0, + panX: 0, + panY: 0, borderRounding: e.key === "e" ? -1 : undefined, backgroundColor: selected.length ? "white" : "", scale: zoomBasis, width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, - ink: inkData ? this.marqueeInkSelect(inkData) : undefined, + ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined, title: "a nested collection" }); this.marqueeInkDelete(inkData); SelectionManager.DeselectAll(); if (e.key === "r") { - let summary = Documents.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - summary.GetPrototype()!.CreateLink(newCollection.GetPrototype()!); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + Doc.MakeLink(summary.proto!, newCollection.proto!); this.props.addLiveTextDocument(summary); e.preventDefault(); } @@ -182,9 +184,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> let bounds = this.Bounds; let selected = this.marqueeSelect(); SelectionManager.DeselectAll(); - let summary = Documents.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + let summary = Docs.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); this.props.addLiveTextDocument(summary); - selected.map(select => summary.GetPrototype()!.CreateLink(select.GetPrototype()!)); + selected.forEach(select => Doc.MakeLink(summary.proto!, select.proto!)); this.cleanupInteractions(true); } @@ -219,19 +221,19 @@ export class MarqueeView extends React.Component<MarqueeViewProps> let idata = new Map(); ink.forEach((value: StrokeData, key: string, map: any) => !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value)); - this.props.container.props.Document.SetDataOnPrototype(KeyStore.Ink, idata, InkField); + Doc.SetOnPrototype(this.props.container.props.Document, "ink", new InkField(idata)); } } marqueeSelect() { let selRect = this.Bounds; - let selection: Document[] = []; + let selection: Doc[] = []; this.props.activeDocuments().map(doc => { - var z = doc.GetNumber(KeyStore.ZoomBasis, 1); - var x = doc.GetNumber(KeyStore.X, 0); - var y = doc.GetNumber(KeyStore.Y, 0); - var w = doc.Width() / z; - var h = doc.Height() / z; + var z = NumCast(doc.zoomBasis, 1); + var x = NumCast(doc.x); + var y = NumCast(doc.y); + var w = NumCast(doc.width) / z; + var h = NumCast(doc.height) / z; if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) { selection.push(doc); } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 1c0e316e8..9bb90de0d 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -2,15 +2,14 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faEdit, faEye, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observer } from "mobx-react"; -import { Document } from "../../../fields/Document"; -import { KeyStore } from '../../../fields/KeyStore'; -import { ListField } from "../../../fields/ListField"; -import { NumberField } from "../../../fields/NumberField"; import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import './LinkBox.scss'; import React = require("react"); +import { Doc } from '../../../new_fields/Doc'; +import { Cast, NumCast } from '../../../new_fields/Types'; +import { listSpec } from '../../../new_fields/Schema'; library.add(faEye); @@ -18,9 +17,9 @@ library.add(faEdit); library.add(faTimes); interface Props { - linkDoc: Document; + linkDoc: Doc; linkName: String; - pairedDoc: Document; + pairedDoc: Doc; type: String; showEditor: () => void; } @@ -29,62 +28,52 @@ interface Props { export class LinkBox extends React.Component<Props> { @undoBatch - onViewButtonPressed = (e: React.PointerEvent): void => { + onViewButtonPressed = async (e: React.PointerEvent): Promise<void> => { e.stopPropagation(); let docView = DocumentManager.Instance.getDocumentView(this.props.pairedDoc); if (docView) { docView.props.focus(docView.props.Document); } else { - this.props.pairedDoc.GetAsync(KeyStore.AnnotationOn, (contextDoc: any) => { - if (!contextDoc) { - CollectionDockingView.Instance.AddRightSplit(this.props.pairedDoc.MakeDelegate()); - } else if (contextDoc instanceof Document) { - this.props.pairedDoc.GetTAsync(KeyStore.Page, NumberField).then((pfield: any) => { - contextDoc.GetTAsync(KeyStore.CurPage, NumberField).then((cfield: any) => { - if (pfield !== cfield) { - contextDoc.SetNumber(KeyStore.CurPage, pfield.Data); - } - let contextView = DocumentManager.Instance.getDocumentView(contextDoc); - if (contextView) { - contextView.props.focus(contextDoc); - } else { - CollectionDockingView.Instance.AddRightSplit(contextDoc); - } - }); - }); + const contextDoc = await Cast(this.props.pairedDoc.annotationOn, Doc); + if (!contextDoc) { + CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(this.props.pairedDoc)); + } else { + const page = NumCast(this.props.pairedDoc.page, undefined); + const curPage = NumCast(contextDoc.curPage, undefined); + if (page !== curPage) { + contextDoc.curPage = page; } - }); + let contextView = DocumentManager.Instance.getDocumentView(contextDoc); + if (contextView) { + contextView.props.focus(contextDoc); + } else { + CollectionDockingView.Instance.AddRightSplit(contextDoc); + } + } } } onEditButtonPressed = (e: React.PointerEvent): void => { - console.log("edit down"); e.stopPropagation(); this.props.showEditor(); } - onDeleteButtonPressed = (e: React.PointerEvent): void => { - console.log("delete down"); + onDeleteButtonPressed = async (e: React.PointerEvent): Promise<void> => { e.stopPropagation(); - this.props.linkDoc.GetTAsync(KeyStore.LinkedFromDocs, Document, field => { - if (field) { - field.GetTAsync<ListField<Document>>(KeyStore.LinkedToDocs, ListField, field => { - if (field) { - field.Data.splice(field.Data.indexOf(this.props.linkDoc)); - } - }); + const [linkedFrom, linkedTo] = await Promise.all([Cast(this.props.linkDoc.linkedFrom, Doc), Cast(this.props.linkDoc.linkedTo, Doc)]); + if (linkedFrom) { + const linkedToDocs = Cast(linkedFrom.linkedToDocs, listSpec(Doc)); + if (linkedToDocs) { + linkedToDocs.splice(linkedToDocs.indexOf(this.props.linkDoc)); } - }); - this.props.linkDoc.GetTAsync(KeyStore.LinkedToDocs, Document, field => { - if (field) { - field.GetTAsync<ListField<Document>>(KeyStore.LinkedFromDocs, ListField, field => { - if (field) { - field.Data.splice(field.Data.indexOf(this.props.linkDoc)); - } - }); + } + if (linkedTo) { + const linkedFromDocs = Cast(linkedTo.linkedToDocs, listSpec(Doc)); + if (linkedFromDocs) { + linkedFromDocs.splice(linkedFromDocs.indexOf(this.props.linkDoc)); } - }); + } } render() { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 79e5a156d..a5f495477 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -91,7 +91,7 @@ export namespace Doc { return Cast(Get(doc, key, ignoreProto), ctor) as T | null | undefined; } export async function SetOnPrototype(doc: Doc, key: string, value: Field) { - const proto = await Cast(doc.proto, Doc); + const proto = doc.proto; if (proto) { proto[key] = value; } diff --git a/src/new_fields/InkField.ts b/src/new_fields/InkField.ts index cdb34cedf..49e6bf61e 100644 --- a/src/new_fields/InkField.ts +++ b/src/new_fields/InkField.ts @@ -27,5 +27,10 @@ const strokeDataSchema = createSimpleSchema({ export class InkField extends ObjectField { @serializable(map(object(strokeDataSchema))) - readonly inkData: Map<string, StrokeData> = new Map; + readonly inkData: Map<string, StrokeData>; + + constructor(data?: Map<string, StrokeData>) { + super(); + this.inkData = data || new Map; + } } diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 079c7b76d..649dfdc3e 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -67,6 +67,10 @@ export function StrCast(field: FieldResult, defaultVal: Opt<string> = "") { return Cast(field, "string", defaultVal); } +export function BoolCast(field: FieldResult, defaultVal: Opt<boolean> = undefined) { + return Cast(field, "boolean", defaultVal); +} + type WithoutList<T extends Field> = T extends List<infer R> ? R[] : T; export function FieldValue<T extends Field, U extends WithoutList<T>>(field: Opt<T> | Promise<Opt<T>>, defaultValue: U): WithoutList<T>; |