aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/pdf')
-rw-r--r--src/client/views/pdf/PDFMenu.tsx75
-rw-r--r--src/client/views/pdf/PDFViewer.tsx368
-rw-r--r--src/client/views/pdf/Page.tsx81
3 files changed, 273 insertions, 251 deletions
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index 2ed891131..39b15fb11 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -15,16 +15,20 @@ export default class PDFMenu extends React.Component {
@observable private _opacity: number = 1;
@observable private _transition: string = "opacity 0.5s";
@observable private _transitionDelay: string = "";
- @observable private _pinned: boolean = false;
+
+ @observable public Pinned: boolean = false;
StartDrag: (e: PointerEvent) => void = emptyFunction;
Highlight: (d: Doc | undefined, color: string | undefined) => void = emptyFunction;
- @observable Highlighting: boolean = false;
+ Delete: () => void = emptyFunction;
+
+ @observable public Highlighting: boolean = false;
+ @observable public Status: "pdf" | "annotation" | "" = "";
- private _timeout: NodeJS.Timeout | undefined;
private _offsetY: number = 0;
private _offsetX: number = 0;
private _mainCont: React.RefObject<HTMLDivElement>;
+ private _dragging: boolean = false;
constructor(props: Readonly<{}>) {
super(props);
@@ -35,27 +39,38 @@ export default class PDFMenu extends React.Component {
}
pointerDown = (e: React.PointerEvent) => {
- document.removeEventListener("pointermove", this.StartDrag);
- document.addEventListener("pointermove", this.StartDrag);
+ document.removeEventListener("pointermove", this.pointerMove);
+ document.addEventListener("pointermove", this.pointerMove);
document.removeEventListener("pointerup", this.pointerUp);
document.addEventListener("pointerup", this.pointerUp);
- console.log(this.StartDrag);
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ pointerMove = (e: PointerEvent) => {
e.stopPropagation();
e.preventDefault();
+
+ if (this._dragging) {
+ return;
+ }
+
+ this.StartDrag(e);
+ this._dragging = true;
}
pointerUp = (e: PointerEvent) => {
- document.removeEventListener("pointermove", this.StartDrag);
+ this._dragging = false;
+ document.removeEventListener("pointermove", this.pointerMove);
document.removeEventListener("pointerup", this.pointerUp);
e.stopPropagation();
e.preventDefault();
}
@action
- jumpTo = (x: number, y: number) => {
- if (!this._pinned) {
+ jumpTo = (x: number, y: number, forceJump: boolean = false) => {
+ if (!this.Pinned || forceJump) {
this._transition = this._transitionDelay = "";
this._opacity = 1;
this._left = x;
@@ -65,7 +80,7 @@ export default class PDFMenu extends React.Component {
@action
fadeOut = (forceOut: boolean) => {
- if (!this._pinned) {
+ if (!this.Pinned) {
if (this._opacity === 0.2) {
this._transition = "opacity 0.1s";
this._transitionDelay = "";
@@ -84,7 +99,7 @@ export default class PDFMenu extends React.Component {
@action
pointerLeave = (e: React.PointerEvent) => {
- if (!this._pinned) {
+ if (!this.Pinned) {
this._transition = "opacity 0.5s";
this._transitionDelay = "1s";
this._opacity = 0.2;
@@ -101,8 +116,8 @@ export default class PDFMenu extends React.Component {
@action
togglePin = (e: React.MouseEvent) => {
- this._pinned = !this._pinned;
- if (!this._pinned) {
+ this.Pinned = !this.Pinned;
+ if (!this.Pinned) {
this.Highlighting = false;
}
}
@@ -138,7 +153,7 @@ export default class PDFMenu extends React.Component {
@action
highlightClicked = (e: React.MouseEvent) => {
- if (!this._pinned) {
+ if (!this.Pinned) {
this.Highlight(undefined, "#f4f442");
}
else {
@@ -147,11 +162,35 @@ export default class PDFMenu extends React.Component {
}
}
+ deleteClicked = (e: React.PointerEvent) => {
+ this.Delete();
+ }
+
+ handleContextMenu = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+
render() {
+ let buttons = this.Status === "pdf" ? [
+ <button className="pdfMenu-button" title="Click to Highlight" onClick={this.highlightClicked}
+ style={this.Highlighting ? { backgroundColor: "#121212" } : {}}>
+ <FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} />
+ </button>,
+ <button className="pdfMenu-button" title="Drag to Annotate" onPointerDown={this.pointerDown}><FontAwesomeIcon icon="comment-alt" size="lg" /></button>,
+ <button className="pdfMenu-button" title="Pin Menu" onClick={this.togglePin}
+ style={this.Pinned ? { backgroundColor: "#121212" } : {}}>
+ <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transition: "transform 0.1s", transform: this.Pinned ? "rotate(45deg)" : "" }} />
+ </button>
+ ] : [
+ <button className="pdfMenu-button" title="Delete Anchor" onPointerDown={this.deleteClicked}><FontAwesomeIcon icon="trash-alt" size="lg" /></button>
+ ];
+
return (
- <div className="pdfMenu-cont" onPointerLeave={this.pointerLeave} onPointerEnter={this.pointerEntered} ref={this._mainCont}
+ <div className="pdfMenu-cont" onPointerLeave={this.pointerLeave} onPointerEnter={this.pointerEntered} ref={this._mainCont} onContextMenu={this.handleContextMenu}
style={{ left: this._left, top: this._top, opacity: this._opacity, transition: this._transition, transitionDelay: this._transitionDelay }}>
- <button className="pdfMenu-button" title="Highlight" onClick={this.highlightClicked}
+ {buttons}
+ {/* <button className="pdfMenu-button" title="Highlight" onClick={this.highlightClicked}
style={this.Highlighting ? { backgroundColor: "#121212" } : {}}>
<FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} />
</button>
@@ -159,8 +198,8 @@ export default class PDFMenu extends React.Component {
<button className="pdfMenu-button" title="Pin Menu" onClick={this.togglePin}
style={this._pinned ? { backgroundColor: "#121212" } : {}}>
<FontAwesomeIcon icon="thumbtack" size="lg" style={{ transition: "transform 0.1s", transform: this._pinned ? "rotate(45deg)" : "" }} />
- </button>
- <div className="pdfMenu-dragger" onPointerDown={this.dragStart} style={{ width: this._pinned ? "20px" : "0px" }} />
+ </button> */}
+ <div className="pdfMenu-dragger" onPointerDown={this.dragStart} style={{ width: this.Pinned ? "20px" : "0px" }} />
</div >
);
}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 8c0aaea00..7000352e7 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -7,7 +7,7 @@ import { Dictionary } from "typescript-collections";
import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
import { List } from "../../../new_fields/List";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { BoolCast, Cast, NumCast, StrCast, FieldValue } from "../../../new_fields/Types";
import { emptyFunction } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { Docs, DocUtils } from "../../documents/Documents";
@@ -19,6 +19,7 @@ import Page from "./Page";
import "./PDFViewer.scss";
import React = require("react");
import PDFMenu from "./PDFMenu";
+import { UndoManager } from "../../util/UndoManager";
export const scale = 2;
interface IPDFViewerProps {
@@ -90,7 +91,8 @@ class Viewer extends React.Component<IViewerProps> {
@action
componentDidMount = () => {
this._reactionDisposer = reaction(
- () => [this.props.parent.props.active(), this.startIndex, this.endIndex],
+
+ () => [this.props.parent.props.active(), this.startIndex, this._pageSizes.length ? this.endIndex : 0],
async () => {
await this.initialLoad();
this.renderPages();
@@ -114,12 +116,16 @@ class Viewer extends React.Component<IViewerProps> {
let pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages);
this._isPage = Array<string>(this.props.pdf.numPages);
for (let i = 0; i < this.props.pdf.numPages; i++) {
- await this.props.pdf.getPage(i + 1).then(page => runInAction(() =>
- pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale }));
+ await this.props.pdf.getPage(i + 1).then(page => runInAction(() => {
+ // pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale };
+ let x = page.getViewport(scale);
+ pageSizes[i] = { width: x.width, height: x.height };
+ }));
}
runInAction(() =>
Array.from(Array((this._pageSizes = pageSizes).length).keys()).map(this.getPlaceholderPage));
- this.props.loaded(pageSizes[0].width, pageSizes[0].height, this.props.pdf.numPages);
+ this.props.loaded(Math.max(...pageSizes.map(i => i.width)), pageSizes[0].height, this.props.pdf.numPages);
+ // this.props.loaded(Math.max(...pageSizes.map(i => i.width)), pageSizes[0].height, this.props.pdf.numPages);
}
}
@@ -132,6 +138,7 @@ class Viewer extends React.Component<IViewerProps> {
makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string): Doc => {
let annoDocs: Doc[] = [];
+ let mainAnnoDoc = new Doc();
this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => {
for (let anno of value) {
let annoDoc = new Doc();
@@ -141,6 +148,7 @@ class Viewer extends React.Component<IViewerProps> {
if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale;
annoDoc.page = key;
annoDoc.target = sourceDoc;
+ annoDoc.group = mainAnnoDoc;
annoDoc.color = color;
annoDoc.type = AnnotationTypes.Region;
annoDocs.push(annoDoc);
@@ -148,13 +156,12 @@ class Viewer extends React.Component<IViewerProps> {
}
});
- let annoDoc = new Doc();
- annoDoc.annotations = new List<Doc>(annoDocs);
+ mainAnnoDoc.annotations = new List<Doc>(annoDocs);
if (sourceDoc) {
- DocUtils.MakeLink(sourceDoc, annoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title));
+ DocUtils.MakeLink(sourceDoc, mainAnnoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title));
}
this._savedAnnotations.clear();
- return annoDoc;
+ return mainAnnoDoc;
}
drop = async (e: Event, de: DragManager.DropEvent) => {
@@ -185,7 +192,7 @@ class Viewer extends React.Component<IViewerProps> {
if (this._isPage[page] !== "none") {
this._isPage[page] = "none";
this._visibleElements[page] = (
- <div key={`placeholder-${page}`} className="pdfviewer-placeholder"
+ <div key={`${this.props.url}-placeholder-${page + 1}`} className="pdfviewer-placeholder"
style={{ width: this._pageSizes[page].width, height: this._pageSizes[page].height }} />
);
}
@@ -199,11 +206,11 @@ class Viewer extends React.Component<IViewerProps> {
pdf={this.props.pdf}
page={page}
numPages={this.props.pdf.numPages}
- key={`rendered-${page + 1}`}
+ key={`${this.props.url}-rendered-${page + 1}`}
name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`}
pageLoaded={this.pageLoaded}
parent={this.props.parent}
- makePin={this.createPinAnnotation}
+ makePin={emptyFunction}
renderAnnotations={this.renderAnnotations}
createAnnotation={this.createAnnotation}
sendAnnotations={this.receiveAnnotations}
@@ -236,7 +243,7 @@ class Viewer extends React.Component<IViewerProps> {
// endIndex: where to end rendering pages
@computed get endIndex(): number {
- return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY) + this._pageBuffer);
+ return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY + this._pageSizes[0].height) + this._pageBuffer);
}
@action
@@ -280,27 +287,27 @@ class Viewer extends React.Component<IViewerProps> {
return this._savedAnnotations.getValue(page);
}
- createPinAnnotation = (x: number, y: number, page: number): void => {
- let targetDoc = Docs.TextDocument({ width: 100, height: 50, title: "New Pin Annotation" });
- let pinAnno = new Doc();
- pinAnno.x = x;
- pinAnno.y = y + this.getScrollFromPage(page);
- pinAnno.width = pinAnno.height = PinRadius;
- pinAnno.page = page;
- pinAnno.target = targetDoc;
- pinAnno.type = AnnotationTypes.Pin;
- // this._annotations.push(pinAnno);
- let annoDoc = new Doc();
- annoDoc.annotations = new List<Doc>([pinAnno]);
- let annotations = DocListCast(this.props.parent.Document.annotations);
- if (annotations && annotations.length) {
- annotations.push(annoDoc);
- this.props.parent.Document.annotations = new List<Doc>(annotations);
- }
- else {
- this.props.parent.Document.annotations = new List<Doc>([annoDoc]);
- }
- }
+ // createPinAnnotation = (x: number, y: number, page: number): void => {
+ // let targetDoc = Docs.TextDocument({ width: 100, height: 50, title: "New Pin Annotation" });
+ // let pinAnno = new Doc();
+ // pinAnno.x = x;
+ // pinAnno.y = y + this.getScrollFromPage(page);
+ // pinAnno.width = pinAnno.height = PinRadius;
+ // pinAnno.page = page;
+ // pinAnno.target = targetDoc;
+ // pinAnno.type = AnnotationTypes.Pin;
+ // // this._annotations.push(pinAnno);
+ // let annoDoc = new Doc();
+ // annoDoc.annotations = new List<Doc>([pinAnno]);
+ // let annotations = DocListCast(this.props.parent.Document.annotations);
+ // if (annotations && annotations.length) {
+ // annotations.push(annoDoc);
+ // this.props.parent.Document.annotations = new List<Doc>(annotations);
+ // }
+ // else {
+ // this.props.parent.Document.annotations = new List<Doc>([annoDoc]);
+ // }
+ // }
// get the page index that the vertical offset passed in is on
getPageFromScroll = (vOffset: number) => {
@@ -334,26 +341,6 @@ class Viewer extends React.Component<IViewerProps> {
else {
this._savedAnnotations.setValue(page, [div]);
}
- PDFMenu.Instance.StartDrag = this.startDrag;
- }
- }
-
- startDrag = (e: PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let thisDoc = this.props.parent.Document;
- // document that this annotation is linked to
- let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" });
- targetDoc.targetPage = Math.min(...this._savedAnnotations.keys());
- let annotationDoc = this.makeAnnotationDocument(targetDoc, 1, "red");
- let dragData = new DragManager.AnnotationDragData(thisDoc, annotationDoc, targetDoc);
- if (this._annotationLayer.current) {
- DragManager.StartAnnotationDrag([this._annotationLayer.current], dragData, e.pageX, e.pageY, {
- handlers: {
- dragComplete: action(emptyFunction),
- },
- hideSource: false
- });
}
}
@@ -362,8 +349,8 @@ class Viewer extends React.Component<IViewerProps> {
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.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} document={a} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
default:
@@ -394,7 +381,7 @@ class Viewer extends React.Component<IViewerProps> {
}
export enum AnnotationTypes {
- Region, Pin
+ Region
}
interface IAnnotationProps {
@@ -406,132 +393,193 @@ interface IAnnotationProps {
document: Doc;
}
-@observer
-class PinAnnotation extends React.Component<IAnnotationProps> {
- @observable private _backgroundColor: string = "green";
- @observable private _display: string = "initial";
+// @observer
+// class PinAnnotation extends React.Component<IAnnotationProps> {
+// @observable private _backgroundColor: string = "green";
+// @observable private _display: string = "initial";
+
+// private _mainCont: React.RefObject<HTMLDivElement>;
+
+// constructor(props: IAnnotationProps) {
+// super(props);
+// this._mainCont = React.createRef();
+// }
+
+// componentDidMount = () => {
+// let selected = this.props.document.selected;
+// if (!BoolCast(selected)) {
+// runInAction(() => {
+// this._backgroundColor = "red";
+// this._display = "none";
+// });
+// }
+// if (selected) {
+// if (BoolCast(selected)) {
+// runInAction(() => {
+// this._backgroundColor = "green";
+// this._display = "initial";
+// });
+// }
+// else {
+// runInAction(() => {
+// this._backgroundColor = "red";
+// this._display = "none";
+// });
+// }
+// }
+// else {
+// runInAction(() => {
+// this._backgroundColor = "red";
+// this._display = "none";
+// });
+// }
+// }
+
+// @action
+// pointerDown = (e: React.PointerEvent) => {
+// let selected = this.props.document.selected;
+// if (selected && BoolCast(selected)) {
+// this._backgroundColor = "red";
+// this._display = "none";
+// this.props.document.selected = false;
+// }
+// else {
+// this._backgroundColor = "green";
+// this._display = "initial";
+// this.props.document.selected = true;
+// }
+// e.preventDefault();
+// e.stopPropagation();
+// }
+
+// @action
+// doubleClick = (e: React.MouseEvent) => {
+// if (this._mainCont.current) {
+// let annotations = DocListCast(this.props.parent.props.parent.Document.annotations);
+// if (annotations && annotations.length) {
+// let index = annotations.indexOf(this.props.document);
+// annotations.splice(index, 1);
+// this.props.parent.props.parent.Document.annotations = new List<Doc>(annotations);
+// }
+// // this._mainCont.current.childNodes.forEach(e => e.remove());
+// this._mainCont.current.style.display = "none";
+// // if (this._mainCont.current.parentElement) {
+// // this._mainCont.current.remove();
+// // }
+// }
+// e.stopPropagation();
+// }
+
+// render() {
+// let targetDoc = Cast(this.props.document.target, Doc);
+// if (targetDoc instanceof Doc) {
+// return (
+// <div className="pdfViewer-pinAnnotation" onPointerDown={this.pointerDown}
+// onDoubleClick={this.doubleClick} ref={this._mainCont}
+// style={{
+// top: this.props.y * scale - PinRadius / 2, left: this.props.x * scale - PinRadius / 2, width: PinRadius,
+// height: PinRadius, pointerEvents: "all", backgroundColor: this._backgroundColor
+// }}>
+// <div style={{
+// position: "absolute", top: "25px", left: "25px", transform: "scale(3)", transformOrigin: "top left",
+// display: this._display, width: targetDoc[WidthSym](), height: targetDoc[HeightSym]()
+// }}>
+// <DocumentView Document={targetDoc}
+// ContainingCollectionView={undefined}
+// ScreenToLocalTransform={this.props.parent.props.parent.props.ScreenToLocalTransform}
+// isTopMost={false}
+// ContentScaling={() => 1}
+// PanelWidth={() => NumCast(this.props.parent.props.parent.Document.nativeWidth)}
+// PanelHeight={() => NumCast(this.props.parent.props.parent.Document.nativeHeight)}
+// focus={emptyFunction}
+// selectOnLoad={false}
+// parentActive={this.props.parent.props.parent.props.active}
+// whenActiveChanged={this.props.parent.props.parent.props.whenActiveChanged}
+// bringToFront={emptyFunction}
+// addDocTab={this.props.parent.props.parent.props.addDocTab}
+// />
+// </div>
+// </div >
+// );
+// }
+// return null;
+// }
+// }
+
+class RegionAnnotation extends React.Component<IAnnotationProps> {
+ @observable private _backgroundColor: string = "red";
+ private _reactionDisposer?: IReactionDisposer;
private _mainCont: React.RefObject<HTMLDivElement>;
constructor(props: IAnnotationProps) {
super(props);
+
this._mainCont = React.createRef();
}
- componentDidMount = () => {
- let selected = this.props.document.selected;
- if (!BoolCast(selected)) {
- runInAction(() => {
- this._backgroundColor = "red";
- this._display = "none";
- });
- }
- if (selected) {
- if (BoolCast(selected)) {
- runInAction(() => {
- this._backgroundColor = "green";
- this._display = "initial";
- });
- }
- else {
- runInAction(() => {
- this._backgroundColor = "red";
- this._display = "none";
- });
- }
- }
- else {
- runInAction(() => {
- this._backgroundColor = "red";
- this._display = "none";
- });
- }
+ 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";
+ }
+ }
+ },
+ { fireImmediately: true }
+ );
}
- @action
- pointerDown = (e: React.PointerEvent) => {
- let selected = this.props.document.selected;
- if (selected && BoolCast(selected)) {
- this._backgroundColor = "red";
- this._display = "none";
- this.props.document.selected = false;
- }
- else {
- this._backgroundColor = "green";
- this._display = "initial";
- this.props.document.selected = true;
- }
- e.preventDefault();
- e.stopPropagation();
+ componentWillUnmount() {
+ this._reactionDisposer && this._reactionDisposer();
}
- @action
- doubleClick = (e: React.MouseEvent) => {
- if (this._mainCont.current) {
- let annotations = DocListCast(this.props.parent.props.parent.Document.annotations);
- if (annotations && annotations.length) {
- let index = annotations.indexOf(this.props.document);
- annotations.splice(index, 1);
- this.props.parent.props.parent.Document.annotations = new List<Doc>(annotations);
- }
- // this._mainCont.current.childNodes.forEach(e => e.remove());
- this._mainCont.current.style.display = "none";
- // if (this._mainCont.current.parentElement) {
- // this._mainCont.current.remove();
- // }
+ deleteAnnotation = () => {
+ let annotation = DocListCast(this.props.parent.props.parent.Document.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.Document.annotations = new List<Doc>(newAnnotations);
}
- e.stopPropagation();
- }
- render() {
- let targetDoc = Cast(this.props.document.target, Doc);
- if (targetDoc instanceof Doc) {
- return (
- <div className="pdfViewer-pinAnnotation" onPointerDown={this.pointerDown}
- onDoubleClick={this.doubleClick} ref={this._mainCont}
- style={{
- top: this.props.y * scale - PinRadius / 2, left: this.props.x * scale - PinRadius / 2, width: PinRadius,
- height: PinRadius, pointerEvents: "all", backgroundColor: this._backgroundColor
- }}>
- <div style={{
- position: "absolute", top: "25px", left: "25px", transform: "scale(3)", transformOrigin: "top left",
- display: this._display, width: targetDoc[WidthSym](), height: targetDoc[HeightSym]()
- }}>
- <DocumentView Document={targetDoc}
- ContainingCollectionView={undefined}
- ScreenToLocalTransform={this.props.parent.props.parent.props.ScreenToLocalTransform}
- isTopMost={false}
- ContentScaling={() => 1}
- PanelWidth={() => NumCast(this.props.parent.props.parent.Document.nativeWidth)}
- PanelHeight={() => NumCast(this.props.parent.props.parent.Document.nativeHeight)}
- focus={emptyFunction}
- selectOnLoad={false}
- parentActive={this.props.parent.props.parent.props.active}
- whenActiveChanged={this.props.parent.props.parent.props.whenActiveChanged}
- bringToFront={emptyFunction}
- addDocTab={this.props.parent.props.parent.props.addDocTab}
- />
- </div>
- </div >
- );
+ if (group) {
+ let groupAnnotations = DocListCast(group.annotations);
+ groupAnnotations.forEach(anno => anno.delete = true);
}
- return null;
+
+ PDFMenu.Instance.fadeOut(true);
}
-}
-class RegionAnnotation extends React.Component<IAnnotationProps> {
- @observable private _backgroundColor: string = "red";
- onPointerDown = (e: React.MouseEvent) => {
- let targetDoc = Cast(this.props.document.target, Doc, null);
- if (targetDoc) {
- DocumentManager.Instance.jumpToDocument(targetDoc);
+ // annotateThis = (e: PointerEvent) => {
+ // e.preventDefault();
+ // e.stopPropagation();
+ // // document that this annotation is linked to
+ // let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" });
+ // let group = FieldValue(Cast(this.props.document.group, Doc));
+ // }
+
+ @action
+ onPointerDown = (e: React.PointerEvent) => {
+ if (e.button === 0) {
+ let targetDoc = Cast(this.props.document.target, Doc, null);
+ if (targetDoc) {
+ DocumentManager.Instance.jumpToDocument(targetDoc);
+ }
+ }
+ if (e.button === 2) {
+ PDFMenu.Instance.Status = "annotation";
+ PDFMenu.Instance.Delete = this.deleteAnnotation;
+ PDFMenu.Instance.Pinned = false;
+ PDFMenu.Instance.jumpTo(e.clientX, e.clientY, true);
}
}
render() {
return (
- <div className="pdfViewer-annotationBox" onClick={this.onPointerDown}
+ <div className="pdfViewer-annotationBox" 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, pointerEvents: "all", backgroundColor: StrCast(this.props.document.color) }}></div>
);
}
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index a19b64eda..b6f362702 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -15,9 +15,11 @@ import { listSpec } from "../../../new_fields/Schema";
import { menuBar } from "prosemirror-menu";
import { AnnotationTypes, PDFViewer, scale } from "./PDFViewer";
import PDFMenu from "./PDFMenu";
+import { UndoManager } from "../../util/UndoManager";
interface IPageProps {
+ size: { width: number, height: number };
pdf: Opt<Pdfjs.PDFDocumentProxy>;
name: string;
numPages: number;
@@ -35,8 +37,8 @@ interface IPageProps {
@observer
export default class Page extends React.Component<IPageProps> {
@observable private _state: string = "N/A";
- @observable private _width: number = 0;
- @observable private _height: number = 0;
+ @observable private _width: number = this.props.size.width;
+ @observable private _height: number = this.props.size.height;
@observable private _page: Opt<Pdfjs.PDFPageProxy>;
@observable private _currPage: number = this.props.page + 1;
@observable private _marqueeX: number = 0;
@@ -51,7 +53,6 @@ export default class Page extends React.Component<IPageProps> {
private _marquee: React.RefObject<HTMLDivElement>;
private _curly: React.RefObject<HTMLImageElement>;
private _marqueeing: boolean = false;
- private _dragging: boolean = false;
private _reactionDisposer?: IReactionDisposer;
constructor(props: IPageProps) {
@@ -151,13 +152,8 @@ export default class Page extends React.Component<IPageProps> {
*/
@action
startDrag = (e: PointerEvent): void => {
- // the first 5 lines is a hack to prevent text selection while dragging
e.preventDefault();
e.stopPropagation();
- if (this._dragging) {
- return;
- }
- this._dragging = true;
let thisDoc = this.props.parent.Document;
// document that this annotation is linked to
let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" });
@@ -168,7 +164,7 @@ export default class Page extends React.Component<IPageProps> {
if (this._textLayer.current) {
DragManager.StartAnnotationDrag([this._textLayer.current], dragData, e.pageX, e.pageY, {
handlers: {
- dragComplete: action(emptyFunction),
+ dragComplete: emptyFunction,
},
hideSource: false
});
@@ -179,7 +175,6 @@ export default class Page extends React.Component<IPageProps> {
endDrag = (e: PointerEvent): void => {
// document.removeEventListener("pointermove", this.startDrag);
// document.removeEventListener("pointerup", this.endDrag);
- this._dragging = false;
e.stopPropagation();
}
@@ -195,6 +190,9 @@ export default class Page extends React.Component<IPageProps> {
// document.addEventListener("pointerup", this.endDrag);
}
else if (e.button === 0) {
+ PDFMenu.Instance.StartDrag = this.startDrag;
+ PDFMenu.Instance.Highlight = this.highlight;
+ PDFMenu.Instance.Status = "pdf";
PDFMenu.Instance.fadeOut(true);
let target: any = e.target;
if (target && target.parentElement === this._textLayer.current) {
@@ -329,68 +327,6 @@ export default class Page extends React.Component<IPageProps> {
PDFMenu.Instance.StartDrag = this.startDrag;
PDFMenu.Instance.Highlight = this.highlight;
}
- // let x = (e.clientX - boundingRect.left) * (current.offsetWidth / boundingRect.width);
- // let y = (e.clientY - boundingRect.top) * (current.offsetHeight / boundingRect.height);
- // if (this._marqueeing) {
- // this._marqueeing = false;
- // if (this._marquee.current) {
- // let copy = document.createElement("div");
- // // make a copy of the marquee
- // copy.style.left = this._marquee.current.style.left;
- // copy.style.top = this._marquee.current.style.top;
- // copy.style.width = this._marquee.current.style.width;
- // copy.style.height = this._marquee.current.style.height;
-
- // // apply the appropriate background, opacity, and transform
- // let { background, opacity, transform } = this.getCurlyTransform();
- // copy.style.background = background;
- // // if curly bracing, add a curly brace
- // if (opacity === "1" && this._curly.current) {
- // copy.style.opacity = opacity;
- // let img = this._curly.current.cloneNode();
- // (img as any).style.opacity = opacity;
- // (img as any).style.transform = transform;
- // copy.appendChild(img);
- // }
- // else {
- // copy.style.opacity = this._marquee.current.style.opacity;
- // }
- // copy.className = this._marquee.current.className;
- // this.props.createAnnotation(copy, this.props.page);
- // this._marquee.current.style.opacity = "0";
- // }
-
- // this._marqueeHeight = this._marqueeWidth = 0;
- // }
- // else {
- // let sel = window.getSelection();
- // // if selecting over a range of things
- // if (sel && sel.type === "Range") {
- // 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();
- // }
- // }
- // }
document.removeEventListener("pointermove", this.onSelectStart);
document.removeEventListener("pointerup", this.onSelectEnd);
}
@@ -403,7 +339,6 @@ export default class Page extends React.Component<IPageProps> {
for (let i = 0; i < clientRects.length; i++) {
let rect = clientRects.item(i);
if (rect && rect.width !== this._textLayer.current.getBoundingClientRect().width && rect.height !== this._textLayer.current.getBoundingClientRect().height) {
- console.log(rect);
let annoBox = document.createElement("div");
annoBox.className = "pdfViewer-annotationBox";
// transforms the positions from screen onto the pdf div