From 9419693f37ad53fcc0763a118d2cb865659a2ff4 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 6 Aug 2019 14:08:59 -0400
Subject: multiple changes to PDF related code -- mostly clean up

---
 src/client/views/nodes/PDFBox.tsx | 241 ++++++++++++++++----------------------
 1 file changed, 100 insertions(+), 141 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index a49709e83..56e720bf7 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,31 +1,24 @@
-import { action, IReactionDisposer, observable, reaction, trace, untracked, computed } from 'mobx';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from "mobx-react";
+import * as Pdfjs from "pdfjs-dist";
+import "pdfjs-dist/web/pdf_viewer.css";
 import 'react-image-lightbox/style.css';
-import { WidthSym, Doc } from "../../../new_fields/Doc";
+import { Doc, WidthSym, Opt } from "../../../new_fields/Doc";
 import { makeInterface } from "../../../new_fields/Schema";
-import { Cast, NumCast, BoolCast } from "../../../new_fields/Types";
+import { ScriptField } from '../../../new_fields/ScriptField';
+import { BoolCast, Cast, NumCast } from "../../../new_fields/Types";
 import { PdfField } from "../../../new_fields/URLField";
-//@ts-ignore
-// import { Document, Page } from "react-pdf";
-// import 'react-pdf/dist/Page/AnnotationLayer.css';
-import { RouteStore } from "../../../server/RouteStore";
+import { KeyCodes } from '../../northstar/utils/KeyCodes';
+import { CompileScript } from '../../util/Scripting';
 import { DocComponent } from "../DocComponent";
 import { InkingControl } from "../InkingControl";
-import { FilterBox } from "../search/FilterBox";
-import { Annotation } from './Annotation';
 import { PDFViewer } from "../pdf/PDFViewer";
 import { positionSchema } from "./DocumentView";
 import { FieldView, FieldViewProps } from './FieldView';
 import { pageSchema } from "./ImageBox";
 import "./PDFBox.scss";
 import React = require("react");
-import { CompileScript } from '../../util/Scripting';
-import { Flyout, anchorPoints } from '../DocumentDecorations';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { ScriptField } from '../../../new_fields/ScriptField';
-import { KeyCodes } from '../../northstar/utils/KeyCodes';
-import { Utils } from '../../../Utils';
-import { Id } from '../../../new_fields/FieldSymbols';
 
 type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
 const PdfDocument = makeInterface(positionSchema, pageSchema);
@@ -35,40 +28,33 @@ export const handleBackspace = (e: React.KeyboardEvent) => { if (e.keyCode === K
 export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) {
     public static LayoutString() { return FieldView.LayoutString(PDFBox); }
 
+    @observable private _flyout: boolean = false;
     @observable private _alt = false;
     @observable private _scrollY: number = 0;
+    @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>;
+    @computed get containingCollectionDocument() { return this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; }
     @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
 
-    @observable private _flyout: boolean = false;
-    private _mainCont: React.RefObject<HTMLDivElement>;
+    private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
     private _reactionDisposer?: IReactionDisposer;
     private _keyValue: string = "";
     private _valueValue: string = "";
     private _scriptValue: string = "";
-    private _keyRef: React.RefObject<HTMLInputElement>;
-    private _valueRef: React.RefObject<HTMLInputElement>;
-    private _scriptRef: React.RefObject<HTMLInputElement>;
+    private _keyRef: React.RefObject<HTMLInputElement> = React.createRef();
+    private _valueRef: React.RefObject<HTMLInputElement> = React.createRef();
+    private _scriptRef: React.RefObject<HTMLInputElement> = React.createRef();
 
-    constructor(props: FieldViewProps) {
-        super(props);
+    componentDidMount() {
+        this.props.setPdfBox && this.props.setPdfBox(this);
 
-        this._mainCont = React.createRef();
+        const pdfUrl = Cast(this.props.Document.data, PdfField);
+        if (pdfUrl instanceof PdfField) {
+            Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf));
+        }
         this._reactionDisposer = reaction(
             () => this.props.Document.scrollY,
-            () => {
-                if (this._mainCont.current) {
-                    this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.scrollY), behavior: "auto" });
-                }
-            }
+            () => this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.scrollY), behavior: "auto" })
         );
-
-        this._keyRef = React.createRef();
-        this._valueRef = React.createRef();
-        this._scriptRef = React.createRef();
-    }
-
-    componentDidMount() {
-        if (this.props.setPdfBox) this.props.setPdfBox(this);
     }
 
     componentWillUnmount() {
@@ -78,6 +64,8 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     public GetPage() {
         return Math.floor(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.pdfHeight)) + 1;
     }
+
+    @action
     public BackPage() {
         let cp = Math.ceil(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.pdfHeight)) + 1;
         cp = cp - 1;
@@ -86,6 +74,8 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
             this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.pdfHeight);
         }
     }
+
+    @action
     public GotoPage(p: number) {
         if (p > 0 && p <= NumCast(this.props.Document.numPages)) {
             this.props.Document.curPage = p;
@@ -93,6 +83,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         }
     }
 
+    @action
     public ForwardPage() {
         let cp = this.GetPage() + 1;
         if (cp <= NumCast(this.props.Document.numPages)) {
@@ -101,6 +92,15 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         }
     }
 
+    scrollTo = (y: number) => {
+        this._mainCont.current && this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current.offsetHeight / 2), 0), behavior: "auto" });
+    }
+
+    @action
+    setPanY = (y: number) => {
+        this.containingCollectionDocument && (this.containingCollectionDocument.panY = y);
+    }
+
     private newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this._keyValue = e.currentTarget.value;
     }
@@ -109,151 +109,110 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         this._valueValue = e.currentTarget.value;
     }
 
