From 88a8ae38f6e9be6a1c51783d68864c6cc47ba8e6 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 3 Jun 2020 17:50:41 -0400 Subject: cleaned up internalDrop code. fixed drop to work with ACLs that don't permit drop --- .../collectionFreeForm/CollectionFreeFormView.tsx | 128 ++++++++++----------- 1 file changed, 62 insertions(+), 66 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c753a703d..a8eef6875 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -46,7 +46,6 @@ import React = require("react"); import { CollectionViewType } from "../CollectionView"; import { Timeline } from "../../animationtimeline/Timeline"; import { SnappingManager } from "../../../util/SnappingManager"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -188,79 +187,76 @@ export class CollectionFreeFormView extends CollectionSubView this.isCurrent(pair.layout)).map(pair => pair.layout); } + onExternalDrop = (e: React.DragEvent) => { + return (pt => super.onExternalDrop(e, { x: pt[0], y: pt[1] }))(this.getTransform().transformPoint(e.pageX, e.pageY)); + } + + @undoBatch + @action + internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number, yp: number) { + if (!super.onInternalDrop(e, de)) return false; + const [xpo, ypo] = this.getTransformOverlay().transformPoint(de.x, de.y); + const z = NumCast(docDragData.droppedDocuments[0].z); + const x = (z ? xpo : xp) - docDragData.offset[0]; + const y = (z ? ypo : yp) - docDragData.offset[1]; + const zsorted = this.childLayoutPairs.map(pair => pair.layout).slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); + zsorted.forEach((doc, index) => doc.zIndex = index + 1); + const dropPos = [NumCast(docDragData.droppedDocuments[0].x), NumCast(docDragData.droppedDocuments[0].y)]; + for (let i = 0; i < docDragData.droppedDocuments.length; i++) { + const d = docDragData.droppedDocuments[i]; + const layoutDoc = Doc.Layout(d); + if (this.Document.currentFrame !== undefined && !this.props.isAnnotationOverlay) { + const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); + CollectionFreeFormDocumentView.setValues(this.Document.currentFrame, d, x + vals.x - dropPos[0], y + vals.y - dropPos[1], vals.opacity); + } else { + d.x = x + NumCast(d.x) - dropPos[0]; + d.y = y + NumCast(d.y) - dropPos[1]; + } + const nd = [NumCast(layoutDoc._nativeWidth), NumCast(layoutDoc._nativeHeight)]; + layoutDoc._width = NumCast(layoutDoc._width, 300); + layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? nd[1] / nd[0] * NumCast(layoutDoc._width) : 300); + d.isBackground === undefined && (d.zIndex = zsorted.length + 1 + i); // bringToFront + } + + (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(docDragData.droppedDocuments); + return true; + } + + @undoBatch @action - onExternalDrop = (e: React.DragEvent): Promise => { - const pt = this.getTransform().transformPoint(e.pageX, e.pageY); - return super.onExternalDrop(e, { x: pt[0], y: pt[1] }); + internalPdfAnnoDrop(e: Event, annoDragData: DragManager.PdfAnnoDragData, xp: number, yp: number) { + const dragDoc = annoDragData.dropDocument; + const dropPos = [NumCast(dragDoc.x), NumCast(dragDoc.y)]; + dragDoc.x = xp - annoDragData.offset[0] + (NumCast(dragDoc.x) - dropPos[0]); + dragDoc.y = yp - annoDragData.offset[1] + (NumCast(dragDoc.y) - dropPos[1]); + annoDragData.targetContext = this.props.Document; // dropped a PDF annotation, so we need to set the targetContext on the dragData which the PDF view uses at the end of the drop operation + this.bringToFront(dragDoc); + return true; } @undoBatch + @action + internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData, xp: number, yp: number) { + if (linkDragData.linkSourceDocument === this.props.Document) return false; + const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" }); + this.props.addDocument(source); + linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation"); // TODODO this is where in text links get passed + e.stopPropagation(); + return true; + } + @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { // if (this.props.Document.isBackground) return false; - const xf = this.getTransform(); - const xfo = this.getTransformOverlay(); - const [xp, yp] = xf.transformPoint(de.x, de.y); - const [xpo, ypo] = xfo.transformPoint(de.x, de.y); - const zsorted = this.childLayoutPairs.map(pair => pair.layout).slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); - if (!this.isAnnotationOverlay && de.complete.linkDragData && de.complete.linkDragData.linkSourceDocument !== this.props.Document) { - const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" }); - this.props.addDocument(source); - (de.complete.linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceDocument }, - "doc annotation")); // TODODO this is where in text links get passed - e.stopPropagation(); + const [xp, yp] = this.getTransform().transformPoint(de.x, de.y); + if (this.isAnnotationOverlay !== true && de.complete.linkDragData) + return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp); + if (de.complete.annoDragData?.dropDocument && super.onInternalDrop(e, de)) + return this.internalPdfAnnoDrop(e, de.complete.annoDragData, xp, yp); + if (de.complete.docDragData?.droppedDocuments.length && this.internalDocDrop(e, de, de.complete.docDragData, xp, yp)) { return true; - } - if (super.onInternalDrop(e, de)) { - if (de.complete.docDragData) { - if (de.complete.docDragData.droppedDocuments.length) { - const firstDoc = de.complete.docDragData.droppedDocuments[0]; - const z = NumCast(firstDoc.z); - const x = (z ? xpo : xp) - de.complete.docDragData.offset[0]; - const y = (z ? ypo : yp) - de.complete.docDragData.offset[1]; - const dropX = NumCast(firstDoc.x); - const dropY = NumCast(firstDoc.y); - const droppedDocs = de.complete.docDragData.droppedDocuments; - runInAction(() => { - zsorted.forEach((doc, index) => doc.zIndex = index + 1); - for (let i = 0; i < droppedDocs.length; i++) { - const d = droppedDocs[i]; - const layoutDoc = Doc.Layout(d); - if (this.Document.currentFrame !== undefined && !this.props.isAnnotationOverlay) { - const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); - CollectionFreeFormDocumentView.setValues(this.Document.currentFrame, d, x + vals.x - dropX, y + vals.y - dropY, vals.opacity); - } else { - d.x = x + NumCast(d.x) - dropX; - d.y = y + NumCast(d.y) - dropY; - } - if (!NumCast(layoutDoc._width)) { - layoutDoc._width = 300; - } - if (!NumCast(layoutDoc._height)) { - const nw = NumCast(layoutDoc._nativeWidth); - const nh = NumCast(layoutDoc._nativeHeight); - layoutDoc._height = nw && nh ? nh / nw * NumCast(layoutDoc._width) : 300; - } - d.isBackground === undefined && (d.zIndex = zsorted.length + 1 + i); // bringToFront - } - }); - - (de.complete.docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(de.complete.docDragData.droppedDocuments); - } - } - else if (de.complete.annoDragData) { - if (de.complete.annoDragData.dropDocument) { - const dragDoc = de.complete.annoDragData.dropDocument; - const x = xp - de.complete.annoDragData.offset[0]; - const y = yp - de.complete.annoDragData.offset[1]; - const dropX = NumCast(dragDoc.x); - const dropY = NumCast(dragDoc.y); - dragDoc.x = x + NumCast(dragDoc.x) - dropX; - dragDoc.y = y + NumCast(dragDoc.y) - dropY; - de.complete.annoDragData.targetContext = this.props.Document; // dropped a PDF annotation, so we need to set the targetContext on the dragData which the PDF view uses at the end of the drop operation - this.bringToFront(dragDoc); - } - } + } else { + UndoManager.Undo(); } return false; } -- cgit v1.2.3-70-g09d2 From e872414f24edddb31a82738bff10e5b9519d92be Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 4 Jun 2020 11:13:39 -0400 Subject: fixed content fitting of freeform views in treeview. --- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 9 ++++----- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a8eef6875..fc5e61026 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -118,10 +118,12 @@ export class CollectionFreeFormView extends CollectionSubView boolean; viewDefDivClick?: ScriptField; children: () => JSX.Element[]; - shifted: boolean; transition?: string; } @@ -1443,7 +1443,6 @@ class CollectionFreeFormViewPannableContents extends React.Component diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index cdfeeaa6b..46804c848 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -607,7 +607,7 @@ export class MarqueeView extends React.Component Date: Fri, 5 Jun 2020 18:30:56 -0400 Subject: changed all scroll behaviors to be _scrollTop to go to a scroll and _scrollY to animate to it. --- src/client/util/DocumentManager.ts | 2 +- src/client/views/animationtimeline/Timeline.tsx | 2 -- src/client/views/animationtimeline/Track.tsx | 5 +++-- src/client/views/collections/CollectionSubView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 14 +++++++------- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 ++-- .../formattedText/FormattedTextBoxComment.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 22 +++++++++------------- src/fields/documentSchemas.ts | 8 ++++---- 11 files changed, 30 insertions(+), 35 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 67f2f244c..78c05f572 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -168,7 +168,7 @@ export class DocumentManager { highlight(); } else { // otherwise try to get a view of the context of the target const targetDocContextView = getFirstDocView(targetDocContext); - targetDocContext.scrollY = 0; // this will force PDFs to activate and load their annotations / allow scrolling + targetDocContext._scrollY = 0; // this will force PDFs to activate and load their annotations / allow scrolling if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. targetDocContext.panTransformType = "Ease"; targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom); diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index 017623120..43f15a33f 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -11,8 +11,6 @@ import { KeyframeFunc } from "./Keyframe"; import "./Timeline.scss"; import { TimelineOverview } from "./TimelineOverview"; import { Track } from "./Track"; -import { utils } from "mocha"; -import { Util } from "../../../../deploy/assets/pdf.worker"; import clamp from "../../util/clamp"; /** diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index fc96c320a..4987006e7 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -31,13 +31,14 @@ export class Track extends React.Component { @observable private _autoKfReaction: any; @observable private _newKeyframe: boolean = false; private readonly MAX_TITLE_HEIGHT = 75; - private _trackHeight = 0; + @observable private _trackHeight = 0; private primitiveWhitelist = [ "x", "y", "_width", "_height", "opacity", + "_scrollTop" ]; private objectWhitelist = [ "data" @@ -51,7 +52,7 @@ export class Track extends React.Component { if (!regions) this.props.node.regions = new List(); //if there is no region, then create new doc to store stuff //these two lines are exactly same from timeline.tsx const relativeHeight = window.innerHeight / 20; - this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness + runInAction(() => this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT); //for responsiveness this._timelineVisibleReaction = this.timelineVisibleReaction(); this._currentBarXReaction = this.currentBarXReaction(); if (DocListCast(this.props.node.regions).length === 0) this.createRegion(this.time); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 423eb1d90..56c6ce457 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -343,7 +343,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: if (focusNode) { const rect = "getBoundingClientRect" in focusNode ? focusNode.getBoundingClientRect() : focusNode?.parentElement.getBoundingClientRect(); const x = (rect?.x || 0); - const y = NumCast(srcWeb.scrollTop) + (rect?.y || 0); + const y = NumCast(srcWeb._scrollTop) + (rect?.y || 0); const anchor = Docs.Create.FreeformDocument([], { _LODdisable: true, _backgroundColor: "transparent", _width: 25, _height: 25, x, y, annotationOn: srcWeb }); anchor.context = srcWeb; const key = Doc.LayoutFieldKey(srcWeb); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index fc5e61026..80ee2a65d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -886,7 +886,7 @@ export class CollectionFreeFormView extends CollectionSubView ({ y: this.layoutDoc.scrollY, x: this.layoutDoc.scrollX }), + this._reactionDisposer = reaction(() => ({ y: this.layoutDoc._scrollY, x: this.layoutDoc._scrollX }), ({ x, y }) => { if (y !== undefined) { this._outerRef.current!.scrollTop = y; - this.layoutDoc.scrollY = undefined; + this.layoutDoc._scrollY = undefined; } if (x !== undefined) { this._outerRef.current!.scrollLeft = x; @@ -83,8 +83,8 @@ export class WebBox extends ViewBoxAnnotatableComponent { const scrollTop = e.target?.children?.[0].scrollTop; const scrollLeft = e.target?.children?.[0].scrollLeft; - this.layoutDoc.scrollTop = this._outerRef.current!.scrollTop = scrollTop; - this.layoutDoc.scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft; + this.layoutDoc._scrollTop = this._outerRef.current!.scrollTop = scrollTop; + this.layoutDoc._scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft; } async componentDidMount() { const urlField = Cast(this.dataDoc[this.props.fieldKey], WebField); @@ -440,7 +440,7 @@ export class WebBox extends ViewBoxAnnotatableComponent); } - scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc.scrollLeft), NumCast(this.layoutDoc.scrollTop)); + scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop)); render() { return (
NumCast(this.layoutDoc.scrollPos), + this._disposers.scroll = reaction(() => NumCast(this.layoutDoc._scrollTop), pos => this._scrollRef.current && this._scrollRef.current.scrollTo({ top: pos }), { fireImmediately: true } ); @@ -1174,7 +1174,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } onscrolled = (ev: React.UIEvent) => { - this.layoutDoc.scrollPos = this._scrollRef.current!.scrollTop; + this.layoutDoc._scrollTop = this._scrollRef.current!.scrollTop; } @action tryUpdateHeight(limitHeight?: number) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index d47ae63af..59a6045ab 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -183,7 +183,7 @@ export class FormattedTextBoxComment { const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.dataDoc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc); const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor; if (anchor !== target && anchor && target) { - target.scrollY = NumCast(anchor?.y); + target._scrollY = NumCast(anchor?.y); } if (target) { ReactDOM.render( this._showWaiting = this._showCover = true); this.props.startupLive && this.setupPdfJsViewer(); + this._mainCont.current!.scrollTop = this.layoutDoc._scrollTop || 0; this._searchReactionDisposer = reaction(() => this.Document.searchMatch, search => { if (search) { this.search(Doc.SearchQuery(), true); @@ -158,14 +155,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent (SelectionManager.SelectedDocuments().length === 1) && this.setupPdfJsViewer(), { fireImmediately: true }); this._reactionDisposer = reaction( - () => this.Document.scrollY, + () => this.Document._scrollY, (scrollY) => { if (scrollY !== undefined) { - if (this._showCover || this._showWaiting) { - this.setupPdfJsViewer(); - } - this._mainCont.current && smoothScroll(1000, this._mainCont.current, (this.Document.scrollY || 0)); - this.Document.scrollY = undefined; + (this._showCover || this._showWaiting) && this.setupPdfJsViewer(); + this._mainCont.current && smoothScroll(1000, this._mainCont.current, (this.Document._scrollY || 0)); + setTimeout(() => this.Document._scrollY = undefined, 1000); } }, { fireImmediately: true } @@ -220,7 +215,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent Cast(this.layoutDoc._scrollTop, "number", null), - (stop) => (stop !== undefined) && this._mainCont.current && smoothScroll(500, this._mainCont.current, stop), { fireImmediately: true }); + (stop) => (stop !== undefined && this.layoutDoc._scrollY === undefined) && (this._mainCont.current!.scrollTop = stop), { fireImmediately: true }); + this._annotationReactionDisposer = reaction( () => DocListCast(this.dataDoc[this.props.fieldKey + "-annotations"]), annotations => annotations?.length && (this._annotations = annotations), @@ -352,7 +348,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent) => { - this._scrollTop = this._mainCont.current!.scrollTop; + this.Document._scrollY === undefined && (this.layoutDoc._scrollTop = this._mainCont.current!.scrollTop); this._pdfViewer && (this.Document.curPage = this._pdfViewer.currentPageNumber); } @@ -604,7 +600,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { - return this._mainCont.current ? this.props.ScreenToLocalTransform().translate(0, this._scrollTop) : this.props.ScreenToLocalTransform(); + return this._mainCont.current ? this.props.ScreenToLocalTransform().translate(0, this.layoutDoc._scrollTop || 0) : this.props.ScreenToLocalTransform(); } onClick = (e: React.MouseEvent) => { this._setPreviewCursor && diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index e7031cc39..e0a02d93c 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -22,10 +22,10 @@ export const documentSchema = createSchema({ y: "number", // y coordinate when in a freeform view z: "number", // z "coordinate" - non-zero specifies the overlay layer of a freeformview zIndex: "number", // zIndex of a document in a freeform view - scrollY: "number", // "command" to scroll a document to a position on load (the value will be reset to 0 after that ) - scrollX: "number", // "command" to scroll a document to a position on load (the value will be reset to 0 after that ) - scrollTop: "number", // scroll position of a scrollable document (pdf, text, web) - scrollLeft: "number", // scroll position of a scrollable document (pdf, text, web) + _scrollY: "number", // "command" to scroll a document to a position on load (the value will be reset to 0 after that ) + _scrollX: "number", // "command" to scroll a document to a position on load (the value will be reset to 0 after that ) + _scrollTop: "number", // scroll position of a scrollable document (pdf, text, web) + _scrollLeft: "number", // scroll position of a scrollable document (pdf, text, web) // appearance properties on the layout _autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents -- cgit v1.2.3-70-g09d2