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/pdf/Annotation.tsx | 69 +++++++++++++++----------------------
 1 file changed, 27 insertions(+), 42 deletions(-)

(limited to 'src/client/views/pdf/Annotation.tsx')

diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index a08ff5969..9d68a86b8 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -4,17 +4,20 @@ import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
-import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
+import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { DocumentManager } from "../../util/DocumentManager";
 import { PresentationView } from "../presentationview/PresentationView";
 import PDFMenu from "./PDFMenu";
 import "./Annotation.scss";
-import { AnnotationTypes, scale, Viewer } from "./PDFViewer";
+import { AnnotationTypes, scale } from "./PDFViewer";
 
 interface IAnnotationProps {
     anno: Doc;
     index: number;
-    parent: Viewer;
+    ParentIndex: () => number;
+    fieldExtensionDoc: Doc;
+    scrollTo?: (n: number) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
 }
 
 export default class Annotation extends React.Component<IAnnotationProps> {
@@ -23,10 +26,8 @@ export default class Annotation extends React.Component<IAnnotationProps> {
         let res = annotationDocs.map(a => {
             let type = NumCast(a.type);
             switch (type) {
-                // case AnnotationTypes.Pin:
-                //     return <PinAnnotation parent={this} document={a} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
                 case AnnotationTypes.Region:
-                    return <RegionAnnotation parent={this.props.parent} document={a} index={this.props.index} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
+                    return <RegionAnnotation addDocTab={this.props.addDocTab} document={a} fieldExtensionDoc={this.props.fieldExtensionDoc} scrollTo={this.props.scrollTo} ParentIndex={this.props.ParentIndex} index={this.props.index} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
                 default:
                     return <div></div>;
             }
@@ -41,7 +42,10 @@ interface IRegionAnnotationProps {
     width: number;
     height: number;
     index: number;
-    parent: Viewer;
+    ParentIndex: () => number;
+    fieldExtensionDoc: Doc;
+    scrollTo?: (n: number) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
     document: Doc;
 }
 
@@ -51,34 +55,18 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
 
     private _reactionDisposer?: IReactionDisposer;
     private _scrollDisposer?: IReactionDisposer;
-    private _mainCont: React.RefObject<HTMLDivElement>;
-
-    constructor(props: IRegionAnnotationProps) {
-        super(props);
-
-        this._mainCont = React.createRef();
-    }
+    private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
 
     componentDidMount() {
         this._reactionDisposer = reaction(
-            () => BoolCast(this.props.document.delete),
-            () => {
-                if (BoolCast(this.props.document.delete)) {
-                    if (this._mainCont.current) {
-                        this._mainCont.current.style.display = "none";
-                    }
-                }
-            },
+            () => this.props.document.delete,
+            () => this.props.document.delete && this._mainCont.current && (this._mainCont.current.style.display = "none"),
             { fireImmediately: true }
         );
 
         this._scrollDisposer = reaction(
-            () => this.props.parent.Index,
-            () => {
-                if (this.props.parent.Index === this.props.index) {
-                    this.props.parent.scrollTo(this.props.y * scale);
-                }
-            }
+            () => this.props.ParentIndex(),
+            () => this.props.ParentIndex() === this.props.index && this.props.scrollTo && this.props.scrollTo(this.props.y * scale)
         );
     }
 
@@ -88,16 +76,15 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
     }
 
     deleteAnnotation = () => {
-        let annotation = DocListCast(this.props.parent.props.parent.fieldExtensionDoc.annotations);
+        let annotation = DocListCast(this.props.fieldExtensionDoc.annotations);
         let group = FieldValue(Cast(this.props.document.group, Doc));
-        if (group && annotation.indexOf(group) !== -1) {
-            let newAnnotations = annotation.filter(a => a !== FieldValue(Cast(this.props.document.group, Doc)));
-            this.props.parent.props.parent.fieldExtensionDoc.annotations = new List<Doc>(newAnnotations);
-        }
-
         if (group) {
-            let groupAnnotations = DocListCast(group.annotations);
-            groupAnnotations.forEach(anno => anno.delete = true);
+            if (annotation.indexOf(group) !== -1) {
+                let newAnnotations = annotation.filter(a => a !== FieldValue(Cast(this.props.document.group, Doc)));
+                this.props.fieldExtensionDoc.annotations = new List<Doc>(newAnnotations);
+            }
+
+            DocListCast(group.annotations).forEach(anno => anno.delete = true);
         }
 
         PDFMenu.Instance.fadeOut(true);
@@ -105,9 +92,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
 
     pinToPres = () => {
         let group = FieldValue(Cast(this.props.document.group, Doc));
-        if (group) {
-            PresentationView.Instance.PinDoc(group);
-        }
+        group && PresentationView.Instance.PinDoc(group);
     }
 
     @action
@@ -118,7 +103,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
                 let context = await Cast(targetDoc.targetContext, Doc);
                 if (context) {
                     DocumentManager.Instance.jumpToDocument(targetDoc, false, false,
-                        ((doc) => this.props.parent.props.parent.props.addDocTab(targetDoc!, undefined, e.ctrlKey ? "onRight" : "inTab")),
+                        ((doc) => this.props.addDocTab(targetDoc!, undefined, e.ctrlKey ? "onRight" : "inTab")),
                         undefined, undefined);
                 }
             }
@@ -151,8 +136,8 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
                     left: this.props.x * scale,
                     width: this.props.width * scale,
                     height: this.props.height * scale,
-                    backgroundColor: this.props.parent.Index === this.props.index ? "green" : StrCast(this.props.document.color)
-                }}></div>
+                    backgroundColor: this.props.ParentIndex() === this.props.index ? "green" : StrCast(this.props.document.color)
+                }} />
         );
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From acbe0ced15150d15d81110cd2259b99e942d02e6 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 6 Aug 2019 18:17:48 -0400
Subject: pdf css cleanup