-    @action
     private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this._scriptValue = e.currentTarget.value;
     }
 
     private applyFilter = () => {
-        let scriptText = "";
-        if (this._scriptValue.length > 0) {
-            scriptText = this._scriptValue;
-        } else if (this._keyValue.length > 0 && this._valueValue.length > 0) {
-            scriptText = `return this.${this._keyValue} === ${this._valueValue}`;
-        }
-        else {
-            scriptText = "return true";
-        }
+        let scriptText = this._scriptValue.length > 0 ? this._scriptValue :
+            this._keyValue.length > 0 && this._valueValue.length > 0 ?
+                `return this.${this._keyValue} === ${this._valueValue}` : "return true";
         let script = CompileScript(scriptText, { params: { this: Doc.name } });
-        if (script.compiled) {
-            this.props.Document.filterScript = new ScriptField(script);
-        }
-    }
-
-    @action
-    private toggleFlyout = () => {
-        this._flyout = !this._flyout;
+        script.compiled && (this.props.Document.filterScript = new ScriptField(script));
     }
 
     @action
     private resetFilters = () => {
         this._keyValue = this._valueValue = "";
         this._scriptValue = "return true";
-        if (this._keyRef.current) {
-            this._keyRef.current.value = "";
-        }
-        if (this._valueRef.current) {
-            this._valueRef.current.value = "";
-        }
-        if (this._scriptRef.current) {
-            this._scriptRef.current.value = "";
-        }
+        this._keyRef.current && (this._keyRef.current.value = "");
+        this._valueRef.current && (this._valueRef.current.value = "");
+        this._scriptRef.current && (this._scriptRef.current.value = "");
         this.applyFilter();
     }
 
-    scrollTo(y: number) {
-        this._mainCont.current && this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current.offsetHeight / 2), 0), behavior: "auto" });
-    }
-
     settingsPanel() {
         return !this.props.active() ? (null) :
-            (
-                <div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}>
-                    <button className="pdfBox-settingsButton" onClick={this.toggleFlyout} title="Open Annotation Settings"
-                        style={{ marginTop: `${NumCast(this.props.ContainingCollectionView!.props.Document.panY)}px` }}>
-                        <div className="pdfBox-settingsButton-arrow"
-                            style={{
-                                borderTop: `25px solid ${this._flyout ? "#121721" : "transparent"}`,
-                                borderBottom: `25px solid ${this._flyout ? "#121721" : "transparent"}`,
-                                borderRight: `25px solid ${this._flyout ? "transparent" : "#121721"}`,
-                                transform: `scaleX(${this._flyout ? -1 : 1})`
-                            }}></div>
-                        <div className="pdfBox-settingsButton-iconCont">
-                            <FontAwesomeIcon style={{ color: "white" }} icon="cog" size="3x" />
-                        </div>
-                    </button>
-                    <div className="pdfBox-settingsFlyout" style={{ left: `${this._flyout ? -600 : 100}px` }} >
-                        <div className="pdfBox-settingsFlyout-title">
-                            Annotation View Settings
-                        </div>
-                        <div className="pdfBox-settingsFlyout-kvpInput">
-                            <input placeholder="Key" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newKeyChange}
-                                style={{ gridColumn: 1 }} ref={this._keyRef} />
-                            <input placeholder="Value" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newValueChange}
-                                style={{ gridColumn: 3 }} ref={this._valueRef} />
-                        </div>
-                        <div className="pdfBox-settingsFlyout-kvpInput">
-                            <input placeholder="Custom Script" onChange={this.newScriptChange} onKeyDown={handleBackspace} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} />
-                        </div>
-                        <div className="pdfBox-settingsFlyout-kvpInput">
-                            <button style={{ gridColumn: 1 }} onClick={this.resetFilters}>
-                                <FontAwesomeIcon style={{ color: "white" }} icon="trash" size="lg" />
-                                &nbsp; Reset Filters
-                            </button>
-                            <button style={{ gridColumn: 3 }} onClick={this.applyFilter}>
-                                <FontAwesomeIcon style={{ color: "white" }} icon="check" size="lg" />
-                                &nbsp; Apply
-                            </button>
-                        </div>
+            (<div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}>
+                <button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings"
+                    style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}>
+                    <div className="pdfBox-settingsButton-arrow"
+                        style={{
+                            borderTop: `25px solid ${this._flyout ? "#121721" : "transparent"}`,
+                            borderBottom: `25px solid ${this._flyout ? "#121721" : "transparent"}`,
+                            borderRight: `25px solid ${this._flyout ? "transparent" : "#121721"}`,
+                            transform: `scaleX(${this._flyout ? -1 : 1})`
+                        }} />
+                    <div className="pdfBox-settingsButton-iconCont">
+                        <FontAwesomeIcon style={{ color: "white" }} icon="cog" size="3x" />
+                    </div>
+                </button>
+                <div className="pdfBox-settingsFlyout" style={{ left: `${this._flyout ? -600 : 100}px` }} >
+                    <div className="pdfBox-settingsFlyout-title">
+                        Annotation View Settings
+                    </div>
+                    <div className="pdfBox-settingsFlyout-kvpInput">
+                        <input placeholder="Key" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newKeyChange}
+                            style={{ gridColumn: 1 }} ref={this._keyRef} />
+                        <input placeholder="Value" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newValueChange}
+                            style={{ gridColumn: 3 }} ref={this._valueRef} />
+                    </div>
+                    <div className="pdfBox-settingsFlyout-kvpInput">
+                        <input placeholder="Custom Script" onChange={this.newScriptChange} onKeyDown={handleBackspace} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} />
+                    </div>
+                    <div className="pdfBox-settingsFlyout-kvpInput">
+                        <button style={{ gridColumn: 1 }} onClick={this.resetFilters}>
+                            <FontAwesomeIcon style={{ color: "white" }} icon="trash" size="lg" />
+                            &nbsp; Reset Filters
+                        </button>
+                        <button style={{ gridColumn: 3 }} onClick={this.applyFilter}>
+                            <FontAwesomeIcon style={{ color: "white" }} icon="check" size="lg" />
+                            &nbsp; Apply
+                        </button>
                     </div>
                 </div>
