diff options
| author | yipstanley <stanley_yip@brown.edu> | 2019-06-14 15:47:43 -0400 |
|---|---|---|
| committer | yipstanley <stanley_yip@brown.edu> | 2019-06-14 15:47:43 -0400 |
| commit | 2ef1dd2089ad991f1d4897022f2d28c2eb130837 (patch) | |
| tree | 57add9cdf31cad56fa93987ab570e5ef3e91fc1d /src | |
| parent | 4818b12510404e7d9cf07b7e872c49d7b752976a (diff) | |
highlighting
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 10 | ||||
| -rw-r--r-- | src/client/views/pdf/PDFMenu.tsx | 25 | ||||
| -rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 6 | ||||
| -rw-r--r-- | src/client/views/pdf/Page.tsx | 74 |
4 files changed, 91 insertions, 24 deletions
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index acb430deb..6ee62bbad 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -34,8 +34,16 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen loaded = (nw: number, nh: number) => { if (this.props.Document) { let doc = this.props.Document.proto ? this.props.Document.proto : this.props.Document; + let oldnw = NumCast(doc.nativeWidth); doc.nativeWidth = nw; - doc.nativeHeight = nh; + if (!doc.nativeHeight) { + doc.nativeHeight = nh; + } + else { + let oldnh = NumCast(doc.nativeHeight); + let aspect = oldnh / oldnw; + doc.nativeHeight = nw * aspect; + } let ccv = this.props.ContainingCollectionView; if (ccv) { ccv.props.Document.pdfHeight = nh; diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index cc5c0b77b..a0230113b 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -3,6 +3,8 @@ import "./PDFMenu.scss"; import { observable } from "mobx"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { emptyFunction } from "../../../Utils"; +import { Doc } from "../../../new_fields/Doc"; @observer export default class PDFMenu extends React.Component { @@ -10,6 +12,8 @@ export default class PDFMenu extends React.Component { @observable Top: number = 0; @observable Left: number = 0; + StartDrag: (e: PointerEvent) => void = emptyFunction; + Highlight: (d: Doc | undefined) => void = emptyFunction; constructor(props: Readonly<{}>) { super(props); @@ -17,11 +21,28 @@ export default class PDFMenu extends React.Component { PDFMenu.Instance = this; } + pointerDown = (e: React.PointerEvent) => { + document.removeEventListener("pointermove", this.StartDrag); + document.addEventListener("pointermove", this.StartDrag); + document.removeEventListener("pointerup", this.pointerUp) + document.addEventListener("pointerup", this.pointerUp) + + e.stopPropagation(); + e.preventDefault(); + } + + pointerUp = (e: PointerEvent) => { + document.removeEventListener("pointermove", this.StartDrag); + document.removeEventListener("pointerup", this.pointerUp); + e.stopPropagation(); + e.preventDefault(); + } + render() { return ( <div className="pdfMenu-cont" style={{ left: this.Left, top: this.Top }}> - <button className="pdfMenu-button" title="Highlight"><FontAwesomeIcon icon="highlighter" size="sm" /></button> - <button className="pdfMenu-button" title="Annotate"><FontAwesomeIcon icon="comment-alt" size="sm" /></button> + <button className="pdfMenu-button" title="Highlight" onClick={() => this.Highlight(undefined)}><FontAwesomeIcon icon="highlighter" size="sm" /></button> + <button className="pdfMenu-button" title="Annotate" onPointerDown={this.pointerDown}><FontAwesomeIcon icon="comment-alt" size="sm" /></button> </div> ) } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d6081142a..fbad39880 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -152,7 +152,7 @@ class Viewer extends React.Component<IViewerProps> { } } - makeAnnotationDocument = (sourceDoc: Doc): Doc => { + makeAnnotationDocument = (sourceDoc: Doc | undefined): Doc => { let annoDocs: Doc[] = []; this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => { for (let anno of value) { @@ -171,7 +171,9 @@ class Viewer extends React.Component<IViewerProps> { let annoDoc = new Doc(); annoDoc.annotations = new List<Doc>(annoDocs); - DocUtils.MakeLink(sourceDoc, annoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title)); + if (sourceDoc) { + DocUtils.MakeLink(sourceDoc, annoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title)); + } this._savedAnnotations.clear(); return annoDoc; } diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index bdb6952cc..44c502a04 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -28,7 +28,7 @@ interface IPageProps { sendAnnotations: (annotations: HTMLDivElement[], page: number) => void; receiveAnnotations: (page: number) => HTMLDivElement[] | undefined; createAnnotation: (div: HTMLDivElement, page: number) => void; - makeAnnotationDocuments: (doc: Doc) => Doc; + makeAnnotationDocuments: (doc: Doc | undefined) => Doc; } @observer @@ -132,6 +132,20 @@ export default class Page extends React.Component<IPageProps> { } } + highlight = (targetDoc: Doc | undefined) => { + // creates annotation documents for current highlights + let annotationDoc = this.props.makeAnnotationDocuments(targetDoc); + let targetAnnotations = DocListCast(this.props.parent.Document.annotations); + if (targetAnnotations) { + targetAnnotations.push(annotationDoc); + this.props.parent.Document.annotations = new List<Doc>(targetAnnotations); + } + else { + this.props.parent.Document.annotations = new List<Doc>([annotationDoc]); + } + return annotationDoc; + } + /** * This is temporary for creating annotations from highlights. It will * start a drag event and create or put the necessary info into the drag event. @@ -149,16 +163,7 @@ export default class Page extends React.Component<IPageProps> { // document that this annotation is linked to let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" }); targetDoc.targetPage = this.props.page; - // creates annotation documents for current highlights - let annotationDoc = this.props.makeAnnotationDocuments(targetDoc); - let targetAnnotations = DocListCast(this.props.parent.Document.annotations); - if (targetAnnotations) { - targetAnnotations.push(annotationDoc); - this.props.parent.Document.annotations = new List<Doc>(targetAnnotations); - } - else { - this.props.parent.Document.annotations = new List<Doc>([annotationDoc]); - } + let annotationDoc = this.highlight(targetDoc); // create dragData and star tdrag let dragData = new DragManager.AnnotationDragData(thisDoc, annotationDoc, targetDoc); if (this._textLayer.current) { @@ -173,8 +178,8 @@ export default class Page extends React.Component<IPageProps> { // cleans up events and boolean endDrag = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.endDrag); + // document.removeEventListener("pointermove", this.startDrag); + // document.removeEventListener("pointerup", this.endDrag); this._dragging = false; e.stopPropagation(); } @@ -185,10 +190,10 @@ export default class Page extends React.Component<IPageProps> { if (e.altKey && e.button === 0) { e.stopPropagation(); - document.removeEventListener("pointermove", this.startDrag); - document.addEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.endDrag); - document.addEventListener("pointerup", this.endDrag); + // document.removeEventListener("pointermove", this.startDrag); + // document.addEventListener("pointermove", this.startDrag); + // document.removeEventListener("pointerup", this.endDrag); + // document.addEventListener("pointerup", this.endDrag); } else if (e.button === 0) { let target: any = e.target; @@ -299,6 +304,8 @@ export default class Page extends React.Component<IPageProps> { } copy.className = this._marquee.current.className; this.props.createAnnotation(copy, this.props.page); + PDFMenu.Instance.StartDrag = this.startDrag; + PDFMenu.Instance.Highlight = this.highlight; this._marquee.current.style.opacity = "0"; } @@ -308,8 +315,10 @@ export default class Page extends React.Component<IPageProps> { } else { let sel = window.getSelection(); - if (sel && sel.type === "range") { - + if (sel && sel.type === "Range") { + PDFMenu.Instance.StartDrag = this.startDrag; + PDFMenu.Instance.Highlight = this.highlight; + this.createTextAnnotation(sel); PDFMenu.Instance.Left = e.clientX; PDFMenu.Instance.Top = e.clientY; } @@ -380,6 +389,33 @@ export default class Page extends React.Component<IPageProps> { document.removeEventListener("pointerup", this.onSelectEnd); } + @action + createTextAnnotation = (sel: Selection) => { + let clientRects = sel.getRangeAt(0).getClientRects(); + if (this._textLayer.current) { + let boundingRect = this._textLayer.current.getBoundingClientRect(); + for (let i = 0; i < clientRects.length; i++) { + let rect = clientRects.item(i); + if (rect) { + let annoBox = document.createElement("div"); + annoBox.className = "pdfViewer-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(); + annoBox.style.width = (rect.width * this._textLayer.current.offsetWidth / boundingRect.width).toString(); + annoBox.style.height = (rect.height * this._textLayer.current.offsetHeight / boundingRect.height).toString(); + this.props.createAnnotation(annoBox, this.props.page); + } + } + } + // clear selection + if (sel.empty) { // Chrome + sel.empty(); + } else if (sel.removeAllRanges) { // Firefox + sel.removeAllRanges(); + } + } + doubleClick = (e: React.MouseEvent) => { let target: any = e.target; // if double clicking text |
