diff options
-rw-r--r-- | src/client/util/DragManager.ts | 6 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 3 | ||||
-rw-r--r-- | src/client/views/PreviewCursor.tsx | 8 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 33 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 16 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 38 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 2 | ||||
-rw-r--r-- | src/fields/Document.ts | 31 |
8 files changed, 80 insertions, 57 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 91b3ce616..5aa7ad8e2 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -41,11 +41,11 @@ export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: } export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Document) { - let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document); - let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ? + let srcTarg = sourceDoc.GetPrototype(); + let draggedDocs = srcTarg ? srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc => (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : []; - let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ? + let draggedFromDocs = srcTarg ? srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc => (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : []; draggedDocs.push(...draggedFromDocs); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 5c57a829a..9995c1c3f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -6,7 +6,7 @@ import { ListField } from "../../fields/ListField"; import { NumberField } from "../../fields/NumberField"; import { TextField } from "../../fields/TextField"; import { Document } from "../../fields/Document"; -import { emptyFunction } from "../../Utils"; +import { emptyFunction, Utils } from "../../Utils"; import { DragLinksAsDocuments, DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; import { undoBatch } from "../util/UndoManager"; @@ -19,7 +19,6 @@ import { CompileScript } from "../util/Scripting"; import { IconBox } from "./nodes/IconBox"; import { FieldValue, Field } from "../../fields/Field"; import { Documents } from "../documents/Documents"; -import { Utils } from "../northstar/utils/Utils"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 39b6c6544..744ec0535 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -17,7 +17,7 @@ export class PreviewCursor extends React.Component<{}> { constructor(props: any) { super(props); - document.addEventListener("keypress", this.onKeyPress) + document.addEventListener("keydown", this.onKeyPress) } @action @@ -28,8 +28,12 @@ export class PreviewCursor extends React.Component<{}> { //if not these keys, make a textbox if preview cursor is active! if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e); + PreviewCursor.Visible = false; + } else if (e.ctrlKey) { + if (e.key == "v") { + PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e); + } } - PreviewCursor.Visible = false; } @action public static Show(x: number, y: number, onKeyPress: (e: KeyboardEvent) => void) { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 39b42dac9..898fff019 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -14,6 +14,7 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; import React = require("react"); import { Utils } from "../../../../Utils"; +import { ListField } from "../../../../fields/ListField"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -128,16 +129,16 @@ export class MarqueeView extends React.Component<MarqueeViewProps> @undoBatch @action marqueeCommand = (e: KeyboardEvent) => { - if (e.key === "Backspace" || e.key === "Delete") { + 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); } - this.cleanupInteractions(); + this.cleanupInteractions(true); e.stopPropagation(); } - if (e.key === "c") { + if (e.key === "c" || e.key === "r") { e.stopPropagation(); let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { @@ -155,16 +156,38 @@ export class MarqueeView extends React.Component<MarqueeViewProps> y: bounds.top, panx: 0, pany: 0, + backgroundColor: selected.length ? "white" : "", scale: zoomBasis, width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, ink: inkData ? this.marqueeInkSelect(inkData) : undefined, title: "a nested collection" }); - this.props.addDocument(newCollection, false); + this.marqueeInkDelete(inkData); - this.cleanupInteractions(); 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()!); + this.props.addLiveTextDocument(summary); + e.preventDefault(); + } + else { + this.props.addDocument(newCollection, false); + } + this.cleanupInteractions(true); + } + if (e.key === "s") { + e.stopPropagation(); + e.preventDefault(); + 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-" }); + this.props.addLiveTextDocument(summary); + selected.map(select => summary.GetPrototype()!.CreateLink(select.GetPrototype()!)); + + this.cleanupInteractions(true); } } @action diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 671bfbc04..420324d40 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -7,7 +7,7 @@ import { Transform } from "../../util/Transform"; import { DocumentView, DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import React = require("react"); -import { OmitKeys } from "../../../Utils"; +import { OmitKeys, Utils } from "../../../Utils"; import { SelectionManager } from "../../util/SelectionManager"; import { ListField } from "../../../fields/ListField"; import { BooleanField } from "../../../fields/BooleanField"; @@ -102,9 +102,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr public toggleIcon = async (): Promise<void> => { SelectionManager.DeselectAll(); let isMinimized: boolean | undefined; - let minDoc = await this.props.Document.GetTAsync(KeyStore.MinimizedDoc, Document); - if (!minDoc) return; - let minimizedDocSet = await minDoc.GetTAsync(KeyStore.LinkTags, ListField); + let minimizedDocSet = await this.props.Document.GetTAsync(KeyStore.LinkTags, ListField); if (!minimizedDocSet) return; minimizedDocSet.Data.map(async minimizedDoc => { if (minimizedDoc instanceof Document) { @@ -136,16 +134,13 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; this._downY = e.clientY; - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); } - onPointerUp = (e: PointerEvent): void => { - document.removeEventListener("pointerup", this.onPointerUp); + onClick = (e: React.MouseEvent): void => { e.stopPropagation(); - if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { + if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && + Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) { this.props.Document.GetTAsync(KeyStore.MaximizedDoc, Document).then(maxdoc => { if (maxdoc instanceof Document) { // bcz: need a better way to associate behaviors with click events on widget-documents - SelectionManager.DeselectAll(); this.props.addDocument && this.props.addDocument(maxdoc, false); this.toggleIcon(); } @@ -170,6 +165,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr return ( <div className="collectionFreeFormDocumentView-container" ref={this._mainCont} onPointerDown={this.onPointerDown} + onClick={this.onClick} style={{ opacity: zoomFade, transformOrigin: "left top", diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 252f4d039..c19b0c342 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -152,7 +152,6 @@ export class DocumentView extends React.Component<DocumentViewProps> { Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { SelectionManager.SelectDoc(this, e.ctrlKey); } - e.stopPropagation(); } onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; @@ -217,43 +216,12 @@ export class DocumentView extends React.Component<DocumentViewProps> { @action drop = (e: Event, de: DragManager.DropEvent) => { if (de.data instanceof DragManager.LinkDragData) { - let sourceDoc: Document = de.data.linkSourceDocument; - let destDoc: Document = this.props.Document; - let linkDoc: Document = new Document(); + let sourceDoc = de.data.linkSourceDocument; + let destDoc = this.props.Document; destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest => sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc => - runInAction(() => { - let batch = UndoManager.StartBatch("document view drop"); - linkDoc.SetText(KeyStore.Title, "New Link"); - linkDoc.SetText(KeyStore.LinkDescription, ""); - linkDoc.SetText(KeyStore.LinkTags, "Default"); - - let dstTarg = protoDest ? protoDest : destDoc; - let srcTarg = protoSrc ? protoSrc : sourceDoc; - if ((de.data as DragManager.LinkDragData).blacklist.indexOf(dstTarg) === -1) { - linkDoc.Set(KeyStore.LinkedToDocs, dstTarg); - linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg); - const prom1 = new Promise(resolve => dstTarg.GetOrCreateAsync( - KeyStore.LinkedFromDocs, - ListField, - field => { - (field as ListField<Document>).Data.push(linkDoc); - resolve(); - } - )); - const prom2 = new Promise(resolve => srcTarg.GetOrCreateAsync( - KeyStore.LinkedToDocs, - ListField, - field => { - (field as ListField<Document>).Data.push(linkDoc); - resolve(); - } - )); - Promise.all([prom1, prom2]).finally(() => batch.end()); - } - }) - ) + (protoSrc ? protoSrc : sourceDoc).CreateLink(protoDest ? protoDest : destDoc)) ); e.stopPropagation(); } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 91b44962d..9cd58c73a 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -270,8 +270,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte } render() { let style = this.props.isOverlay ? "scroll" : "hidden"; + let color = this.props.Document.GetText(KeyStore.BackgroundColor, ""); return ( <div className={`formattedTextBox-cont-${style}`} + style={{ background: color }} onKeyDown={this.onKeyPress} onKeyPress={this.onKeyPress} onFocus={this.onFocused} diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 7cf784f0e..7a7dbc3fe 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -371,6 +371,37 @@ export class Document extends Field { return alias; } + @action + CreateLink(dstTarg: Document) { + let batch = UndoManager.StartBatch("document view drop"); + let linkDoc: Document = new Document(); + linkDoc.SetText(KeyStore.Title, "New Link"); + linkDoc.SetText(KeyStore.LinkDescription, ""); + linkDoc.SetText(KeyStore.LinkTags, "Default"); + + let srcTarg = this; + linkDoc.Set(KeyStore.LinkedToDocs, dstTarg); + linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg); + const prom1 = new Promise(resolve => dstTarg.GetOrCreateAsync( + KeyStore.LinkedFromDocs, + ListField, + field => { + (field as ListField<Document>).Data.push(linkDoc); + resolve(); + } + )); + const prom2 = new Promise(resolve => srcTarg.GetOrCreateAsync( + KeyStore.LinkedToDocs, + ListField, + field => { + (field as ListField<Document>).Data.push(linkDoc); + resolve(); + } + )); + Promise.all([prom1, prom2]).finally(() => batch.end()); + return linkDoc; + } + MakeDelegate(id?: string): Document { let delegate = new Document(id); |