-            );
+            </div>);
     }
 
     loaded = (nw: number, nh: number, np: number) => {
-        if (this.props.Document) {
-            let doc = this.dataDoc;
-            doc.numPages = np;
-            if (doc.nativeWidth && doc.nativeHeight) return;
-            let oldaspect = NumCast(doc.nativeHeight) / NumCast(doc.nativeWidth, 1);
-            doc.nativeWidth = nw;
-            if (doc.nativeHeight) doc.nativeHeight = nw * oldaspect;
-            else doc.nativeHeight = nh;
-            let ccv = this.props.ContainingCollectionView;
-            if (ccv) {
-                ccv.props.Document.pdfHeight = nh;
-            }
-            doc.height = nh * (doc[WidthSym]() / nw);
+        this.dataDoc.numPages = np;
+        if (!this.dataDoc.nativeWidth || !this.dataDoc.nativeHeight) {
+            let oldaspect = NumCast(this.dataDoc.nativeHeight) / NumCast(this.dataDoc.nativeWidth, 1);
+            this.dataDoc.nativeWidth = nw;
+            this.dataDoc.nativeHeight = this.dataDoc.nativeHeight ? nw * oldaspect : nh;
+            this.containingCollectionDocument && (this.containingCollectionDocument.pdfHeight = nh);
+            this.dataDoc.height = nh * (this.dataDoc[WidthSym]() / nw);
         }
     }
 
     @action
     onScroll = (e: React.UIEvent<HTMLDivElement>) => {
-
-        if (e.currentTarget) {
-            this._scrollY = e.currentTarget.scrollTop;
-            let ccv = this.props.ContainingCollectionView;
-            if (ccv) {
-                ccv.props.Document.panTransformType = "None";
-                ccv.props.Document.scrollY = this._scrollY;
-            }
+        if (e.currentTarget && this.containingCollectionDocument) {
+            this.containingCollectionDocument.panTransformType = "None";
+            this.containingCollectionDocument.scrollY = this._scrollY = e.currentTarget.scrollTop;
         }
     }
 
-
     @computed get fieldExtensionDoc() {
         return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true");
     }
+
     render() {
-        // uses mozilla pdf as default
         const pdfUrl = Cast(this.props.Document.data, PdfField);
-        if (!(pdfUrl instanceof PdfField)) return <div>{`pdf, ${this.props.Document.data}, not found`}</div>;
         let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : "");
-        return (
+        return (!(pdfUrl instanceof PdfField) || !this._pdf ?
+            <div>{`pdf, ${this.props.Document.data}, not found`}</div> :
             <div className={classname}
                 onScroll={this.onScroll}
-                style={{
-                    marginTop: `${NumCast(this.props.ContainingCollectionView!.props.Document.panY)}px`
-                }}
+                style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}
                 ref={this._mainCont}
-                onWheel={(e: React.WheelEvent) => {
-                    e.stopPropagation();
-                }}>
-                <PDFViewer url={pdfUrl.url.pathname} loaded={this.loaded} scrollY={this._scrollY} parent={this} />
-                {/* <div style={{ width: "100px", height: "300px" }}></div> */}
+                onWheel={(e: React.WheelEvent) => { e.stopPropagation(); }}>
+                <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} scrollY={this._scrollY}
+                    Document={this.props.Document} DataDoc={this.props.DataDoc}
+                    addDocTab={this.props.addDocTab} setPanY={this.setPanY}
+                    fieldKey={this.props.fieldKey} fieldExtensionDoc={this.fieldExtensionDoc} />
                 {this.settingsPanel()}
             </div>
         );
     }
-
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From adb91b035bd18ff407ce0b2decc07c779282c008 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 7 Aug 2019 12:40:45 -0400
Subject: added zooming to pdfs

---
 src/client/views/Main.tsx                          |  5 ++
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 63 ++++++++++------------
 src/client/views/nodes/PDFBox.scss                 |  3 ++
 src/client/views/nodes/PDFBox.tsx                  | 59 ++++++++------------
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 src/client/views/pdf/Page.tsx                      | 29 +++++-----
 6 files changed, 75 insertions(+), 86 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 1cf13aa74..5fd42c0df 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -39,5 +39,10 @@ let swapDocs = async () => {
     (await Cast(CurrentUserUtils.UserDocument.sidebar, Doc))!.chromeStatus = "disabled";
     CurrentUserUtils.UserDocument.chromeStatus = "disabled";
     await swapDocs();
+    document.getElementById('root')!.addEventListener('wheel', event => {
+        if (event.ctrlKey) {
+            event.preventDefault()
+        }
+    }, true);
     ReactDOM.render(<MainView />, document.getElementById('root'));
 })();
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a08a12426..d347e02b6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -352,12 +352,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
         if (BoolCast(this.props.Document.lockedPosition)) return;
