aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-05-03 22:08:56 -0400
committerbobzel <zzzman@gmail.com>2024-05-03 22:08:56 -0400
commit139600ab7e8a82a31744cd3798247236cd5616fc (patch)
tree6bbc5c6fb6825ef969ed0342e4851667b81577cc /src
parent93ab35c251b399f3e44ab2fa016e2af13df5a53b (diff)
fixed pdf rendering. fixed cropping images. fixed zooming out of an image that is fitWidth to set scroll bar properly.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx87
-rw-r--r--src/client/views/nodes/ImageBox.tsx14
-rw-r--r--src/client/views/nodes/PDFBox.tsx8
-rw-r--r--src/client/views/nodes/WebBox.tsx1
-rw-r--r--src/client/views/pdf/PDFViewer.tsx2
5 files changed, 42 insertions, 70 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a36c36261..21a069bd8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -22,7 +22,7 @@ import { ImageField } from '../../../../fields/URLField';
import { TraceMobx } from '../../../../fields/util';
import { Gestures, PointData } from '../../../../pen-gestures/GestureTypes';
import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, emptyFunction, intersectRect, Utils } from '../../../../Utils';
+import { aggregateBounds, clamp, emptyFunction, intersectRect, Utils } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { DocUtils } from '../../../documents/DocUtils';
@@ -377,7 +377,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (didMove) {
const focusTime = options?.instant ? 0 : options.zoomTime ?? 500;
(options.zoomScale ?? options.willZoomCentered) && scale && (this.Document[this.scaleFieldKey] = scale);
- this.setPan(panX, panY, focusTime, 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
+ this.setPan(panX, panY, focusTime); // 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
return focusTime;
}
return undefined;
@@ -399,8 +399,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const refDoc = docDragData.droppedDocuments[0];
const fromScreenXf = NumCast(refDoc.z) ? this.ScreenToLocalBoxXf() : this.screenToFreeformContentsXf;
const [xpo, ypo] = fromScreenXf.transformPoint(de.x, de.y);
- const x = xpo - docDragData.offset[0];
- const y = ypo - docDragData.offset[1];
+ const [x, y] = [xpo - docDragData.offset[0], ypo - docDragData.offset[1]];
const zsorted = this.childLayoutPairs
.map(pair => pair.layout)
.slice()
@@ -411,8 +410,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000));
const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)];
- for (let i = 0; i < docDragData.droppedDocuments.length; i++) {
- const d = docDragData.droppedDocuments[i];
+ docDragData.droppedDocuments.forEach((d, i) => {
const layoutDoc = Doc.Layout(d);
const delta = Utils.rotPt(x - dropPos[0], y - dropPos[1], fromScreenXf.Rotate);
if (this.Document._currentFrame !== undefined) {
@@ -431,7 +429,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
layoutDoc._width = NumCast(layoutDoc._width, 300);
layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? (nd[1] / nd[0]) * NumCast(layoutDoc._width) : 300);
!d._keepZWhenDragged && (d.zIndex = zsorted.length + 1 + i); // bringToFront
- }
+ });
(docDragData.droppedDocuments.length === 1 || de.shiftKey) && this._clusters.addDocuments(docDragData.droppedDocuments);
return true;
@@ -457,11 +455,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData) {
if (this.DocumentView?.() && linkDragData.linkDragView.containerViewPath?.().includes(this.DocumentView())) {
const [x, y] = this.screenToFreeformContentsXf.transformPoint(de.x, de.y);
- let added = false;
// do nothing if link is dropped into any freeform view parent of dragged document
const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, x, y, title: 'dropped annotation' });
- added = !!this._props.addDocument?.(source);
- de.complete.linkDocument = DocUtils.MakeLink(linkDragData.linkSourceGetAnchor(), source, { link_relationship: 'annotated by:annotation of' }); // TODODO this is where in text links get passed
+ const added = !!this._props.addDocument?.(source);
+ de.complete.linkDocument = DocUtils.MakeLink(linkDragData.linkSourceGetAnchor(), source, { link_relationship: 'annotated by:annotation of' });
if (de.complete.linkDocument) {
de.complete.linkDocument.layout_isSvg = true;
this.addDocument(de.complete.linkDocument);
@@ -572,18 +569,17 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
scrollPan = (e: WheelEvent | { deltaX: number; deltaY: number }): void => {
SnappingManager.TriggerUserPanned();
- this.setPan(NumCast(this.Document[this.panXFieldKey]) - e.deltaX, NumCast(this.Document[this.panYFieldKey]) - e.deltaY, 0, true);
+ this.setPan(NumCast(this.Document[this.panXFieldKey]) - e.deltaX, NumCast(this.Document[this.panYFieldKey]) - e.deltaY, 0);
};
@action
pan = (e: PointerEvent): void => {
- const ctrlKey = e.ctrlKey && !e.shiftKey;
- const shiftKey = e.shiftKey && !e.ctrlKey;
+ const [ctrlKey, shiftKey] = [e.ctrlKey && !e.shiftKey, e.shiftKey && !e.ctrlKey];
SnappingManager.TriggerUserPanned();
this.DocumentView?.().clearViewTransition();
const [dxi, dyi] = this.screenToFreeformContentsXf.transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
const { x: dx, y: dy } = Utils.rotPt(dxi, dyi, this.ScreenToLocalBoxXf().Rotate);
- this.setPan(NumCast(this.Document[this.panXFieldKey]) - (ctrlKey ? 0 : dx), NumCast(this.Document[this.panYFieldKey]) - (shiftKey ? 0 : dy), 0, true);
+ this.setPan(NumCast(this.Document[this.panXFieldKey]) - (ctrlKey ? 0 : dx), NumCast(this.Document[this.panYFieldKey]) - (shiftKey ? 0 : dy), 0);
this._lastX = e.clientX;
this._lastY = e.clientY;
};
@@ -795,18 +791,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.setPan(0, 0);
return;
}
- if (deltaScale * invTransform.Scale > NumCast(this.Document[this.scaleFieldKey + '_max'], Number.MAX_VALUE)) {
- deltaScale = NumCast(this.Document[this.scaleFieldKey + '_max'], 1) / invTransform.Scale;
- }
- if (deltaScale * invTransform.Scale < NumCast(this.Document[this.scaleFieldKey + '_min'], this.isAnnotationOverlay ? 1 : 0)) {
- deltaScale = NumCast(this.Document[this.scaleFieldKey + '_min'], 1) / invTransform.Scale;
- }
-
+ const minScale = NumCast(this.Document[this.scaleFieldKey + '_min'], this.isAnnotationOverlay ? 1 : 0);
+ const maxScale = NumCast(this.Document[this.scaleFieldKey + '_max'], Number.MAX_VALUE);
+ deltaScale = clamp(deltaScale, minScale / invTransform.Scale, maxScale / invTransform.Scale);
const localTransform = invTransform.scaleAbout(deltaScale, x, y);
if (localTransform.Scale >= 0.05 || localTransform.Scale > this.zoomScaling()) {
const safeScale = Math.min(Math.max(0.05, localTransform.Scale), 20);
+ const allowScroll = this.Document[this.scaleFieldKey] !== minScale && Math.abs(safeScale) === minScale;
this.Document[this.scaleFieldKey] = Math.abs(safeScale);
- this.setPan(-localTransform.TranslateX / safeScale, (this._props.originTopLeft ? undefined : NumCast(this.Document.layout_scrollTop) * safeScale) || -localTransform.TranslateY / safeScale);
+ this.setPan(-localTransform.TranslateX / safeScale, (this._props.originTopLeft ? undefined : NumCast(this.Document.layout_scrollTop) * safeScale) || -localTransform.TranslateY / safeScale, undefined, allowScroll);
}
};
@@ -843,35 +836,18 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
- setPan(panXIn: number, panYIn: number, panTime: number = 0, clamp: boolean = false) {
- let panX = panXIn;
- let panY = panYIn;
+ setPan(panXIn: number, panYIn: number, panTime: number = 0, allowScroll = false) {
+ let [panX, panY] = [panXIn, panYIn];
// this is the easiest way to do this -> will talk with Bob about using mobx to do this to remove this line of code.
if (Doc.UserDoc()?.presentationMode === 'watching') ReplayMovements.Instance.pauseFromInteraction();
- if (!this.isAnnotationOverlay && clamp) {
+ if (!this.isAnnotationOverlay && this.childDocs.length) {
// this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds
- const docs = this.childLayoutPairs.map(pair => pair.layout).filter(doc => doc instanceof Doc && doc.type !== DocumentType.LINK);
- const measuredDocs = docs.map(doc => ({ x: NumCast(doc.x), y: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) }));
- if (measuredDocs.length) {
- const { originTopLeft } = this._props;
- // const xrangeMin = Math.min(...measuredDocs.map(doc => doc.x), originTopLeft ? 0 : Number.MAX_VALUE);
- // const yrangeMin = Math.min(...measuredDocs.map(doc => doc.y), originTopLeft ? 0 : Number.MAX_VALUE);
- // const xrangeMax = Math.max(...measuredDocs.map(doc => doc.x + doc.width));
- // const yrangeMax = Math.max(...measuredDocs.map(doc => doc.y + doc.height));
- const { bounds: { x: xrangeMin, y: yrangeMin, r: xrangeMax, b: yrangeMax } } = this.contentBounds(); // prettier-ignore
- const nativeScaling = this._props.NativeDimScaling?.() || 1;
- const scaling = this.zoomScaling() * nativeScaling;
- const [widScaling, hgtScaling] = [this._props.PanelWidth() / scaling, this._props.PanelHeight() / scaling];
- const panelWidMax = widScaling * (originTopLeft ? 2 / nativeScaling : 1);
- const panelHgtMax = hgtScaling * (originTopLeft ? 2 / nativeScaling : 1);
- const panelWidMin = widScaling * (originTopLeft ? 0 : 1);
- const panelHgtMin = hgtScaling * (originTopLeft ? 0 : 1);
- if (xrangeMin >= panX + panelWidMax / 2) panX = xrangeMax + (originTopLeft ? 0 : panelWidMax / 2);
- else if (xrangeMax <= panX - panelWidMin / 2) panX = xrangeMin - (originTopLeft ? panelWidMax / 2 : panelWidMin / 2); // prettier-ignore
- if (yrangeMin >= panY + panelHgtMax / 2) panY = yrangeMax + (originTopLeft ? 0 : panelHgtMax / 2);
- else if (yrangeMax <= panY - panelHgtMin / 2) panY = yrangeMin - (originTopLeft ? panelHgtMax / 2 : panelHgtMin / 2); // prettier-ignore
- }
+ const { bounds: { x: xrangeMin, y: yrangeMin, r: xrangeMax, b: yrangeMax } } = this.contentBounds(); // prettier-ignore
+ const scaling = this.zoomScaling() * (this._props.NativeDimScaling?.() || 1);
+ const [widScaling, hgtScaling] = [this._props.PanelWidth() / scaling, this._props.PanelHeight() / scaling];
+ panX = clamp(panX, xrangeMin - widScaling / 2, xrangeMax + widScaling / 2);
+ panY = clamp(panY, yrangeMin - hgtScaling / 2, yrangeMax + hgtScaling / 2);
}
if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc) {
this.setPanZoomTransition(panTime);
@@ -880,22 +856,22 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const minPanX = NumCast(this.dataDoc._freeform_panX_min, 0);
const minPanY = NumCast(this.dataDoc._freeform_panY_min, 0);
const maxPanX = NumCast(this.dataDoc._freeform_panX_max, this.nativeWidth);
- const newPanX = Math.min(minPanX + scale * maxPanX, Math.max(minPanX, panX));
+ const newPanX = clamp(panX, minPanX, minPanX + scale * maxPanX);
const fitYscroll = (((this.nativeHeight / this.nativeWidth) * this._props.PanelWidth() - this._props.PanelHeight()) * this.ScreenToLocalBoxXf().Scale) / minScale;
const nativeHeight = (this._props.PanelHeight() / this._props.PanelWidth() / (this.nativeHeight / this.nativeWidth)) * this.nativeHeight;
const maxScrollTop = this.nativeHeight / this.ScreenToLocalBoxXf().Scale - this._props.PanelHeight();
const maxPanY =
minPanY + // minPanY + scrolling introduced by view scaling + scrolling introduced by layout_fitWidth
- scale * NumCast(this.dataDoc._panY_max, nativeHeight) +
+ scale * NumCast(this.dataDoc._freeform_panY_max, nativeHeight) +
(!this._props.getScrollHeight?.() ? fitYscroll : 0); // when not zoomed, scrolling is handled via a scrollbar, not panning
- let newPanY = Math.max(minPanY, Math.min(maxPanY, panY));
- if (fitYscroll > 2 && this.layoutDoc.layout_scrollTop === undefined && NumCast(this.layoutDoc._freeform_scale, minScale) === minScale) {
- const maxPanScrollY = minPanY + fitYscroll;
- const relTop = (panY - minPanY) / (maxPanScrollY - minPanY);
+ const newPanY = clamp(panY, minPanY, maxPanY);
+ // this mess fixes a problem when zooming to the default on an image that is fit width and can scroll.
+ // Without this, the scroll always goes to the top, instead of matching the pan position.
+ if (fitYscroll > 2 && allowScroll && NumCast(this.layoutDoc._freeform_scale, minScale) === minScale) {
setTimeout(() => {
+ const relTop = (clamp(panY, minPanY, fitYscroll) - minPanY) / fitYscroll;
this.layoutDoc.layout_scrollTop = relTop * maxScrollTop;
}, 10);
- newPanY = minPanY;
}
!this.Document._verticalScroll && (this.Document[this.panXFieldKey] = this.isAnnotationOverlay ? newPanX : panX);
!this.Document._horizontalScroll && (this.Document[this.panYFieldKey] = this.isAnnotationOverlay ? newPanY : panY);
@@ -909,8 +885,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.setPan(
NumCast(this.layoutDoc[this.panXFieldKey]) + ((this._props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale
NumCast(this.layoutDoc[this.panYFieldKey]) + ((this._props.PanelHeight() / 2) * -y) / this.zoomScaling(),
- nudgeTime,
- true
+ nudgeTime
);
return true;
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index d4f8b5550..3d10408d6 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -60,7 +60,7 @@ export class ImageEditorData {
public static set AddDoc(addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean>) { ImageEditorData.set(this.imageData.open, this.imageData.rootDoc, this.imageData.source, addDoc); } // prettier-ignore
}
@observer
-export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
+export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(ImageBox, fieldKey);
}
@@ -191,12 +191,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']);
this.dataDoc[this.fieldKey + '_nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']) * nw;
this.dataDoc[this.fieldKey + '_nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']) * nw;
- this.layoutDoc._freeform_panX = nw * NumCast(this.layoutDoc._freeform_panX);
- this.layoutDoc._freeform_panY = nw * NumCast(this.layoutDoc._freeform_panY);
- this.dataDoc._freeform_panXMax = this.dataDoc._freeform_panXMax ? nw * NumCast(this.dataDoc._freeform_panXMax) : undefined;
- this.dataDoc._freeform_panXMin = this.dataDoc._freeform_panXMin ? nw * NumCast(this.dataDoc._freeform_panXMin) : undefined;
- this.dataDoc._freeform_panYMax = this.dataDoc._freeform_panYMax ? nw * NumCast(this.dataDoc._freeform_panYMax) : undefined;
- this.dataDoc._freeform_panYMin = this.dataDoc._freeform_panYMin ? nw * NumCast(this.dataDoc._freeform_panYMin) : undefined;
+ this.dataDoc._freeform_panX = nw * NumCast(this.dataDoc._freeform_panX);
+ this.dataDoc._freeform_panY = nw * NumCast(this.dataDoc._freeform_panY);
+ this.dataDoc._freeform_panX_max = this.dataDoc._freeform_panX_max ? nw * NumCast(this.dataDoc._freeform_panX_max) : undefined;
+ this.dataDoc._freeform_panX_min = this.dataDoc._freeform_panX_min ? nw * NumCast(this.dataDoc._freeform_panX_min) : undefined;
+ this.dataDoc._freeform_panY_max = this.dataDoc._freeform_panY_max ? nw * NumCast(this.dataDoc._freeform_panY_max) : undefined;
+ this.dataDoc._freeform_panY_min = this.dataDoc._freeform_panY_min ? nw * NumCast(this.dataDoc._freeform_panY_min) : undefined;
});
@undoBatch
rotate = action(() => {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index b8b9f63a9..1dc194c42 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -656,11 +656,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
);
else {
if (!PDFBox.pdfpromise.get(href)) PDFBox.pdfpromise.set(href, Pdfjs.getDocument(href).promise);
- PDFBox.pdfpromise.get(href)?.then(
- action((pdf: any) => {
- PDFBox.pdfcache.set(href, (this._pdf = pdf));
- })
- );
+ PDFBox.pdfpromise.get(href)?.then((pdf: any) => {
+ PDFBox.pdfcache.set(href, (this._pdf = pdf));
+ });
}
}
return pdfView ?? this.renderTitleBox;
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 198652310..b6ef36974 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1049,7 +1049,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
setContentViewBox={this.setInnerContent}
NativeWidth={returnZero}
NativeHeight={returnZero}
- originTopLeft={false}
isAnnotationOverlayScrollable
renderDepth={this._props.renderDepth + 1}
isAnnotationOverlay
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 45b1d727e..2327ee0d8 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -33,7 +33,7 @@ import './PDFViewer.scss';
// pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`;
// The workerSrc property shall be specified.
-Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.1.392/build/pdf.worker.mjs';
+Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.2.67/build/pdf.worker.mjs';
interface IViewerProps extends FieldViewProps {
pdfBox: PDFBox;