From 223262242f7db021c8449e920645892cc5ed2820 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 17 Oct 2020 17:45:10 -0400 Subject: major rewrite of native width/height/aspect. Fixed scaling of text note sidebars. --- .../collectionFreeForm/CollectionFreeFormView.tsx | 25 +++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b32a3bd52..c863addd2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -105,11 +105,11 @@ export class CollectionFreeFormView extends CollectionSubView e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); } - @computed get nativeWidth() { return this.fitToContent ? 0 : returnVal(this.props.NativeWidth?.(), NumCast(this.Document._nativeWidth)); } - @computed get nativeHeight() { return this.fitToContent ? 0 : returnVal(this.props.NativeHeight?.(), NumCast(this.Document._nativeHeight)); } + @computed get nativeWidth() { return this.fitToContent ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document)); } + @computed get nativeHeight() { return this.fitToContent ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.Document)); } private get isAnnotationOverlay() { return this.props.isAnnotationOverlay; } private get scaleFieldKey() { return this.props.scaleField || "_viewScale"; } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } @@ -120,7 +120,7 @@ export class CollectionFreeFormView extends CollectionSubView { - const pw = this.isAnnotationOverlay ? NumCast(this.props.Document._nativeWidth) : this.props.PanelWidth(); - const ph = this.isAnnotationOverlay ? NumCast(this.props.Document._nativeHeight) : this.props.PanelHeight(); + const pw = this.isAnnotationOverlay ? Doc.NativeWidth(this.props.Document) : this.props.PanelWidth(); + const ph = this.isAnnotationOverlay ? Doc.NativeHeight(this.props.Document) : this.props.PanelHeight(); pw && ph && (this.Document[this.scaleFieldKey] = scale * Math.min(pw / NumCast(doc._width), ph / NumCast(doc._height))); } @@ -979,7 +979,6 @@ export class CollectionFreeFormView extends CollectionSubView Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" }); if (!Doc.UserDoc().noviceMode) { - optionItems.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" }); + optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" }); optionItems.push({ description: `${this.Document._freeformLOD ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._freeformLOD = !this.Document._freeformLOD, icon: "table" }); } @@ -1454,8 +1453,8 @@ export class CollectionFreeFormView extends CollectionSubView Date: Sat, 17 Oct 2020 22:01:53 -0400 Subject: fixed rubberbadning ink shapes not to get cutoff. fixed animating annotations. fixed ink masks. fixed warnings. --- src/client/views/InkingStroke.tsx | 4 +--- src/client/views/collections/CollectionMenu.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 6 ++++-- src/client/views/nodes/PresBox.tsx | 12 ++++++------ src/client/views/pdf/PDFViewer.tsx | 6 +++++- src/server/websocket.ts | 4 ++-- 6 files changed, 19 insertions(+), 15 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 186406424..7e424d8f0 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -38,7 +38,7 @@ export class InkingStroke extends ViewBoxBaseComponent pair.layout).slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); zsorted.forEach((doc, index) => doc.zIndex = doc.isInkMask ? 5000 : index + 1); - const dropPos = [NumCast(docDragData.droppedDocuments[0].x), NumCast(docDragData.droppedDocuments[0].y)]; + const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000)); + const dropPos = this.Document._currentFrame !== undefined ? [dvals.x, dvals.y] : [NumCast(refDoc.x), NumCast(refDoc.y)]; for (let i = 0; i < docDragData.droppedDocuments.length; i++) { const d = docDragData.droppedDocuments[i]; const layoutDoc = Doc.Layout(d); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 3b7794815..01a7bed8c 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -288,7 +288,7 @@ export class PresBox extends ViewBoxBaseComponent const willZoom = false; const openInTab = () => { collectionDocView ? collectionDocView.props.addDocTab(activeItem, "replace") : this.props.addDocTab(activeItem, "replace:left"); - } + }; // If openDocument is selected then it should open the document for the user if (activeItem.openDocument) { openInTab(); @@ -299,10 +299,10 @@ export class PresBox extends ViewBoxBaseComponent } else if (docToJump === curDoc) { //checking if curDoc has navigation open if (curDoc.presMovement === PresMovement.Pan && targetDoc) { - await DocumentManager.Instance.jumpToDocument(targetDoc, false, () => { openInTab() }, srcContext); // documents open in new tab instead of on right + await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext); // documents open in new tab instead of on right } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) { //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(targetDoc, true, () => { openInTab() }, srcContext); // documents open in new tab instead of on right + await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext); // documents open in new tab instead of on right } } else { //awaiting jump so that new scale can be found, since jumping is async @@ -442,7 +442,7 @@ export class PresBox extends ViewBoxBaseComponent } } }; - this.layoutDoc.presStatus = PresStatus.Auto; + this.layoutDoc.presStatus = PresStatus.Autoplay; this.startPresentation(startSlide); this.gotoDocument(startSlide, this.itemIndex); load(); @@ -450,7 +450,7 @@ export class PresBox extends ViewBoxBaseComponent @action pauseAutoPres = () => { - if (this.layoutDoc.presStatus === PresStatus.Auto) { + if (this.layoutDoc.presStatus === PresStatus.Autoplay) { if (this._presTimer) clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; this.layoutDoc.presLoop = false; @@ -611,7 +611,7 @@ export class PresBox extends ViewBoxBaseComponent return true; } childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement; - removeDocument = (doc: Doc) => { return Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); }; + removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight() - 40; active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc._isBackground) && diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d278612b1..76b218972 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -730,7 +730,11 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); @computed get overlayLayer() { return
+ style={{ + pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined, + mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined, + transform: `scale(${this._zoomed})` + }}> !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; + const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields.filter((item: any) => item !== undefined) || []; + diff.diff.$set[updatefield].fields = [...curList, ...newListItems.filter((newItem: any) => newItem && !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; delete diff.diff.length; Database.Instance.update(diff.id, diff.diff, -- cgit v1.2.3-70-g09d2 From 6cfd2a37494bf531c88e26ea89b5b776805d31a8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 20 Oct 2020 23:36:45 -0400 Subject: fixes for overlayDocs for undo/redo in presBox - undo/redo of minimize/show sidebar. --- src/client/util/CurrentUserUtils.ts | 1 + src/client/views/OverlayView.tsx | 9 ++------- .../collectionFreeForm/CollectionFreeFormView.tsx | 5 +++-- src/client/views/nodes/DocumentView.tsx | 8 ++++---- src/client/views/nodes/PresBox.tsx | 19 +++++++++---------- src/fields/documentSchemas.ts | 1 - 6 files changed, 19 insertions(+), 24 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index f43b6df44..38bfe3fb6 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1190,6 +1190,7 @@ export class CurrentUserUtils { public static get MyRecentlyClosed() { return Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc, null); } public static get MyDashboards() { return Cast(Doc.UserDoc().myDashboards, Doc, null); } public static get EmptyPane() { return Cast(Doc.UserDoc().emptyPane, Doc, null); } + public static get OverlayDocs() { return DocListCast((Doc.UserDoc().myOverlayDocs as Doc)?.data); } } Scripting.addGlobal(function openDragFactory(dragFactory: Doc) { diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index b40c9edfb..7d47abdce 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -14,6 +14,7 @@ import { Scripting } from "../util/Scripting"; import { ScriptingRepl } from './ScriptingRepl'; import { DragManager } from "../util/DragManager"; import { List } from "../../fields/List"; +import { CurrentUserUtils } from "../util/CurrentUserUtils"; export type OverlayDisposer = () => void; @@ -146,12 +147,7 @@ export class OverlayView extends React.Component { @computed get overlayDocs() { - const userDocOverlays = Doc.UserDoc().myOverlayDocs; - if (!userDocOverlays) { - return null; - } - return userDocOverlays instanceof Doc && DocListCast(userDocOverlays.data).map(d => { - setTimeout(() => d.inOverlay = true, 0); + return CurrentUserUtils.OverlayDocs?.map(d => { let offsetx = 0, offsety = 0; const dref = React.createRef(); const onPointerMove = action((e: PointerEvent, down: number[]) => { @@ -161,7 +157,6 @@ export class OverlayView extends React.Component { } if (e.metaKey) { const dragData = new DragManager.DocumentDragData([d]); - d.removeDropProperties = new List(["inOverlay"]); dragData.offset = [-offsetx, -offsety]; dragData.dropAction = "move"; dragData.removeDocument = (doc: Doc | Doc[]) => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 56624f42d..fdcfb00d8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -46,6 +46,7 @@ import "./CollectionFreeFormView.scss"; import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); +import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; export const panZoomSchema = createSchema({ _panX: "number", @@ -803,7 +804,7 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.layoutDoc._lockedTransform || this.props.Document.inOverlay || this.props.Document.treeViewOutlineMode) return; + if (this.layoutDoc._lockedTransform || CurrentUserUtils.OverlayDocs.includes(this.props.Document) || this.props.Document.treeViewOutlineMode) return; if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) { // things that can scroll vertically should do that instead of zooming e.stopPropagation(); } @@ -839,7 +840,7 @@ export class CollectionFreeFormView extends CollectionSubView(Docu this._downX = touch.clientX; this._downY = touch.clientY; if (!e.nativeEvent.cancelBubble) { - if ((this.active || this.layoutDoc.onDragStart || this.onClickHandler) && !e.ctrlKey && !this.layoutDoc.lockedPosition && !this.layoutDoc.inOverlay) e.stopPropagation(); + if ((this.active || this.layoutDoc.onDragStart || this.onClickHandler) && !e.ctrlKey && !this.layoutDoc.lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) e.stopPropagation(); this.removeMoveListeners(); this.addMoveListeners(); this.removeEndListeners(); @@ -438,7 +438,7 @@ export class DocumentView extends DocComponent(Docu if (e.cancelBubble && this.active) { this.removeMoveListeners(); } - else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.layoutDoc.onDragStart || this.onClickHandler) && !this.layoutDoc.lockedPosition && !this.layoutDoc.inOverlay) { + else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.layoutDoc.onDragStart || this.onClickHandler) && !this.layoutDoc.lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { const touch = me.touchEvent.changedTouches.item(0); if (touch && (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3)) { @@ -554,7 +554,7 @@ export class DocumentView extends DocComponent(Docu if ((this.active || this.layoutDoc.onDragStart) && !e.ctrlKey && (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) && - !this.layoutDoc.inOverlay) { + !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { e.stopPropagation(); if (SelectionManager.IsSelected(this, true) && this.layoutDoc._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it } @@ -573,7 +573,7 @@ export class DocumentView extends DocComponent(Docu if (e.cancelBubble && this.active) { document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView) } - else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.layoutDoc.onDragStart) && !this.layoutDoc.lockedPosition && !this.layoutDoc.inOverlay) { + else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.layoutDoc.onDragStart) && !this.layoutDoc.lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) { document.removeEventListener("pointermove", this.onPointerMove); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 53b2433e8..9723937a7 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -520,11 +520,10 @@ export class PresBox extends ViewBoxBaseComponent @action updateMinimize = () => { const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc); - if (this.layoutDoc.inOverlay) { + if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { this.layoutDoc.presStatus = PresStatus.Edit; Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc); CollectionDockingView.AddSplit(this.rootDoc, "right"); - this.layoutDoc.inOverlay = false; } else if (this.layoutDoc.context && docView) { this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); @@ -716,7 +715,7 @@ export class PresBox extends ViewBoxBaseComponent const anchorNode = document.activeElement as HTMLDivElement; if (anchorNode && anchorNode.className?.includes("lm_title")) return; if (e.keyCode === 27) { // Escape key - if (this.layoutDoc.inOverlay) { this.updateMinimize(); } + if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { this.updateMinimize(); } else if (this.layoutDoc.presStatus === "edit") { this._selectedArray = []; this._eleArray = []; this._dragArray = []; } else this.layoutDoc.presStatus = "edit"; if (this._presTimer) clearTimeout(this._presTimer); @@ -1360,10 +1359,10 @@ export class PresBox extends ViewBoxBaseComponent @computed get presentDropdown() { return (
e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> -
{ this.updateMinimize(); this.turnOffEdit(true); }))}> +
{ this.updateMinimize(); this.turnOffEdit(true); })))}> Minimize
-
{ this.layoutDoc.presStatus = "manual"; this.turnOffEdit(true); }))}> +
{ this.layoutDoc.presStatus = "manual"; this.turnOffEdit(true); })))}> Sidebar view
@@ -1949,8 +1948,8 @@ export class PresBox extends ViewBoxBaseComponent {this.playButtonFrames}
- {this.props.PanelWidth() > 250 ?
{ this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }}>EXIT
- :
this.layoutDoc.presStatus = "edit"}> + {this.props.PanelWidth() > 250 ?
{ this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }))}>EXIT
+ :
this.layoutDoc.presStatus = "edit"))}>
}
); @@ -1968,7 +1967,7 @@ export class PresBox extends ViewBoxBaseComponent // needed to ensure that the childDocs are loaded for looking up fields this.childDocs.slice(); const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; - return this.layoutDoc.inOverlay ? + return CurrentUserUtils.OverlayDocs.includes(this.rootDoc) ?
{"Loop"}
}>
this.layoutDoc.presLoop = !this.layoutDoc.presLoop}>
@@ -1982,11 +1981,11 @@ export class PresBox extends ViewBoxBaseComponent {this.playButtonFrames}
-
{ this.updateMinimize(); this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }}>EXIT
+
{ this.updateMinimize(); this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }))}>EXIT
: -
+
{this.topPanel} {this.toolbar} {this.newDocumentToolbarDropdown} diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 71294c59c..311aaa769 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -19,7 +19,6 @@ export const documentSchema = createSchema({ activeFrame: "number", // the active frame of a frame based animated document _currentTimecode: "number", // current play back time of a temporal document (video / audio) displayTimecode: "number", // the time that a document should be displayed (e.g., time an annotation should be displayed on a video) - inOverlay: "boolean", // whether the document is rendered in an OverlayView which handles selection/dragging differently isLabel: "boolean", // whether the document is a label or not (video / audio) audioStart: "number", // the time frame where the audio should begin playing audioEnd: "number", // the time frame where the audio should stop playing -- cgit v1.2.3-70-g09d2 From 0ddd75da0f0b42cf3e1692e1cb1761c0e70ed551 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 2 Nov 2020 14:11:25 -0500 Subject: fixed up dropping documents into a collection that doesn't have an activeFrame set so that they can be resized --- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index fdcfb00d8..58a9c4974 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -169,14 +169,23 @@ export class CollectionFreeFormView extends CollectionSubView Date: Tue, 3 Nov 2020 14:26:19 -0500 Subject: added undo's for icon/deiconifying pile docs and icon docs. added a zoom hack to focus on stacking documents. stopped autoscroll on nested collections. --- src/client/views/collections/CollectionPileView.tsx | 14 ++++++++------ src/client/views/collections/CollectionStackingView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 5b4730848..2636b98e5 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -6,7 +6,7 @@ import { emptyFunction, setupMoveUpEvents } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; import { SelectionManager } from "../../util/SelectionManager"; import { SnappingManager } from "../../util/SnappingManager"; -import { UndoManager } from "../../util/UndoManager"; +import { UndoManager, undoBatch } from "../../util/UndoManager"; import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView"; import "./CollectionPileView.scss"; import { CollectionSubView } from "./CollectionSubView"; @@ -34,14 +34,14 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { const draggingSelf = this.props.isSelected(); return
{ + addDocument={undoBatch((doc: Doc | Doc[]) => { (doc instanceof Doc ? [doc] : doc).map((d) => DocUtils.iconify(d)); return this.props.addDocument(doc); - }} - moveDocument={(doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { - (doc instanceof Doc ? [doc] : doc).map((d) => Doc.deiconifyView(d)); + })} + moveDocument={undoBatch((doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { + (doc instanceof Doc ? [doc] : doc).map(undoBatch((d) => Doc.deiconifyView(d))); return this.props.moveDocument(doc, targetCollection, addDoc); - }} /> + })} />
; } @@ -107,6 +107,8 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { } // onClick for toggling the pileup view + @undoBatch + @action onClick = (e: React.MouseEvent) => { if (e.button === 0) { SelectionManager.DeselectAll(); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4880d342c..7a3257525 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -172,7 +172,7 @@ export class CollectionStackingView extends CollectionSubView boolean) => { Doc.BrushDoc(doc); - this.props.focus(doc); + this.props.focus(this.props.Document, true); // bcz: HACK ARgh.. need to update all focus() functions to take parameters about how to focus. in this case, we want to zoom so we pass true and hope an ancestor is a collection view Doc.linkFollowHighlight(doc); const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName("documentView-node")).find((node: any) => node.id === doc[Id]); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 58a9c4974..703776e72 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1218,7 +1218,7 @@ export class CollectionFreeFormView extends CollectionSubView(Docu thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey }, console.log); - func(); + undoBatch(func)(); } else if (!Doc.IsSystem(this.props.Document)) { if (this.props.Document.type === DocumentType.INK) { InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlBtn = true); -- cgit v1.2.3-70-g09d2 From aba91357df33b49e9c09208a53b757ef8f8dc724 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 8 Nov 2020 21:35:16 -0500 Subject: added an optional background grid for collections. --- src/client/views/MainView.tsx | 4 +-- src/client/views/collections/CollectionMenu.tsx | 13 ++++++-- .../collectionFreeForm/CollectionFreeFormView.scss | 7 ++++ .../collectionFreeForm/CollectionFreeFormView.tsx | 37 +++++++++++++++++++++- src/client/views/nodes/PresBox.tsx | 4 +-- 5 files changed, 57 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 3a3dbc68f..452ce61ff 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -133,7 +133,7 @@ export class MainView extends React.Component { } library.add(fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar, - fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, + fa.faSquare, far.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone, fa.faKeyboard, fa.faQuestion, fa.faTasks, fa.faPalette, fa.faAngleLeft, fa.faAngleRight, fa.faBell, fa.faCamera, fa.faExpand, fa.faCaretDown, fa.faCaretLeft, fa.faCaretRight, fa.faCaretSquareDown, fa.faCaretSquareRight, fa.faArrowsAltH, fa.faPlus, fa.faMinus, fa.faTerminal, fa.faToggleOn, fa.faFile, fa.faLocationArrow, @@ -151,7 +151,7 @@ export class MainView extends React.Component { fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, faBuffer, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl, fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faTextHeight, fa.faClosedCaptioning, fa.faInfoCircle, fa.faTag, fa.faSyncAlt, fa.faPhotoVideo, fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical, - fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, + fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll, fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines); this.initAuthenticationRouters(); } diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index cf94a93d3..b2b23115f 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -489,13 +489,19 @@ export class CollectionViewBaseChrome extends React.Component{"Show Lightbox of Images"}
} placement="top"> - ; } - - + @computed get gridbackgroundButton() { + const targetDoc = this.selectedDoc; + return !targetDoc ? (null) : {"Toggle background grid"}
} placement="top"> + + ; + } render() { return ( @@ -513,6 +519,7 @@ export class CollectionViewBaseChrome extends React.Component } {this.notACollection ? (null) : this.lightboxButton} + {this.notACollection ? (null) : this.gridbackgroundButton} {this.aliasButton} {/* {this.pinButton} */} {this.pinWithViewButton} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index e92100c50..a50b41198 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -12,6 +12,13 @@ border-radius: inherit; } +.collectionfreeformview-grid { + transform-origin: top left; + position: absolute; + top: 0; + left: 0; +} + .collectionfreeformview-viewdef { >.collectionFreeFormDocumentView-container { pointer-events: none; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 703776e72..8a4ce826f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1434,6 +1434,38 @@ export class CollectionFreeFormView extends CollectionSubView { + const ctx = el?.getContext('2d'); + if (ctx) { + const Cx = (cx / this.zoomScaling()) % gridSpace - 0; + const Cy = (cy / this.zoomScaling()) % gridSpace - 0; + ctx.clearRect(0, 0, w, h); + if (ctx) { + ctx.strokeStyle = "rgba(0, 0, 0, 0.5)"; + ctx.lineWidth = Math.min(1, Math.max(0.5, 0.5 / this.zoomScaling())); + ctx.beginPath(); + for (let x = Cx; x <= -Cx + w; x += gridSpace) { + ctx.moveTo(x, Cy - h); + ctx.lineTo(x, Cy + h); + } + for (let y = Cy; y <= -Cy + h; y += gridSpace) { + ctx.moveTo(Cx - w, y); + ctx.lineTo(Cx + w, y); + } + ctx.stroke(); + } + } + }} />; + } @computed get marqueeView() { return
+ {this.layoutDoc["_backgroundGrid-show"] ? this.grid : (null)} ; } + @computed get contentScaling() { if (this.props.annotationsKey && !this.props.forceScaling) return 0; const nw = returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document)); @@ -1635,7 +1669,7 @@ class CollectionFreeFormViewPannableContents extends React.Component; } + render() { // trace(); const freeformclass = "collectionfreeformview" + (this.props.viewDefDivClick ? "-viewDef" : "-none"); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 52e09a469..683cb938a 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -426,7 +426,7 @@ export class PresBox extends ViewBoxBaseComponent if (tagDoc) tagDoc.opacity = 1; const itemIndexes: number[] = this.getAllIndexes(this.tagDocs, tagDoc); const curInd: number = itemIndexes.indexOf(index); - if (tagDoc === this.layoutDoc.presCollection) { tagDoc.opacity = 1 } + if (tagDoc === this.layoutDoc.presCollection) { tagDoc.opacity = 1; } else { if (itemIndexes.length > 1 && curDoc.presHideBefore && curInd !== 0) { } else if (curDoc.presHideBefore) { @@ -1210,7 +1210,7 @@ export class PresBox extends ViewBoxBaseComponent const targetDoc: Doc = this.targetDoc; this.updateMovement(activeItem.presMovement, true); this.updateEffect(targetDoc.presEffect, true); - this.updateEffectDirection(targetDoc.presEffectDirection, true) + this.updateEffectDirection(targetDoc.presEffectDirection, true); array.forEach((doc) => { const curDoc = Cast(doc, Doc, null); const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null); -- cgit v1.2.3-70-g09d2 From ce5512a3fdd451ad47263f896a9e855229133eaf Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 9 Nov 2020 15:04:28 -0500 Subject: added fullScreen alias option for opening documents so that opened document can have different scale than original. fixed pushpins to not toggle target if something must be panned/zoomed to show the target. fixed drag drop to ignore the document being dragged properly when dropping (which prevented a document over a collection from being dropped on the colelction when move slightly). --- src/client/util/DocumentManager.ts | 10 ++--- src/client/util/DragManager.ts | 18 +++++---- src/client/views/DocumentDecorations.tsx | 10 ++--- .../views/collections/CollectionStackingView.tsx | 5 ++- src/client/views/collections/TabDocView.tsx | 6 +-- .../collectionFreeForm/CollectionFreeFormView.tsx | 45 ++++++++++++++-------- src/client/views/nodes/DocumentView.tsx | 13 +++---- src/client/views/nodes/FieldView.tsx | 3 +- src/fields/documentSchemas.ts | 1 + 9 files changed, 62 insertions(+), 49 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 14aaeaec0..a6816c7f9 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -163,21 +163,19 @@ export class DocumentManager { if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? const sameContext = annotatedDoc && annotatedDoc === originatingDoc?.context; if (originatingDoc?.isPushpin) { - const hide = !docView.props.Document.hidden; - docView.props.focus(docView.props.Document, willZoom, undefined, (notfocused: boolean) => { // bcz: Argh! TODO: Need to add a notFocused argument to the after finish callback function that indicates whether the window had to scroll to show the target - if (notfocused || docView.props.Document.hidden) { + docView.props.focus(docView.props.Document, willZoom, undefined, (didFocus: boolean) => { + if (!didFocus || docView.props.Document.hidden) { docView.props.Document.hidden = !docView.props.Document.hidden; } return focusAndFinish(); - // @ts-ignore bcz: Argh TODO: Need to add a parameter to focus() everywhere for whether focus should center the target's container in the view or not. // here we don't want to focus the container if the source and target are in the same container - }, sameContext); + }, sameContext, false);// don't want to focus the container if the source and target are in the same container, so pass 'sameContext' for dontCenter parameter //finished?.(); } else { docView.select(false); docView.props.Document.hidden && (docView.props.Document.hidden = undefined); // @ts-ignore - docView.props.focus(docView.props.Document, willZoom, undefined, focusAndFinish, sameContext); + docView.props.focus(docView.props.Document, willZoom, undefined, focusAndFinish, sameContext, false); } highlight(); } else { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 9e91b4f55..86e2d339e 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -416,7 +416,13 @@ export namespace DragManager { }); const hideSource = options?.hideSource ? true : false; - eles.map(ele => ele.parentElement && ele.parentElement?.className === dragData.dragDivName ? (ele.parentElement.hidden = hideSource) : (ele.hidden = hideSource)); + eles.forEach(ele => { + if (ele.parentElement && ele.parentElement?.className === dragData.dragDivName) { + ele.parentElement.hidden = hideSource; + } else { + ele.hidden = hideSource; + } + }); SnappingManager.SetIsDragging(true); let lastX = downX; @@ -514,27 +520,25 @@ export namespace DragManager { const hideDragShowOriginalElements = () => { dragLabel.style.display = "none"; dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); - eles.map(ele => ele.parentElement && ele.parentElement?.className === dragData.dragDivName ? (ele.parentElement.hidden = false) : (ele.hidden = false)); + eles.map(ele => ele.parentElement && ele.parentElement?.className === dragData.dragDivName ? (ele.hidden = ele.parentElement.hidden = false) : (ele.hidden = false)); }; const endDrag = action(() => { + hideDragShowOriginalElements(); document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); + SnappingManager.SetIsDragging(false); SnappingManager.clearSnapLines(); batch.end(); }); AbortDrag = () => { - hideDragShowOriginalElements(); - SnappingManager.SetIsDragging(false); options?.dragComplete?.(new DragCompleteEvent(true, dragData)); endDrag(); }; const upHandler = (e: PointerEvent) => { - hideDragShowOriginalElements(); dispatchDrag(eles, e, dragData, xFromLeft, yFromTop, xFromRight, yFromBottom, options, finishDrag); - SnappingManager.SetIsDragging(false); - endDrag(); options?.dragComplete?.(new DragCompleteEvent(false, dragData)); + endDrag(); }; document.addEventListener("pointermove", moveHandler, true); document.addEventListener("pointerup", upHandler); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 4dcae8e60..63b99cd85 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -177,19 +177,17 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const selectedDocs = SelectionManager.SelectedDocuments(); if (selectedDocs.length) { if (e.ctrlKey) { // open an alias in a new tab with Ctrl Key - const alias = Doc.MakeAlias(selectedDocs[0].props.Document); - alias.context = undefined; - //CollectionDockingView.Instance?.OpenFullScreen(selectedDocs[0]); - CollectionDockingView.AddSplit(alias, "right"); + selectedDocs[0].props.Document._fullScreenView = Doc.MakeAlias(selectedDocs[0].props.Document); + (selectedDocs[0].props.Document._fullScreenView as Doc).context = undefined; + CollectionDockingView.AddSplit(selectedDocs[0].props.Document._fullScreenView as Doc, "right"); } else if (e.shiftKey) { // open centered in a new workspace with Shift Key const alias = Doc.MakeAlias(selectedDocs[0].props.Document); alias.context = undefined; alias.x = -alias[WidthSym]() / 2; alias.y = -alias[HeightSym]() / 2; - //CollectionDockingView.Instance?.OpenFullScreen(selectedDocs[0]); CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([alias], { title: "Tab for " + alias.title }), "right"); } else { // open same document in new tab - CollectionDockingView.ToggleSplit(selectedDocs[0].props.Document, "right"); + CollectionDockingView.ToggleSplit(Cast(selectedDocs[0].props.Document._fullScreenView, Doc, null) || selectedDocs[0].props.Document, "right"); } } } diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 2285bcb8f..62f733058 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -28,6 +28,7 @@ import { CollectionViewType } from "./CollectionView"; import { SnappingManager } from "../../util/SnappingManager"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DocUtils } from "../../documents/Documents"; +import { DocAfterFocusFunc } from "../nodes/DocumentView"; const _global = (window /* browser */ || global /* node */) as any; type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; @@ -170,9 +171,9 @@ export class CollectionStackingView extends CollectionSubView boolean) => { + focusDocument = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, didFocus?: boolean) => { Doc.BrushDoc(doc); - this.props.focus(this.props.Document, true); // bcz: HACK ARgh.. need to update all focus() functions to take parameters about how to focus. in this case, we want to zoom so we pass true and hope an ancestor is a collection view + this.props.focus(this.props.Document, true); // bcz: want our containing collection to zoom Doc.linkFollowHighlight(doc); const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName("documentView-node")).find((node: any) => node.id === doc[Id]); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 38b9b399d..530595cd0 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -21,7 +21,7 @@ import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from "../../util/UndoManager"; -import { DocumentView } from "../nodes/DocumentView"; +import { DocumentView, DocAfterFocusFunc } from "../nodes/DocumentView"; import { PresBox, PresMovement } from '../nodes/PresBox'; import { CollectionDockingView } from './CollectionDockingView'; import { CollectionDockingViewMenu } from './CollectionDockingViewMenu'; @@ -343,11 +343,11 @@ export class TabDocView extends React.Component { ; } - focusFunc = (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: () => void) => { + focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, notFocused?: boolean) => { if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) { this.tab.header.parent.setActiveContentItem(this.tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost) } - afterFocus?.(); + afterFocus?.(false); } setView = action((view: DocumentView) => this._view = view); active = () => this._isActive; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8a4ce826f..4541716f3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -33,7 +33,7 @@ import { ContextMenu } from "../../ContextMenu"; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth } from "../../InkingStroke"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentLinksButton } from "../../nodes/DocumentLinksButton"; -import { DocumentViewProps } from "../../nodes/DocumentView"; +import { DocumentViewProps, DocAfterFocusFunc } from "../../nodes/DocumentView"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { pageSchema } from "../../nodes/ImageBox"; import { PresBox } from "../../nodes/PresBox"; @@ -887,7 +887,7 @@ export class CollectionFreeFormView extends CollectionSubView boolean, dontCenter?: boolean) => { + focusDocument = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, didFocus?: boolean) => { const state = HistoryUtil.getState(); // TODO This technically isn't correct if type !== "doc", as @@ -927,7 +927,7 @@ export class CollectionFreeFormView extends CollectionSubView { - // @ts-ignore - if (afterFocus?.(notFocused)) { // bcz: TODO Aragh -- need to add a parameter to afterFocus() functions to indicate whether the focus function didn't need to scroll - this.Document._panX = savedState.px; - this.Document._panY = savedState.py; - this.Document[this.scaleFieldKey] = savedState.s; - this.Document._viewTransition = savedState.pt; - } - }, notFocused ? 0 : 500); + const newDidFocus = didFocus || (newPanX !== savedState.px || newPanY !== savedState.py); + + const newAfterFocus = (didFocus: boolean) => { + afterFocus && setTimeout(() => { + // @ts-ignore + if (afterFocus?.(didFocus || (newPanX !== savedState.px || newPanY !== savedState.py))) { + this.Document._panX = savedState.px; + this.Document._panY = savedState.py; + this.Document[this.scaleFieldKey] = savedState.s; + this.Document._viewTransition = savedState.pt; + } + }, newPanX !== savedState.px || newPanY !== savedState.py ? 500 : 0); + return false; + }; + this.props.focus(this.props.Document, undefined, undefined, newAfterFocus, undefined, newDidFocus); + Doc.linkFollowHighlight(doc); } } @@ -1434,8 +1438,15 @@ export class CollectionFreeFormView extends CollectionSubView { + const w = this.props.PanelWidth() / this.zoomScaling() + 3 * start; + if (w / start > 60) return this.chooseGridSpace(start * 10); + return start; + } + @computed get grid() { - const gridSpace = NumCast(this.layoutDoc["_backgroundGrid-space"], 50); + const gridSpace = this.chooseGridSpace(NumCast(this.layoutDoc["_backgroundGrid-space"], 50)); const shiftX = this.props.isAnnotationOverlay ? 0 : -(this.panX()) % gridSpace - gridSpace; const shiftY = this.props.isAnnotationOverlay ? 0 : -(this.panY()) % gridSpace - gridSpace; const cx = this.centeringShiftX(); @@ -1448,6 +1459,8 @@ export class CollectionFreeFormView extends CollectionSubView 50 ? 3 : 1); + ctx.setLineDash(gridSpace > 50 ? [3, 3] : [1, 5]); ctx.clearRect(0, 0, w, h); if (ctx) { ctx.strokeStyle = "rgba(0, 0, 0, 0.5)"; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4efa5d67f..77f63b457 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -42,7 +42,8 @@ import { RadialMenu } from './RadialMenu'; import { TaskCompletionBox } from './TaskCompletedBox'; import React = require("react"); -export type DocFocusFunc = () => boolean; +export type DocAfterFocusFunc = (notFocused: boolean) => boolean; +export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => void; export interface DocumentViewProps { ContainingCollectionView: Opt; @@ -82,7 +83,7 @@ export interface DocumentViewProps { PanelHeight: () => number; pointerEvents?: string; contentsPointerEvents?: string; - focus: (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: DocFocusFunc) => void; + focus: DocFocusFunc; parentActive: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc, sendToBack?: boolean) => void; @@ -331,11 +332,7 @@ export class DocumentView extends DocComponent(Docu InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlBtn = true); } else { UndoManager.RunInBatch(() => { - let fullScreenDoc = this.props.Document; - if (StrCast(this.props.Document.layoutKey) !== "layout_fullScreen" && this.props.Document.layout_fullScreen) { - fullScreenDoc = Doc.MakeAlias(this.props.Document); - fullScreenDoc.layoutKey = "layout_fullScreen"; - } + const fullScreenDoc = Cast(this.props.Document._fullScreenView, Doc, null) || this.props.Document; this.props.addDocTab(fullScreenDoc, "add"); }, "double tap"); SelectionManager.DeselectAll(); @@ -385,7 +382,7 @@ export class DocumentView extends DocComponent(Docu // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place // depending on the followLinkLocation property of the source (or the link itself as a fallback); public static followLinkClick = async (linkDoc: Opt, sourceDoc: Doc, docView: { - focus: (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: DocFocusFunc) => void, + focus: DocFocusFunc, addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean, ContainingCollectionDoc?: Doc }, shiftKey: boolean, altKey: boolean) => { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 3a5b27b21..79947c023 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -11,6 +11,7 @@ import { CollectionView } from "../collections/CollectionView"; import { AudioBox } from "./AudioBox"; import { VideoBox } from "./VideoBox"; import { dropActionType } from "../../util/DragManager"; +import { DocAfterFocusFunc, DocFocusFunc } from "./DocumentView"; // // these properties get assigned through the render() method of the DocumentView when it creates this node. @@ -47,7 +48,7 @@ export interface FieldViewProps { whenActiveChanged: (isActive: boolean) => void; LayoutTemplateString?: string; dontRegisterView?: boolean; - focus: (doc: Doc) => void; + focus: DocFocusFunc; presMultiSelect?: (doc: Doc) => void; //added for selecting multiple documents in a presentation ignoreAutoHeight?: boolean; PanelWidth: () => number; diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 311aaa769..6e58f7f13 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -15,6 +15,7 @@ export const documentSchema = createSchema({ // "Location" properties in a very general sense _curPage: "number", // current page of a page based document _currentFrame: "number", // current frame of a frame based collection (e.g., a progressive slide) + _fullScreenView: Doc, // alias to display when double-clicking to open document in a full-screen view lastFrame: "number", // last frame of a frame based collection (e.g., a progressive slide) activeFrame: "number", // the active frame of a frame based animated document _currentTimecode: "number", // current play back time of a temporal document (video / audio) -- cgit v1.2.3-70-g09d2 From 83d3756537cfcd8a2248c4b8a2a6f75f77154602 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 9 Nov 2020 21:40:59 -0500 Subject: fixed autoHeight for formattedTextSidebars when the text document has been scaled. cleaned up link groups. fixed pushpins that don't focus on target (e.g., a si m ple pushpin on a PDF). --- src/client/util/LinkManager.ts | 9 +---- .../views/collections/CollectionStackingView.tsx | 10 +++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 3 +- src/client/views/linking/LinkMenu.tsx | 29 ++++++--------- src/client/views/linking/LinkMenuGroup.tsx | 43 +++------------------- src/client/views/nodes/LinkDocPreview.tsx | 17 ++++----- .../views/nodes/formattedText/FormattedTextBox.tsx | 20 +++++----- 7 files changed, 42 insertions(+), 89 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 3a0c0e3eb..802b8ae7b 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -35,7 +35,7 @@ export class LinkManager { allLinks = computedFn(function allLinks(this: any): Doc[] { const lset = new Set(DocListCast(Doc.LinkDBDoc().data)); - SharingManager.Instance.users.forEach(user => DocListCast(user.linkDatabase?.data).map(doc => lset.add(doc))); + SharingManager.Instance.users.forEach(user => DocListCast(user.linkDatabase?.data).forEach(doc => lset.add(doc))); return Array.from(lset); }, true); @@ -69,13 +69,6 @@ export class LinkManager { return anchorGroups; } - // returns a list of all metadata docs associated with the given group type - public getAllMetadataDocsInGroup(groupType: string): Array { - const md: Doc[] = []; - LinkManager.Instance.allLinks().forEach(linkDoc => StrCast(linkDoc.linkRelationship).toUpperCase() === groupType.toUpperCase() && md.push(linkDoc)); - return md; - } - // checks if a link with the given anchors exists public doesLinkExist(anchor1: Doc, anchor2: Doc): boolean { return -1 !== LinkManager.Instance.allLinks().findIndex(linkDoc => diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 62f733058..97eacaeab 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -352,8 +352,12 @@ export class CollectionStackingView extends CollectionSubView { if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { - const height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); - Doc.Layout(doc)._height = Math.max(height, NumCast(doc[this.props.fieldKey + "-height"])); + const height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => NumCast(Doc.Layout(doc)._viewScale, 1) * Number(getComputedStyle(r).height.replace("px", ""))))); + if (this.props.annotationsKey) { + doc[this.props.annotationsKey + "-height"] = height; + } else { + Doc.Layout(doc)._height = height * NumCast(Doc.Layout(doc)._viewScale, 1); + } } })); this.observer.observe(ref); @@ -406,7 +410,7 @@ export class CollectionStackingView extends CollectionSubView { if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); - Doc.Layout(doc)._height = Math.max(height, NumCast(doc[this.props.fieldKey + "-height"])); + Doc.Layout(doc)._height = Math.max(height * NumCast(doc[this.props.fieldKey + "-height"]), NumCast(doc[this.props.fieldKey + "-height"])); } })); this.observer.observe(ref); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4541716f3..21e653e02 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -926,8 +926,7 @@ export class CollectionFreeFormView extends CollectionSubView { } renderAllGroups = (groups: Map>): Array => { - const linkItems: Array = []; - groups.forEach((group, groupType) => { - linkItems.push( - this._editingLink = linkDoc)} - addDocTab={this.props.addDocTab} /> - ); - }); - - // if source doc has no links push message - if (linkItems.length === 0) linkItems.push(

No links have been created yet. Drag the linking button onto another document to create a link.

); - - return linkItems; + const linkItems = Array.from(groups.entries()).map(group => + this._editingLink = linkDoc)} + addDocTab={this.props.addDocTab} />); + + return linkItems.length ? linkItems : [

No links have been created yet. Drag the linking button onto another document to create a link.

]; } @computed diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index e76227ccf..e53655fd3 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -1,17 +1,12 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action } from "mobx"; import { observer } from "mobx-react"; import { Doc } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; -import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { Docs } from "../../documents/Documents"; -import { DragManager, SetupDrag } from "../../util/DragManager"; +import { Cast } from "../../../fields/Types"; import { LinkManager } from "../../util/LinkManager"; import { DocumentView } from "../nodes/DocumentView"; import './LinkMenu.scss'; -import { LinkMenuItem, StartLinkTargetsDrag } from "./LinkMenuItem"; +import { LinkMenuItem } from "./LinkMenuItem"; import React = require("react"); -import { Cast } from "../../../fields/Types"; interface LinkMenuGroupProps { sourceDoc: Doc; @@ -26,34 +21,8 @@ interface LinkMenuGroupProps { export class LinkMenuGroup extends React.Component { private _drag = React.createRef(); - private _table = React.createRef(); private _menuRef = React.createRef(); - onLinkButtonDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.addEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); - document.addEventListener("pointerup", this.onLinkButtonUp); - } - - onLinkButtonUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); - e.stopPropagation(); - } - - onLinkButtonMoved = async (e: PointerEvent) => { - if (this._drag.current && (e.movementX > 1 || e.movementY > 1)) { - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); - - const targets = this.props.group.map(l => LinkManager.getOppositeAnchor(l, this.props.sourceDoc)).filter(d => d) as Doc[]; - StartLinkTargetsDrag(this._drag.current, this.props.docView, e.x, e.y, this.props.sourceDoc, targets); - } - e.stopPropagation(); - } - render() { const set = new Set(this.props.group); const groupItems = Array.from(set.keys()).map(linkDoc => { @@ -75,11 +44,9 @@ export class LinkMenuGroup extends React.Component { return (
- {/*
-

{this.props.groupType}:

- {this.props.groupType === "*" || this.props.groupType === "" ? <> : this.viewGroupAsTable(this.props.groupType)} -
*/} +
+

{this.props.groupType}:

+
{groupItems} diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 867be9735..d47942bd9 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -77,19 +77,16 @@ export class LinkDocPreview extends React.Component { this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { _fitWidth: true, title: this.props.href, _width: 200, _height: 400, useCors: true }), "add:right"); } } - width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225)) - 16; - height = () => Math.min(225, NumCast(this._targetDoc?.[HeightSym](), 225)) - 16; + width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225)); + height = () => Math.min(225, NumCast(this._targetDoc?.[HeightSym](), 225)); @computed get targetDocView() { return !this._targetDoc ? -
+
{this._toolTipText}
-
: - +
+ : { ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} renderDepth={-1} - PanelWidth={this.width} //Math.min(350, NumCast(target._width, 350))} - PanelHeight={this.height} //Math.min(250, NumCast(target._height, 250))} + PanelWidth={this.width} + PanelHeight={this.height} focus={emptyFunction} whenActiveChanged={returnFalse} bringToFront={returnFalse} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index bc9e8e99d..fe38939c5 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -812,6 +812,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } componentDidMount() { this._cachedLinks = DocListCast(this.Document.links); + this._disposers.sidebarheight = reaction( + () => ({ annoHeight: NumCast(this.rootDoc[this.annotationKey + "-height"]), textHeight: NumCast(this.rootDoc[this.fieldKey + "-height"]) }), + ({ annoHeight, textHeight }) => { + this.layoutDoc._autoHeight && (this.rootDoc._height = Math.max(annoHeight, textHeight)); + }); this._disposers.links = reaction(() => DocListCast(this.Document.links), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks newLinks => { this._cachedLinks.forEach(l => !newLinks.includes(l) && this.RemoveLinkFromDoc(l)); @@ -1540,18 +1545,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp }, 10); } else { try { - const boxHeight = Number(getComputedStyle(this._boxRef.current!).height.replace("px", "")); + const boxHeight = Number(getComputedStyle(this._boxRef.current!).height.replace("px", "")) * NumCast(this.Document._viewScale, 1); const outer = this.rootDoc[HeightSym]() - boxHeight - (this.props.ChromeHeight ? this.props.ChromeHeight() : 0); - const finalHeight = newHeight + Math.max(0, outer); - const maxsidebar = !this.sidebarWidth() ? 0 : Array.from(this._boxRef.current!.getElementsByClassName("collectionStackingViewFieldColumn")).reduce((prev, ele) => Math.max(prev, Number(getComputedStyle(ele).height.replace("px", ""))), 0); - if (this.rootDoc._height !== finalHeight && finalHeight > maxsidebar) { - this.rootDoc._height = finalHeight; - this.layoutDoc._nativeHeight = nh ? scrollHeight : undefined; - } - this.rootDoc[this.fieldKey + "-height"] = finalHeight; + this.rootDoc[this.fieldKey + "-height"] = newHeight + Math.max(0, outer); } catch (e) { console.log("Error in tryUpdateHeight"); } } - } else this.rootDoc[this.fieldKey + "-height"] = 0; + } //else this.rootDoc[this.fieldKey + "-height"] = 0; } @computed get audioHandle() { @@ -1609,7 +1608,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); } sidebarWidth = () => Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth(); - sidebarScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth()) / this.props.ContentScaling(), 0); + sidebarScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth()) / this.props.ContentScaling(), 0).scale(1 / NumCast(this.layoutDoc._viewScale, 1)); @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); } render() { TraceMobx(); @@ -1631,6 +1630,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp transformOrigin: "top left", width: `${100 / scale}%`, height: `calc(${100 / scale}% - ${this.props.ChromeHeight?.() || 0}px)`, + overflowY: this.layoutDoc._autoHeight ? "hidden" : undefined, ...this.styleFromLayoutString(scale) // this converts any expressions in the format string to style props. e.g., }}>
Date: Tue, 10 Nov 2020 12:51:48 -0500 Subject: fixed performance issues with background grid by avoiding making really big canvases. --- .../collectionFreeForm/CollectionFreeFormView.tsx | 33 ++++++++++------------ src/fields/documentSchemas.ts | 1 + 2 files changed, 16 insertions(+), 18 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 21e653e02..1033050b9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1438,38 +1438,35 @@ export class CollectionFreeFormView extends CollectionSubView { - const w = this.props.PanelWidth() / this.zoomScaling() + 3 * start; - if (w / start > 60) return this.chooseGridSpace(start * 10); - return start; + chooseGridSpace = (gridSpace: number): number => { + const divisions = this.props.PanelWidth() / this.zoomScaling() / gridSpace + 3; + return divisions < 60 ? gridSpace : this.chooseGridSpace(gridSpace * 10); } @computed get grid() { - const gridSpace = this.chooseGridSpace(NumCast(this.layoutDoc["_backgroundGrid-space"], 50)); - const shiftX = this.props.isAnnotationOverlay ? 0 : -(this.panX()) % gridSpace - gridSpace; - const shiftY = this.props.isAnnotationOverlay ? 0 : -(this.panY()) % gridSpace - gridSpace; - const cx = this.centeringShiftX(); - const cy = this.centeringShiftY(); - const w = this.props.PanelWidth() / this.zoomScaling() + 3 * gridSpace; - const h = this.props.PanelHeight() / this.zoomScaling() + 3 * gridSpace; - return { const ctx = el?.getContext('2d'); if (ctx) { - const Cx = (cx / this.zoomScaling()) % gridSpace - 0; - const Cy = (cy / this.zoomScaling()) % gridSpace - 0; - ctx.lineWidth = Math.min(1, Math.max(0.5, 0.5 / this.zoomScaling())) * (gridSpace > 50 ? 3 : 1); + const Cx = this.centeringShiftX() % renderGridSpace; + const Cy = this.centeringShiftY() % renderGridSpace; + ctx.lineWidth = Math.min(1, Math.max(0.5, this.zoomScaling())); ctx.setLineDash(gridSpace > 50 ? [3, 3] : [1, 5]); ctx.clearRect(0, 0, w, h); if (ctx) { ctx.strokeStyle = "rgba(0, 0, 0, 0.5)"; - ctx.lineWidth = Math.min(1, Math.max(0.5, 0.5 / this.zoomScaling())); ctx.beginPath(); - for (let x = Cx; x <= -Cx + w; x += gridSpace) { + for (let x = Cx - renderGridSpace; x <= w - Cx; x += renderGridSpace) { ctx.moveTo(x, Cy - h); ctx.lineTo(x, Cy + h); } - for (let y = Cy; y <= -Cy + h; y += gridSpace) { + for (let y = Cy - renderGridSpace; y <= h - Cy; y += renderGridSpace) { ctx.moveTo(Cx - w, y); ctx.lineTo(Cx + w, y); } diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 6e58f7f13..e0404d9d3 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -34,6 +34,7 @@ export const documentSchema = createSchema({ _scrollLeft: "number", // scroll position of a scrollable document (pdf, text, web) // appearance properties on the layout + "_backgroundGrid-spacing": "number", // the size of the grid for collection views _autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents _nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set _nativeHeight: "number", // " -- cgit v1.2.3-70-g09d2