-        // if (!this.props.active()) {
-        //     return;
-        // }
-        if (this.props.Document.type === "pdf") {
+        if (!e.ctrlKey && this.props.Document.scrollY !== undefined) {
+            e.stopPropagation();
             return;
         }
+
         let childSelected = this.childDocs.some(doc => {
             var dv = DocumentManager.Instance.getDocumentView(doc);
             return dv && SelectionManager.IsSelected(dv) ? true : false;
@@ -366,21 +365,20 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             return;
         }
         e.stopPropagation();
-        const coefficient = 1000;
-
-        if (e.ctrlKey) {
-            let deltaScale = (1 - (e.deltaY / coefficient));
-            let nw = this.nativeWidth * deltaScale;
-            let nh = this.nativeHeight * deltaScale;
-            if (nw && nh) {
-                this.props.Document.nativeWidth = nw;
-                this.props.Document.nativeHeight = nh;
-            }
-            e.stopPropagation();
-            e.preventDefault();
-        } else {
-            // if (modes[e.deltaMode] === 'pixels') coefficient = 50;
-            // else if (modes[e.deltaMode] === 'lines') coefficient = 1000; // This should correspond to line-height??
+
+        // bcz: this changes the nativewidth/height, but ImageBox will just revert it back to its defaults.  need more logic to fix.
+        // if (e.ctrlKey && this.props.Document.scrollY === undefined) {
+        //     let deltaScale = (1 - (e.deltaY / coefficient));
+        //     let nw = this.nativeWidth * deltaScale;
+        //     let nh = this.nativeHeight * deltaScale;
+        //     if (nw && nh) {
+        //         this.props.Document.nativeWidth = nw;
+        //         this.props.Document.nativeHeight = nh;
+        //     }
+        //     e.preventDefault();
+        // } 
+        // else 
+        {
             let deltaScale = e.deltaY > 0 ? (1 / 1.1) : 1.1;
             if (deltaScale * this.zoomScaling() < 1 && this.isAnnotationOverlay) {
                 deltaScale = 1 / this.zoomScaling();
@@ -392,21 +390,21 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             let safeScale = Math.min(Math.max(0.15, localTransform.Scale), 40);
             this.props.Document.scale = Math.abs(safeScale);
             this.setPan(-localTransform.TranslateX / safeScale, -localTransform.TranslateY / safeScale);
-            e.stopPropagation();
+            e.preventDefault();
         }
     }
 
     @action
     setPan(panX: number, panY: number) {
-        if (BoolCast(this.props.Document.lockedPosition)) return;
-        this.props.Document.panTransformType = "None";
-        var scale = this.getLocalTransform().inverse().Scale;
-        const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
-        const newPanY = Math.min((1 - 1 / scale) * this.nativeHeight, Math.max(0, panY));
-        this.props.Document.panX = this.isAnnotationOverlay ? newPanX : panX;
-        this.props.Document.panY = this.isAnnotationOverlay && StrCast(this.props.Document.backgroundLayout).indexOf("PDFBox") === -1 ? newPanY : panY;
-        if (this.props.Document.scrollY) {
-            this.props.Document.scrollY = panY - scale * this.props.Document[HeightSym]();
+        if (!BoolCast(this.props.Document.lockedPosition)) {
+            this.props.Document.panTransformType = "None";
+            var scale = this.getLocalTransform().inverse().Scale;
+            const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
+            const newPanY = Math.min((this.props.Document.scrollHeight !== undefined ? NumCast(this.props.Document.scrollHeight) : (1 - 1 / scale) * this.nativeHeight), Math.max(0, panY));
+            this.props.Document.panX = this.isAnnotationOverlay ? newPanX : panX;
+            this.props.Document.panY = this.isAnnotationOverlay ? newPanY : panY;
+            if (this.props.Document.scrollHeight !== undefined) this.props.Document.scrollY = this.isAnnotationOverlay ? newPanY : panY;
+            else this.props.Document.panY = this.isAnnotationOverlay ? newPanY : panY;
         }
     }
 
@@ -490,12 +488,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         this.Document.scale = scale;
     }
 
-    getScale = () => {
-        if (this.Document.scale) {
-            return this.Document.scale;
-        }
-        return 1;
-    }
+    getScale = () => this.Document.scale ? this.Document.scale : 1;
 
 
     getChildDocumentViewProps(childDocLayout: Doc): DocumentViewProps {
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index a1bab0409..c88a94c28 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -5,6 +5,9 @@
     height: 100%;
     overflow-y: scroll;
     overflow-x: hidden;
+    .pdfBox-scrollHack {
+        pointer-events: none;
+    }
 }
 
 .pdfBox-cont {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 56e720bf7..2759b46d4 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -30,10 +30,11 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
 
     @observable private _flyout: boolean = false;
     @observable private _alt = false;
-    @observable private _scrollY: number = 0;
     @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>;
+
     @computed get containingCollectionDocument() { return this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; }
     @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
+    @computed get fieldExtensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); }
 
     private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
     private _reactionDisposer?: IReactionDisposer;
@@ -62,16 +63,16 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     }
 
     public GetPage() {
-        return Math.floor(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.pdfHeight)) + 1;
+        return Math.floor(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.nativeHeight)) + 1;
     }
 
     @action
     public BackPage() {
-        let cp = Math.ceil(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.pdfHeight)) + 1;
+        let cp = Math.ceil(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.nativeHeight)) + 1;
         cp = cp - 1;
         if (cp > 0) {
             this.props.Document.curPage = cp;
-            this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.pdfHeight);
+            this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
         }
     }
 
@@ -79,7 +80,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     public GotoPage(p: number) {
         if (p > 0 && p <= NumCast(this.props.Document.numPages)) {
             this.props.Document.curPage = p;
-            this.props.Document.scrollY = (p - 1) * NumCast(this.dataDoc.pdfHeight);
+            this.props.Document.scrollY = (p - 1) * NumCast(this.dataDoc.nativeHeight);
         }
     }
 
@@ -88,31 +89,16 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         let cp = this.GetPage() + 1;
         if (cp <= NumCast(this.props.Document.numPages)) {
             this.props.Document.curPage = cp;
-            this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.pdfHeight);
+            this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
         }
     }
 
-    scrollTo = (y: number) => {
-        this._mainCont.current && this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current.offsetHeight / 2), 0), behavior: "auto" });
-    }
-
     @action
     setPanY = (y: number) => {
         this.containingCollectionDocument && (this.containingCollectionDocument.panY = y);
     }
 
-    private newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        this._keyValue = e.currentTarget.value;
-    }
-
-    private newValueChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        this._valueValue = e.currentTarget.value;
-    }
-
-    private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        this._scriptValue = e.currentTarget.value;
-    }
-
+    @action
     private applyFilter = () => {
         let scriptText = this._scriptValue.length > 0 ? this._scriptValue :
             this._keyValue.length > 0 && this._valueValue.length > 0 ?
@@ -121,7 +107,10 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         script.compiled && (this.props.Document.filterScript = new ScriptField(script));
     }
 
-    @action
+    scrollTo = (y: number) => {
+        this._mainCont.current && this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current.offsetHeight / 2), 0), behavior: "auto" });
+    }
+
     private resetFilters = () => {
         this._keyValue = this._valueValue = "";
         this._scriptValue = "return true";
@@ -130,6 +119,9 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         this._scriptRef.current && (this._scriptRef.current.value = "");
         this.applyFilter();
     }
