aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-05-18 14:05:39 -0400
committerbobzel <zzzman@gmail.com>2022-05-18 14:05:39 -0400
commite6b882080471d915a80400e7e9a97ff78a232147 (patch)
treeca4174517116f12c605efd815bc8344243405130
parent4fc450184f61f79bdf25ffdbb529fd371cd019d2 (diff)
fixed linking bug so that both start and end link can be regions. added zoom to target checkbox for link editing. extracted out a new field pointerEvents so that lockPosition is not automatically conflratd with no pointer events. updated freeformview focus to work with zooming on region selections.
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/views/DocumentButtonBar.tsx2
-rw-r--r--src/client/views/PropertiesView.tsx37
-rw-r--r--src/client/views/StyleProvider.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx24
-rw-r--r--src/client/views/linking/LinkEditor.scss18
-rw-r--r--src/client/views/linking/LinkEditor.tsx30
-rw-r--r--src/client/views/nodes/DocumentView.tsx4
-rw-r--r--src/client/views/nodes/ImageBox.tsx6
-rw-r--r--src/client/views/nodes/PDFBox.tsx2
-rw-r--r--src/client/views/nodes/WebBox.tsx4
-rw-r--r--src/client/views/pdf/PDFViewer.tsx29
12 files changed, 120 insertions, 44 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 797a129c4..2dd8de089 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -173,6 +173,7 @@ export class DocumentOptions {
label?: string;
hidden?: boolean;
_hidden?: boolean;
+ pointerEvents?: string; // pointer events that the documentview should have
mediaState?: string; // status of media document: "pendingRecording", "recording", "paused", "playing"
autoPlayAnchors?: boolean; // whether to play audio/video when an anchor is clicked in a stackedTimeline.
dontPlayLinkOnSelect?: boolean; // whether an audio/video should start playing when a link is followed to it.
@@ -482,7 +483,7 @@ export namespace Docs {
}],
[DocumentType.MARKER, {
layout: { view: CollectionView, dataField: defaultDataKey },
- options: { links: "@links(self)", hideLinkButton: true }
+ options: { links: "@links(self)", hideLinkButton: true, pointerEvents: "none" }
}],
[DocumentType.INK, { // NOTE: this is unused!! ink fields are filled in directly within the InkDocument() method
layout: { view: InkingStroke, dataField: defaultDataKey },
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 9b95f1525..ffa168f6b 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -192,7 +192,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
<div className="dash-tooltip">{"Set onClick to follow primary link"}</div>}>
<div className="documentButtonBar-icon"
style={{ backgroundColor: targetDoc.isLinkButton ? Colors.LIGHT_BLUE : Colors.DARK_GRAY, color: targetDoc.isLinkButton ? Colors.BLACK : Colors.WHITE }}
- onClick={undoBatch(e => this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, false, false)))}>
+ onClick={undoBatch(e => this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, undefined, false)))}>
<FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="hand-point-right" />
</div>
</Tooltip>;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index bba2ac211..bcfd2dd56 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1227,6 +1227,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.selectedDoc.displayArrow = !this.selectedDoc.displayArrow)));
}
+ toggleZoomToTarget1 = (e: React.PointerEvent) => {
+ setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => Cast(this.selectedDoc.anchor1, Doc, null).followLinkZoom = !Cast(this.selectedDoc.anchor1, Doc, null).followLinkZoom)));
+ }
+ toggleZoomToTarget2 = (e: React.PointerEvent) => {
+ setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => Cast(this.selectedDoc.anchor2, Doc, null).followLinkZoom = !Cast(this.selectedDoc.anchor2, Doc, null).followLinkZoom)));
+ }
+
@computed
get editRelationship() {
return <input
@@ -1283,18 +1290,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
</div>
<div className="propertiesView-section">
<p className="propertiesView-label">Information</p>
- <div className="propertiesView-input first" id="propertiesView-category">
+ <div className="propertiesView-input first">
<p>Link Relationship</p>
{this.editRelationship}
</div>
- <div className="propertiesView-input" id="propertiesView-description">
+ <div className="propertiesView-input">
<p>Description</p>
{this.editDescription}
</div>
</div>
<div className="propertiesView-section">
<p className="propertiesView-label">Behavior</p>
- <div className="propertiesView-input inline first" id="propertiesView-follow">
+ <div className="propertiesView-input inline first">
<p>Follow</p>
<select
name="selectList"
@@ -1314,7 +1321,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
: null}
</select>
</div>
- <div className="propertiesView-input inline" id="propertiesView-anchor">
+ <div className="propertiesView-input inline">
<p>Auto-move anchor</p>
<button
style={{ background: this.selectedDoc.hidden ? "gray" : !this.selectedDoc.linkAutoMove ? "" : "#4476f7", borderRadius: 3 }}
@@ -1324,7 +1331,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
</button>
</div>
- <div className="propertiesView-input inline" id="propertiesView-displayArrow">
+ <div className="propertiesView-input inline">
<p>Display arrow</p>
<button
style={{ background: this.selectedDoc.hidden ? "gray" : !this.selectedDoc.displayArrow ? "" : "#4476f7", borderRadius: 3 }}
@@ -1334,6 +1341,26 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" />
</button>
</div>
+ <div className="propertiesView-input inline">
+ <p>Zoom to target</p>
+ <button
+ style={{ background: this.selectedDoc.hidden ? "gray" : !Cast(this.selectedDoc.anchor1, Doc, null).followLinkZoom ? "" : "#4476f7", borderRadius: 3 }}
+ onPointerDown={this.toggleZoomToTarget1} onClick={e => e.stopPropagation()}
+ className="propertiesButton"
+ >
+ <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" />
+ </button>
+ </div>
+ <div className="propertiesView-input inline">
+ <p>Zoom to source</p>
+ <button
+ style={{ background: this.selectedDoc.hidden ? "gray" : !Cast(this.selectedDoc.anchor2, Doc, null).followLinkZoom ? "" : "#4476f7", borderRadius: 3 }}
+ onPointerDown={this.toggleZoomToTarget2} onClick={e => e.stopPropagation()}
+ className="propertiesButton"
+ >
+ <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" />
+ </button>
+ </div>
</div>
</div >;
}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 334415b38..93da2fa19 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -55,6 +55,7 @@ function darkScheme() { return CurrentUserUtils.ActiveDashboard?.colorScheme ===
function toggleLockedPosition(doc: Doc) {
UndoManager.RunInBatch(() => runInAction(() => {
doc._lockedPosition = !doc._lockedPosition;
+ doc._pointerEvents = doc._lockedPosition ? "none" : undefined;
}), "toggleBackground");
}
@@ -194,10 +195,10 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
}
}
case StyleProp.PointerEvents:
- if (doc?.type === DocumentType.MARKER) return "none";
+ if (doc?.pointerEvents) return StrCast(doc.pointerEvents);
if (props?.pointerEvents?.() === "none") return "none";
const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name);
- if (doc?._lockedPosition || opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
+ if (opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
if (!isInk) return "all";
return undefined;
case StyleProp.Decorations:
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b37754b73..916cc9c05 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1081,7 +1081,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const xfToCollection = options?.docTransform ?? Transform.Identity();
const savedState = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY), scale: this.Document[this.scaleFieldKey] };
const newState = HistoryUtil.getState();
- const cantTransform = this.props.isAnnotationOverlay || ((this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc);
+ const cantTransform = /*this.props.isAnnotationOverlay ||*/ ((this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc);
const { panX, panY, scale } = cantTransform ? savedState : this.calculatePanIntoView(doc, xfToCollection, options?.willZoom ? options?.scale || .75 : undefined);
if (!cantTransform) { // only pan and zoom to focus on a document if the document is not an annotation in an annotation overlay collection
newState.initializers![this.Document[Id]] = { panX: panX, panY: panY };
@@ -1092,8 +1092,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const focusSpeed = options?.instant ? 0 : didMove ? (doc.focusSpeed !== undefined ? Number(doc.focusSpeed) : 500) : 0;
// glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
if (didMove) {
- this.setPan(panX, panY, focusSpeed, true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
scale && (this.Document[this.scaleFieldKey] = scale);
+ this.setPan(panX, panY, focusSpeed, true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
}
const startTime = Date.now();
@@ -1130,23 +1130,24 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
calculatePanIntoView = (doc: Doc, xf: Transform, scale?: number) => {
const layoutdoc = Doc.Layout(doc);
- const pw = this.props.PanelWidth() / NumCast(this.layoutDoc._viewScale, 1);
- const ph = this.props.PanelHeight() / NumCast(this.layoutDoc._viewScale, 1);
const pt = xf.transformPoint(NumCast(doc.x), NumCast(doc.y));
const pt2 = xf.transformPoint(NumCast(doc.x) + layoutdoc[WidthSym](), NumCast(doc.y) + layoutdoc[HeightSym]());
- const bounds = { left: pt[0], right: pt2[0], top: pt[1], bot: pt2[1] };
- const cx = NumCast(this.layoutDoc._panX);
- const cy = NumCast(this.layoutDoc._panY);
- const screen = { left: cx - pw / 2, right: cx + pw / 2, top: cy - ph / 2, bot: cy + ph / 2 };
+ const bounds = { left: pt[0], right: pt2[0], top: pt[1], bot: pt2[1], width: pt2[0] - pt[0], height: pt2[1] - pt[1] };
if (scale) {
const maxZoom = 5; // sets the limit for how far we will zoom. this is useful for preventing small text boxes from filling the screen. So probably needs to be more sophisticated to consider more about the target and context
+ const newScale = Math.min(maxZoom, 1 / (this.contentScaling || 1) * scale * Math.min(this.props.PanelWidth() / Math.abs(bounds.width), this.props.PanelHeight() / Math.abs(bounds.height)));
return {
- panX: (bounds.left + bounds.right) / 2,
- panY: (bounds.top + bounds.bot) / 2,
- scale: Math.min(maxZoom, scale * Math.min(this.props.PanelWidth() / Math.abs(pt2[0] - pt[0]), this.props.PanelHeight() / Math.abs(pt2[1] - pt[1])))
+ panX: this.props.isAnnotationOverlay ? bounds.left - (Doc.NativeWidth(this.layoutDoc) / newScale - bounds.width) / 2 : (bounds.left + bounds.right) / 2,
+ panY: this.props.isAnnotationOverlay ? bounds.top - (Doc.NativeHeight(this.layoutDoc) / newScale - bounds.height) / 2 : (bounds.top + bounds.bot) / 2,
+ scale: newScale
};
}
+ const pw = this.props.PanelWidth() / NumCast(this.layoutDoc._viewScale, 1);
+ const ph = this.props.PanelHeight() / NumCast(this.layoutDoc._viewScale, 1);
+ const cx = NumCast(this.layoutDoc._panX);
+ const cy = NumCast(this.layoutDoc._panY);
+ const screen = { left: cx - pw / 2, right: cx + pw / 2, top: cy - ph / 2, bot: cy + ph / 2 };
if ((screen.right - screen.left) < (bounds.right - bounds.left) ||
(screen.bot - screen.top) < (bounds.bot - bounds.top)) {
return {
@@ -1990,6 +1991,7 @@ class CollectionFreeFormBackgroundGrid extends React.Component<CollectionFreeFor
}
export function CollectionBrowseClick(dv: DocumentView, clientX: number, clientY: number) {
+ SelectionManager.DeselectAll();
dv.props.focus(dv.props.Document, {
willZoom: true, afterFocus: async (didMove) => {
if (!didMove) {
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
index abd413f57..1d6496d3c 100644
--- a/src/client/views/linking/LinkEditor.scss
+++ b/src/client/views/linking/LinkEditor.scss
@@ -60,6 +60,24 @@
}
}
+.linkEditor-zoomFollow {
+ padding-left: 26px;
+ padding-right: 6.5px;
+ padding-bottom: 3.5px;
+ display: flex;
+
+ .linkEditor-zoomFollow-label {
+ text-decoration-color: black;
+ color: black;
+ line-height: 1.7;
+ }
+
+ .linkEditor-zoomFollow-input {
+ display: block;
+ width: 20px;
+ }
+}
+
.linkEditor-description {
padding-left: 26px;
padding-right: 6.5px;
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index db331bb75..c3e0aff11 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -9,7 +9,6 @@ import { undoBatch } from "../../util/UndoManager";
import './LinkEditor.scss';
import { LinkRelationshipSearch } from "./LinkRelationshipSearch";
import React = require("react");
-import { ToString } from "../../../fields/FieldSymbols";
interface LinkEditorProps {
@@ -23,6 +22,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
@observable description = Field.toString(LinkManager.currentLink?.description as any as Field);
@observable relationship = StrCast(LinkManager.currentLink?.linkRelationship);
+ @observable zoomFollow1 = StrCast(this.props.sourceDoc.followLinkZoom);
@observable openDropdown: boolean = false;
@observable showInfo: boolean = false;
@computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; }
@@ -143,9 +143,9 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
@action
handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.description = e.target.value; }
@action
- handleRelationshipChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- this.relationship = e.target.value;
- }
+ handleRelationshipChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.relationship = e.target.value; }
+ @action
+ handleZoomFollowChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.props.sourceDoc.followLinkZoom = e.target.checked; }
@action
handleRelationshipSearchChange = (result: string) => {
this.setRelationshipValue(result);
@@ -183,6 +183,27 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
</div>
</div>;
}
+ @computed
+ get editZoomFollow() {
+ //NOTE: confusingly, the classnames for the following relationship JSX elements are the same as the for the description elements for shared CSS
+ return <div className="linkEditor-zoomFollow">
+ <div className="linkEditor-zoomFollow-label">Zoom To Link Target:</div>
+ <div className="linkEditor-zoomFollow-input">
+ <div className="linkEditor-zoomFollow-editing">
+ <input
+ style={{ width: "100%" }}
+ type="checkbox"
+ value={this.zoomFollow1}
+ autoComplete={"off"}
+ placeholder={""}
+ onChange={this.handleZoomFollowChange}
+ onFocus={this.onFocus}
+ onBlur={this.onBlur}
+ ></input>
+ </div>
+ </div>
+ </div>;
+ }
@computed
get editDescription() {
@@ -303,6 +324,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
{this.editDescription}
{this.editRelationship}
+ {this.editZoomFollow}
{this.followingDropdown}
</div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b6a2fae1a..49c2761b2 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -605,7 +605,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
@undoBatch @action
- toggleFollowLink = (location: Opt<string>, zoom: boolean, setPushpin: boolean): void => {
+ toggleFollowLink = (location: Opt<string>, zoom?: boolean, setPushpin?: boolean): void => {
this.Document.ignoreClick = false;
if (setPushpin) {
this.Document.isPushpin = !this.Document.isPushpin;
@@ -614,7 +614,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
this.Document._isLinkButton = !this.Document._isLinkButton;
}
if (this.Document._isLinkButton && !this.onClickHandler) {
- this.Document.followLinkZoom = zoom;
+ zoom !== undefined && (this.Document.followLinkZoom = zoom);
this.Document.followLinkLocation = location;
} else if (this.Document._isLinkButton && this.onClickHandler) {
this.Document._isLinkButton = false;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 3b04aa807..dd0acb311 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,7 +1,7 @@
import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from "mobx-react";
import { extname } from 'path';
-import { DataSym, Doc, DocListCast, WidthSym } from '../../../fields/Doc';
+import { DataSym, Doc, DocListCast, Opt, WidthSym } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
@@ -49,6 +49,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ImageBox, fieldKey); }
private _dropDisposer?: DragManager.DragDropDisposer;
private _disposers: { [name: string]: IReactionDisposer } = {};
+ private _getAnchor: (savedAnnotations?: ObservableMap<number, HTMLDivElement[]>) => Opt<Doc> = () => undefined;
@observable _curSuffix = "";
@observable _uploadIcon = uploadIcons.idle;
@@ -62,7 +63,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
getAnchor = () => {
- const anchor = AnchorMenu.Instance?.GetAnchor(this._savedAnnotations);
+ const anchor = this._getAnchor?.(this._savedAnnotations);
anchor && this.addDocument(anchor);
return anchor ?? this.rootDoc;
}
@@ -366,6 +367,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}
@action
finishMarquee = () => {
+ this._getAnchor = AnchorMenu.Instance?.GetAnchor;
this._marqueeing = undefined;
this.props.select(false);
}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 35b5e78a8..cbe7a5cc6 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -198,7 +198,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
getAnchor = () => {
const anchor =
- AnchorMenu.Instance?.GetAnchor() ??
+ this._pdfViewer?._getAnchor(this._pdfViewer.savedAnnotations()) ??
Docs.Create.TextanchorDocument({
title: StrCast(this.rootDoc.title + "@" + NumCast(this.layoutDoc._scrollTop)?.toFixed(0)),
y: NumCast(this.layoutDoc._scrollTop),
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 445df8ddd..2112c1d44 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -52,6 +52,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _keyInput = React.createRef<HTMLInputElement>();
private _initialScroll: Opt<number> = NumCast(this.layoutDoc.thumbScrollTop, NumCast(this.layoutDoc.scrollTop));
+ private _getAnchor: (savedAnnotations?: ObservableMap<number, HTMLDivElement[]>) => Opt<Doc> = () => undefined;
private _sidebarRef = React.createRef<SidebarAnnos>();
private _searchRef = React.createRef<HTMLInputElement>();
private _searchString = "";
@@ -256,7 +257,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
getAnchor = () => {
const anchor =
- AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ??
+ this._getAnchor(this._savedAnnotations) ??
Docs.Create.WebanchorDocument(this._url, {
title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
y: NumCast(this.layoutDoc._scrollTop),
@@ -555,6 +556,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
}
@action finishMarquee = (x?: number, y?: number, e?: PointerEvent) => {
+ this._getAnchor = AnchorMenu.Instance?.GetAnchor;
this._marqueeing = undefined;
this._isAnnotating = false;
this._iframeClick = undefined;
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index b0a5fc93b..305b1fe68 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -6,7 +6,6 @@ import { Doc, DocListCast, Field, HeightSym, Opt } from "../../../fields/Doc";
import { Id } from "../../../fields/FieldSymbols";
import { InkTool } from "../../../fields/InkField";
import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { PdfField } from "../../../fields/URLField";
import { TraceMobx } from "../../../fields/util";
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, returnFalse, smoothScroll, Utils } from "../../../Utils";
import { DocUtils } from "../../documents/Documents";
@@ -59,7 +58,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
@observable private _marqueeing: number[] | undefined;
@observable private _textSelecting = true;
@observable private _showWaiting = true;
- @observable private _zoomed = 1;
@observable private _overlayAnnoInfo: Opt<Doc>;
@observable private Index: number = -1;
@@ -70,6 +68,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _disposers: { [name: string]: IReactionDisposer } = {};
private _viewer: React.RefObject<HTMLDivElement> = React.createRef();
+ public _getAnchor: (savedAnnotations?: ObservableMap<number, HTMLDivElement[]>) => Opt<Doc> = () => undefined;
_mainCont: React.RefObject<HTMLDivElement> = React.createRef();
private _selectionText: string = "";
private _downX: number = 0;
@@ -184,7 +183,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
pagesinit = () => {
if (this._pdfViewer._setDocumentViewerElement?.offsetParent) {
- runInAction(() => this._pdfViewer.currentScaleValue = this._zoomed = 1);
+ runInAction(() => this._pdfViewer.currentScaleValue = this.props.layoutDoc._viewScale = 1);
this.gotoPage(NumCast(this.props.Document._curPage, 1));
}
document.removeEventListener("pagesinit", this.pagesinit);
@@ -355,6 +354,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
@action
finishMarquee = (x?: number, y?: number) => {
+ this._getAnchor = AnchorMenu.Instance?.GetAnchor;
this.isAnnotating = false;
this._marqueeing = undefined;
this._textSelecting = true;
@@ -387,13 +387,14 @@ export class PDFViewer extends React.Component<IViewerProps> {
const rect = clientRects.item(i);
if (rect && rect.width !== this._mainCont.current.clientWidth && rect.width) {
const scaleX = this._mainCont.current.offsetWidth / boundingRect.width;
+ const pdfScale = NumCast(this.props.layoutDoc._viewScale, 1);
const annoBox = document.createElement("div");
annoBox.className = "marqueeAnnotator-annotationBox";
// transforms the positions from screen onto the pdf div
- annoBox.style.top = ((rect.top - boundingRect.top) * scaleX / this._zoomed + this._mainCont.current.scrollTop).toString();
- annoBox.style.left = ((rect.left - boundingRect.left) * scaleX / this._zoomed).toString();
- annoBox.style.width = (rect.width * this._mainCont.current.offsetWidth / boundingRect.width / this._zoomed).toString();
- annoBox.style.height = (rect.height * this._mainCont.current.offsetHeight / boundingRect.height / this._zoomed).toString();
+ annoBox.style.top = ((rect.top - boundingRect.top) * scaleX / pdfScale + this._mainCont.current.scrollTop).toString();
+ annoBox.style.left = ((rect.left - boundingRect.left) * scaleX / pdfScale).toString();
+ annoBox.style.width = (rect.width * this._mainCont.current.offsetWidth / boundingRect.width / pdfScale).toString();
+ annoBox.style.height = (rect.height * this._mainCont.current.offsetHeight / boundingRect.height / pdfScale).toString();
this._annotationLayer.current && MarqueeAnnotator.previewNewAnnotation(this._savedAnnotations, this._annotationLayer.current, annoBox, this.getPageFromScroll(rect.top));
}
}
@@ -430,14 +431,14 @@ export class PDFViewer extends React.Component<IViewerProps> {
if (e.ctrlKey) {
const curScale = Number(this._pdfViewer.currentScaleValue);
this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - curScale * e.deltaY / 1000));
- this._zoomed = Number(this._pdfViewer.currentScaleValue);
+ this.props.layoutDoc._viewScale = Number(this._pdfViewer.currentScaleValue);
}
}
}
pointerEvents = () => this.props.isContentActive() && this.props.pointerEvents?.() !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" : SnappingManager.GetIsDragging() ? undefined : "none";
@computed get annotationLayer() {
- return <div className="pdfViewerDash-annotationLayer" style={{ height: Doc.NativeHeight(this.props.Document), transform: `scale(${this._zoomed})` }} ref={this._annotationLayer}>
+ return <div className="pdfViewerDash-annotationLayer" style={{ height: Doc.NativeHeight(this.props.Document), transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})` }} ref={this._annotationLayer}>
{this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno =>
<Annotation {...this.props} fieldKey={this.props.fieldKey + "-annotations"} pointerEvents={this.pointerEvents} showInfo={this.showInfo} dataDoc={this.props.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} />)}
</div>;
@@ -453,7 +454,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
showInfo = action((anno: Opt<Doc>) => this._overlayAnnoInfo = anno);
- overlayTransform = () => this.scrollXf().scale(1 / this._zoomed);
+ overlayTransform = () => this.scrollXf().scale(1 / NumCast(this.props.layoutDoc._viewScale, 1));
panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter("textInlineAnnotations")];
@@ -498,7 +499,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
style={{
pointerEvents: SnappingManager.GetIsDragging() ? "all" : "none",
mixBlendMode: "multiply",
- transform: `scale(${this._zoomed})`
+ transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})`
}}>
{this.overlayTransparentAnnotations}
</div>
@@ -506,7 +507,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
style={{
pointerEvents: SnappingManager.GetIsDragging() ? "all" : "none",
mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined,
- transform: `scale(${this._zoomed})`
+ transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})`
}}>
{this.overlayOpaqueAnnotations}
{this.overlayClickableAnnotations}
@@ -517,7 +518,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
return <div className={"pdfViewerDash-text" + (this.props.pointerEvents?.() !== "none" && this._textSelecting && this.props.isContentActive() ? "-selected" : "")} ref={this._viewer} />;
}
@computed get contentScaling() { return this.props.ContentScaling?.() || 1; }
- contentZoom = () => this._zoomed;
+ contentZoom = () => NumCast(this.props.layoutDoc._viewScale, 1);
savedAnnotations = () => this._savedAnnotations;
render() {
TraceMobx();
@@ -525,7 +526,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
<div className={`pdfViewerDash${this.props.isContentActive() && this.props.pointerEvents?.() !== "none" ? "-interactive" : ""}`} ref={this._mainCont}
onScroll={this.onScroll} onWheel={this.onZoomWheel} onPointerDown={this.onPointerDown} onClick={this.onClick}
style={{
- overflowX: this._zoomed !== 1 ? "scroll" : undefined,
+ overflowX: NumCast(this.props.layoutDoc._viewScale, 1) !== 1 ? "scroll" : undefined,
height: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeHeight(this.props.Document) : `${100 / this.contentScaling}%`,
transform: `scale(${this.contentScaling})`
}} >