From b742c8850b184408fd61d8571fa68ecf01386141 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 26 Apr 2019 00:08:21 -0400 Subject: fixed some things with pdfs --- .../views/collections/CollectionPDFView.scss | 26 +++++++++++++++-- src/client/views/collections/CollectionPDFView.tsx | 34 +++++++++++++++++++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 8 ++--- 3 files changed, 57 insertions(+), 11 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss index 0eca3f1cd..f6fb79582 100644 --- a/src/client/views/collections/CollectionPDFView.scss +++ b/src/client/views/collections/CollectionPDFView.scss @@ -1,20 +1,39 @@ .collectionPdfView-buttonTray { - top : 25px; + top : 15px; left : 20px; position: relative; transform-origin: left top; position: absolute; } +.collectionPdfView-thumb { + width:25px; + height:25px; + transform-origin: left top; + position: absolute; + background: darkgray; +} +.collectionPdfView-slider { + width:25px; + height:25px; + transform-origin: left top; + position: absolute; + background: lightgray; +} .collectionPdfView-cont{ width: 100%; height: 100%; position: absolute; top: 0; left:0; - +} +.collectionPdfView-cont-dragging { + span { + user-select: none; + } } .collectionPdfView-backward { color : white; + font-size: 24px; top :0px; left : 0px; position: absolute; @@ -22,8 +41,9 @@ } .collectionPdfView-forward { color : white; + font-size: 24px; top :0px; - left : 35px; + left : 45px; position: absolute; background-color: rgba(50, 50, 50, 0.2); } \ No newline at end of file diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index 229bc4059..497c3ee3c 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -1,4 +1,4 @@ -import { action } from "mobx"; +import { action, observable } from "mobx"; import { observer } from "mobx-react"; import { KeyStore } from "../../../fields/KeyStore"; import { ContextMenu } from "../ContextMenu"; @@ -16,18 +16,44 @@ export class CollectionPDFView extends React.Component { public static LayoutString(fieldKey: string = "DataKey") { return FieldView.LayoutString(CollectionPDFView, fieldKey); } + @observable _inThumb = false; private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); } + private set curPage(value: number) { this.props.Document.SetNumber(KeyStore.CurPage, value); } private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); } @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : -1; @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : -1; + @action + onThumbDown = (e: React.PointerEvent) => { + document.addEventListener("pointermove", this.onThumbMove, false); + document.addEventListener("pointerup", this.onThumbUp, false); + e.stopPropagation(); + this._inThumb = true; + } + @action + onThumbMove = (e: PointerEvent) => { + let pso = (e.clientY - (e as any).target.parentElement.getBoundingClientRect().top) / (e as any).target.parentElement.getBoundingClientRect().height; + this.curPage = Math.trunc(Math.min(this.numPages, pso * this.numPages + 1)); + e.stopPropagation(); + } + @action + onThumbUp = (e: PointerEvent) => { + this._inThumb = false; + document.removeEventListener("pointermove", this.onThumbMove); + document.removeEventListener("pointerup", this.onThumbUp); + } + nativeWidth = () => this.props.Document.GetNumber(KeyStore.NativeWidth, 0); + nativeHeight = () => this.props.Document.GetNumber(KeyStore.NativeHeight, 0); private get uIButtons() { - let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale); + let ratio = (this.curPage - 1) / this.numPages * 100; return ( -
+
+
+
+
); } @@ -50,7 +76,7 @@ export class CollectionPDFView extends React.Component { render() { return ( - + {this.subView} ); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 56342c84c..405594eb1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -283,7 +283,7 @@ export class CollectionFreeFormView extends CollectionSubView { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); } - private childViews = () => [...this.views, ]; + private childViews = () => [...this.views, ]; render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; return ( @@ -307,7 +307,7 @@ export class CollectionFreeFormView extends CollectionSubView { - +
); @@ -328,12 +328,12 @@ class CollectionFreeFormOverlayView extends React.Component { } @observer -class CollectionFreeFormBackgroundView extends React.Component { +class CollectionFreeFormBackgroundView extends React.Component boolean }> { @computed get backgroundView() { let backgroundLayout = this.props.Document.GetText(KeyStore.BackgroundLayout, ""); return !backgroundLayout ? (null) : (); + isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />); } render() { return this.backgroundView; -- cgit v1.2.3-70-g09d2 From b2d9133f2fdb6dd2af3b74c4dd9de49145611b1b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 26 Apr 2019 22:08:20 -0400 Subject: fixed previewcursor appearing on select. adjusted rounded border text. --- src/client/views/PreviewCursor.tsx | 2 +- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/collections/collectionFreeForm/MarqueeView.tsx | 6 +++++- src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/FormattedTextBox.scss | 11 ++++++++++- src/client/views/nodes/FormattedTextBox.tsx | 11 +++++++---- 6 files changed, 25 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 2e63f751b..4359ba093 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -27,7 +27,7 @@ export class PreviewCursor extends React.Component<{}> { // the keyPress here. //if not these keys, make a textbox if preview cursor is active! if (e.key.startsWith("F") && !e.key.endsWith("F")) { - } else if (e.key != "Alt" && e.key != "Shift" && e.key != "Meta" && e.key != "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { + } else if (e.key != "Escape" && e.key != "Alt" && e.key != "Shift" && e.key != "Meta" && e.key != "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { if ((!e.ctrlKey && !e.metaKey) || e.key === "v") { PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e); PreviewCursor.Visible = false; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 405594eb1..1a953006a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -295,7 +295,7 @@ export class CollectionFreeFormView extends CollectionSubView { {this.props.Document.Title} */} - void; removeDocument: (doc: Document) => boolean; addLiveTextDocument: (doc: Document) => void; + isSelected: () => boolean; } @observer @@ -102,7 +103,9 @@ export class MarqueeView extends React.Component onClick = (e: React.MouseEvent): void => { if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) { - PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress); + if (this.props.isSelected()) { + PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress); + } // let the DocumentView stopPropagation of this event when it selects this document } else { // why do we get a click event when the cursor have moved a big distance? // let's cut it off here so no one else has to deal with it. @@ -137,6 +140,7 @@ export class MarqueeView extends React.Component e.stopPropagation(); } if (e.key === "c" || e.key === "r" || e.key === "e") { + console.log("DO MARQUEE"); e.stopPropagation(); let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index aaedd5b1c..3d6e0c4d8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -172,6 +172,7 @@ export class DocumentView extends React.Component { document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); e.preventDefault(); + e.stopPropagation(); } } onPointerMove = (e: PointerEvent): void => { diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index f4f37250f..727d3c0b2 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -10,7 +10,7 @@ outline: none !important; } -.formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden { +.formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden { background: $light-color-secondary; padding: 0; border-width: 0px; @@ -24,10 +24,19 @@ height: 100%; pointer-events: all; } + .formattedTextBox-cont-hidden { overflow: hidden; pointer-events: none; } +.formattedTextBox-inner-rounded { + height: calc(100% - 40px); + width: calc(100% - 40px); + position: absolute; + overflow: scroll; + top: 20; + left: 20; +} .menuicon { display: inline-block; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 8fb86f320..02d98de6b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -270,11 +270,12 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte }; } render() { - let style = this.props.isOverlay ? "scroll" : "hidden"; + let style = this.props.isOverlay ? "-scroll" : "-hidden"; + let rounded = this.props.Document.GetNumber(KeyStore.BorderRounding, 0) < 0 ? "-rounded" : ""; let color = this.props.Document.GetText(KeyStore.BackgroundColor, ""); - let interactive = InkingControl.Instance.selectedTool ? "" : "interactive"; + let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; return ( -
+ > +
+
); } } -- cgit v1.2.3-70-g09d2 From e2bb0381150aa62c041f3fc6beb0a7b0fed7b58e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Apr 2019 00:41:29 -0400 Subject: fixed various interactions with marquee --- src/client/views/collections/CollectionBaseView.tsx | 3 +-- .../collections/collectionFreeForm/MarqueeView.tsx | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 87b767c93..6cb650770 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -104,8 +104,7 @@ export class CollectionBaseView extends React.Component { // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument? if (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid) { let zoom = this.props.Document.GetNumber(KeyStore.Scale, 1); - let screen = this.props.ScreenToLocalTransform().inverse().Scale / (this.props as any).ContentScaling() * zoom; - doc.SetNumber(KeyStore.ZoomBasis, screen); + doc.SetNumber(KeyStore.ZoomBasis, zoom); } } return true; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 0e2ac0a80..89308d573 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -35,12 +35,13 @@ export class MarqueeView extends React.Component @observable _downX: number = 0; @observable _downY: number = 0; @observable _visible: boolean = false; + _commandExecuted = false; @action cleanupInteractions = (all: boolean = false) => { if (all) { - document.removeEventListener("pointermove", this.onPointerMove, true); document.removeEventListener("pointerup", this.onPointerUp, true); + document.removeEventListener("pointermove", this.onPointerMove, true); } document.removeEventListener("keydown", this.marqueeCommand, true); this._visible = false; @@ -58,6 +59,7 @@ export class MarqueeView extends React.Component onPointerDown = (e: React.PointerEvent): void => { this._downX = this._lastX = e.pageX; this._downY = this._lastY = e.pageY; + this._commandExecuted = false; PreviewCursor.Visible = false; if ((CollectionFreeFormView.RIGHT_BTN_DRAG && e.button === 0 && !e.altKey && !e.metaKey && this.props.container.props.active()) || (!CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && this.props.container.props.active())) { @@ -130,17 +132,21 @@ export class MarqueeView extends React.Component @undoBatch @action marqueeCommand = (e: KeyboardEvent) => { + if (this._commandExecuted) { + return; + } if (e.key === "Backspace" || e.key === "Delete" || e.key == "d") { + this._commandExecuted = true; 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(true); + this.cleanupInteractions(false); e.stopPropagation(); } if (e.key === "c" || e.key === "r" || e.key === "e") { - console.log("DO MARQUEE"); + this._commandExecuted = true; e.stopPropagation(); let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { @@ -159,7 +165,6 @@ export class MarqueeView extends React.Component panx: 0, pany: 0, borderRounding: e.key === "e" ? -1 : undefined, - backgroundColor: selected.length ? "white" : "", scale: zoomBasis, width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, @@ -178,9 +183,10 @@ export class MarqueeView extends React.Component else { this.props.addDocument(newCollection, false); } - this.cleanupInteractions(true); + this.cleanupInteractions(false); } if (e.key === "s") { + this._commandExecuted = true; e.stopPropagation(); e.preventDefault(); let bounds = this.Bounds; @@ -190,7 +196,7 @@ export class MarqueeView extends React.Component this.props.addLiveTextDocument(summary); selected.map(select => summary.GetPrototype()!.CreateLink(select.GetPrototype()!)); - this.cleanupInteractions(true); + this.cleanupInteractions(false); } } @action -- cgit v1.2.3-70-g09d2 From a367ba38db64e758e04ee1139a89400113e22bc4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Apr 2019 00:42:25 -0400 Subject: undo for golden layout that's still not working. --- src/client/views/collections/CollectionDockingView.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 3267f2455..2a8191c3a 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -10,7 +10,7 @@ import Measure from "react-measure"; import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field"; import { Utils, returnTrue, emptyFunction, emptyDocFunction, returnOne, returnZero } from "../../../Utils"; import { Server } from "../../Server"; -import { undoBatch } from "../../util/UndoManager"; +import { undoBatch, UndoManager } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; import React = require("react"); @@ -48,7 +48,11 @@ export class CollectionDockingView extends React.Component this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener. onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 })); @@ -236,6 +240,11 @@ export class CollectionDockingView extends React.Component { var json = JSON.stringify(this._goldenLayout.toConfig()); this.props.Document.SetText(KeyStore.Data, json); + if (this.undohack && !this.hack) { + this.undohack.end(); + this.undohack = undefined; + } + this.hack = false; } itemDropped = () => { -- cgit v1.2.3-70-g09d2 From 36fd1b6b6c1ba02be08609176ed7c3e5d0e7f4c4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Apr 2019 09:17:13 -0400 Subject: fixed marquee and doc decorations bugs --- src/client/views/collections/CollectionBaseView.tsx | 2 ++ src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 6cb650770..aa8fce923 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -8,6 +8,7 @@ import { ListField } from '../../../fields/ListField'; import { NumberField } from '../../../fields/NumberField'; import { ContextMenu } from '../ContextMenu'; import { FieldViewProps } from '../nodes/FieldView'; +import { SelectionManager } from '../../util/SelectionManager'; export enum CollectionViewType { Invalid, @@ -173,6 +174,7 @@ export class CollectionBaseView extends React.Component { return true; } if (this.removeDocument(doc)) { + SelectionManager.DeselectAll(); return addDocument(doc); } return false; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 89308d573..da1170759 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -78,7 +78,9 @@ export class MarqueeView extends React.Component if (!e.cancelBubble) { if (Math.abs(this._lastX - this._downX) > Utils.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > Utils.DRAG_THRESHOLD) { - this._visible = true; + if (!this._commandExecuted) { + this._visible = true; + } e.stopPropagation(); e.preventDefault(); } @@ -173,7 +175,7 @@ export class MarqueeView extends React.Component }); this.marqueeInkDelete(inkData); - SelectionManager.DeselectAll(); + // 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()!); -- cgit v1.2.3-70-g09d2 From 73fb401abe04633112b45691e6e05657a0fbe2dc Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Apr 2019 16:27:48 -0400 Subject: extended link lines to work for documents nested one-level in collections. --- .../collectionFreeForm/CollectionFreeFormLinksView.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index ebdb0c75c..6d6b6e309 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -72,7 +72,15 @@ export class CollectionFreeFormLinksView extends React.Component + child.Id === collid).map(view => + DocumentManager.Instance.getDocumentViews(view).map(view => + equalViews.push(view))); } return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document); } -- cgit v1.2.3-70-g09d2 From 3ac2d1ed68fb4190c5ac6ca4f383ddaac6dbc1db Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Apr 2019 23:18:05 -0400 Subject: added a UI to access the link document as a Text document --- .../CollectionFreeFormLinkView.scss | 6 ++++ .../CollectionFreeFormLinkView.tsx | 33 ++++++++++++++++++---- .../CollectionFreeFormLinksView.tsx | 3 +- src/fields/Document.ts | 4 +-- 4 files changed, 37 insertions(+), 9 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index 3b2f79be1..3e8a8a442 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -3,4 +3,10 @@ stroke-width: 3; transform: translate(10000px,10000px); pointer-events: all; +} +.collectionfreeformlinkview-linkCircle { + stroke: black; + stroke-width: 3; + transform: translate(10000px,10000px); + pointer-events: all; } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 20c5a84bf..8cd6c7624 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -5,19 +5,36 @@ import { Utils } from "../../../../Utils"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); import v5 = require("uuid/v5"); +import { InkingControl } from "../../InkingControl"; export interface CollectionFreeFormLinkViewProps { A: Document; B: Document; LinkDocs: Document[]; + addDocument: (document: Document, allowDuplicates?: boolean) => boolean; + removeDocument: (document: Document) => boolean; } @observer export class CollectionFreeFormLinkView extends React.Component { onPointerDown = (e: React.PointerEvent) => { - this.props.LinkDocs.map(l => - console.log("Link:" + l.Title)); + if (e.button === 0 && !InkingControl.Instance.selectedTool) { + let a = this.props.A; + let b = this.props.B; + let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Width() / 2); + let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Height() / 2); + let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Width() / 2); + let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Height() / 2); + this.props.LinkDocs.map(l => { + let width = l.GetNumber(KeyStore.Width, 0); + l.SetNumber(KeyStore.X, (x1 + x2) / 2 - width / 2); + l.SetNumber(KeyStore.Y, (y1 + y2) / 2 + 10); + if (!this.props.removeDocument(l)) this.props.addDocument(l, false); + }); + e.stopPropagation(); + e.preventDefault(); + } } render() { let l = this.props.LinkDocs; @@ -28,10 +45,14 @@ export class CollectionFreeFormLinkView extends React.Component + <> + + + ); } } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 6d6b6e309..b97df7556 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -105,7 +105,8 @@ export class CollectionFreeFormLinksView extends React.Component ); + return connections.map(c => ); } render() { diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 7a7dbc3fe..2797efc09 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -13,6 +13,7 @@ import { BooleanField } from "./BooleanField"; import { allLimit } from "async"; import { prototype } from "nodemailer/lib/smtp-pool"; import { HistogramField } from "../client/northstar/dash-fields/HistogramField"; +import { Documents } from "../client/documents/Documents"; export class Document extends Field { //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field @@ -374,8 +375,7 @@ export class Document extends Field { @action CreateLink(dstTarg: Document) { let batch = UndoManager.StartBatch("document view drop"); - let linkDoc: Document = new Document(); - linkDoc.SetText(KeyStore.Title, "New Link"); + let linkDoc: Document = Documents.TextDocument({ width: 100, height: 25, title: "-link-" }); linkDoc.SetText(KeyStore.LinkDescription, ""); linkDoc.SetText(KeyStore.LinkTags, "Default"); -- cgit v1.2.3-70-g09d2 From 877b104a61d2ab072e3b6a006168ec03e2c46365 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 30 Apr 2019 00:11:27 -0400 Subject: Mostly fixed lists --- src/client/util/UndoManager.ts | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + src/debug/Test.tsx | 8 +- src/new_fields/Doc.ts | 10 +- src/new_fields/List.ts | 192 +++++++++++++++++---- src/new_fields/util.ts | 8 + 6 files changed, 179 insertions(+), 44 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index f7c3e5a7b..0b5280c4a 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -141,10 +141,10 @@ export namespace UndoManager { }); //TODO Make this return the return value - export function RunInBatch(fn: () => void, batchName: string) { + export function RunInBatch(fn: () => T, batchName: string) { let batch = StartBatch(batchName); try { - runInAction(fn); + return runInAction(fn); } finally { batch.end(); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index dcded7648..d796bd8d5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -272,6 +272,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { get views() { let curPage = FieldValue(this.Document.curPage, -1); let docviews = (this.children || []).filter(doc => doc).reduce((prev, doc) => { + if (!FieldValue(doc)) return prev; var page = Cast(doc.page, "number", -1); if (page === curPage || page === -1) { let minim = Cast(doc.isMinimized, "boolean"); diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx index 7415d4b28..04ef00722 100644 --- a/src/debug/Test.tsx +++ b/src/debug/Test.tsx @@ -61,14 +61,12 @@ class Test extends React.Component { assert(test2.testDoc === undefined); test2.url = 35; assert(test2.url === 35); - const l = new List(); + const l = new List(); //TODO push, and other array functions don't go through the proxy - l.push(1); + l.push(doc2); //TODO currently length, and any other string fields will get serialized - l.length = 3; - l[2] = 5; + doc.list = l; console.log(l.slice()); - console.log(SerializationHelper.Serialize(l)); } render() { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index d15b6309d..6ddb0df89 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -3,7 +3,7 @@ import { serializable, primitive, map, alias, list } from "serializr"; import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper"; import { Utils } from "../Utils"; import { DocServer } from "../client/DocServer"; -import { setter, getter, getField, updateFunction } from "./util"; +import { setter, getter, getField, updateFunction, deleteProperty } from "./util"; import { Cast, ToConstructor, PromiseValue, FieldValue } from "./Types"; import { UndoManager, undoBatch } from "../client/util/UndoManager"; import { listSpec } from "./Schema"; @@ -34,7 +34,7 @@ export class Doc extends RefField { set: setter, get: getter, ownKeys: target => Object.keys(target.__fields), - deleteProperty: () => { throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); }, + deleteProperty: deleteProperty, defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); }, }); if (!id || forceSave) { @@ -151,8 +151,8 @@ export namespace Doc { } export function MakeLink(source: Doc, target: Doc): Doc { - let linkDoc = new Doc; - UndoManager.RunInBatch(() => { + return UndoManager.RunInBatch(() => { + let linkDoc = new Doc; linkDoc.title = "New Link"; linkDoc.linkDescription = ""; linkDoc.linkTags = "Default"; @@ -171,8 +171,8 @@ export namespace Doc { source.linkedToDocs = linkedTo = new List(); } linkedTo.push(linkDoc); + return linkDoc; }, "make link"); - return linkDoc; } export function MakeDelegate(doc: Doc): Doc; diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts index e4a80f7a1..ec1bf44a9 100644 --- a/src/new_fields/List.ts +++ b/src/new_fields/List.ts @@ -1,21 +1,173 @@ import { Deserializable, autoObject } from "../client/util/SerializationHelper"; import { Field, Update, Self } from "./Doc"; -import { setter, getter } from "./util"; +import { setter, getter, deleteProperty } from "./util"; import { serializable, alias, list } from "serializr"; import { observable, observe, IArrayChange, IArraySplice, IObservableArray, Lambda, reaction } from "mobx"; import { ObjectField, OnUpdate } from "./ObjectField"; +import { RefField } from "./RefField"; +import { ProxyField } from "./Proxy"; const listHandlers: any = { - push(...items: any[]) { - // console.log("push"); - // console.log(...items); - return this[Self].__fields.push(...items); + /// Mutator methods + copyWithin() { + throw new Error("copyWithin not supported yet"); + }, + fill(value: any, start?: number, end?: number) { + if (value instanceof RefField) { + throw new Error("fill with RefFields not supported yet"); + } + const res = this[Self].__fields.fill(value, start, end); + this[Update](); + return res; }, pop(): any { - return this[Self].__fields.pop(); + const field = toRealField(this[Self].__fields.pop()); + this[Update](); + return field; + }, + push(...items: any[]) { + items = items.map(toObjectField); + const res = this[Self].__fields.push(...items); + this[Update](); + return res; + }, + reverse() { + const res = this[Self].__fields.reverse(); + this[Update](); + return res; + }, + shift() { + const res = toRealField(this[Self].__fields.shift()); + this[Update](); + return res; + }, + sort(cmpFunc: any) { + const res = this[Self].__fields.sort(cmpFunc ? (first: any, second: any) => cmpFunc(toRealField(first), toRealField(second)) : undefined); + this[Update](); + return res; + }, + splice(start: number, deleteCount: number, ...items: any[]) { + items = items.map(toObjectField); + const res = this[Self].__fields.splice(start, deleteCount, ...items); + this[Update](); + return res.map(toRealField); + }, + unshift(...items: any[]) { + items = items.map(toObjectField); + const res = this[Self].__fields.unshift(...items); + this[Update](); + return res; + + }, + /// Accessor methods + concat(...items: any[]) { + return this[Self].__fields.map(toRealField).concat(...items); + }, + includes(valueToFind: any, fromIndex: number) { + const fields = this[Self].__fields; + if (valueToFind instanceof RefField) { + return fields.map(toRealField).includes(valueToFind, fromIndex); + } else { + return fields.includes(valueToFind, fromIndex); + } + }, + indexOf(valueToFind: any, fromIndex: number) { + const fields = this[Self].__fields; + if (valueToFind instanceof RefField) { + return fields.map(toRealField).indexOf(valueToFind, fromIndex); + } else { + return fields.indexOf(valueToFind, fromIndex); + } + }, + join(separator: any) { + return this[Self].__fields.map(toRealField).join(separator); + }, + lastIndexOf(valueToFind: any, fromIndex: number) { + const fields = this[Self].__fields; + if (valueToFind instanceof RefField) { + return fields.map(toRealField).lastIndexOf(valueToFind, fromIndex); + } else { + return fields.lastIndexOf(valueToFind, fromIndex); + } + }, + slice(begin: number, end: number) { + return this[Self].__fields.slice(begin, end).map(toRealField); + }, + + /// Iteration methods + entries() { + return this[Self].__fields.map(toRealField).entries(); + }, + every(callback: any, thisArg: any) { + return this[Self].__fields.map(toRealField).every(callback, thisArg); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.every((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg); + }, + filter(callback: any, thisArg: any) { + return this[Self].__fields.map(toRealField).filter(callback, thisArg); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.filter((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg); + }, + find(callback: any, thisArg: any) { + return this[Self].__fields.map(toRealField).find(callback, thisArg); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.find((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg); + }, + findIndex(callback: any, thisArg: any) { + return this[Self].__fields.map(toRealField).findIndex(callback, thisArg); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.findIndex((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg); + }, + forEach(callback: any, thisArg: any) { + return this[Self].__fields.map(toRealField).forEach(callback, thisArg); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.forEach((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg); + }, + map(callback: any, thisArg: any) { + return this[Self].__fields.map(toRealField).map(callback, thisArg); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.map((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg); + }, + reduce(callback: any, initialValue: any) { + return this[Self].__fields.map(toRealField).reduce(callback, initialValue); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.reduce((acc:any, element:any, index:number, array:any) => callback(acc, toRealField(element), index, array), initialValue); + }, + reduceRight(callback: any, initialValue: any) { + return this[Self].__fields.map(toRealField).reduceRight(callback, initialValue); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.reduceRight((acc:any, element:any, index:number, array:any) => callback(acc, toRealField(element), index, array), initialValue); + }, + some(callback: any, thisArg: any) { + return this[Self].__fields.map(toRealField).some(callback, thisArg); + // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway. + // If we don't want to support the array parameter, we should use this version instead + // return this[Self].__fields.some((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg); + }, + values() { + return this[Self].__fields.map(toRealField).values(); + }, + [Symbol.iterator]() { + return this[Self].__fields.map(toRealField).values(); } }; +function toObjectField(field: Field) { + return field instanceof RefField ? new ProxyField(field) : field; +} + +function toRealField(field: Field) { + return field instanceof ProxyField ? field.value() : field; +} + function listGetter(target: any, prop: string | number | symbol, receiver: any): any { if (listHandlers.hasOwnProperty(prop)) { return listHandlers[prop]; @@ -38,36 +190,15 @@ interface ListIndexUpdate { type ListUpdate = ListSpliceUpdate | ListIndexUpdate; -const ObserveDisposer = Symbol("Observe Disposer"); - -function listObserver(this: ListImpl, change: IArrayChange | IArraySplice) { - if (change.type === "splice") { - this[Update]({ - index: change.index, - removedCount: change.removedCount, - added: change.added, - type: change.type - }); - } else { - //This should already be handled by the getter for the Proxy - // this[Update]({ - // index: change.index, - // newValue: change.newValue, - // type: change.type - // }); - } -} - @Deserializable("list") class ListImpl extends ObjectField { constructor(fields: T[] = []) { super(); this.___fields = fields; - this[ObserveDisposer] = observe(this.__fields as IObservableArray, listObserver.bind(this)); const list = new Proxy(this, { set: setter, - get: getter, - deleteProperty: () => { throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); }, + get: listGetter, + deleteProperty: deleteProperty, defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); }, }); return list; @@ -82,8 +213,6 @@ class ListImpl extends ObjectField { private set __fields(value) { this.___fields = value; - this[ObserveDisposer](); - this[ObserveDisposer] = observe(this.__fields as IObservableArray, listObserver.bind(this)); } // @serializable(alias("fields", list(autoObject()))) @@ -97,7 +226,6 @@ class ListImpl extends ObjectField { update && update(); } - private [ObserveDisposer]: Lambda; private [Self] = this; } export type List = ListImpl & T[]; diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 511820115..128817ab8 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -78,6 +78,14 @@ export function getField(target: any, prop: string | number, ignoreProto: boolea return field; } +export function deleteProperty(target: any, prop: string | number | symbol) { + if (typeof prop === "symbol") { + delete target[prop]; + return true; + } + throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); +} + export function updateFunction(target: any, prop: any, value: any) { return (diff?: any) => { if (!diff) diff = { '$set': { ["fields." + prop]: SerializationHelper.Serialize(value) } }; -- cgit v1.2.3-70-g09d2 From 6b116d69a5b1a991c7aa00e2b23af3f8db7c7d77 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 30 Apr 2019 09:27:24 -0400 Subject: fixed schema column default/persistence --- src/client/documents/Documents.ts | 8 ++++--- .../views/collections/CollectionSchemaView.tsx | 28 ++++++++++++---------- src/fields/Document.ts | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a7514f1d6..847f604d0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -60,6 +60,7 @@ export interface DocumentOptions { copyDraggedItems?: boolean; documentText?: string; borderRounding?: number; + columnsKey?: Array; } export namespace Documents { @@ -116,6 +117,7 @@ export namespace Documents { if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); } if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); } if (options.borderRounding !== undefined) { doc.SetNumber(KeyStore.BorderRounding, options.borderRounding); } + if (options.columnsKey !== undefined) { doc.SetData(KeyStore.ColumnsKey, options.columnsKey, ListField); } return doc; } @@ -271,13 +273,13 @@ export namespace Documents { if (!makePrototype) { return SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id); } - return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options); + return assignToDelegate(SetInstanceOptions(collProto, { columnsKey: [KeyStore.Title], ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options); } export function SchemaDocument(documents: Array, options: DocumentOptions, id?: string) { - return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options); + return assignToDelegate(SetInstanceOptions(collProto, { columnsKey: [KeyStore.Title], ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options); } export function TreeDocument(documents: Array, options: DocumentOptions, id?: string) { - return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options); + return assignToDelegate(SetInstanceOptions(collProto, { columnsKey: [KeyStore.Title], ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options); } export function DockDocument(config: string, options: DocumentOptions, id?: string) { return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b6d5f1bfa..b3cc3fbd5 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -2,13 +2,13 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, untracked } from "mobx"; +import { action, computed, observable, untracked, runInAction } from "mobx"; import { observer } from "mobx-react"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss' import "react-table/react-table.css"; import { Document } from "../../../fields/Document"; -import { Field, Opt } from "../../../fields/Field"; +import { Field, Opt, FieldWaiting } from "../../../fields/Field"; import { Key } from "../../../fields/Key"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; @@ -165,18 +165,22 @@ export class CollectionSchemaView extends CollectionSubView { super.CreateDropTarget(ele); } - @action toggleKey = (key: Key) => { - this.props.Document.GetOrCreateAsync>(KeyStore.ColumnsKey, ListField, - (field) => { - const index = field.Data.indexOf(key); - if (index === -1) { - this.columns.push(key); - } else { - this.columns.splice(index, 1); + this.props.Document.GetTAsync>(KeyStore.ColumnsKey, ListField).then(field => + runInAction(() => { + if (field !== FieldWaiting) { + if (field) { + const index = field.Data.indexOf(key); + if (index === -1) { + this.columns.push(key); + } else { + this.columns.splice(index, 1); + } + } else { + this.props.Document.SetData(KeyStore.ColumnsKey, [key], ListField); + } } - - }); + })); } //toggles preview side-panel of schema diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 2797efc09..55ac731dd 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -204,7 +204,7 @@ export class Document extends Field { callback: (field: T) => void ): void { //This currently doesn't deal with prototypes - if (this._proxies.has(key.Id)) { + if (this._proxies.has(key.Id) || this.fields.has(key.Id)) { Server.GetDocumentField(this, key, field => { if (field && field instanceof ctor) { callback(field); -- cgit v1.2.3-70-g09d2 From 654ad2b11a3dc98c2e802c535b0cd615e50a486c Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 30 Apr 2019 09:36:00 -0400 Subject: fixed marquee select doc placement --- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 644a8784c..df1e7a90e 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -143,8 +143,8 @@ export class MarqueeView extends React.Component let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { this.props.removeDocument(d); - d.x = NumCast(d.X) - bounds.left - bounds.width / 2; - d.y = NumCast(d.Y) - bounds.top - bounds.height / 2; + 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; }); -- cgit v1.2.3-70-g09d2 From e013b7b146f91b0ffbc26e3770f5f90f417da60b Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 30 Apr 2019 12:09:54 -0400 Subject: fixed inking --- src/client/views/InkingCanvas.tsx | 18 +++++++++++------- src/client/views/InkingStroke.scss | 3 +++ src/client/views/InkingStroke.tsx | 8 ++++++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 17 ++++++++++------- src/new_fields/Doc.ts | 6 +++++- 5 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 src/client/views/InkingStroke.scss (limited to 'src/client/views/collections') diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index 1e26893c5..1c0d13545 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -139,21 +139,25 @@ export class InkingCanvas extends React.Component { let curPage = NumCast(this.props.Document.curPage, -1); let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => { if (strokeData.page === -1 || strokeData.page === curPage) { - paths.push(); + color={strokeData.color} + width={strokeData.width} + tool={strokeData.tool} + deleteCallback={this.removeLine} />); } return paths; }, [] as JSX.Element[]); - return [ - {paths.filter(path => path.props.tool === InkTool.Highlighter)} + {paths.filter(path => path.props.tool !== InkTool.Highlighter)} , - - {paths.filter(path => path.props.tool !== InkTool.Highlighter)} + {paths.filter(path => path.props.tool === InkTool.Highlighter)} ]; } diff --git a/src/client/views/InkingStroke.scss b/src/client/views/InkingStroke.scss new file mode 100644 index 000000000..cdbfdcff3 --- /dev/null +++ b/src/client/views/InkingStroke.scss @@ -0,0 +1,3 @@ +.inkingStroke-marker { + mix-blend-mode: multiply +} \ No newline at end of file diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 616299146..37b1f5899 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -1,14 +1,16 @@ import { observer } from "mobx-react"; -import { observable } from "mobx"; +import { observable, trace } from "mobx"; import { InkingControl } from "./InkingControl"; import React = require("react"); import { InkTool } from "../../new_fields/InkField"; +import "./InkingStroke.scss"; interface StrokeProps { offsetX: number; offsetY: number; id: string; + count: number; line: Array<{ x: number, y: number }>; color: string; width: string; @@ -48,10 +50,12 @@ export class InkingStroke extends React.Component { render() { let pathStyle = this.createStyle(); let pathData = this.parseData(this.props.line); + let pathlength = this.props.count; // bcz: this is needed to force reactions to the line data changes + let marker = this.props.tool === InkTool.Highlighter ? "-marker" : ""; let pointerEvents: any = InkingControl.Instance.selectedTool === InkTool.Eraser ? "all" : "none"; return ( - ); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d796bd8d5..2689f48cd 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,4 +1,4 @@ -import { action, computed } from "mobx"; +import { action, computed, trace } from "mobx"; import { observer } from "mobx-react"; import { emptyFunction, returnFalse, returnOne } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; @@ -19,7 +19,7 @@ import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); import { createSchema, makeInterface, listSpec } from "../../../../new_fields/Schema"; -import { Doc } from "../../../../new_fields/Doc"; +import { Doc, WidthSym, HeightSym } from "../../../../new_fields/Doc"; import { FieldValue, Cast, NumCast } from "../../../../new_fields/Types"; import { pageSchema } from "../../nodes/ImageBox"; import { List } from "../../../../new_fields/List"; @@ -243,11 +243,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { focusDocument = (doc: Doc) => { this.setPan( - Cast(doc.x, "number", 0) + Cast(doc.width, "number", 0) / 2, - Cast(doc.y, "number", 0) + Cast(doc.height, "number", 0) / 2); + NumCast(doc.x) + NumCast(doc.width) / 2, + NumCast(doc.y) + NumCast(doc.height) / 2); this.props.focus(this.props.Document); } + getDocumentViewProps(document: Doc): DocumentViewProps { return { Document: document, @@ -258,8 +259,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ScreenToLocalTransform: this.getTransform, isTopMost: false, selectOnLoad: document[Id] === this._selectOnLoaded, - PanelWidth: () => Cast(document.width, "number", 0),//TODO Types These are inline functions - PanelHeight: () => Cast(document.height, "number", 0), + PanelWidth: document[WidthSym], + PanelHeight: document[HeightSym], ContentScaling: returnOne, ContainingCollectionView: this.props.CollectionView, focus: this.focusDocument, @@ -268,8 +269,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }; } - @computed + @computed.struct get views() { + trace(); let curPage = FieldValue(this.Document.curPage, -1); let docviews = (this.children || []).filter(doc => doc).reduce((prev, doc) => { if (!FieldValue(doc)) return prev; @@ -295,6 +297,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private childViews = () => [...this.views, ]; render() { + trace(); const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; return (
= Opt | FieldWaiting { return NumCast(this.__fields.width); } // bcz: is this the right way to access width/height? it didn't work with : this.width + public [HeightSym] = () => { return NumCast(this.__fields.height); } } export namespace Doc { -- cgit v1.2.3-70-g09d2 From 37062ef8b33efebd9fafcd2c076d5cb49f5a288f Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 30 Apr 2019 13:43:15 -0400 Subject: from commit --- src/client/documents/Documents.ts | 12 ++++-------- src/client/views/DocumentDecorations.tsx | 3 +-- .../collectionFreeForm/CollectionFreeFormView.tsx | 8 ++------ 3 files changed, 7 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index aa5277910..ff21dd5b0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -32,11 +32,7 @@ import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; import { StrokeData, InkField } from "../../new_fields/InkField"; -import { KeyStore } from "../../fields/KeyStore"; -// export class stringArray implements List { -// public Values: string[] = []; -// } export interface DocumentOptions { x?: number; y?: number; @@ -60,7 +56,7 @@ export interface DocumentOptions { curPage?: number; documentText?: string; borderRounding?: number; - //schemaColumns?: stringArray; + schemaColumns?: List; // [key: string]: Opt; } const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; @@ -243,13 +239,13 @@ export namespace Docs { if (!makePrototype) { return SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, new List(documents)); } - return CreateInstance(collProto, new List(documents), { /*schemaColumns: [KeyStore.SchemaColumns],*/...options, viewType: CollectionViewType.Freeform }); + return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["schemaColumns"]), ...options, viewType: CollectionViewType.Freeform }); } export function SchemaDocument(documents: Array, options: DocumentOptions) { - return CreateInstance(collProto, new List(documents), { /*schemaColumns: [KeyStore.SchemaColumns], */...options, viewType: CollectionViewType.Schema }); + return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["schemaColumns"]), ...options, viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions) { - return CreateInstance(collProto, new List(documents), { /*schemaColumns: [KeyStore.SchemaColumns], */...options, viewType: CollectionViewType.Tree }); + return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["schemaColumns"]), ...options, viewType: CollectionViewType.Tree }); } export function DockDocument(config: string, options: DocumentOptions) { return CreateInstance(collProto, config, { ...options, viewType: CollectionViewType.Docking }); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 556117c54..8632286ab 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -18,7 +18,6 @@ import { Doc, FieldResult } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; import { Docs } from "../documents/Documents"; import { List } from "../../new_fields/List"; -import { KeyStore } from "../../fields/KeyStore"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -40,7 +39,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @observable private _minimizedY = 0; @observable private _title: string = ""; @observable private _edtingTitle = false; - @observable private _fieldKey = KeyStore.Title; + @observable private _fieldKey = "title"; @observable private _hidden = false; @observable private _opacity = 1; @observable private _iconifying = false; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f99800e21..8d10666b7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -22,9 +22,7 @@ import { createSchema, makeInterface, listSpec } from "../../../../new_fields/Sc import { Doc, WidthSym, HeightSym } from "../../../../new_fields/Doc"; import { FieldValue, Cast, NumCast } from "../../../../new_fields/Types"; import { pageSchema } from "../../nodes/ImageBox"; -import { List } from "../../../../new_fields/List"; import { Id } from "../../../../new_fields/RefField"; -import { KeyStore } from "../../../../fields/KeyStore"; export const panZoomSchema = createSchema({ panX: "number", @@ -272,7 +270,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @computed.struct get views() { - trace(); let curPage = FieldValue(this.Document.curPage, -1); let docviews = (this.children || []).filter(doc => doc).reduce((prev, doc) => { if (!FieldValue(doc)) return prev; @@ -298,7 +295,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private childViews = () => [...this.views, ]; render() { - trace(); const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; return (
{ @computed get overlayView() { let overlayLayout = Cast(this.props.Document.overlayLayout, "string", ""); return !overlayLayout ? (null) : - (); } render() { @@ -346,7 +342,7 @@ class CollectionFreeFormBackgroundView extends React.Component); } render() { -- cgit v1.2.3-70-g09d2 From 7261d69c9e9dcdbcc413eff062eb01de2032f9ef Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 30 Apr 2019 15:21:20 -0400 Subject: fixed link lines --- src/client/views/DocumentDecorations.tsx | 2 +- .../CollectionFreeFormLinksView.tsx | 4 ++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 19 +++++-------------- .../collections/collectionFreeForm/MarqueeView.tsx | 4 +--- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 ++ src/client/views/nodes/DocumentView.tsx | 9 +++++---- 6 files changed, 16 insertions(+), 24 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8632286ab..1dc7c8394 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -268,7 +268,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> minDocs.map(minDoc => { minDoc.x = NumCast(minDocs[0].x); minDoc.y = NumCast(minDocs[0].y); - minDoc.linkTags = new List(minDocs); + minDoc.linkTags = new List(minDocs.filter(d => d != minDoc)); if (this._iconifying && selectedDocs[0].props.removeDocument) { selectedDocs[0].props.removeDocument(minDoc); (minDoc.maximizedDoc as Doc).minimizedDoc = undefined; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index e5dcf8c29..4a75fccff 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -85,10 +85,10 @@ export class CollectionFreeFormLinksView extends React.Component - child.Id === collid).map(view => + child[Id] === collid).map(view => DocumentManager.Instance.getDocumentViews(view).map(view => equalViews.push(view))); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8d10666b7..e54553d2b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -97,7 +97,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (!NumCast(d.height)) { let nw = NumCast(d.nativeWidth); let nh = NumCast(d.nativeHeight); - d.height = nw && nh ? nh / nw * NumCast(d.Width) : 300; + d.height = nw && nh ? nh / nw * NumCast(d.width) : 300; } this.bringToFront(d); }); @@ -108,12 +108,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return false; } - @action - cleanupInteractions = () => { - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - @action onPointerDown = (e: React.PointerEvent): void => { let childSelected = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), [] as Doc[]).filter(doc => doc).reduce((childSelected, doc) => { @@ -125,7 +119,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { (e.button === 0 && e.altKey)) && (childSelected || this.props.active()))) || (!CollectionFreeFormView.RIGHT_BTN_DRAG && ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())))) { - this.cleanupInteractions(); + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); document.addEventListener("pointerup", this.onPointerUp); this._lastX = e.pageX; @@ -134,7 +129,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } onPointerUp = (e: PointerEvent): void => { - this.cleanupInteractions(); + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); } @action @@ -300,11 +296,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
- {/* - - {this.props.Document.Title} - - */} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1d3850a72..85a12defa 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -109,9 +109,7 @@ export class MarqueeView extends React.Component onClick = (e: React.MouseEvent): void => { if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) { - if (this.props.isSelected()) { - PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress); - } + PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress); // let the DocumentView stopPropagation of this event when it selects this document } else { // why do we get a click event when the cursor have moved a big distance? // let's cut it off here so no one else has to deal with it. diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index bd084bfe0..c8f0bca91 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -114,6 +114,8 @@ export class CollectionFreeFormDocumentView extends DocComponent d); + docs.push(this.props.Document); minimizedDocSet.map(async minimizedDoc => { if (minimizedDoc instanceof Document) { this.props.addDocument && this.props.addDocument(minimizedDoc, false); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index ac3dcde42..eab068355 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -308,8 +308,8 @@ export class DocumentView extends DocComponent(Docu isSelected = () => SelectionManager.IsSelected(this); select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed); - @computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); } - @computed get nativeHeight() { return FieldValue(this.Document.nativeHeight, 0); } + @computed get nativeWidth() { return this.Document.nativeWidth || 0; } + @computed get nativeHeight() { return this.Document.nativeHeight || 0; } @computed get contents() { return (); } render() { @@ -322,8 +322,9 @@ export class DocumentView extends DocComponent(Docu ref={this._mainCont} style={{ borderRadius: "inherit", - background: FieldValue(this.Document.backgroundColor) || "", - width: nativeWidth, height: nativeHeight, + background: this.Document.backgroundColor || "", + width: nativeWidth, + height: nativeHeight, transform: `scale(${scaling}, ${scaling})` }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} -- cgit v1.2.3-70-g09d2