+    private newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => this._keyValue = e.currentTarget.value;
+    private newValueChange = (e: React.ChangeEvent<HTMLInputElement>) => this._valueValue = e.currentTarget.value;
+    private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => this._scriptValue = e.currentTarget.value;
 
     settingsPanel() {
         return !this.props.active() ? (null) :
@@ -176,12 +168,12 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
 
     loaded = (nw: number, nh: number, np: number) => {
         this.dataDoc.numPages = np;
-        if (!this.dataDoc.nativeWidth || !this.dataDoc.nativeHeight) {
+        if (!this.dataDoc.nativeWidth || !this.dataDoc.nativeHeight || !this.dataDoc.scrollHeight) {
             let oldaspect = NumCast(this.dataDoc.nativeHeight) / NumCast(this.dataDoc.nativeWidth, 1);
             this.dataDoc.nativeWidth = nw;
             this.dataDoc.nativeHeight = this.dataDoc.nativeHeight ? nw * oldaspect : nh;
-            this.containingCollectionDocument && (this.containingCollectionDocument.pdfHeight = nh);
-            this.dataDoc.height = nh * (this.dataDoc[WidthSym]() / nw);
+            this.dataDoc.height = this.dataDoc[WidthSym]() * (nh / nw);
+            this.dataDoc.scrollHeight = np * this.dataDoc.nativeHeight;
         }
     }
 
@@ -189,14 +181,10 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     onScroll = (e: React.UIEvent<HTMLDivElement>) => {
         if (e.currentTarget && this.containingCollectionDocument) {
             this.containingCollectionDocument.panTransformType = "None";
-            this.containingCollectionDocument.scrollY = this._scrollY = e.currentTarget.scrollTop;
+            this.containingCollectionDocument.scrollY = e.currentTarget.scrollTop;
         }
     }
 
-    @computed get fieldExtensionDoc() {
-        return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true");
-    }
-
     render() {
         const pdfUrl = Cast(this.props.Document.data, PdfField);
         let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : "");
@@ -205,14 +193,13 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
             <div className={classname}
                 onScroll={this.onScroll}
                 style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}
-                ref={this._mainCont}
-                onWheel={(e: React.WheelEvent) => { e.stopPropagation(); }}>
-                <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} scrollY={this._scrollY}
+                ref={this._mainCont}>
+                <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + (NumCast(this.props.Document.nativeHeight) - NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.scale)), width: "100%" }} />
+                <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} scrollY={NumCast(this.props.Document.scrollY)}
                     Document={this.props.Document} DataDoc={this.props.DataDoc}
                     addDocTab={this.props.addDocTab} setPanY={this.setPanY}
                     fieldKey={this.props.fieldKey} fieldExtensionDoc={this.fieldExtensionDoc} />
                 {this.settingsPanel()}
-            </div>
-        );
+            </div>);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 7c445c373..021c04723 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -160,7 +160,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
                 }))));
             this.props.loaded(Math.max(...this._pageSizes.map(i => i.width)), this._pageSizes[0].height, this.props.pdf.numPages);
 
-            let startY = NumCast(this.props.Document.startY);
+            let startY = NumCast(this.props.Document.startY, NumCast(this.props.Document.scrollY));
             this.props.setPanY && this.props.setPanY(startY);
             this.props.Document.scrollY = startY + 1;
         }
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index a15bed255..6de2db427 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -143,6 +143,7 @@ export default class Page extends React.Component<IPageProps> {
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         // if alt+left click, drag and annotate
+        if (this.props.Document.scale !== 1) return;
         if (e.altKey && e.button === 0) {
             e.stopPropagation();
         }
@@ -197,21 +198,21 @@ export default class Page extends React.Component<IPageProps> {
     onSelectEnd = (e: PointerEvent): void => {
         if (this._marqueeing) {
             this._marqueeing = false;
-            if (this._marquee.current) { // make a copy of the marquee
-                let copy = document.createElement("div");
-                let style = this._marquee.current.style;
-                copy.style.left = style.left;
-                copy.style.top = style.top;
-                copy.style.width = style.width;
-                copy.style.height = style.height;
-                copy.style.border = style.border;
-                copy.style.opacity = style.opacity;
-                copy.className = "pdfPage-annotationBox";
-                this.props.createAnnotation(copy, this.props.page);
-                this._marquee.current.style.opacity = "0";
-            }
-
             if (this._marqueeWidth > 10 || this._marqueeHeight > 10) {
+                if (this._marquee.current) { // make a copy of the marquee
+                    let copy = document.createElement("div");
+                    let style = this._marquee.current.style;
+                    copy.style.left = style.left;
+                    copy.style.top = style.top;
+                    copy.style.width = style.width;
+                    copy.style.height = style.height;
+                    copy.style.border = style.border;
+                    copy.style.opacity = style.opacity;
+                    copy.className = "pdfPage-annotationBox";
+                    this.props.createAnnotation(copy, this.props.page);
+                    this._marquee.current.style.opacity = "0";
+                }
+
                 if (!e.ctrlKey) {
                     PDFMenu.Instance.Status = "snippet";
                     PDFMenu.Instance.Marquee = { left: this._marqueeX, top: this._marqueeY, width: this._marqueeWidth, height: this._marqueeHeight };
-- 
cgit v1.2.3-70-g09d2


From 221acd0cfb4831435d1d1b61b86c2cc5e3d3b413 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 7 Aug 2019 12:50:58 -0400
Subject: got rid of scrollY from pdfs!

---
 src/client/views/collections/CollectionPDFView.tsx  | 16 +---------------
 .../collectionFreeForm/CollectionFreeFormView.tsx   |  6 ++----
 src/client/views/nodes/PDFBox.tsx                   | 18 +++++++++---------
 src/client/views/pdf/PDFViewer.tsx                  | 21 ++++++++++-----------
 4 files changed, 22 insertions(+), 39 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 3736ebada..8eda4d9ee 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -1,7 +1,6 @@
-import { action, IReactionDisposer, observable, reaction, computed } from "mobx";
+import { computed } from "mobx";
 import { observer } from "mobx-react";
 import { Id } from "../../../new_fields/FieldSymbols";
-import { NumCast } from "../../../new_fields/Types";
 import { emptyFunction } from "../../../Utils";
 import { ContextMenu } from "../ContextMenu";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
@@ -19,21 +18,8 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
     }
 
     private _pdfBox?: PDFBox;
-    private _reactionDisposer?: IReactionDisposer;
     private _buttonTray: React.RefObject<HTMLDivElement> = React.createRef();
 
-    componentDidMount() {
-        this._reactionDisposer = reaction(
-            () => NumCast(this.props.Document.scrollY),
-            () => this.props.Document.panY = NumCast(this.props.Document.scrollY),
-            { fireImmediately: true }
-        );
-    }
-
-    componentWillUnmount() {
-        this._reactionDisposer && this._reactionDisposer();
-    }
-
     @computed
     get uIButtons() {
         return (
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d347e02b6..8322625f1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -352,7 +352,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
         if (BoolCast(this.props.Document.lockedPosition)) return;
-        if (!e.ctrlKey && this.props.Document.scrollY !== undefined) {
+        if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) { // things that can scroll vertically should do that instead of zooming
             e.stopPropagation();
             return;
         }
@@ -367,7 +367,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         e.stopPropagation();
 
         // bcz: this changes the nativewidth/height, but ImageBox will just revert it back to its defaults.  need more logic to fix.
-        // if (e.ctrlKey && this.props.Document.scrollY === undefined) {
+        // if (e.ctrlKey && this.props.Document.scrollHeight === undefined) {
         //     let deltaScale = (1 - (e.deltaY / coefficient));
         //     let nw = this.nativeWidth * deltaScale;
         //     let nh = this.nativeHeight * deltaScale;
@@ -403,8 +403,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             const newPanY = Math.min((this.props.Document.scrollHeight !== undefined ? NumCast(this.props.Document.scrollHeight) : (1 - 1 / scale) * this.nativeHeight), Math.max(0, panY));
             this.props.Document.panX = this.isAnnotationOverlay ? newPanX : panX;
             this.props.Document.panY = this.isAnnotationOverlay ? newPanY : panY;
-            if (this.props.Document.scrollHeight !== undefined) this.props.Document.scrollY = this.isAnnotationOverlay ? newPanY : panY;
-            else this.props.Document.panY = this.isAnnotationOverlay ? newPanY : panY;
         }
     }
 
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 2759b46d4..e9207404e 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -53,8 +53,8 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
             Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf));
         }
         this._reactionDisposer = reaction(
-            () => this.props.Document.scrollY,
-            () => this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.scrollY), behavior: "auto" })
+            () => this.props.Document.panY,
+            () => this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.panY), behavior: "auto" })
         );
     }
 
