aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryipstanley <stanley_yip@brown.edu>2019-06-11 15:04:47 -0400
committeryipstanley <stanley_yip@brown.edu>2019-06-11 15:04:47 -0400
commit64f6a0d54656ded133af113746003d61eaa1d651 (patch)
tree7d62011420fb31bdaa7ee885dd4c473a79482b54
parent46b9a18bf278ab17845d1082a1152d16c07b1240 (diff)
pin annotations base
-rw-r--r--src/client/views/pdf/PDFViewer.scss6
-rw-r--r--src/client/views/pdf/PDFViewer.tsx72
-rw-r--r--src/client/views/pdf/Page.tsx22
3 files changed, 96 insertions, 4 deletions
diff --git a/src/client/views/pdf/PDFViewer.scss b/src/client/views/pdf/PDFViewer.scss
index 831e6add1..57be04b93 100644
--- a/src/client/views/pdf/PDFViewer.scss
+++ b/src/client/views/pdf/PDFViewer.scss
@@ -34,4 +34,10 @@
position: absolute;
top: 0;
overflow: visible hidden;
+}
+
+.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 092765324..bc773ebef 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -9,9 +9,11 @@ import { PDFBox } from "../nodes/PDFBox";
import Page from "./Page";
import { NumCast, Cast, BoolCast } from "../../../new_fields/Types";
import { Id } from "../../../new_fields/FieldSymbols";
-import { DocUtils } from "../../documents/Documents";
+import { DocUtils, Docs } from "../../documents/Documents";
import { DocumentManager } from "../../util/DocumentManager";
import { SelectionManager } from "../../util/SelectionManager";
+import { List } from "../../../new_fields/List";
+import { DocumentContentsView } from "../nodes/DocumentContentsView";
interface IPDFViewerProps {
url: string;
@@ -56,6 +58,8 @@ interface IViewerProps {
url: string;
}
+const PinRadius = 25;
+
/**
* Handles rendering and virtualization of the pdf
*/
@@ -193,6 +197,7 @@ class Viewer extends React.Component<IViewerProps> {
pageLoaded={this.pageLoaded}
parent={this.props.parent}
renderAnnotations={this.renderAnnotations}
+ makePin={this.createPinAnnotation}
{...this.props} />
));
let arr = Array.from(Array(numPages).keys()).map(() => false);
@@ -229,6 +234,7 @@ class Viewer extends React.Component<IViewerProps> {
name={`${this.props.pdf ? this.props.pdf.fingerprint + `-page${i + 1}` : "undefined"}`}
pageLoaded={this.pageLoaded}
parent={this.props.parent}
+ makePin={this.createPinAnnotation}
renderAnnotations={this.renderAnnotations}
{...this.props} />
);
@@ -242,6 +248,33 @@ class Viewer extends React.Component<IViewerProps> {
return;
}
+ createPinAnnotation = (x: number, y: number): void => {
+ let targetDoc = Docs.TextDocument({ title: "New Pin Annotation" });
+
+ let pinAnno = new Doc();
+ pinAnno.x = x;
+ pinAnno.y = y;
+ pinAnno.width = pinAnno.height = PinRadius;
+ pinAnno.page = this.getIndex(y);
+ pinAnno.target = targetDoc;
+ pinAnno.type = AnnotationTypes.Pin;
+ // this._annotations.push(pinAnno);
+ let annotations = DocListCast(this.props.parent.Document.annotations);
+ if (annotations && annotations.length) {
+ annotations.push(pinAnno);
+ this.props.parent.Document.annotations = new List<Doc>(annotations);
+ }
+ else {
+ this.props.parent.Document.annotations = new List<Doc>([pinAnno]);
+ }
+ // let pinAnno = document.createElement("div");
+ // pinAnno.className = "pdfViewer-pinAnnotation";
+ // pinAnno.style.top = (y - (radius / 2)).toString();
+ // pinAnno.style.left = (x - (radius / 2)).toString();
+ // pinAnno.style.height = pinAnno.style.width = radius.toString();
+ // if (this._annotationLayer.current) this._annotationLayer.current.append(pinAnno);
+ }
+
// get the page index that the vertical offset passed in is on
getIndex = (vOffset: number) => {
if (this._loaded) {
@@ -295,6 +328,18 @@ class Viewer extends React.Component<IViewerProps> {
return counter;
}
+ renderAnnotation = (anno: Doc): JSX.Element => {
+ let type = NumCast(anno.type);
+ switch (type) {
+ case AnnotationTypes.Pin:
+ return <PinAnnotation document={anno} x={NumCast(anno.x)} y={NumCast(anno.y) + this.getPageHeight(NumCast(anno.page))} width={anno[WidthSym]()} height={anno[HeightSym]()} key={anno[Id]} />;
+ case AnnotationTypes.Region:
+ return <RegionAnnotation document={anno} x={NumCast(anno.x)} y={NumCast(anno.y) + this.getPageHeight(NumCast(anno.page))} width={anno[WidthSym]()} height={anno[HeightSym]()} key={anno[Id]} />;
+ default:
+ return <div></div>;
+ }
+ }
+
render() {
return (
<div>
@@ -303,7 +348,7 @@ class Viewer extends React.Component<IViewerProps> {
</div>
<div className="pdfViewer-annotationLayer" style={{ height: this.props.parent.Document.nativeHeight, width: `100%`, pointerEvents: "none" }}>
<div className="pdfViewer-annotationLayer-subCont" style={{ transform: `translateY(${-this.scrollY}px)` }}>
- {this._annotations.map(anno => <RegionAnnotation document={anno} x={NumCast(anno.x)} y={NumCast(anno.y) + this.getPageHeight(NumCast(anno.page))} width={anno[WidthSym]()} height={anno[HeightSym]()} key={anno[Id]} />)}
+ {this._annotations.map(anno => this.renderAnnotation(anno))}
</div>
</div>
</div>
@@ -311,6 +356,10 @@ class Viewer extends React.Component<IViewerProps> {
}
}
+export enum AnnotationTypes {
+ Region, Pin
+}
+
interface IAnnotationProps {
x: number;
y: number;
@@ -319,6 +368,25 @@ interface IAnnotationProps {
document: Doc;
}
+class PinAnnotation extends React.Component<IAnnotationProps> {
+ @observable private _backgroundColor: string = "red";
+
+ pointerDown = (e: React.PointerEvent) => {
+
+ }
+
+ render() {
+ let targetDoc = Cast(this.props.document.targetDoc, Doc, Docs.TextDocument({ title: "New Pin Annotation" }));
+ return (
+ <div className="pdfViewer-pinAnnotation" onPointerDown={this.pointerDown}
+ style={{ top: this.props.y - PinRadius / 2, left: this.props.x - PinRadius / 2, width: PinRadius, height: PinRadius, pointerEvents: "all", backgroundColor: this._backgroundColor }}>
+ {/* <DocumentContentsView Document={targetDoc}
+ isSelected={} /> */}
+ </div>
+ );
+ }
+}
+
class RegionAnnotation extends React.Component<IAnnotationProps> {
@observable private _backgroundColor: string = "red";
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 5738889c4..fe7369aeb 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -13,6 +13,7 @@ import { emptyFunction } from "../../../Utils";
import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
import { listSpec } from "../../../new_fields/Schema";
import { menuBar } from "prosemirror-menu";
+import { AnnotationTypes } from "./PDFViewer";
interface IPageProps {
pdf: Opt<Pdfjs.PDFDocumentProxy>;
@@ -22,6 +23,7 @@ interface IPageProps {
pageLoaded: (index: number, page: Pdfjs.PDFPageViewport) => void;
parent: PDFBox;
renderAnnotations: (annotations: Doc[], removeOld: boolean) => void;
+ makePin: (x: number, y: number) => void;
}
@observer
@@ -142,6 +144,7 @@ export default class Page extends React.Component<IPageProps> {
annoDoc.width = anno.offsetWidth;
annoDoc.page = this.props.page;
annoDoc.target = targetDoc;
+ annoDoc.type = AnnotationTypes.Region;
annoDocs.push(annoDoc);
DocUtils.MakeLink(annoDoc, targetDoc, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title));
anno.remove();
@@ -169,7 +172,6 @@ export default class Page extends React.Component<IPageProps> {
targetDoc.targetPage = this.props.page;
// creates annotation documents for current highlights
let annotationDocs = this.makeAnnotationDocuments(targetDoc);
- console.log(annotationDocs);
let targetAnnotations = DocListCast(this.props.parent.Document.annotations);
if (targetAnnotations) {
targetAnnotations.push(...annotationDocs);
@@ -364,6 +366,22 @@ export default class Page extends React.Component<IPageProps> {
document.removeEventListener("pointerup", this.onSelectEnd);
}
+ doubleClick = (e: React.MouseEvent) => {
+ let target: any = e.target;
+ // if double clicking text
+ if (target && target.parentElement === this._textLayer.current) {
+ // do something to select the paragraph ideally
+ }
+
+ let current = this._textLayer.current;
+ if (current) {
+ let boundingRect = current.getBoundingClientRect();
+ let x = (e.clientX - boundingRect.left) * (current.offsetWidth / boundingRect.width);
+ let y = (e.clientY - boundingRect.top) * (current.offsetHeight / boundingRect.height);
+ this.props.makePin(x, y);
+ }
+ }
+
renderAnnotation = (anno: Doc | undefined): HTMLDivElement => {
let annoBox = document.createElement("div");
if (anno) {
@@ -379,7 +397,7 @@ export default class Page extends React.Component<IPageProps> {
render() {
return (
- <div onPointerDown={this.onPointerDown} className={this.props.name} style={{ "width": this._width, "height": this._height }}>
+ <div onPointerDown={this.onPointerDown} onDoubleClick={this.doubleClick} className={this.props.name} style={{ "width": this._width, "height": this._height }}>
<div className="canvasContainer">
<canvas ref={this._canvas} />
</div>