---
 src/client/views/nodes/PDFBox.scss   |  64 +++---------
 src/client/views/pdf/Annotation.scss |   5 +-
 src/client/views/pdf/Annotation.tsx  |   2 +-
 src/client/views/pdf/PDFMenu.tsx     |   2 +-
 src/client/views/pdf/PDFViewer.scss  | 186 ++++++++++++++---------------------
 src/client/views/pdf/PDFViewer.tsx   |  37 +++----
 src/client/views/pdf/Page.scss       |  31 ++++++
 src/client/views/pdf/Page.tsx        |  32 +++---
 8 files changed, 161 insertions(+), 198 deletions(-)
 create mode 100644 src/client/views/pdf/Page.scss

(limited to 'src/client/views/pdf/Annotation.tsx')

diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index e7655d598..a1bab0409 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -1,37 +1,3 @@
-.react-pdf__Page {
-    transform-origin: left top;
-    position: absolute;
-    top: 0;
-    left: 0;
-}
-
-.react-pdf__Page__textContent span {
-    user-select: text;
-}
-
-.react-pdf__Document {
-    position: absolute;
-}
-
-.pdfBox-buttonTray {
-    position: absolute;
-    top: 0;
-    left: 0;
-    z-index: 25;
-    pointer-events: all;
-}
-
-.pdfBox-thumbnail {
-    position: absolute;
-    width: 100%;
-}
-
-.pdfButton {
-    pointer-events: all;
-    width: 100px;
-    height: 100px;
-}
-
 .pdfBox-cont,
 .pdfBox-cont-interactive {
     display: flex;
@@ -43,26 +9,17 @@
 
 .pdfBox-cont {
     pointer-events: none;
-
-    .textlayer {
-        pointer-events: none;
-
+    .pdfPage-textlayer {
         span {
             pointer-events: none !important;
+            user-select: none; 
         }
     }
-
-    .page-cont {
-        pointer-events: none;
-    }
 }
 
 .pdfBox-cont-interactive {
     pointer-events: all;
-    display: flex;
-    flex-direction: row;
-
-    .textlayer {
+    .pdfPage-textlayer {
         span {
             pointer-events: all !important;
             user-select: text;
@@ -70,11 +27,22 @@
     }
 }
 
-.pdfBox-contentContainer {
-    position: absolute;
+.react-pdf__Page {
     transform-origin: left top;
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+
+.react-pdf__Page__textContent span {
+    user-select: text;
+}
+
+.react-pdf__Document {
+    position: absolute;
 }
 
+
 .pdfBox-settingsCont {
     position: absolute;
     right: 0;
diff --git a/src/client/views/pdf/Annotation.scss b/src/client/views/pdf/Annotation.scss
index 0ea85d522..817115690 100644
--- a/src/client/views/pdf/Annotation.scss
+++ b/src/client/views/pdf/Annotation.scss
@@ -1,4 +1,7 @@
-.pdfViewer-annotationBox {
+.pdfAnnotation {
     pointer-events: all;
     user-select: none;
+    position: absolute;
+    background-color: pink;
+    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 9d68a86b8..947f5a2e8 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -130,7 +130,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
 
     render() {
         return (
-            <div className="pdfViewer-annotationBox" onPointerDown={this.onPointerDown} ref={this._mainCont}
+            <div className="pdfAnnotation" onPointerDown={this.onPointerDown} ref={this._mainCont}
                 style={{
                     top: this.props.y * scale,
                     left: this.props.x * scale,
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index 7b3d5bfae..3ed81faef 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -32,7 +32,7 @@ export default class PDFMenu extends React.Component {
     @observable public Pinned: boolean = false;
 
     public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = emptyFunction;
-    public Highlight: (d: Doc | undefined, color: string | undefined) => void = emptyFunction;
+    public Highlight: (d: Doc | undefined, color: string) => void = emptyFunction;
     public Delete: () => void = emptyFunction;
     public Snippet: (marquee: { left: number, top: number, width: number, height: number }) => void = emptyFunction;
     public AddTag: (key: string, value: string) => boolean = returnFalse;
diff --git a/src/client/views/pdf/PDFViewer.scss b/src/client/views/pdf/PDFViewer.scss
index 41efb0c00..a2f3911c5 100644
--- a/src/client/views/pdf/PDFViewer.scss
+++ b/src/client/views/pdf/PDFViewer.scss
@@ -1,131 +1,93 @@
 
-.textLayer {
-    div {
-        user-select: text;
-    }
-}
-.viewer-button-cont {
-    position: absolute;
-    display: flex;
-    justify-content: space-evenly;
-    align-items: center;
-}
-
-.viewer-previousPage,
-.viewer-nextPage {
-    background: grey;
-    font-weight: bold;
-    opacity: 0.5;
-    padding: 0 10px;
-    border-radius: 5px;
-}
-
-.textLayer {
-    user-select: auto;
-}
 .pdfViewer-viewer {
     pointer-events:inherit;
     width: 100%;
-}
-
-.pdfViewer-text {
-    transform: scale(1.5);
-    transform-origin: top left;
-    .page {
-        .canvasWrapper {
-            display: none;
-        }
-
-        .textLayer {
-            position: relative;
-            user-select: none;
+    .pdfViewer-visibleElements {
+        .pdfPage-cont {
+            .pdfPage-textLayer {
+                div {
+                    user-select: text;
+                }
+                span {
+                    color: transparent;
+                    position: absolute;
+                    white-space: pre;
+                    cursor: text;
+                    -webkit-transform-origin: 0% 0%;
+                    transform-origin: 0% 0%;
+                }
+            }
         }
     }
-}
-
-.page-cont {
-    .textLayer {
-        user-select: auto;
-
-        div {
-            user-select: text;
-        }
+    .pdfViewer-text {
+        transform: scale(1.5);
+        transform-origin: top left;
     }
-}
-
-.pdfViewer-overlayCont {
-    position: absolute;
-    width: 100%;
-    height: 100px;
-    background: #121721;
-    bottom: 0;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    padding: 20px;
-    overflow: hidden;
-    transition: left .5s;
-}
 
-.pdfViewer-overlaySearchBar {
-    width: 20%;
-    height: 100%;
-    font-size: 30px;
-    padding: 5px;
-}
-
-.pdfViewer-overlayButton {
-    border-bottom-left-radius: 50%;
-    display: flex;
-    justify-content: space-evenly;
-    align-items: center;
-    height: 70px;
-    background: none;
-    padding: 0;
-    position: absolute;
-
-    .pdfViewer-overlayButton-arrow {
-        width: 0;
-        height: 0;
-        border-top: 25px solid transparent;
-        border-bottom: 25px solid transparent;
-        border-right: 25px solid #121721;
-        transition: all 0.5s;
+    .pdfViewer-annotationLayer {
+        position: absolute;
+        top: 0;
+        width: 100%;
+        pointer-events: none;
+        .pdfPage-annotationBox {
+            position: absolute;
+            background-color: red;
+            opacity: 0.1;
+        }
     }
 
-    .pdfViewer-overlayButton-iconCont {
+    .pdfViewer-overlayCont {
+        position: absolute;
+        width: 100%;
+        height: 100px;
         background: #121721;
-        height: 50px;
-        width: 70px;
+        bottom: 0;
         display: flex;
         justify-content: center;
         align-items: center;
-        margin-left: -2px;
-        border-radius: 3px;
+        padding: 20px;
+        overflow: hidden;
+        transition: left .5s;
+        .pdfViewer-overlaySearchBar {
+            width: 20%;
+            height: 100%;
+            font-size: 30px;
+            padding: 5px;
+        }
     }
-}
 
-.pdfViewer-overlayButton:hover {
-    background: none;
-}
+    .pdfViewer-overlayButton {
+        border-bottom-left-radius: 50%;
+        display: flex;
+        justify-content: space-evenly;
+        align-items: center;
+        height: 70px;
+        background: none;
+        padding: 0;
+        position: absolute;
+
+        .pdfViewer-overlayButton-arrow {
+            width: 0;
+            height: 0;
+            border-top: 25px solid transparent;
+            border-bottom: 25px solid transparent;
+            border-right: 25px solid #121721;
+            transition: all 0.5s;
+        }
 
-.pdfViewer-annotationBox {
-    position: absolute;
-    background-color: red;
-    opacity: 0.1;
-}
+        .pdfViewer-overlayButton-iconCont {
+            background: #121721;
+            height: 50px;
+            width: 70px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin-left: -2px;
+            border-radius: 3px;
+        }
+    }
 
-.pdfViewer-annotationLayer {
-    position: absolute;
-    top: 0;
-         width: 100%;
-        pointer-events: none;
+    .pdfViewer-overlayButton:hover {
+        background: none;
+    }
 }
-
-
-
-.pdfViewer-pinAnnotation {
-    background-color: red;
-    position: absolute;
-    border-radius: 100%;
-}
\ No newline at end of file
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 524bb0420..9abb22553 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -427,14 +427,13 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
         if (this._searching) {
             let container = this._mainCont.current;
-            let viewer = this._viewer.current;
 
             if (!this._pdfFindController) {
-                if (container && viewer) {
+                if (container && this._viewer.current) {
                     let simpleLinkService = new SimpleLinkService();
                     this._pdfViewer = new PDFJSViewer.PDFViewer({
                         container: container,
-                        viewer: viewer,
+                        viewer: this._viewer.current,
                         linkService: simpleLinkService
                     });
                     simpleLinkService.setPdf(this.props.pdf);
@@ -483,25 +482,23 @@ export class PDFViewer extends React.Component<IViewerProps> {
     render() {
         return (
             <div className="pdfViewer-viewer" ref={this._mainCont} >
-                <div className="viewer" style={this._searching ? { position: "absolute", top: 0 } : {}}>
+                <div className="pdfViewer-visibleElements" style={this._searching ? { position: "absolute", top: 0 } : {}}>
                     {this._visibleElements}
                 </div>
                 <div className="pdfViewer-text" ref={this._viewer} />
-                <div className="pdfViewer-annotationLayer" style={{ height: NumCast(this.props.Document.nativeHeight) }}>
-                    <div className="pdfViewer-annotationLayer-subCont" ref={this._annotationLayer}>
-                        {this._annotations.filter(anno => {
-                            if (this._script && this._script.compiled) {
-                                let run = this._script.run({ this: anno });
-                                if (run.success) {
-                                    return run.result;
-                                }
+                <div className="pdfViewer-annotationLayer" style={{ height: NumCast(this.props.Document.nativeHeight) }} ref={this._annotationLayer}>
+                    {this._annotations.filter(anno => {
+                        if (this._script && this._script.compiled) {
+                            let run = this._script.run({ this: anno });
+                            if (run.success) {
+                                return run.result;
                             }
-                            return true;
-                        }).sort((a: Doc, b: Doc) => NumCast(a.y) - NumCast(b.y))
-                            .map((anno: Doc, index: number) =>
-                                <Annotation anno={anno} scrollTo={this.props.scrollTo} fieldExtensionDoc={this.props.fieldExtensionDoc} ParentIndex={this.getIndex} addDocTab={this.props.addDocTab} index={index} key={`${anno[Id]}-annotation`} />
-                            )}
-                    </div>
+                        }
+                        return true;
+                    }).sort((a: Doc, b: Doc) => NumCast(a.y) - NumCast(b.y))
+                        .map((anno: Doc, index: number) =>
+                            <Annotation anno={anno} scrollTo={this.props.scrollTo} fieldExtensionDoc={this.props.fieldExtensionDoc} ParentIndex={this.getIndex} addDocTab={this.props.addDocTab} index={index} key={`${anno[Id]}-annotation`} />
+                        )}
                 </div>
                 <div className="pdfViewer-overlayCont" onPointerDown={(e) => e.stopPropagation()}
                     style={{
@@ -509,9 +506,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
                         left: `${this._searching ? 0 : 100}%`
                     }}>
                     <button className="pdfViewer-overlayButton" title="Open Search Bar"></button>
-                    {/* <button title="Previous Result" onClick={() => this.search(this._searchString)}><FontAwesomeIcon icon="arrow-up" size="3x" color="white" /></button>
-                    <button title="Next Result" onClick={this.nextResult}><FontAwesomeIcon icon="arrow-down" size="3x" color="white" /></button> */}
-                    <input onKeyDown={(e: React.KeyboardEvent) => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} placeholder="Search" className="pdfViewer-overlaySearchBar" onChange={this.searchStringChanged} />
+                    <input className="pdfViewer-overlaySearchBar" onKeyDown={(e: React.KeyboardEvent) => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} placeholder="Search" onChange={this.searchStringChanged} />
                     <button title="Search" onClick={() => this.search(this._searchString)}><FontAwesomeIcon icon="search" size="3x" color="white" /></button>
                 </div>
                 <button className="pdfViewer-overlayButton" onClick={this.prevAnnotation} title="Previous Annotation"
diff --git a/src/client/views/pdf/Page.scss b/src/client/views/pdf/Page.scss
new file mode 100644
index 000000000..6467c4979
--- /dev/null
+++ b/src/client/views/pdf/Page.scss
@@ -0,0 +1,31 @@
+
+.pdfPage-cont {
+
+    .pdfPage-dragAnnotationBox {
+        position: absolute;
+        background-color: transparent;
+        opacity: 0.1;
+    }
+    .pdfPage-annotationLayer {
+        pointer-events: none;
+        width: 100%;
+        height: 100%;
+        position: relative;
+        top: -100%;
+    }
+
+    .PdfPage-textLayer {
+        position: relative;
+        div {
+            user-select: text;
+        }
+        span {
+            color: transparent;
+            position: absolute;
+            white-space: pre;
+            cursor: text;
+            -webkit-transform-origin: 0% 0%;
+            transform-origin: 0% 0%;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 1da41bca1..47f2e7b56 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -8,7 +8,7 @@ import { Docs, DocUtils } from "../../documents/Documents";
 import { DragManager } from "../../util/DragManager";
 import PDFMenu from "./PDFMenu";
 import { scale } from "./PDFViewer";
-import "./PDFViewer.scss";
+import "./Page.scss";
 import React = require("react");
 
 
@@ -43,7 +43,6 @@ export default class Page extends React.Component<IPageProps> {
 
     private _canvas: React.RefObject<HTMLCanvasElement> = React.createRef();
     private _textLayer: React.RefObject<HTMLDivElement> = React.createRef();
-    private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
     private _marquee: React.RefObject<HTMLDivElement> = React.createRef();
     private _marqueeing: boolean = false;
     private _reactionDisposer?: IReactionDisposer;
@@ -95,7 +94,7 @@ export default class Page extends React.Component<IPageProps> {
     }
 
     @action
-    highlight = (targetDoc?: Doc, color: string = "red") => {
+    highlight = (targetDoc: Doc | undefined, color: string) => {
         // creates annotation documents for current highlights
         let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, scale, color, false);
         Doc.GetProto(annotationDoc).annotationOn = this.props.Document;
@@ -114,7 +113,7 @@ export default class Page extends React.Component<IPageProps> {
         if (this._textLayer.current) {
             let targetDoc = Docs.Create.TextDocument({ width: 200, height: 200, title: "New Annotation" });
             targetDoc.targetPage = this.props.page;
-            let annotationDoc = this.highlight(undefined, "red");
+            let annotationDoc = this.highlight(undefined, "pink");
             annotationDoc.linkedToDoc = false;
             let dragData = new DragManager.AnnotationDragData(this.props.Document, annotationDoc, targetDoc);
             DragManager.StartAnnotationDrag([ele], dragData, e.pageX, e.pageY, {
@@ -196,7 +195,6 @@ export default class Page extends React.Component<IPageProps> {
             this._marqueeX = Math.min(this._startX, this._startX + this._marqueeWidth);
             this._marqueeY = Math.min(this._startY, this._startY + this._marqueeHeight);
             this._marqueeWidth = Math.abs(this._marqueeWidth);
-            this._marquee.current && (this._marquee.current.style.background = "red");
             e.stopPropagation();
             e.preventDefault();
         }
@@ -219,10 +217,9 @@ export default class Page extends React.Component<IPageProps> {
                 copy.style.height = style.height;
 
                 // apply the appropriate background, opacity, and transform
-                copy.style.background = "red";
                 copy.style.border = style.border;
                 copy.style.opacity = style.opacity;
-                copy.className = this._marquee.current.className;
+                copy.className = "pdfPage-annotationBox";
                 this.props.createAnnotation(copy, this.props.page);
                 this._marquee.current.style.opacity = "0";
             }
@@ -266,7 +263,7 @@ export default class Page extends React.Component<IPageProps> {
                 let rect = clientRects.item(i);
                 if (rect && rect.width !== this._textLayer.current.getBoundingClientRect().width && rect.height !== this._textLayer.current.getBoundingClientRect().height) {
                     let annoBox = document.createElement("div");
-                    annoBox.className = "pdfViewer-annotationBox";
+                    annoBox.className = "pdfPage-annotationBox";
                     // transforms the positions from screen onto the pdf div
                     annoBox.style.top = ((rect.top - boundingRect.top) * (this._textLayer.current.offsetHeight / boundingRect.height)).toString();
                     annoBox.style.left = ((rect.left - boundingRect.left) * (this._textLayer.current.offsetWidth / boundingRect.width)).toString();
@@ -295,16 +292,23 @@ export default class Page extends React.Component<IPageProps> {
 
     render() {
         return (
-            <div onPointerDown={this.onPointerDown} onDoubleClick={this.doubleClick} className={"page-cont"} style={{ "width": this._width, "height": this._height }}>
-                <div className="canvasContainer">
+            <div className={"pdfPage-cont"} onPointerDown={this.onPointerDown} onDoubleClick={this.doubleClick} style={{ "width": this._width, "height": this._height }}>
+                <div className="PdfPage-canvasContainer">
                     <canvas ref={this._canvas} />
                 </div>
-                <div className="pdfInkingLayer-cont" ref={this._annotationLayer} style={{ width: "100%", height: "100%", position: "relative", top: "-100%" }}>
-                    <div className="pdfViewer-annotationBox" ref={this._marquee}
-                        style={{ left: `${this._marqueeX}px`, top: `${this._marqueeY}px`, width: `${this._marqueeWidth}px`, height: `${this._marqueeHeight}px`, background: "red", border: `${this._marqueeWidth === 0 ? "" : "10px dashed black"}` }}>
+                <div className="pdfPage-annotationLayer">
+                    <div className="pdfPage-dragAnnotationBox" ref={this._marquee}
+                        style={{
+                            left: `${this._marqueeX}px`, top: `${this._marqueeY}px`,
+                            width: `${this._marqueeWidth}px`, height: `${this._marqueeHeight}px`,
+                            border: `${this._marqueeWidth === 0 ? "" : "10px dashed black"}`
+                        }}>
                     </div>
                 </div>
-                <div className="textlayer" ref={this._textLayer} style={{ "position": "relative", "top": `-${2 * this._height}px`, "height": `${this._height}px` }} />
+                <div className="pdfPage-textlayer"
+                    ref={this._textLayer}
+                    style={{ top: `-${2 * this._height}px`, height: `${this._height}px` }}
+                />
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 913055f1b6f8eac88eda2ba08715c9cc3b013f08 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 6 Aug 2019 23:54:39 -0400
Subject: pdf tweaks.

---
 src/client/views/pdf/Annotation.tsx | 39 +++++++++++++------------------------
 src/client/views/pdf/Page.tsx       |  8 ++------
 2 files changed, 15 insertions(+), 32 deletions(-)

(limited to 'src/client/views/pdf/Annotation.tsx')

diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 947f5a2e8..2610f6c6e 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -9,7 +9,7 @@ import { DocumentManager } from "../../util/DocumentManager";
 import { PresentationView } from "../presentationview/PresentationView";
 import PDFMenu from "./PDFMenu";
 import "./Annotation.scss";
-import { AnnotationTypes, scale } from "./PDFViewer";
+import { scale } from "./PDFViewer";
 
 interface IAnnotationProps {
     anno: Doc;
@@ -22,17 +22,8 @@ interface IAnnotationProps {
 
 export default class Annotation extends React.Component<IAnnotationProps> {
     render() {
-        let annotationDocs = DocListCast(this.props.anno.annotations);
-        let res = annotationDocs.map(a => {
-            let type = NumCast(a.type);
-            switch (type) {
-                case AnnotationTypes.Region:
-                    return <RegionAnnotation addDocTab={this.props.addDocTab} document={a} fieldExtensionDoc={this.props.fieldExtensionDoc} scrollTo={this.props.scrollTo} ParentIndex={this.props.ParentIndex} index={this.props.index} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
-                default:
-                    return <div></div>;
-            }
-        });
-        return res;
+        return DocListCast(this.props.anno.annotations).map(a => (
+            <RegionAnnotation {...this.props} document={a} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />));
     }
 }
 
@@ -51,8 +42,6 @@ interface IRegionAnnotationProps {
 
 @observer
 class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
-    @observable private _backgroundColor: string = "red";
-
     private _reactionDisposer?: IReactionDisposer;
     private _scrollDisposer?: IReactionDisposer;
     private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
@@ -60,13 +49,13 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
     componentDidMount() {
         this._reactionDisposer = reaction(
             () => this.props.document.delete,
-            () => this.props.document.delete && this._mainCont.current && (this._mainCont.current.style.display = "none"),
+            (del) => del && this._mainCont.current && (this._mainCont.current.style.display = "none"),
             { fireImmediately: true }
         );
 
         this._scrollDisposer = reaction(
             () => this.props.ParentIndex(),
-            () => this.props.ParentIndex() === this.props.index && this.props.scrollTo && this.props.scrollTo(this.props.y * scale)
+            (ind) => ind === this.props.index && this.props.scrollTo && this.props.scrollTo(this.props.y * scale)
         );
     }
 
@@ -129,15 +118,13 @@ 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,
-                    backgroundColor: this.props.ParentIndex() === this.props.index ? "green" : StrCast(this.props.document.color)
-                }} />
-        );
+        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,
+                backgroundColor: this.props.ParentIndex() === this.props.index ? "green" : StrCast(this.props.document.color)
+            }} />);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index fd4fbfb21..a1f807f13 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -198,16 +198,13 @@ export default class Page extends React.Component<IPageProps> {
     onSelectEnd = (e: PointerEvent): void => {
         if (this._marqueeing) {
             this._marqueeing = false;
-            if (this._marquee.current) {
+            if (this._marquee.current) { // make a copy of the marquee
                 let copy = document.createElement("div");
-                // make a copy of the marquee
                 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;
-
-                // apply the appropriate background, opacity, and transform
                 copy.style.border = style.border;
                 copy.style.opacity = style.opacity;
                 copy.className = "pdfPage-annotationBox";
@@ -293,7 +290,6 @@ export default class Page extends React.Component<IPageProps> {
                     }}>
                 </div>
                 <div className="pdfPage-textlayer" ref={this._textLayer} />
-            </div>
-        );
+            </div>);
     }
 }
\ No newline at end of file
-- 
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/pdf/Annotation.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