@@ -63,16 +63,16 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     }
 
     public GetPage() {
-        return Math.floor(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.nativeHeight)) + 1;
+        return Math.floor(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1;
     }
 
     @action
     public BackPage() {
-        let cp = Math.ceil(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.nativeHeight)) + 1;
+        let cp = Math.ceil(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1;
         cp = cp - 1;
         if (cp > 0) {
             this.props.Document.curPage = cp;
-            this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
+            this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
         }
     }
 
@@ -80,7 +80,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     public GotoPage(p: number) {
         if (p > 0 && p <= NumCast(this.props.Document.numPages)) {
             this.props.Document.curPage = p;
-            this.props.Document.scrollY = (p - 1) * NumCast(this.dataDoc.nativeHeight);
+            this.props.Document.panY = (p - 1) * NumCast(this.dataDoc.nativeHeight);
         }
     }
 
@@ -89,7 +89,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         let cp = this.GetPage() + 1;
         if (cp <= NumCast(this.props.Document.numPages)) {
             this.props.Document.curPage = cp;
-            this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
+            this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
         }
     }
 
@@ -181,7 +181,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     onScroll = (e: React.UIEvent<HTMLDivElement>) => {
         if (e.currentTarget && this.containingCollectionDocument) {
             this.containingCollectionDocument.panTransformType = "None";
-            this.containingCollectionDocument.scrollY = e.currentTarget.scrollTop;
+            this.containingCollectionDocument.panY = e.currentTarget.scrollTop;
         }
     }
 
@@ -195,7 +195,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
                 style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}
                 ref={this._mainCont}>
                 <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + (NumCast(this.props.Document.nativeHeight) - NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.scale)), width: "100%" }} />
-                <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} scrollY={NumCast(this.props.Document.scrollY)}
+                <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={NumCast(this.props.Document.panY)}
                     Document={this.props.Document} DataDoc={this.props.DataDoc}
                     addDocTab={this.props.addDocTab} setPanY={this.setPanY}
                     fieldKey={this.props.fieldKey} fieldExtensionDoc={this.fieldExtensionDoc} />
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 021c04723..f3281047a 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -31,7 +31,7 @@ interface IViewerProps {
     fieldExtensionDoc: Doc;
     fieldKey: string;
     loaded: (nw: number, nh: number, np: number) => void;
-    scrollY: number;
+    panY: number;
     scrollTo: (y: number) => void;
     active: () => boolean;
     setPanY?: (n: number) => void;
@@ -64,14 +64,14 @@ export class PDFViewer extends React.Component<IViewerProps> {
     private _searchString: string = "";
     private _selectionText: string = "";
 
-    @computed get scrollY(): number { return this.props.scrollY; }
+    @computed get panY(): number { return this.props.panY; }
 
     // startIndex: where to start rendering pages
-    @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.scrollY) - this._pageBuffer); }
+    @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.panY) - this._pageBuffer); }
 
     // endIndex: where to end rendering pages
     @computed get endIndex(): number {
-        return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY + (this._pageSizes[0] ? this._pageSizes[0].height : 0)) + this._pageBuffer);
+        return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.panY + (this._pageSizes[0] ? this._pageSizes[0].height : 0)) + this._pageBuffer);
     }
 
     @computed get filteredAnnotations() {
@@ -81,7 +81,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         });
     }
 
-    componentDidUpdate = (prevProps: IViewerProps) => this.scrollY !== prevProps.scrollY && this.renderPages();
+    componentDidUpdate = (prevProps: IViewerProps) => this.panY !== prevProps.panY && this.renderPages();
 
     componentDidMount = async () => {
         await this.initialLoad();
@@ -160,9 +160,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
                 }))));
             this.props.loaded(Math.max(...this._pageSizes.map(i => i.width)), this._pageSizes[0].height, this.props.pdf.numPages);
 
-            let startY = NumCast(this.props.Document.startY, NumCast(this.props.Document.scrollY));
+            let startY = NumCast(this.props.Document.startY, NumCast(this.props.Document.panY));
             this.props.setPanY && this.props.setPanY(startY);
-            this.props.Document.scrollY = startY + 1;
         }
     }
 
@@ -435,7 +434,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
                     <Annotation {...this.props} ParentIndex={this.getIndex} anno={anno} index={index} key={`${anno[Id]}-annotation`} />)}
             </div>
             <div className="pdfViewer-overlayCont" onPointerDown={(e) => e.stopPropagation()}
-                style={{ bottom: -this.props.scrollY, left: `${this._searching ? 0 : 100}%` }}>
+                style={{ bottom: -this.props.panY, left: `${this._searching ? 0 : 100}%` }}>
                 <button className="pdfViewer-overlayButton" title="Open Search Bar" />
                 <input className="pdfViewer-overlaySearchBar" placeholder="Search" onChange={this.searchStringChanged}
                     onKeyDown={(e: React.KeyboardEvent) => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} />
@@ -443,17 +442,17 @@ export class PDFViewer extends React.Component<IViewerProps> {
                     <FontAwesomeIcon icon="search" size="3x" color="white" /></button>
             </div>
             <button className="pdfViewer-overlayButton" onClick={this.prevAnnotation} title="Previous Annotation"
-                style={{ bottom: -this.props.scrollY + 280, right: 10, display: this.props.active() ? "flex" : "none" }}>
+                style={{ bottom: -this.props.panY + 280, right: 10, display: this.props.active() ? "flex" : "none" }}>
                 <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
                     <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="3x" /></div>
             </button>
             <button className="pdfViewer-overlayButton" onClick={this.nextAnnotation} title="Next Annotation"
-                style={{ bottom: -this.props.scrollY + 200, right: 10, display: this.props.active() ? "flex" : "none" }}>
+                style={{ bottom: -this.props.panY + 200, right: 10, display: this.props.active() ? "flex" : "none" }}>
                 <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
                     <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="3x" /></div>
             </button>
             <button className="pdfViewer-overlayButton" onClick={this.toggleSearch} title="Open Search Bar"
-                style={{ bottom: -this.props.scrollY + 10, right: 0, display: this.props.active() ? "flex" : "none" }}>
+                style={{ bottom: -this.props.panY + 10, right: 0, display: this.props.active() ? "flex" : "none" }}>
                 <div className="pdfViewer-overlayButton-arrow" onPointerDown={(e) => e.stopPropagation()}></div>
                 <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
                     <FontAwesomeIcon style={{ color: "white" }} icon={this._searching ? "times" : "search"} size="3x" /></div>
-- 
cgit v1.2.3-70-g09d2


From 941c50617a0cbaef054f2be856de013bd69ea81f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 7 Aug 2019 18:15:38 -0400
Subject: pdf annotaitons

---
 src/client/documents/Documents.ts    |  1 +
 src/client/views/nodes/PDFBox.tsx    |  3 +-
 src/client/views/pdf/Annotation.scss |  2 +-
 src/client/views/pdf/Annotation.tsx  |  8 +--
 src/client/views/pdf/PDFViewer.tsx   | 95 ++++++++++++++----------------------
 src/client/views/pdf/Page.tsx        |  6 +--
 6 files changed, 47 insertions(+), 68 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e804d5440..9c1278150 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -84,6 +84,7 @@ export interface DocumentOptions {
     templates?: List<string>;
     viewType?: number;
     backgroundColor?: string;
+    opacity?: number;
     defaultBackgroundColor?: string;
     dropAction?: dropActionType;
     backgroundLayout?: string;
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index e9207404e..6450cb826 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -194,10 +194,11 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
                 onScroll={this.onScroll}
                 style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}
                 ref={this._mainCont}>
-                <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + (NumCast(this.props.Document.nativeHeight) - NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.scale)), width: "100%" }} />
+                <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + (NumCast(this.props.Document.nativeHeight) - NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.scale, 1)), width: "100%" }} />
                 <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={NumCast(this.props.Document.panY)}
                     Document={this.props.Document} DataDoc={this.props.DataDoc}
                     addDocTab={this.props.addDocTab} setPanY={this.setPanY}
+                    addDocument={this.props.addDocument}
                     fieldKey={this.props.fieldKey} fieldExtensionDoc={this.fieldExtensionDoc} />
                 {this.settingsPanel()}
             </div>);
diff --git a/src/client/views/pdf/Annotation.scss b/src/client/views/pdf/Annotation.scss
index 817115690..0c6df74f0 100644
--- a/src/client/views/pdf/Annotation.scss
+++ b/src/client/views/pdf/Annotation.scss
@@ -2,6 +2,6 @@
     pointer-events: all;
     user-select: none;
     position: absolute;
-    background-color: pink;
+    background-color: red;
     opacity: 0.1;
 }
\ No newline at end of file
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 2610f6c6e..7ba7b6d14 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -120,10 +120,10 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
     render() {
         return (<div className="pdfAnnotation" onPointerDown={this.onPointerDown} ref={this._mainCont}
             style={{
-                top: this.props.y * scale,
-                left: this.props.x * scale,
-                width: this.props.width * scale,
-                height: this.props.height * scale,
+                top: this.props.y,
+                left: this.props.x,
+                width: this.props.width,
+                height: this.props.height,
                 backgroundColor: this.props.ParentIndex() === this.props.index ? "green" : StrCast(this.props.document.color)
             }} />);
     }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index f3281047a..95df10c58 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -36,6 +36,7 @@ interface IViewerProps {
     active: () => boolean;
     setPanY?: (n: number) => void;
     addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean;
 }
 
 /**
@@ -124,7 +125,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         if (this.props.active() && e.clipboardData) {
             e.clipboardData.setData("text/plain", this._selectionText);
             e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]);
-            e.clipboardData.setData("dash/pdfRegion", this.makeAnnotationDocument(undefined, 0, "#0390fc")[Id]);
+            e.clipboardData.setData("dash/pdfRegion", this.makeAnnotationDocument(undefined, "#0390fc")[Id]);
             e.preventDefault();
         }
     }
@@ -133,7 +134,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         if (e.clipboardData && e.clipboardData.getData("dash/pdfOrigin") === this.props.Document[Id]) {
             let linkDocId = e.clipboardData.getData("dash/linkDoc");
             linkDocId && DocServer.GetRefField(linkDocId).then(async (link) =>
-                (link instanceof Doc) && (Doc.GetProto(link).anchor2 = this.makeAnnotationDocument(await Cast(Doc.GetProto(link), Doc), 0, "#0390fc", false)));
+                (link instanceof Doc) && (Doc.GetProto(link).anchor2 = this.makeAnnotationDocument(await Cast(Doc.GetProto(link), Doc), "#0390fc", false)));
         }
     }
 
@@ -166,32 +167,50 @@ export class PDFViewer extends React.Component<IViewerProps> {
     }
 
     @action
-    makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string, createLink: boolean = true): Doc => {
+    makeAnnotationDocument = (sourceDoc: Doc | undefined, color: string, createLink: boolean = true): Doc => {
         let mainAnnoDoc = Docs.Create.InstanceFromProto(new Doc(), "", {});
+        let mainAnnoDocProto = Doc.GetProto(mainAnnoDoc);
         let annoDocs: Doc[] = [];
         let minY = Number.MAX_VALUE;
-        this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => value.map(anno => {
-            let annoDoc = new Doc();
-            if (anno.style.left) annoDoc.x = parseInt(anno.style.left) / scale;
-            if (anno.style.top) annoDoc.y = parseInt(anno.style.top) / scale;
-            if (anno.style.height) annoDoc.height = parseInt(anno.style.height) / scale;
-            if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale;
-            annoDoc.page = key;
+        if (this._savedAnnotations.size() === 1 && this._savedAnnotations.values()[0].length === 1 && !createLink) {
+            let anno = this._savedAnnotations.values()[0][0];
+            let annoDoc = Docs.Create.FreeformDocument([], { backgroundColor: "rgba(255, 0, 0, 0.1)", title: "Annotation on " + StrCast(this.props.Document.title) });
+            if (anno.style.left) annoDoc.x = parseInt(anno.style.left);
+            if (anno.style.top) annoDoc.y = parseInt(anno.style.top);
+            if (anno.style.height) annoDoc.height = parseInt(anno.style.height);
+            if (anno.style.width) annoDoc.width = parseInt(anno.style.width);
             annoDoc.target = sourceDoc;
             annoDoc.group = mainAnnoDoc;
             annoDoc.color = color;
             annoDoc.type = AnnotationTypes.Region;
             annoDocs.push(annoDoc);
+            annoDoc.isBackground = true;
             anno.remove();
-            (annoDoc.y !== undefined) && (minY = Math.min(NumCast(annoDoc.y), minY));
-        }));
-
-        let mainAnnoDocProto = Doc.GetProto(mainAnnoDoc);
-        mainAnnoDocProto.title = "Annotation on " + StrCast(this.props.Document.title);
+            this.props.addDocument && this.props.addDocument(annoDoc, false);
+            mainAnnoDoc = annoDoc;
+            mainAnnoDocProto = Doc.GetProto(annoDoc);
+        } else {
+            this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => value.map(anno => {
+                let annoDoc = new Doc();
+                if (anno.style.left) annoDoc.x = parseInt(anno.style.left);
+                if (anno.style.top) annoDoc.y = parseInt(anno.style.top);
+                if (anno.style.height) annoDoc.height = parseInt(anno.style.height);
+                if (anno.style.width) annoDoc.width = parseInt(anno.style.width);
+                annoDoc.target = sourceDoc;
+                annoDoc.group = mainAnnoDoc;
+                annoDoc.color = color;
+                annoDoc.type = AnnotationTypes.Region;
+                annoDocs.push(annoDoc);
+                anno.remove();
+                (annoDoc.y !== undefined) && (minY = Math.min(NumCast(annoDoc.y), minY));
+            }));
+
+            mainAnnoDocProto.y = Math.max(minY, 0);
+            mainAnnoDocProto.annotations = new List<Doc>(annoDocs);
+        }
         mainAnnoDocProto.pdfDoc = this.props.Document;
+        mainAnnoDocProto.title = "Annotation on " + StrCast(this.props.Document.title);
         mainAnnoDocProto.annotationOn = this.props.Document;
-        mainAnnoDocProto.y = Math.max(minY, 0);
-        mainAnnoDocProto.annotations = new List<Doc>(annoDocs);
         if (sourceDoc && createLink) {
             DocUtils.MakeLink(sourceDoc, mainAnnoDocProto, undefined, `Annotation from ${StrCast(this.props.Document.title)}`, "", StrCast(this.props.Document.title));
         }
@@ -346,48 +365,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
             this._mainCont.current.addEventListener("pagesloaded", executeFind);
             this._mainCont.current.addEventListener("pagerendered", executeFind);
         }
-
-        // let viewer = this._viewer.current;
-
-        // if (!this._pdfFindController) {
-        //     if (container && viewer) {
-        //         let simpleLinkService = new SimpleLinkService();
-        //         let pdfViewer = new PDFJSViewer.PDFViewer({
-        //             container: container,
-        //             viewer: viewer,
-        //             linkService: simpleLinkService
-        //         });
-        //         simpleLinkService.setPdf(this.props.pdf);
-        //         container.addEventListener("pagesinit", () => {
-        //             pdfViewer.currentScaleValue = 1;
-        //         });
-        //         container.addEventListener("pagerendered", () => {
-        //             console.log("rendered");
-        //             this._pdfFindController.executeCommand('find',
-        //                 {
-        //                     caseSensitive: false,
-        //                     findPrevious: undefined,
-        //                     highlightAll: true,
-        //                     phraseSearch: true,
-        //                     query: searchString
-        //                 });
-        //         });
-        //         pdfViewer.setDocument(this.props.pdf);
-        //         this._pdfFindController = new PDFJSViewer.PDFFindController(pdfViewer);
-        //         // this._pdfFindController._linkService = pdfLinkService;
-        //         pdfViewer.findController = this._pdfFindController;
-        //     }
-        // }
-        // else {
-        //     this._pdfFindController.executeCommand('find',
-        //         {
-        //             caseSensitive: false,
-        //             findPrevious: undefined,
-        //             highlightAll: true,
-        //             phraseSearch: true,
-        //             query: searchString
-        //         });
-        // }
     }
 
 
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 6de2db427..4986f44d5 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -24,7 +24,7 @@ interface IPageProps {
     renderAnnotations: (annotations: Doc[], removeOld: boolean) => void;
     sendAnnotations: (annotations: HTMLDivElement[], page: number) => void;
     createAnnotation: (div: HTMLDivElement, page: number) => void;
-    makeAnnotationDocuments: (doc: Doc | undefined, scale: number, color: string, linkTo: boolean) => Doc;
+    makeAnnotationDocuments: (doc: Doc | undefined, color: string, linkTo: boolean) => Doc;
     getScrollFromPage: (page: number) => number;
     setSelectionText: (text: string) => void;
 }
@@ -87,7 +87,7 @@ export default class Page extends React.Component<IPageProps> {
     @action
     highlight = (targetDoc: Doc | undefined, color: string) => {
         // creates annotation documents for current highlights
-        let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, scale, color, false);
+        let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, color, false);
         Doc.AddDocToList(this.props.fieldExtensionDoc, "annotations", annotationDoc);
         return annotationDoc;
     }
@@ -143,7 +143,7 @@ export default class Page extends React.Component<IPageProps> {
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         // if alt+left click, drag and annotate
-        if (this.props.Document.scale !== 1) return;
+        if (NumCast(this.props.Document.scale, 1) !== 1) return;
         if (e.altKey && e.button === 0) {
             e.stopPropagation();
         }
-- 
cgit v1.2.3-70-g09d2

