aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/DocumentDecorations.tsx3
-rw-r--r--src/client/views/InkingStroke.tsx536
-rw-r--r--src/client/views/SidebarAnnos.tsx4
-rw-r--r--src/client/views/StyleProvider.tsx4
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx2
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx11
-rw-r--r--src/client/views/collections/TreeView.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx30
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx187
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx180
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx5
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx384
-rw-r--r--src/client/views/nodes/DocumentView.tsx24
-rw-r--r--src/client/views/nodes/EquationBox.tsx90
-rw-r--r--src/client/views/nodes/FieldView.tsx55
-rw-r--r--src/client/views/nodes/ImageBox.tsx10
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx9
-rw-r--r--src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx2
-rw-r--r--src/client/views/nodes/PDFBox.tsx12
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx4
-rw-r--r--src/client/views/nodes/VideoBox.tsx6
-rw-r--r--src/client/views/nodes/WebBox.tsx25
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx10
-rw-r--r--src/client/views/nodes/trails/PresElementBox.tsx8
-rw-r--r--src/client/views/pdf/PDFViewer.tsx17
25 files changed, 883 insertions, 741 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 780dcfb6d..964fd36c8 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -521,7 +521,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
} else doc._height = actualdH;
}
} else {
- dH && (doc._height = actualdH);
+ const maxHeight = Math.max(nheight, NumCast(doc.scrollHeight)) * docView.NativeDimScaling();
+ dH && (doc._height = actualdH > maxHeight ? maxHeight : actualdH);
dW && (doc._width = actualdW);
dH && (doc._autoHeight = false);
}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index dace9716a..e5de7a0c5 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -20,35 +20,37 @@
Most of the operations that can be performed on an InkStroke (eg delete a point, rotate, stretch) are implemented in the InkStrokeProperties helper class
*/
-import React = require("react");
-import { action, IReactionDisposer, observable, reaction } from "mobx";
-import { observer } from "mobx-react";
-import { Doc, WidthSym } from "../../fields/Doc";
-import { InkData, InkField, InkTool } from "../../fields/InkField";
-import { Cast, NumCast, RTFCast, StrCast } from "../../fields/Types";
-import { TraceMobx } from "../../fields/util";
-import { OmitKeys, returnFalse, setupMoveUpEvents } from "../../Utils";
-import { CognitiveServices } from "../cognitive_services/CognitiveServices";
-import { InteractionUtils } from "../util/InteractionUtils";
-import { SnappingManager } from "../util/SnappingManager";
-import { Transform } from "../util/Transform";
-import { UndoManager } from "../util/UndoManager";
-import { ContextMenu } from "./ContextMenu";
-import { ViewBoxBaseComponent } from "./DocComponent";
-import { Colors } from "./global/globalEnums";
-import { InkControlPtHandles, InkEndPtHandles } from "./InkControlPtHandles";
-import { InkStrokeProperties } from "./InkStrokeProperties";
-import { InkTangentHandles } from "./InkTangentHandles";
-import { DocComponentView } from "./nodes/DocumentView";
-import { FieldView, FieldViewProps } from "./nodes/FieldView";
-import { FormattedTextBox } from "./nodes/formattedText/FormattedTextBox";
-import "./InkStroke.scss";
-import Color = require("color");
+import React = require('react');
+import { action, IReactionDisposer, observable, reaction } from 'mobx';
+import { observer } from 'mobx-react';
+import { Doc, WidthSym } from '../../fields/Doc';
+import { InkData, InkField, InkTool } from '../../fields/InkField';
+import { Cast, NumCast, RTFCast, StrCast } from '../../fields/Types';
+import { TraceMobx } from '../../fields/util';
+import { OmitKeys, returnFalse, setupMoveUpEvents } from '../../Utils';
+import { CognitiveServices } from '../cognitive_services/CognitiveServices';
+import { InteractionUtils } from '../util/InteractionUtils';
+import { SnappingManager } from '../util/SnappingManager';
+import { Transform } from '../util/Transform';
+import { UndoManager } from '../util/UndoManager';
+import { ContextMenu } from './ContextMenu';
+import { ViewBoxBaseComponent } from './DocComponent';
+import { Colors } from './global/globalEnums';
+import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles';
+import { InkStrokeProperties } from './InkStrokeProperties';
+import { InkTangentHandles } from './InkTangentHandles';
+import { DocComponentView } from './nodes/DocumentView';
+import { FieldView, FieldViewProps } from './nodes/FieldView';
+import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import './InkStroke.scss';
+import Color = require('color');
@observer
export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
static readonly MaskDim = 50000; // choose a really big number to make sure mask fits over container (which in theory can be arbitrarily big)
- public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); }
+ public static LayoutString(fieldStr: string) {
+ return FieldView.LayoutString(InkingStroke, fieldStr);
+ }
public static IsClosed(inkData: InkData) {
return inkData && inkData.lastElement().X === inkData[0].X && inkData.lastElement().Y === inkData[0].Y;
}
@@ -56,13 +58,15 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
private _selDisposer?: IReactionDisposer;
@observable _nearestSeg?: number; // nearest Bezier segment along the ink stroke to the cursor (used for displaying the Add Point highlight)
- @observable _nearestT?: number; // nearest t value within the nearest Bezier segment "
- @observable _nearestScrPt?: { X: number, Y: number }; // nearst screen point on the ink stroke ""
+ @observable _nearestT?: number; // nearest t value within the nearest Bezier segment "
+ @observable _nearestScrPt?: { X: number; Y: number }; // nearst screen point on the ink stroke ""
componentDidMount() {
this.props.setContentView?.(this);
- this._selDisposer = reaction(() => this.props.isSelected(), // react to stroke being deselected by turning off ink handles
- selected => !selected && (InkStrokeProperties.Instance._controlButton = false));
+ this._selDisposer = reaction(
+ () => this.props.isSelected(), // react to stroke being deselected by turning off ink handles
+ selected => !selected && (InkStrokeProperties.Instance._controlButton = false)
+ );
}
componentWillUnmount() {
this._selDisposer?.();
@@ -70,36 +74,36 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
// transform is the inherited screentolocal xf plus any scaling that was done to make the stroke
// fit within its panel (e.g., for content fitting views like Lightbox or multicolumn, etc)
- screenToLocal = () => this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1);
+ screenToLocal = () => this.props.ScreenToLocalTransform().scale(this.props.NativeDimScaling?.() || 1);
getAnchor = () => {
console.log(document.activeElement);
return this._subContentView?.getAnchor?.() || this.rootDoc;
- }
+ };
scrollFocus = (textAnchor: Doc, smooth: boolean) => {
return this._subContentView?.scrollFocus?.(textAnchor, smooth);
- }
+ };
/**
- * @returns the center of the ink stroke in the ink document's coordinate space (not screen space, and not the ink data coordinate space);
- * DocumentDecorations calls getBounds() on DocumentViews which call getCenter() if defined - in the case of ink it needs to be defined since
- * the center of the ink stroke changes as the stroke is rotated.
- */
+ * @returns the center of the ink stroke in the ink document's coordinate space (not screen space, and not the ink data coordinate space);
+ * DocumentDecorations calls getBounds() on DocumentViews which call getCenter() if defined - in the case of ink it needs to be defined since
+ * the center of the ink stroke changes as the stroke is rotated.
+ */
getCenter = (xf: Transform) => {
const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
const angle = -NumCast(this.layoutDoc.rotation);
const newPoints = inkData.map(pt => {
- const newX = Math.cos(angle) * pt.X - Math.sin(angle) * pt.Y * inkScaleY / inkScaleX;
- const newY = Math.sin(angle) * pt.X * inkScaleX / inkScaleY + Math.cos(angle) * pt.Y;
+ const newX = Math.cos(angle) * pt.X - (Math.sin(angle) * pt.Y * inkScaleY) / inkScaleX;
+ const newY = (Math.sin(angle) * pt.X * inkScaleX) / inkScaleY + Math.cos(angle) * pt.Y;
return { X: newX, Y: newY };
});
const crx = (Math.max(...newPoints.map(np => np.X)) + Math.min(...newPoints.map(np => np.X))) / 2;
const cry = (Math.max(...newPoints.map(np => np.Y)) + Math.min(...newPoints.map(np => np.Y))) / 2;
- const cx = Math.cos(-angle) * crx - Math.sin(-angle) * cry * inkScaleY / inkScaleX;
- const cy = Math.sin(-angle) * crx * inkScaleX / inkScaleY + Math.cos(-angle) * cry;
+ const cx = Math.cos(-angle) * crx - (Math.sin(-angle) * cry * inkScaleY) / inkScaleX;
+ const cy = (Math.sin(-angle) * crx * inkScaleX) / inkScaleY + Math.cos(-angle) * cry;
const tc = xf.transformPoint((cx - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2, (cy - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2);
return { X: tc[0], Y: tc[1] };
- }
+ };
/**
* analyzes the ink stroke and saves the analysis of the stroke to the 'inkAnalysis' field,
@@ -107,7 +111,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
*/
analyzeStrokes() {
const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
- CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]);
+ CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ['inkAnalysis', 'handwriting'], [data]);
}
/**
@@ -115,12 +119,12 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
* When displayed as a mask, the stroke is rendered with mixBlendMode set to multiply so that the stroke will
* appear to illuminate what it covers up. At the same time, all pixels that are not under the stroke will be
* dimmed by a semi-opaque overlay mask.
- */
+ */
public static toggleMask = action((inkDoc: Doc) => {
inkDoc.isInkMask = !inkDoc.isInkMask;
- inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined;
- inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined;
- inkDoc.color = "#9b9b9bff";
+ inkDoc._backgroundColor = inkDoc.isInkMask ? 'rgba(0,0,0,0.7)' : undefined;
+ inkDoc.mixBlendMode = inkDoc.isInkMask ? 'hard-light' : undefined;
+ inkDoc.color = '#9b9b9bff';
inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined;
});
/**
@@ -132,46 +136,60 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
this._handledClick = false;
const inkView = this.props.docViewPath().lastElement();
const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
- const screenPts = inkData.map(point => this.screenToLocal().inverse().transformPoint(
- (point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2,
- (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)).map(p => ({ X: p[0], Y: p[1] }));
+ const screenPts = inkData
+ .map(point =>
+ this.screenToLocal()
+ .inverse()
+ .transformPoint((point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2, (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)
+ )
+ .map(p => ({ X: p[0], Y: p[1] }));
const { nearestSeg } = InkStrokeProperties.nearestPtToStroke(screenPts, { X: e.clientX, Y: e.clientY });
const controlIndex = nearestSeg;
const wasSelected = InkStrokeProperties.Instance._currentPoint === controlIndex;
var controlUndo: UndoManager.Batch | undefined;
const isEditing = InkStrokeProperties.Instance._controlButton && this.props.isSelected();
- setupMoveUpEvents(this, e,
- !isEditing ? returnFalse : action((e: PointerEvent, down: number[], delta: number[]) => {
- if (!controlUndo) controlUndo = UndoManager.StartBatch("drag ink ctrl pt");
- const inkMoveEnd = this.ptFromScreen({ X: delta[0], Y: delta[1] });
- const inkMoveStart = this.ptFromScreen({ X: 0, Y: 0 });
- InkStrokeProperties.Instance.moveControlPtHandle(inkView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex);
- InkStrokeProperties.Instance.moveControlPtHandle(inkView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex + 3);
- return false;
- }),
- !isEditing ? returnFalse : action(() => {
- controlUndo?.end();
- controlUndo = undefined;
- UndoManager.FilterBatches(["data", "x", "y", "width", "height"]);
- }),
+ setupMoveUpEvents(
+ this,
+ e,
+ !isEditing
+ ? returnFalse
+ : action((e: PointerEvent, down: number[], delta: number[]) => {
+ if (!controlUndo) controlUndo = UndoManager.StartBatch('drag ink ctrl pt');
+ const inkMoveEnd = this.ptFromScreen({ X: delta[0], Y: delta[1] });
+ const inkMoveStart = this.ptFromScreen({ X: 0, Y: 0 });
+ InkStrokeProperties.Instance.moveControlPtHandle(inkView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex);
+ InkStrokeProperties.Instance.moveControlPtHandle(inkView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex + 3);
+ return false;
+ }),
+ !isEditing
+ ? returnFalse
+ : action(() => {
+ controlUndo?.end();
+ controlUndo = undefined;
+ UndoManager.FilterBatches(['data', 'x', 'y', 'width', 'height']);
+ }),
action((e: PointerEvent, doubleTap: boolean | undefined) => {
doubleTap = doubleTap || this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick;
if (doubleTap) {
InkStrokeProperties.Instance._controlButton = true;
InkStrokeProperties.Instance._currentPoint = -1;
- this._handledClick = true; // mark the double-click pseudo pointerevent so we can block the real mouse event from propagating to DocumentView
+ this._handledClick = true; // mark the double-click pseudo pointerevent so we can block the real mouse event from propagating to DocumentView
if (isEditing) {
this._nearestT && this._nearestSeg !== undefined && InkStrokeProperties.Instance.addPoints(this.props.docViewPath().lastElement(), this._nearestT, this._nearestSeg, this.inkScaledData().inkData.slice());
}
}
- }), isEditing, isEditing, action(() => wasSelected && (InkStrokeProperties.Instance._currentPoint = -1)));
- }
+ }),
+ isEditing,
+ isEditing,
+ action(() => wasSelected && (InkStrokeProperties.Instance._currentPoint = -1))
+ );
+ };
/**
* @param scrPt a point in the screen coordinate space
* @returns the point in the ink data's coordinate space.
*/
- ptFromScreen = (scrPt: { X: number, Y: number }) => {
+ ptFromScreen = (scrPt: { X: number; Y: number }) => {
const { inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
const docPt = this.screenToLocal().transformPoint(scrPt.X, scrPt.Y);
const inkPt = {
@@ -179,39 +197,39 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
Y: (docPt[1] - inkStrokeWidth / 2) / inkScaleY + inkStrokeWidth / 2 + inkTop,
};
return inkPt;
- }
+ };
/**
* @param inkPt a point in the ink data's coordinate space
* @returns the screen point corresponding to the ink point
*/
- ptToScreen = (inkPt: { X: number, Y: number }) => {
+ ptToScreen = (inkPt: { X: number; Y: number }) => {
const { inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
const docPt = {
X: (inkPt.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2,
- Y: (inkPt.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2
+ Y: (inkPt.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2,
};
const scrPt = this.screenToLocal().inverse().transformPoint(docPt.X, docPt.Y);
return { X: scrPt[0], Y: scrPt[1] };
- }
+ };
/**
- * Snaps a screen space point to this stroke, optionally skipping bezier segments indicated by 'excludeSegs'
- * @param scrPt - the point to snap to this stroke
- * @param excludeSegs - optional segments in this stroke to skip (this is used when dragging a point on the stroke and not wanting the drag point to snap to its neighboring segments)
- *
- * @returns the nearest ink space point on this stroke to the screen point AND the screen space distance from the snapped point to the nearest point
- */
- snapPt = (scrPt: { X: number, Y: number }, excludeSegs?: number[]) => {
+ * Snaps a screen space point to this stroke, optionally skipping bezier segments indicated by 'excludeSegs'
+ * @param scrPt - the point to snap to this stroke
+ * @param excludeSegs - optional segments in this stroke to skip (this is used when dragging a point on the stroke and not wanting the drag point to snap to its neighboring segments)
+ *
+ * @returns the nearest ink space point on this stroke to the screen point AND the screen space distance from the snapped point to the nearest point
+ */
+ snapPt = (scrPt: { X: number; Y: number }, excludeSegs?: number[]) => {
const { inkData } = this.inkScaledData();
const { nearestPt, distance } = InkStrokeProperties.nearestPtToStroke(inkData, this.ptFromScreen(scrPt), excludeSegs ?? []);
return { nearestPt, distance: distance * this.screenToLocal().inverse().Scale };
- }
+ };
/**
- * extracts key features from the inkData, including: the data points, the ink width, the ink bounds (top,left, width, height), and the scale
- * factor for converting between ink and screen space.
- */
+ * extracts key features from the inkData, including: the data points, the ink width, the ink bounds (top,left, width, height), and the scale
+ * factor for converting between ink and screen space.
+ */
inkScaledData = () => {
const inkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
const inkStrokeWidth = NumCast(this.rootDoc.strokeWidth, 1);
@@ -228,27 +246,31 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
inkLeft,
inkWidth,
inkHeight,
- inkScaleX: ((this.props.PanelWidth() - inkStrokeWidth) / ((inkWidth - inkStrokeWidth) || 1) || 1),
- inkScaleY: ((this.props.PanelHeight() - inkStrokeWidth) / ((inkHeight - inkStrokeWidth) || 1) || 1)
+ inkScaleX: (this.props.PanelWidth() - inkStrokeWidth) / (inkWidth - inkStrokeWidth || 1) || 1,
+ inkScaleY: (this.props.PanelHeight() - inkStrokeWidth) / (inkHeight - inkStrokeWidth || 1) || 1,
};
- }
+ };
//
- // this updates the highlight for the nearest point on the curve to the cursor.
+ // this updates the highlight for the nearest point on the curve to the cursor.
// if the user double clicks, this highlighted point will be added as a control point in the curve.
//
@action
onPointerMove = (e: React.PointerEvent) => {
const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
- const screenPts = inkData.map(point => this.screenToLocal().inverse().transformPoint(
- (point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2,
- (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)).map(p => ({ X: p[0], Y: p[1] }));
+ const screenPts = inkData
+ .map(point =>
+ this.screenToLocal()
+ .inverse()
+ .transformPoint((point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2, (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)
+ )
+ .map(p => ({ X: p[0], Y: p[1] }));
const { distance, nearestT, nearestSeg, nearestPt } = InkStrokeProperties.nearestPtToStroke(screenPts, { X: e.clientX, Y: e.clientY });
this._nearestT = nearestT;
this._nearestSeg = nearestSeg;
this._nearestScrPt = nearestPt;
- }
+ };
/**
* @returns the nearest screen point to the cursor (to render a highlight for the point to be added)
@@ -263,50 +285,66 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
componentUI = (boundsLeft: number, boundsTop: number) => {
const inkDoc = this.props.Document;
const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
- const screenSpaceCenterlineStrokeWidth = Math.min(3, inkStrokeWidth * this.screenToLocal().inverse().Scale); // the width of the blue line widget that shows the centerline of the ink stroke
+ const screenSpaceCenterlineStrokeWidth = Math.min(3, inkStrokeWidth * this.screenToLocal().inverse().Scale); // the width of the blue line widget that shows the centerline of the ink stroke
const screenInkWidth = this.screenToLocal().inverse().transformDirection(inkStrokeWidth, inkStrokeWidth);
- const screenPts = inkData.map(point => this.screenToLocal().inverse().transformPoint(
- (point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2,
- (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)).map(p => ({ X: p[0], Y: p[1] }));
+ const screenPts = inkData
+ .map(point =>
+ this.screenToLocal()
+ .inverse()
+ .transformPoint((point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2, (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)
+ )
+ .map(p => ({ X: p[0], Y: p[1] }));
const screenHdlPts = screenPts;
const startMarker = StrCast(this.layoutDoc.strokeStartMarker);
const endMarker = StrCast(this.layoutDoc.strokeEndMarker);
const markerScale = NumCast(this.layoutDoc.strokeMarkerScale);
- return SnappingManager.GetIsDragging() ? (null) :
- !InkStrokeProperties.Instance._controlButton ?
- (!this.props.isSelected() || InkingStroke.IsClosed(inkData) ? (null) :
- <div className="inkstroke-UI" style={{ clip: `rect(${boundsTop}px, 10000px, 10000px, ${boundsLeft}px)` }}>
- <InkEndPtHandles
- inkView={this.props.docViewPath().lastElement()}
- inkDoc={inkDoc}
- startPt={screenPts[0]}
- endPt={screenPts.lastElement()}
- screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} />
- </div>) :
+ return SnappingManager.GetIsDragging() ? null : !InkStrokeProperties.Instance._controlButton ? (
+ !this.props.isSelected() || InkingStroke.IsClosed(inkData) ? null : (
<div className="inkstroke-UI" style={{ clip: `rect(${boundsTop}px, 10000px, 10000px, ${boundsLeft}px)` }}>
- {InteractionUtils.CreatePolyline(screenPts, 0, 0, Colors.MEDIUM_BLUE, screenInkWidth[0], screenSpaceCenterlineStrokeWidth,
- StrCast(inkDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap), StrCast(inkDoc.strokeBezier),
- "none", startMarker, endMarker, markerScale * Math.min(screenSpaceCenterlineStrokeWidth, screenInkWidth[0] / screenSpaceCenterlineStrokeWidth), StrCast(inkDoc.strokeDash), 1, 1, "", "none", 1.0, false)}
- <InkControlPtHandles
- inkView={this.props.docViewPath().lastElement()}
- inkDoc={inkDoc}
- inkCtrlPoints={inkData}
- screenCtrlPoints={screenHdlPts}
- nearestScreenPt={this.nearestScreenPt}
- screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} />
- <InkTangentHandles
- inkView={this.props.docViewPath().lastElement()}
- inkDoc={inkDoc}
- screenCtrlPoints={screenHdlPts}
- screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth}
- ScreenToLocalTransform={this.screenToLocal} />
- </div>;
- }
+ <InkEndPtHandles inkView={this.props.docViewPath().lastElement()} inkDoc={inkDoc} startPt={screenPts[0]} endPt={screenPts.lastElement()} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} />
+ </div>
+ )
+ ) : (
+ <div className="inkstroke-UI" style={{ clip: `rect(${boundsTop}px, 10000px, 10000px, ${boundsLeft}px)` }}>
+ {InteractionUtils.CreatePolyline(
+ screenPts,
+ 0,
+ 0,
+ Colors.MEDIUM_BLUE,
+ screenInkWidth[0],
+ screenSpaceCenterlineStrokeWidth,
+ StrCast(inkDoc.strokeLineJoin),
+ StrCast(this.layoutDoc.strokeLineCap),
+ StrCast(inkDoc.strokeBezier),
+ 'none',
+ startMarker,
+ endMarker,
+ markerScale * Math.min(screenSpaceCenterlineStrokeWidth, screenInkWidth[0] / screenSpaceCenterlineStrokeWidth),
+ StrCast(inkDoc.strokeDash),
+ 1,
+ 1,
+ '',
+ 'none',
+ 1.0,
+ false
+ )}
+ <InkControlPtHandles
+ inkView={this.props.docViewPath().lastElement()}
+ inkDoc={inkDoc}
+ inkCtrlPoints={inkData}
+ screenCtrlPoints={screenHdlPts}
+ nearestScreenPt={this.nearestScreenPt}
+ screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth}
+ />
+ <InkTangentHandles inkView={this.props.docViewPath().lastElement()} inkDoc={inkDoc} screenCtrlPoints={screenHdlPts} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} ScreenToLocalTransform={this.screenToLocal} />
+ </div>
+ );
+ };
_subContentView: DocComponentView | undefined;
- setSubContentView = (doc: DocComponentView) => this._subContentView = doc;
+ setSubContentView = (doc: DocComponentView) => (this._subContentView = doc);
render() {
TraceMobx();
const { inkData, inkStrokeWidth, inkLeft, inkTop, inkScaleX, inkScaleY, inkWidth, inkHeight } = this.inkScaledData();
@@ -315,105 +353,181 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
const endMarker = StrCast(this.layoutDoc.strokeEndMarker);
const markerScale = NumCast(this.layoutDoc.strokeMarkerScale, 1);
const closed = InkingStroke.IsClosed(inkData);
- const fillColor = StrCast(this.layoutDoc.fillColor, "transparent");
- const strokeColor = !closed && fillColor && fillColor !== "transparent" ? fillColor : StrCast(this.layoutDoc.color);
+ const fillColor = StrCast(this.layoutDoc.fillColor, 'transparent');
+ const strokeColor = !closed && fillColor && fillColor !== 'transparent' ? fillColor : StrCast(this.layoutDoc.color);
// Visually renders the polygonal line made by the user.
- const inkLine = InteractionUtils.CreatePolyline(inkData, inkLeft, inkTop, strokeColor, inkStrokeWidth, inkStrokeWidth,
- StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap),
- StrCast(this.layoutDoc.strokeBezier), !closed ? "none" : fillColor === "transparent" ? "none" : fillColor, startMarker, endMarker,
- markerScale, StrCast(this.layoutDoc.strokeDash), inkScaleX, inkScaleY, "", "none", 1.0, false);
+ const inkLine = InteractionUtils.CreatePolyline(
+ inkData,
+ inkLeft,
+ inkTop,
+ strokeColor,
+ inkStrokeWidth,
+ inkStrokeWidth,
+ StrCast(this.layoutDoc.strokeLineJoin),
+ StrCast(this.layoutDoc.strokeLineCap),
+ StrCast(this.layoutDoc.strokeBezier),
+ !closed ? 'none' : fillColor === 'transparent' ? 'none' : fillColor,
+ startMarker,
+ endMarker,
+ markerScale,
+ StrCast(this.layoutDoc.strokeDash),
+ inkScaleX,
+ inkScaleY,
+ '',
+ 'none',
+ 1.0,
+ false
+ );
const highlightIndex = /*BoolCast(this.props.Document.isLinkButton) && */ Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString
- const highlightColor = !highlightIndex ?
- StrCast(this.layoutDoc.strokeOutlineColor, !closed && fillColor && fillColor !== "transparent" ? StrCast(this.layoutDoc.color, "transparent") : "transparent") :
- ["transparent", "rgb(68, 118, 247)", "rgb(68, 118, 247)", "yellow", "magenta", "cyan", "orange"][highlightIndex];
+ const highlightColor = !highlightIndex
+ ? StrCast(this.layoutDoc.strokeOutlineColor, !closed && fillColor && fillColor !== 'transparent' ? StrCast(this.layoutDoc.color, 'transparent') : 'transparent')
+ : ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'yellow', 'magenta', 'cyan', 'orange'][highlightIndex];
// Invisible polygonal line that enables the ink to be selected by the user.
- const clickableLine = (downHdlr?: (e: React.PointerEvent) => void, suppressFill: boolean = false) => InteractionUtils.CreatePolyline(inkData, inkLeft, inkTop, highlightColor,
- inkStrokeWidth, fillColor && closed && highlightIndex ? highlightIndex / 2 : inkStrokeWidth + (fillColor ? closed ? 0 : (highlightIndex + 2) : 0),
- StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap),
- StrCast(this.layoutDoc.strokeBezier), !closed ? "none" : fillColor === "transparent" || suppressFill ? "none" : fillColor, startMarker, endMarker,
- markerScale, undefined, inkScaleX, inkScaleY, "", this.props.pointerEvents?.() ?? (this.rootDoc._lockedPosition ? "none" : "visiblepainted"), 0.0,
- false, downHdlr);
- const fsize = +(StrCast(this.props.Document.fontSize, "12px").replace("px", ""));
- // bootsrap 3 style sheet sets line height to be 20px for default 14 point font size.
+ const clickableLine = (downHdlr?: (e: React.PointerEvent) => void, suppressFill: boolean = false) =>
+ InteractionUtils.CreatePolyline(
+ inkData,
+ inkLeft,
+ inkTop,
+ highlightColor,
+ inkStrokeWidth,
+ fillColor && closed && highlightIndex ? highlightIndex / 2 : inkStrokeWidth + (fillColor ? (closed ? 0 : highlightIndex + 2) : 0),
+ StrCast(this.layoutDoc.strokeLineJoin),
+ StrCast(this.layoutDoc.strokeLineCap),
+ StrCast(this.layoutDoc.strokeBezier),
+ !closed ? 'none' : fillColor === 'transparent' || suppressFill ? 'none' : fillColor,
+ startMarker,
+ endMarker,
+ markerScale,
+ undefined,
+ inkScaleX,
+ inkScaleY,
+ '',
+ this.props.pointerEvents?.() ?? (this.rootDoc._lockedPosition ? 'none' : 'visiblepainted'),
+ 0.0,
+ false,
+ downHdlr
+ );
+ const fsize = +StrCast(this.props.Document.fontSize, '12px').replace('px', '');
+ // bootsrap 3 style sheet sets line height to be 20px for default 14 point font size.
// this attempts to figure out the lineHeight ratio by inquiring the body's lineHeight and dividing by the fontsize which should yield 1.428571429
// see: https://bibwild.wordpress.com/2019/06/10/bootstrap-3-to-4-changes-in-how-font-size-line-height-and-spacing-is-done-or-what-happened-to-line-height-computed/
- const lineHeightGuess = (+getComputedStyle(document.body).lineHeight.replace("px", "")) / (+getComputedStyle(document.body).fontSize.replace("px", ""));
+ const lineHeightGuess = +getComputedStyle(document.body).lineHeight.replace('px', '') / +getComputedStyle(document.body).fontSize.replace('px', '');
const interactions = {
- onPointerLeave: action(() => this._nearestScrPt = undefined),
+ onPointerLeave: action(() => (this._nearestScrPt = undefined)),
onPointerMove: this.props.isSelected() ? this.onPointerMove : undefined,
onClick: (e: React.MouseEvent) => this._handledClick && e.stopPropagation(),
onContextMenu: () => {
const cm = ContextMenu.Instance;
- !Doc.noviceMode && cm?.addItem({ description: "Recognize Writing", event: this.analyzeStrokes, icon: "paint-brush" });
- cm?.addItem({ description: "Toggle Mask", event: () => InkingStroke.toggleMask(this.rootDoc), icon: "paint-brush" });
- cm?.addItem({ description: "Edit Points", event: action(() => InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton), icon: "paint-brush" });
- }
+ !Doc.noviceMode && cm?.addItem({ description: 'Recognize Writing', event: this.analyzeStrokes, icon: 'paint-brush' });
+ cm?.addItem({ description: 'Toggle Mask', event: () => InkingStroke.toggleMask(this.rootDoc), icon: 'paint-brush' });
+ cm?.addItem({ description: 'Edit Points', event: action(() => (InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton)), icon: 'paint-brush' });
+ },
};
- return <div className="inkStroke-wrapper">
- <svg className="inkStroke"
- style={{
- transform: this.props.Document.isInkMask ? `translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined,
- mixBlendMode: this.layoutDoc.tool === InkTool.Highlighter ? "multiply" : "unset",
- cursor: this.props.isSelected() ? "default" : undefined
- }}
- {...(!closed ? interactions : {})}
- >
- {closed ? inkLine : clickableLine(this.onPointerDown)}
- {closed ? clickableLine(this.onPointerDown) : inkLine}
- </svg>
- {!closed || (!RTFCast(this.rootDoc.text)?.Text && !this.props.isSelected()) ? (null) :
- <div className="inkStroke-text" style={{
- color: StrCast(this.layoutDoc.textColor, "black"),
- pointerEvents: this.props.isDocumentActive?.() ? "all" : undefined,
- width: this.layoutDoc[WidthSym](),
- transform: `scale(${this.props.scaling?.() || 1})`,
- transformOrigin: "top left",
- top: (this.props.PanelHeight() - (lineHeightGuess * fsize + 20) * (this.props.scaling?.() || 1)) / 2
- }}>
- <FormattedTextBox
- {...OmitKeys(this.props, ['children']).omit}
- setContentView={this.setSubContentView} // this makes the inkingStroke the "dominant" component - ie, it will show the inking UI when selected (not text)
- yPadding={10}
- xPadding={10}
- fieldKey={"text"}
- fontSize={fsize}
- dontRegisterView={true}
- noSidebar={true}
- dontScale={true}
- isContentActive={this.isContentActive}
- />
- </div>
- }
- {!closed ? null : <svg className="inkStroke"
- style={{
- transform: this.props.Document.isInkMask ? `translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined,
- mixBlendMode: this.layoutDoc.tool === InkTool.Highlighter ? "multiply" : "unset",
- cursor: this.props.isSelected() ? "default" : undefined, position: "absolute"
- }}
- {...interactions}
- >
- {clickableLine(this.onPointerDown, true)}
- </svg>}
- </div>;
+ return (
+ <div className="inkStroke-wrapper">
+ <svg
+ className="inkStroke"
+ style={{
+ transform: this.props.Document.isInkMask ? `translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined,
+ mixBlendMode: this.layoutDoc.tool === InkTool.Highlighter ? 'multiply' : 'unset',
+ cursor: this.props.isSelected() ? 'default' : undefined,
+ }}
+ {...(!closed ? interactions : {})}>
+ {closed ? inkLine : clickableLine(this.onPointerDown)}
+ {closed ? clickableLine(this.onPointerDown) : inkLine}
+ </svg>
+ {!closed || (!RTFCast(this.rootDoc.text)?.Text && !this.props.isSelected()) ? null : (
+ <div
+ className="inkStroke-text"
+ style={{
+ color: StrCast(this.layoutDoc.textColor, 'black'),
+ pointerEvents: this.props.isDocumentActive?.() ? 'all' : undefined,
+ width: this.layoutDoc[WidthSym](),
+ transform: `scale(${this.props.NativeDimScaling?.() || 1})`,
+ transformOrigin: 'top left',
+ top: (this.props.PanelHeight() - (lineHeightGuess * fsize + 20) * (this.props.NativeDimScaling?.() || 1)) / 2,
+ }}>
+ <FormattedTextBox
+ {...OmitKeys(this.props, ['children']).omit}
+ setContentView={this.setSubContentView} // this makes the inkingStroke the "dominant" component - ie, it will show the inking UI when selected (not text)
+ yPadding={10}
+ xPadding={10}
+ fieldKey={'text'}
+ fontSize={fsize}
+ dontRegisterView={true}
+ noSidebar={true}
+ dontScale={true}
+ isContentActive={this.isContentActive}
+ />
+ </div>
+ )}
+ {!closed ? null : (
+ <svg
+ className="inkStroke"
+ style={{
+ transform: this.props.Document.isInkMask ? `translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined,
+ mixBlendMode: this.layoutDoc.tool === InkTool.Highlighter ? 'multiply' : 'unset',
+ cursor: this.props.isSelected() ? 'default' : undefined,
+ position: 'absolute',
+ }}
+ {...interactions}>
+ {clickableLine(this.onPointerDown, true)}
+ </svg>
+ )}
+ </div>
+ );
}
}
-
-export function SetActiveInkWidth(width: string): void { !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width); }
-export function SetActiveBezierApprox(bezier: string): void { ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? "" : bezier); }
-export function SetActiveInkColor(value: string) { ActiveInkPen() && (ActiveInkPen().activeInkColor = value); }
-export function SetActiveFillColor(value: string) { ActiveInkPen() && (ActiveInkPen().activeFillColor = value); }
-export function SetActiveArrowStart(value: string) { ActiveInkPen() && (ActiveInkPen().activeArrowStart = value); }
-export function SetActiveArrowEnd(value: string) { ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value); }
-export function SetActiveArrowScale(value: number) { ActiveInkPen() && (ActiveInkPen().activeArrowScale = value); }
-export function SetActiveDash(dash: string): void { !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); }
-export function ActiveInkPen(): Doc { return Doc.UserDoc(); }
-export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, "black"); }
-export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ""); }
-export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ""); }
-export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ""); }
-export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); }
-export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, "0"); }
-export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); }
-export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); }
+export function SetActiveInkWidth(width: string): void {
+ !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width);
+}
+export function SetActiveBezierApprox(bezier: string): void {
+ ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier);
+}
+export function SetActiveInkColor(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeInkColor = value);
+}
+export function SetActiveFillColor(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeFillColor = value);
+}
+export function SetActiveArrowStart(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeArrowStart = value);
+}
+export function SetActiveArrowEnd(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value);
+}
+export function SetActiveArrowScale(value: number) {
+ ActiveInkPen() && (ActiveInkPen().activeArrowScale = value);
+}
+export function SetActiveDash(dash: string): void {
+ !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash);
+}
+export function ActiveInkPen(): Doc {
+ return Doc.UserDoc();
+}
+export function ActiveInkColor(): string {
+ return StrCast(ActiveInkPen()?.activeInkColor, 'black');
+}
+export function ActiveFillColor(): string {
+ return StrCast(ActiveInkPen()?.activeFillColor, '');
+}
+export function ActiveArrowStart(): string {
+ return StrCast(ActiveInkPen()?.activeArrowStart, '');
+}
+export function ActiveArrowEnd(): string {
+ return StrCast(ActiveInkPen()?.activeArrowEnd, '');
+}
+export function ActiveArrowScale(): number {
+ return NumCast(ActiveInkPen()?.activeArrowScale, 1);
+}
+export function ActiveDash(): string {
+ return StrCast(ActiveInkPen()?.activeDash, '0');
+}
+export function ActiveInkWidth(): number {
+ return Number(ActiveInkPen()?.activeInkWidth);
+}
+export function ActiveInkBezierApprox(): string {
+ return StrCast(ActiveInkPen()?.activeInkBezier);
+}
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index e81a9c40f..9fdf9d2be 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -93,7 +93,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
this.props
.ScreenToLocalTransform()
.translate(Doc.NativeWidth(this.props.dataDoc), 0)
- .scale(this.props.scaling?.() || 1);
+ .scale(this.props.NativeDimScaling?.() || 1);
// panelWidth = () => !this.props.layoutDoc._showSidebar ? 0 :
// this.props.usePanelWidth ? this.props.PanelWidth() :
// (NumCast(this.props.layoutDoc.nativeWidth) - Doc.NativeWidth(this.props.dataDoc)) * this.props.PanelWidth() / NumCast(this.props.layoutDoc.nativeWidth);
@@ -164,7 +164,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
setHeight={this.setHeightCallback}
isAnnotationOverlay={false}
select={emptyFunction}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
childShowTitle={this.showTitle}
childDocumentsActive={this.props.isContentActive}
whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 340a5df45..334f381be 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -250,9 +250,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
return doc.z
? `#9c9396 ${StrCast(doc?.boxShadow, '10px 10px 0.9vw')}` // if it's a floating doc, give it a big shadow
: props?.ContainingCollectionDoc?._useClusters && doc.type !== DocumentType.INK
- ? `${backgroundCol()} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.ContentScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent
+ ? `${backgroundCol()} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.NativeDimScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent
: NumCast(doc.group, -1) !== -1 && doc.type !== DocumentType.INK
- ? `gray ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.ContentScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent
+ ? `gray ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.NativeDimScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent
: isBackground()
? undefined // if it's a background & has a cluster color, make the shadow spread really big
: StrCast(doc.boxShadow, '');
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index f1d842386..714d8421a 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -519,7 +519,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
isAnnotationOverlay={true}
isDocumentActive={returnFalse}
select={emptyFunction}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
xMargin={25}
yMargin={10}
ScreenToLocalTransform={this.dictationScreenToLocalTransform}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 809a73a77..dce792d19 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -235,7 +235,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
forceAutoHeight={true} // needed to make the title resize even if the rest of the tree view is not autoHeight
PanelWidth={this.documentTitleWidth}
PanelHeight={this.documentTitleHeight}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
onKey={this.onKey}
docFilters={returnEmptyFilter}
docRangeFilters={returnEmptyFilter}
@@ -351,7 +351,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
return Doc.NativeHeight(this.Document, undefined, true);
}
- @computed get contentScaling() {
+ /// scale factor for tree view so that it will fit within it's panel bounds
+ @computed get nativeDimScaling() {
const nw = this.nativeWidth;
const nh = this.nativeHeight;
const hscale = nh ? this.props.PanelHeight() / nh : 1;
@@ -365,7 +366,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins);
truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
- panelWidth = () => Math.max(0, this.props.PanelWidth() - this.marginX() - CollectionTreeView.expandViewLabelSize) * (this.props.scaling?.() || 1);
+ panelWidth = () => Math.max(0, this.props.PanelWidth() - this.marginX() - CollectionTreeView.expandViewLabelSize) * (this.props.NativeDimScaling?.() || 1);
addAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.addDocument(doc, `${this.props.fieldKey}-annotations`) || false;
remAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false;
@@ -389,9 +390,9 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
<div
className="collectionTreeView-container"
style={{
- transform: this.outlineMode ? `scale(${this.contentScaling})` : '',
+ transform: this.outlineMode ? `scale(${this.nativeDimScaling})` : '',
paddingLeft: `${this.marginX()}px`,
- width: this.outlineMode ? `calc(${100 / this.contentScaling}%)` : '',
+ width: this.outlineMode ? `calc(${100 / this.nativeDimScaling}%)` : '',
}}
onContextMenu={this.onContextMenu}>
{!this.buttonMenu && !this.noviceExplainer ? null : (
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 5a2103e98..aa1330762 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -403,7 +403,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const aspect = Doc.NativeAspect(layoutDoc);
if (layoutDoc._fitWidth) return Math.min(this.props.panelWidth() - treeBulletWidth(), layoutDoc[WidthSym]());
if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.panelWidth() - treeBulletWidth()));
- return Math.min((this.props.panelWidth() - treeBulletWidth()) / (this.props.treeView.props.scaling?.() || 1), Doc.NativeWidth(layoutDoc) ? layoutDoc[WidthSym]() : this.layoutDoc[WidthSym]());
+ return Math.min((this.props.panelWidth() - treeBulletWidth()) / (this.props.treeView.props.NativeDimScaling?.() || 1), Doc.NativeWidth(layoutDoc) ? layoutDoc[WidthSym]() : this.layoutDoc[WidthSym]());
};
docHeight = () => {
const layoutDoc = this.layoutDoc;
@@ -514,7 +514,7 @@ export class TreeView extends React.Component<TreeViewProps> {
rtfWidth = () => {
const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
- return Math.min(layout[WidthSym](), this.props.panelWidth() - treeBulletWidth()) / (this.props.treeView.props.scaling?.() || 1);
+ return Math.min(layout[WidthSym](), this.props.panelWidth() - treeBulletWidth()) / (this.props.treeView.props.NativeDimScaling?.() || 1);
};
rtfHeight = () => {
const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
@@ -921,7 +921,6 @@ export class TreeView extends React.Component<TreeViewProps> {
searchFilterDocs={returnEmptyDoclist}
ContainingCollectionView={undefined}
ContainingCollectionDoc={this.props.treeView.props.Document}
- ContentScaling={returnOne}
/>
);
@@ -992,7 +991,6 @@ export class TreeView extends React.Component<TreeViewProps> {
hideResizeHandles={this.props.treeView.outlineMode}
onClick={this.onChildClick}
focus={this.refocus}
- ContentScaling={returnOne}
onKey={this.onKeyDown}
hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 5d7a12122..3e938ec1c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -58,7 +58,7 @@ import e = require('connect-flash');
export type collectionFreeformViewProps = {
annotationLayerHostsContent?: boolean; // whether to force scaling of content (needed by ImageBox)
viewDefDivClick?: ScriptField;
- childPointerEvents?: boolean;
+ childPointerEvents?: string;
scaleField?: string;
noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale)
engineProps?: any;
@@ -150,11 +150,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return this.fitContentsToBox ? 0 : Doc.NativeHeight(this.Document, Cast(this.Document.resolvedDataDoc, Doc, null));
}
@computed get cachedCenteringShiftX(): number {
- const scaling = this.fitContentsToBox || !this.contentScaling ? 1 : this.contentScaling;
+ const scaling = this.fitContentsToBox || !this.nativeDimScaling ? 1 : this.nativeDimScaling;
return this.props.isAnnotationOverlay ? 0 : this.props.PanelWidth() / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
}
@computed get cachedCenteringShiftY(): number {
- const scaling = this.fitContentsToBox || !this.contentScaling ? 1 : this.contentScaling;
+ const scaling = this.fitContentsToBox || !this.nativeDimScaling ? 1 : this.nativeDimScaling;
return this.props.isAnnotationOverlay ? 0 : this.props.PanelHeight() / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
}
@computed get cachedGetLocalTransform(): Transform {
@@ -1065,7 +1065,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
onPointerWheel = (e: React.WheelEvent): void => {
- if (this.layoutDoc._Transform || (this.layoutDoc._fitWidth && this.layoutDoc.nativeHeight) || DocListCast(Doc.MyOverlayDocs?.data).includes(this.props.Document) || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
+ if (this.layoutDoc._Transform || DocListCast(Doc.MyOverlayDocs?.data).includes(this.props.Document) || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
// things that can scroll vertically should do that instead of zooming
e.stopPropagation();
@@ -1251,7 +1251,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
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)));
+ const newScale = Math.min(maxZoom, (1 / (this.nativeDimScaling || 1)) * scale * Math.min(this.props.PanelWidth() / Math.abs(bounds.width), this.props.PanelHeight() / Math.abs(bounds.height)));
return {
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,
@@ -1301,7 +1301,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
pointerEvents = () => {
const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine);
- const pointerEvents = this.props.isContentActive() === false ? 'none' : this.props.childPointerEvents ? 'all' : this.props.viewDefDivClick || (engine === 'pass' && !this.props.isSelected(true)) ? 'none' : this.props.pointerEvents?.();
+ const pointerEvents = this.props.isContentActive() === false ? 'none' : this.props.childPointerEvents ?? (this.props.viewDefDivClick || (engine === 'pass' && !this.props.isSelected(true)) ? 'none' : this.props.pointerEvents?.());
return pointerEvents;
};
getChildDocView(entry: PoolData) {
@@ -1631,9 +1631,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
img.style.width = canvas.style.width;
img.style.height = canvas.style.height;
const newCan = newDiv as HTMLCanvasElement;
- const parEle = newCan.parentElement as HTMLElement;
- parEle.removeChild(newCan);
- parEle.appendChild(img);
+ if (newCan) {
+ const parEle = newCan.parentElement as HTMLElement;
+ parEle.removeChild(newCan);
+ parEle.appendChild(img);
+ }
}
}
}
@@ -1943,13 +1945,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
);
}
- @computed get contentScaling() {
+ @computed get nativeDimScaling() {
if (this._firstRender || (this.props.isAnnotationOverlay && !this.props.annotationLayerHostsContent)) return 0;
const nw = this.nativeWidth;
const nh = this.nativeHeight;
const hscale = nh ? this.props.PanelHeight() / nh : 1;
const wscale = nw ? this.props.PanelWidth() / nw : 1;
- return wscale < hscale ? wscale : hscale;
+ return wscale < hscale || this.layoutDoc.fitWidth ? wscale : hscale;
}
private groupDropDisposer?: DragManager.DragDropDisposer;
@@ -1983,9 +1985,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
: SnappingManager.GetIsDragging() && this.childDocs.includes(DragManager.docsBeingDragged.lastElement())
? 'all'
: (this.props.pointerEvents?.() as any),
- transform: `scale(${this.contentScaling || 1})`,
- width: `${100 / (this.contentScaling || 1)}%`,
- height: this.isAnnotationOverlay && this.Document.scrollHeight ? NumCast(this.Document.scrollHeight) : `${100 / (this.contentScaling || 1)}%`, // : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
+ transform: `scale(${this.nativeDimScaling || 1})`,
+ width: `${100 / (this.nativeDimScaling || 1)}%`,
+ height: this.isAnnotationOverlay && this.Document.scrollHeight ? NumCast(this.Document.scrollHeight) : `${100 / (this.nativeDimScaling || 1)}%`, // : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
}}>
{this._firstRender ? this.placeholder : this.marqueeView}
{this.props.noOverlay ? null : <CollectionFreeFormOverlayView elements={this.elementFunc} />}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 777ef464f..465dbfe6d 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -1,6 +1,6 @@
import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
-import * as React from "react";
+import * as React from 'react';
import { Doc, DocListCast } from '../../../../fields/Doc';
import { List } from '../../../../fields/List';
import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
@@ -11,11 +11,10 @@ import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
import { DocumentView } from '../../nodes/DocumentView';
import { CollectionSubView } from '../CollectionSubView';
-import "./CollectionMulticolumnView.scss";
+import './CollectionMulticolumnView.scss';
import ResizeBar from './MulticolumnResizer';
import WidthLabel from './MulticolumnWidthLabel';
-
interface WidthSpecifier {
magnitude: number;
unit: string;
@@ -27,8 +26,8 @@ interface LayoutData {
}
export const DimUnit = {
- Pixel: "px",
- Ratio: "*"
+ Pixel: 'px',
+ Ratio: '*',
};
const resolvedUnits = Object.values(DimUnit);
@@ -36,14 +35,13 @@ const resizerWidth = 8;
@observer
export class CollectionMulticolumnView extends CollectionSubView() {
-
/**
* @returns the list of layout documents whose width unit is
* *, denoting that it will be displayed with a ratio, not fixed pixel, value
*/
@computed
private get ratioDefinedDocs() {
- return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio);
+ return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, '*') === DimUnit.Ratio);
}
@computed
@@ -65,10 +63,10 @@ export class CollectionMulticolumnView extends CollectionSubView() {
let starSum = 0;
const widthSpecifiers: WidthSpecifier[] = [];
this.childLayoutPairs.map(pair => {
- const unit = StrCast(pair.layout._dimUnit, "*");
+ const unit = StrCast(pair.layout._dimUnit, '*');
const magnitude = NumCast(pair.layout._dimMagnitude, this.minimumDim);
if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) {
- (unit === DimUnit.Ratio) && (starSum += magnitude);
+ unit === DimUnit.Ratio && (starSum += magnitude);
widthSpecifiers.push({ magnitude, unit });
}
/**
@@ -100,14 +98,13 @@ export class CollectionMulticolumnView extends CollectionSubView() {
* This returns the total quantity, in pixels, that this
* view needs to reserve for child documents that have
* (with higher priority) requested a fixed pixel width.
- *
+ *
* If the underlying resolvedLayoutInformation returns null
* because we're waiting on promises to resolve, this value will be undefined as well.
*/
@computed
private get totalFixedAllocation(): number | undefined {
- return this.resolvedLayoutInformation?.widthSpecifiers.reduce(
- (sum, { magnitude, unit }) => sum + (unit === DimUnit.Pixel ? magnitude : 0), 0);
+ return this.resolvedLayoutInformation?.widthSpecifiers.reduce((sum, { magnitude, unit }) => sum + (unit === DimUnit.Pixel ? magnitude : 0), 0);
}
/**
@@ -115,7 +112,7 @@ export class CollectionMulticolumnView extends CollectionSubView() {
* view needs to reserve for child documents that have
* (with lower priority) requested a certain relative proportion of the
* remaining pixel width not allocated for fixed widths.
- *
+ *
* If the underlying totalFixedAllocation returns undefined
* because we're waiting indirectly on promises to resolve, this value will be undefined as well.
*/
@@ -135,7 +132,7 @@ export class CollectionMulticolumnView extends CollectionSubView() {
* this accessor returns 1000 / (2 + 2 + 1), or 200px.
* Elsewhere, this is then multiplied by each relative-width
* document's (potentially decimal) * count to compute its actual width (400px, 400px and 200px).
- *
+ *
* If the underlying totalRatioAllocation or this.resolveLayoutInformation return undefined
* because we're waiting indirectly on promises to resolve, this value will be undefined as well.
*/
@@ -165,17 +162,17 @@ export class CollectionMulticolumnView extends CollectionSubView() {
return 0; // we're still waiting on promises to resolve
}
let width = NumCast(layout._dimMagnitude, this.minimumDim);
- if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) {
+ if (StrCast(layout._dimUnit, '*') === DimUnit.Ratio) {
width *= columnUnitLength;
}
return width;
- }
+ };
/**
* @returns the transform that will correctly place
* the document decorations box, shifted to the right by
* the sum of all the resolved column widths of the
- * documents before the target.
+ * documents before the target.
*/
private lookupIndividualTransform = (layout: Doc) => {
const columnUnitLength = this.columnUnitLength;
@@ -185,12 +182,12 @@ export class CollectionMulticolumnView extends CollectionSubView() {
let offset = 0;
for (const { layout: candidate } of this.childLayoutPairs) {
if (candidate === layout) {
- return this.props.ScreenToLocalTransform().translate(-offset / (this.props.scaling?.() || 1), 0);
+ return this.props.ScreenToLocalTransform().translate(-offset / (this.props.NativeDimScaling?.() || 1), 0);
}
offset += this.lookupPixels(candidate) + resizerWidth;
}
return Transform.Identity(); // type coersion, this case should never be hit
- }
+ };
@undoBatch
@action
@@ -198,16 +195,17 @@ export class CollectionMulticolumnView extends CollectionSubView() {
let dropInd = -1;
if (de.complete.docDragData && this._mainCont) {
let curInd = -1;
- de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
- curInd = this.childDocs.indexOf(d);
- }));
+ de.complete.docDragData?.droppedDocuments.forEach(
+ action((d: Doc) => {
+ curInd = this.childDocs.indexOf(d);
+ })
+ );
Array.from(this._mainCont.children).forEach((child, index) => {
const brect = child.getBoundingClientRect();
if (brect.x < de.x && brect.x + brect.width > de.x) {
if (curInd !== -1 && curInd === Math.floor(index / 2)) {
dropInd = curInd;
- }
- else if (child.className === "multiColumnResizer") {
+ } else if (child.className === 'multiColumnResizer') {
dropInd = Math.floor(index / 2);
} else {
dropInd = Math.ceil(index / 2 + (de.x - brect.x > brect.width / 2 ? 0 : -1));
@@ -215,76 +213,80 @@ export class CollectionMulticolumnView extends CollectionSubView() {
}
});
if (super.onInternalDrop(e, de)) {
- de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
- d._dimUnit = "*";
- d._dimMagnitude = 1;
- if (dropInd !== curInd || dropInd === -1) {
- if (this.childDocs.includes(d)) {
- if (dropInd > this.childDocs.indexOf(d)) dropInd--;
+ de.complete.docDragData?.droppedDocuments.forEach(
+ action((d: Doc) => {
+ d._dimUnit = '*';
+ d._dimMagnitude = 1;
+ if (dropInd !== curInd || dropInd === -1) {
+ if (this.childDocs.includes(d)) {
+ if (dropInd > this.childDocs.indexOf(d)) dropInd--;
+ }
+ Doc.RemoveDocFromList(this.rootDoc, this.props.fieldKey, d);
+ Doc.AddDocToList(this.rootDoc, this.props.fieldKey, d, DocListCast(this.rootDoc[this.props.fieldKey])[dropInd], undefined, dropInd === -1);
}
- Doc.RemoveDocFromList(this.rootDoc, this.props.fieldKey, d);
- Doc.AddDocToList(this.rootDoc, this.props.fieldKey, d, DocListCast(this.rootDoc[this.props.fieldKey])[dropInd], undefined, dropInd === -1);
- }
- }));
+ })
+ );
}
}
return false;
- }
-
+ };
onChildClickHandler = () => ScriptCast(this.Document.onChildClick);
onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick);
addDocTab = (doc: Doc, where: string) => {
- if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) {
+ if (where === 'inPlace' && this.layoutDoc.isInPlaceContainer) {
this.dataDoc[this.props.fieldKey] = new List<Doc>([doc]);
return true;
}
return this.props.addDocTab(doc, where);
- }
+ };
isContentActive = () => this.props.isSelected() || this.props.isContentActive();
- isChildContentActive = () => ((this.props.childDocumentsActive?.() || this.Document._childDocumentsActive) && this.props.isDocumentActive?.() && SnappingManager.GetIsDragging()) || this.props.isSelected() || this.props.isAnyChildContentActive() ? true : false;
+ isChildContentActive = () =>
+ ((this.props.childDocumentsActive?.() || this.Document._childDocumentsActive) && this.props.isDocumentActive?.() && SnappingManager.GetIsDragging()) || this.props.isSelected() || this.props.isAnyChildContentActive() ? true : false;
getDisplayDoc = (layout: Doc, dxf: () => Transform, width: () => number, height: () => number) => {
- return <DocumentView
- Document={layout}
- DataDoc={layout.resolvedDataDoc as Doc}
- styleProvider={this.props.styleProvider}
- docViewPath={this.props.docViewPath}
- LayoutTemplate={this.props.childLayoutTemplate}
- LayoutTemplateString={this.props.childLayoutString}
- renderDepth={this.props.renderDepth + 1}
- PanelWidth={width}
- PanelHeight={height}
- rootSelected={this.rootSelected}
- dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
- onClick={this.onChildClickHandler}
- onDoubleClick={this.onChildDoubleClickHandler}
- suppressSetHeight={true}
- ScreenToLocalTransform={dxf}
- isContentActive={this.isChildContentActive}
- isDocumentActive={this.props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
- hideResizeHandles={this.props.childHideResizeHandles?.()}
- hideDecorationTitle={this.props.childHideDecorationTitle?.()}
- fitContentsToBox={this.props.fitContentsToBox}
- focus={this.props.focus}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
- searchFilterDocs={this.searchFilterDocs}
- ContainingCollectionDoc={this.props.CollectionView?.props.Document}
- ContainingCollectionView={this.props.CollectionView}
- dontRegisterView={this.props.dontRegisterView}
- addDocument={this.props.addDocument}
- moveDocument={this.props.moveDocument}
- removeDocument={this.props.removeDocument}
- whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
- addDocTab={this.addDocTab}
- pinToPres={this.props.pinToPres}
- bringToFront={returnFalse}
- />;
- }
+ return (
+ <DocumentView
+ Document={layout}
+ DataDoc={layout.resolvedDataDoc as Doc}
+ styleProvider={this.props.styleProvider}
+ docViewPath={this.props.docViewPath}
+ LayoutTemplate={this.props.childLayoutTemplate}
+ LayoutTemplateString={this.props.childLayoutString}
+ renderDepth={this.props.renderDepth + 1}
+ PanelWidth={width}
+ PanelHeight={height}
+ rootSelected={this.rootSelected}
+ dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
+ onClick={this.onChildClickHandler}
+ onDoubleClick={this.onChildDoubleClickHandler}
+ suppressSetHeight={true}
+ ScreenToLocalTransform={dxf}
+ isContentActive={this.isChildContentActive}
+ isDocumentActive={this.props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
+ hideResizeHandles={this.props.childHideResizeHandles?.()}
+ hideDecorationTitle={this.props.childHideDecorationTitle?.()}
+ fitContentsToBox={this.props.fitContentsToBox}
+ focus={this.props.focus}
+ docFilters={this.childDocFilters}
+ docRangeFilters={this.childDocRangeFilters}
+ searchFilterDocs={this.searchFilterDocs}
+ ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+ ContainingCollectionView={this.props.CollectionView}
+ dontRegisterView={this.props.dontRegisterView}
+ addDocument={this.props.addDocument}
+ moveDocument={this.props.moveDocument}
+ removeDocument={this.props.removeDocument}
+ whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+ addDocTab={this.addDocTab}
+ pinToPres={this.props.pinToPres}
+ bringToFront={returnFalse}
+ />
+ );
+ };
/**
* @returns the resolved list of rendered child documents, displayed
- * at their resolved pixel widths, each separated by a resizer.
+ * at their resolved pixel widths, each separated by a resizer.
*/
@computed
private get contents(): JSX.Element[] | null {
@@ -293,22 +295,20 @@ export class CollectionMulticolumnView extends CollectionSubView() {
const collector: JSX.Element[] = [];
for (let i = 0; i < childLayoutPairs.length; i++) {
const { layout } = childLayoutPairs[i];
- const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1));
+ const dxf = () =>
+ this.lookupIndividualTransform(layout)
+ .translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin))
+ .scale(this.props.NativeDimScaling?.() || 1);
const width = () => this.lookupPixels(layout);
const height = () => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
collector.push(
- <div className={"document-wrapper"}
- key={"wrapper" + i}
- style={{ width: width() }} >
+ <div className={'document-wrapper'} key={'wrapper' + i} style={{ width: width() }}>
{this.getDisplayDoc(layout, dxf, width, height)}
- <WidthLabel
- layout={layout}
- collectionDoc={Document}
- />
+ <WidthLabel layout={layout} collectionDoc={Document} />
</div>,
<ResizeBar
width={resizerWidth}
- key={"resizer" + i}
+ key={'resizer' + i}
styleProvider={this.props.styleProvider}
isContentActive={this.props.isContentActive}
select={this.props.select}
@@ -324,16 +324,19 @@ export class CollectionMulticolumnView extends CollectionSubView() {
render(): JSX.Element {
return (
- <div className={"collectionMulticolumnView_contents"} ref={this.createDashEventsTarget}
+ <div
+ className={'collectionMulticolumnView_contents'}
+ ref={this.createDashEventsTarget}
style={{
width: `calc(100% - ${2 * NumCast(this.props.Document._xMargin)}px)`,
height: `calc(100% - ${2 * NumCast(this.props.Document._yMargin)}px)`,
- marginLeft: NumCast(this.props.Document._xMargin), marginRight: NumCast(this.props.Document._xMargin),
- marginTop: NumCast(this.props.Document._yMargin), marginBottom: NumCast(this.props.Document._yMargin)
- }} >
+ marginLeft: NumCast(this.props.Document._xMargin),
+ marginRight: NumCast(this.props.Document._xMargin),
+ marginTop: NumCast(this.props.Document._yMargin),
+ marginBottom: NumCast(this.props.Document._yMargin),
+ }}>
{this.contents}
</div>
);
}
-
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 08385bcb5..f8de4e5de 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -1,6 +1,6 @@
import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
-import * as React from "react";
+import * as React from 'react';
import { Doc, DocListCast } from '../../../../fields/Doc';
import { List } from '../../../../fields/List';
import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
@@ -11,7 +11,7 @@ import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
import { DocumentView } from '../../nodes/DocumentView';
import { CollectionSubView } from '../CollectionSubView';
-import "./CollectionMultirowView.scss";
+import './CollectionMultirowView.scss';
import HeightLabel from './MultirowHeightLabel';
import ResizeBar from './MultirowResizer';
@@ -26,8 +26,8 @@ interface LayoutData {
}
export const DimUnit = {
- Pixel: "px",
- Ratio: "*"
+ Pixel: 'px',
+ Ratio: '*',
};
const resolvedUnits = Object.values(DimUnit);
@@ -35,14 +35,13 @@ const resizerHeight = 8;
@observer
export class CollectionMultirowView extends CollectionSubView() {
-
/**
* @returns the list of layout documents whose width unit is
* *, denoting that it will be displayed with a ratio, not fixed pixel, value
*/
@computed
private get ratioDefinedDocs() {
- return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio);
+ return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, '*') === DimUnit.Ratio);
}
@computed
@@ -64,10 +63,10 @@ export class CollectionMultirowView extends CollectionSubView() {
let starSum = 0;
const heightSpecifiers: HeightSpecifier[] = [];
this.childLayoutPairs.map(pair => {
- const unit = StrCast(pair.layout._dimUnit, "*");
+ const unit = StrCast(pair.layout._dimUnit, '*');
const magnitude = NumCast(pair.layout._dimMagnitude, this.minimumDim);
if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) {
- (unit === DimUnit.Ratio) && (starSum += magnitude);
+ unit === DimUnit.Ratio && (starSum += magnitude);
heightSpecifiers.push({ magnitude, unit });
}
/**
@@ -99,14 +98,13 @@ export class CollectionMultirowView extends CollectionSubView() {
* This returns the total quantity, in pixels, that this
* view needs to reserve for child documents that have
* (with higher priority) requested a fixed pixel width.
- *
+ *
* If the underlying resolvedLayoutInformation returns null
* because we're waiting on promises to resolve, this value will be undefined as well.
*/
@computed
private get totalFixedAllocation(): number | undefined {
- return this.resolvedLayoutInformation?.heightSpecifiers.reduce(
- (sum, { magnitude, unit }) => sum + (unit === DimUnit.Pixel ? magnitude : 0), 0);
+ return this.resolvedLayoutInformation?.heightSpecifiers.reduce((sum, { magnitude, unit }) => sum + (unit === DimUnit.Pixel ? magnitude : 0), 0);
}
/**
@@ -114,7 +112,7 @@ export class CollectionMultirowView extends CollectionSubView() {
* view needs to reserve for child documents that have
* (with lower priority) requested a certain relative proportion of the
* remaining pixel width not allocated for fixed widths.
- *
+ *
* If the underlying totalFixedAllocation returns undefined
* because we're waiting indirectly on promises to resolve, this value will be undefined as well.
*/
@@ -134,7 +132,7 @@ export class CollectionMultirowView extends CollectionSubView() {
* this accessor returns 1000 / (2 + 2 + 1), or 200px.
* Elsewhere, this is then multiplied by each relative-width
* document's (potentially decimal) * count to compute its actual width (400px, 400px and 200px).
- *
+ *
* If the underlying totalRatioAllocation or this.resolveLayoutInformation return undefined
* because we're waiting indirectly on promises to resolve, this value will be undefined as well.
*/
@@ -164,17 +162,17 @@ export class CollectionMultirowView extends CollectionSubView() {
return 0; // we're still waiting on promises to resolve
}
let height = NumCast(layout._dimMagnitude, this.minimumDim);
- if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) {
+ if (StrCast(layout._dimUnit, '*') === DimUnit.Ratio) {
height *= rowUnitLength;
}
return height;
- }
+ };
/**
* @returns the transform that will correctly place
* the document decorations box, shifted to the right by
* the sum of all the resolved row widths of the
- * documents before the target.
+ * documents before the target.
*/
private lookupIndividualTransform = (layout: Doc) => {
const rowUnitLength = this.rowUnitLength;
@@ -184,13 +182,12 @@ export class CollectionMultirowView extends CollectionSubView() {
let offset = 0;
for (const { layout: candidate } of this.childLayoutPairs) {
if (candidate === layout) {
- return this.props.ScreenToLocalTransform().translate(0, -offset / (this.props.scaling?.() || 1));
+ return this.props.ScreenToLocalTransform().translate(0, -offset / (this.props.NativeDimScaling?.() || 1));
}
offset += this.lookupPixels(candidate) + resizerHeight;
}
return Transform.Identity(); // type coersion, this case should never be hit
- }
-
+ };
@undoBatch
@action
@@ -198,16 +195,17 @@ export class CollectionMultirowView extends CollectionSubView() {
let dropInd = -1;
if (de.complete.docDragData && this._mainCont) {
let curInd = -1;
- de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
- curInd = this.childDocs.indexOf(d);
- }));
+ de.complete.docDragData?.droppedDocuments.forEach(
+ action((d: Doc) => {
+ curInd = this.childDocs.indexOf(d);
+ })
+ );
Array.from(this._mainCont.children).forEach((child, index) => {
const brect = child.getBoundingClientRect();
if (brect.y < de.y && brect.y + brect.height > de.y) {
if (curInd !== -1 && curInd === Math.floor(index / 2)) {
dropInd = curInd;
- }
- else if (child.className === "multiColumnResizer") {
+ } else if (child.className === 'multiColumnResizer') {
dropInd = Math.floor(index / 2);
} else {
dropInd = Math.ceil(index / 2 + (de.y - brect.y > brect.height / 2 ? 0 : -1));
@@ -215,75 +213,79 @@ export class CollectionMultirowView extends CollectionSubView() {
}
});
if (super.onInternalDrop(e, de)) {
- de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
- d._dimUnit = "*";
- d._dimMagnitude = 1;
- if (dropInd !== curInd || dropInd === -1) {
- if (this.childDocs.includes(d)) {
- if (dropInd > this.childDocs.indexOf(d)) dropInd--;
+ de.complete.docDragData?.droppedDocuments.forEach(
+ action((d: Doc) => {
+ d._dimUnit = '*';
+ d._dimMagnitude = 1;
+ if (dropInd !== curInd || dropInd === -1) {
+ if (this.childDocs.includes(d)) {
+ if (dropInd > this.childDocs.indexOf(d)) dropInd--;
+ }
+ Doc.RemoveDocFromList(this.rootDoc, this.props.fieldKey, d);
+ Doc.AddDocToList(this.rootDoc, this.props.fieldKey, d, DocListCast(this.rootDoc[this.props.fieldKey])[dropInd], undefined, dropInd === -1);
}
- Doc.RemoveDocFromList(this.rootDoc, this.props.fieldKey, d);
- Doc.AddDocToList(this.rootDoc, this.props.fieldKey, d, DocListCast(this.rootDoc[this.props.fieldKey])[dropInd], undefined, dropInd === -1);
- }
- }));
+ })
+ );
}
}
return false;
- }
-
+ };
onChildClickHandler = () => ScriptCast(this.Document.onChildClick);
onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick);
addDocTab = (doc: Doc, where: string) => {
- if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) {
+ if (where === 'inPlace' && this.layoutDoc.isInPlaceContainer) {
this.dataDoc[this.props.fieldKey] = new List<Doc>([doc]);
return true;
}
return this.props.addDocTab(doc, where);
- }
+ };
isContentActive = () => this.props.isSelected() || this.props.isContentActive();
- isChildContentActive = () => ((this.props.childDocumentsActive?.() || this.Document._childDocumentsActive) && this.props.isDocumentActive?.() && SnappingManager.GetIsDragging()) || this.props.isSelected() || this.props.isAnyChildContentActive() ? true : false;
+ isChildContentActive = () =>
+ ((this.props.childDocumentsActive?.() || this.Document._childDocumentsActive) && this.props.isDocumentActive?.() && SnappingManager.GetIsDragging()) || this.props.isSelected() || this.props.isAnyChildContentActive() ? true : false;
getDisplayDoc = (layout: Doc, dxf: () => Transform, width: () => number, height: () => number) => {
- return <DocumentView
- Document={layout}
- DataDoc={layout.resolvedDataDoc as Doc}
- styleProvider={this.props.styleProvider}
- docViewPath={this.props.docViewPath}
- LayoutTemplate={this.props.childLayoutTemplate}
- LayoutTemplateString={this.props.childLayoutString}
- renderDepth={this.props.renderDepth + 1}
- PanelWidth={width}
- PanelHeight={height}
- rootSelected={this.rootSelected}
- dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
- onClick={this.onChildClickHandler}
- onDoubleClick={this.onChildDoubleClickHandler}
- ScreenToLocalTransform={dxf}
- isContentActive={this.isChildContentActive}
- isDocumentActive={this.props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
- hideResizeHandles={this.props.childHideResizeHandles?.()}
- hideDecorationTitle={this.props.childHideDecorationTitle?.()}
- fitContentsToBox={this.props.fitContentsToBox}
- focus={this.props.focus}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
- searchFilterDocs={this.searchFilterDocs}
- ContainingCollectionDoc={this.props.CollectionView?.props.Document}
- ContainingCollectionView={this.props.CollectionView}
- dontRegisterView={this.props.dontRegisterView}
- addDocument={this.props.addDocument}
- moveDocument={this.props.moveDocument}
- removeDocument={this.props.removeDocument}
- whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
- addDocTab={this.addDocTab}
- pinToPres={this.props.pinToPres}
- bringToFront={returnFalse}
- />;
- }
+ return (
+ <DocumentView
+ Document={layout}
+ DataDoc={layout.resolvedDataDoc as Doc}
+ styleProvider={this.props.styleProvider}
+ docViewPath={this.props.docViewPath}
+ LayoutTemplate={this.props.childLayoutTemplate}
+ LayoutTemplateString={this.props.childLayoutString}
+ renderDepth={this.props.renderDepth + 1}
+ PanelWidth={width}
+ PanelHeight={height}
+ rootSelected={this.rootSelected}
+ dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
+ onClick={this.onChildClickHandler}
+ onDoubleClick={this.onChildDoubleClickHandler}
+ ScreenToLocalTransform={dxf}
+ isContentActive={this.isChildContentActive}
+ isDocumentActive={this.props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
+ hideResizeHandles={this.props.childHideResizeHandles?.()}
+ hideDecorationTitle={this.props.childHideDecorationTitle?.()}
+ fitContentsToBox={this.props.fitContentsToBox}
+ focus={this.props.focus}
+ docFilters={this.childDocFilters}
+ docRangeFilters={this.childDocRangeFilters}
+ searchFilterDocs={this.searchFilterDocs}
+ ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+ ContainingCollectionView={this.props.CollectionView}
+ dontRegisterView={this.props.dontRegisterView}
+ addDocument={this.props.addDocument}
+ moveDocument={this.props.moveDocument}
+ removeDocument={this.props.removeDocument}
+ whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+ addDocTab={this.addDocTab}
+ pinToPres={this.props.pinToPres}
+ bringToFront={returnFalse}
+ />
+ );
+ };
/**
* @returns the resolved list of rendered child documents, displayed
- * at their resolved pixel widths, each separated by a resizer.
+ * at their resolved pixel widths, each separated by a resizer.
*/
@computed
private get contents(): JSX.Element[] | null {
@@ -292,13 +294,14 @@ export class CollectionMultirowView extends CollectionSubView() {
const collector: JSX.Element[] = [];
for (let i = 0; i < childLayoutPairs.length; i++) {
const { layout } = childLayoutPairs[i];
- const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1));
+ const dxf = () =>
+ this.lookupIndividualTransform(layout)
+ .translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin))
+ .scale(this.props.NativeDimScaling?.() || 1);
const height = () => this.lookupPixels(layout);
const width = () => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
collector.push(
- <div className={"document-wrapper"}
- style={{ height: height() }}
- key={"wrapper" + i} >
+ <div className={'document-wrapper'} style={{ height: height() }} key={'wrapper' + i}>
{this.getDisplayDoc(layout, dxf, width, height)}
<HeightLabel layout={layout} collectionDoc={Document} />
</div>,
@@ -306,7 +309,7 @@ export class CollectionMultirowView extends CollectionSubView() {
height={resizerHeight}
styleProvider={this.props.styleProvider}
isContentActive={this.props.isContentActive}
- key={"resizer" + i}
+ key={'resizer' + i}
columnUnitLength={this.getRowUnitLength}
toTop={layout}
toBottom={childLayoutPairs[i + 1]?.layout}
@@ -319,16 +322,19 @@ export class CollectionMultirowView extends CollectionSubView() {
render(): JSX.Element {
return (
- <div className={"collectionMultirowView_contents"}
+ <div
+ className={'collectionMultirowView_contents'}
style={{
width: `calc(100% - ${2 * NumCast(this.props.Document._xMargin)}px)`,
height: `calc(100% - ${2 * NumCast(this.props.Document._yMargin)}px)`,
- marginLeft: NumCast(this.props.Document._xMargin), marginRight: NumCast(this.props.Document._xMargin),
- marginTop: NumCast(this.props.Document._yMargin), marginBottom: NumCast(this.props.Document._yMargin)
- }} ref={this.createDashEventsTarget}>
+ marginLeft: NumCast(this.props.Document._xMargin),
+ marginRight: NumCast(this.props.Document._xMargin),
+ marginTop: NumCast(this.props.Document._yMargin),
+ marginBottom: NumCast(this.props.Document._yMargin),
+ }}
+ ref={this.createDashEventsTarget}>
{this.contents}
</div>
);
}
-
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index f1d8123da..381436a56 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -118,7 +118,7 @@ export class DocumentContentsView extends React.Component<
FormattedTextBoxProps & {
isSelected: (outsideReaction: boolean) => boolean;
select: (ctrl: boolean) => void;
- scaling?: () => number;
+ NativeDimScaling?: () => number;
setHeight?: (height: number) => void;
layoutKey: string;
}
@@ -161,7 +161,6 @@ export class DocumentContentsView extends React.Component<
'LayoutTemplateString',
'LayoutTemplate',
'dontCenter',
- 'ContentScaling',
'contextMenuItems',
'onClick',
'onDoubleClick',
@@ -195,7 +194,7 @@ export class DocumentContentsView extends React.Component<
// replace HTML<tag> with corresponding HTML tag as in: <HTMLdiv> becomes <HTMLtag Document={props.Document} htmltag='div'>
const replacer2 = (match: any, p1: string, offset: any, string: any) => {
- return `<HTMLtag RootDoc={props.RootDoc} Document={props.Document} scaling='${this.props.scaling?.() || 1}' htmltag='${p1}'`;
+ return `<HTMLtag RootDoc={props.RootDoc} Document={props.Document} scaling='${this.props.NativeDimScaling?.() || 1}' htmltag='${p1}'`;
};
layoutFrame = layoutFrame.replace(/<HTML([a-zA-Z0-9_-]+)/g, replacer2);
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 78d35ab99..5939d1680 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -1,24 +1,24 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
-import { action, computed, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { Doc, Opt } from "../../../fields/Doc";
-import { StrCast } from "../../../fields/Types";
-import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../../Utils";
-import { DocUtils } from "../../documents/Documents";
-import { DragManager } from "../../util/DragManager";
-import { Hypothesis } from "../../util/HypothesisUtils";
-import { LinkManager } from "../../util/LinkManager";
-import { undoBatch, UndoManager } from "../../util/UndoManager";
-import { Colors } from "../global/globalEnums";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Tooltip } from '@material-ui/core';
+import { action, computed, observable, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import { Doc, Opt } from '../../../fields/Doc';
+import { StrCast } from '../../../fields/Types';
+import { TraceMobx } from '../../../fields/util';
+import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils';
+import { DocUtils } from '../../documents/Documents';
+import { DragManager } from '../../util/DragManager';
+import { Hypothesis } from '../../util/HypothesisUtils';
+import { LinkManager } from '../../util/LinkManager';
+import { undoBatch, UndoManager } from '../../util/UndoManager';
+import { Colors } from '../global/globalEnums';
import './DocumentLinksButton.scss';
-import { DocumentView } from "./DocumentView";
-import { LinkDescriptionPopup } from "./LinkDescriptionPopup";
-import { TaskCompletionBox } from "./TaskCompletedBox";
-import React = require("react");
+import { DocumentView } from './DocumentView';
+import { LinkDescriptionPopup } from './LinkDescriptionPopup';
+import { TaskCompletionBox } from './TaskCompletedBox';
+import React = require('react');
-const higflyout = require("@hig/flyout");
+const higflyout = require('@hig/flyout');
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -28,7 +28,7 @@ interface DocumentLinksButtonProps {
AlwaysOn?: boolean;
InMenu?: boolean;
StartLink?: boolean; //whether the link HAS been started (i.e. now needs to be completed)
- ContentScaling?: () => number;
+ scaling?: () => number; // how uch doc is scaled so that link buttons can invert it
}
@observer
export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> {
@@ -42,53 +42,71 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
@observable public static invisibleWebDoc: Opt<Doc>;
public static invisibleWebRef = React.createRef<HTMLDivElement>();
- @action @undoBatch
+ @action
+ @undoBatch
onLinkButtonMoved = (e: PointerEvent) => {
if (this.props.InMenu && this.props.StartLink) {
if (this._linkButton.current !== null) {
- const linkDrag = UndoManager.StartBatch("Drag Link");
- this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View, this.props.View.ComponentView?.getAnchor, e.pageX, e.pageY, {
- dragComplete: dropEv => {
- if (this.props.View && dropEv.linkDocument) {// dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
- !dropEv.linkDocument.linkRelationship && (Doc.GetProto(dropEv.linkDocument).linkRelationship = "hyperlink");
- }
- linkDrag?.end();
- },
- hideSource: false
- });
+ const linkDrag = UndoManager.StartBatch('Drag Link');
+ this.props.View &&
+ DragManager.StartLinkDrag(this._linkButton.current, this.props.View, this.props.View.ComponentView?.getAnchor, e.pageX, e.pageY, {
+ dragComplete: dropEv => {
+ if (this.props.View && dropEv.linkDocument) {
+ // dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
+ !dropEv.linkDocument.linkRelationship && (Doc.GetProto(dropEv.linkDocument).linkRelationship = 'hyperlink');
+ }
+ linkDrag?.end();
+ },
+ hideSource: false,
+ });
return true;
}
return false;
}
return false;
- }
+ };
onLinkMenuOpen = (e: React.PointerEvent): void => {
- setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
- if (doubleTap) {
- DocumentView.showBackLinks(this.props.View.rootDoc);
- }
- }), undefined, undefined,
- action(() => DocumentLinksButton.LinkEditorDocView = this.props.View));
- }
+ setupMoveUpEvents(
+ this,
+ e,
+ this.onLinkButtonMoved,
+ emptyFunction,
+ action((e, doubleTap) => {
+ if (doubleTap) {
+ DocumentView.showBackLinks(this.props.View.rootDoc);
+ }
+ }),
+ undefined,
+ undefined,
+ action(() => (DocumentLinksButton.LinkEditorDocView = this.props.View))
+ );
+ };
@undoBatch
onLinkButtonDown = (e: React.PointerEvent): void => {
- setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
- if (doubleTap && this.props.InMenu && this.props.StartLink) {
- //action(() => Doc.BrushDoc(this.props.View.Document));
- if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
- DocumentLinksButton.StartLink = undefined;
- DocumentLinksButton.StartLinkView = undefined;
- } else {
- DocumentLinksButton.StartLink = this.props.View.props.Document;
- DocumentLinksButton.StartLinkView = this.props.View;
+ setupMoveUpEvents(
+ this,
+ e,
+ this.onLinkButtonMoved,
+ emptyFunction,
+ action((e, doubleTap) => {
+ if (doubleTap && this.props.InMenu && this.props.StartLink) {
+ //action(() => Doc.BrushDoc(this.props.View.Document));
+ if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
+ DocumentLinksButton.StartLink = undefined;
+ DocumentLinksButton.StartLinkView = undefined;
+ } else {
+ DocumentLinksButton.StartLink = this.props.View.props.Document;
+ DocumentLinksButton.StartLinkView = this.props.View;
+ }
}
- }
- }));
- }
+ })
+ );
+ };
- @action @undoBatch
+ @action
+ @undoBatch
onLinkClick = (e: React.MouseEvent): void => {
if (this.props.InMenu && this.props.StartLink) {
DocumentLinksButton.AnnotationId = undefined;
@@ -96,108 +114,125 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
- } else { //if this LinkButton's Document is undefined
+ } else {
+ //if this LinkButton's Document is undefined
DocumentLinksButton.StartLink = this.props.View.props.Document;
DocumentLinksButton.StartLinkView = this.props.View;
}
//action(() => Doc.BrushDoc(this.props.View.Document));
}
- }
-
+ };
completeLink = (e: React.PointerEvent): void => {
- setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action((e, doubleTap) => {
- if (doubleTap && !this.props.StartLink) {
- if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
- DocumentLinksButton.StartLink = undefined;
- DocumentLinksButton.StartLinkView = undefined;
- DocumentLinksButton.AnnotationId = undefined;
- } else if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) {
- const sourceDoc = DocumentLinksButton.StartLink;
- const targetDoc = this.props.View.ComponentView?.getAnchor?.() || this.props.View.Document;
- const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, "links"); //why is long drag here when this is used for completing links by clicking?
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ emptyFunction,
+ undoBatch(
+ action((e, doubleTap) => {
+ if (doubleTap && !this.props.StartLink) {
+ if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
+ DocumentLinksButton.StartLink = undefined;
+ DocumentLinksButton.StartLinkView = undefined;
+ DocumentLinksButton.AnnotationId = undefined;
+ } else if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) {
+ const sourceDoc = DocumentLinksButton.StartLink;
+ const targetDoc = this.props.View.ComponentView?.getAnchor?.() || this.props.View.Document;
+ const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, 'links'); //why is long drag here when this is used for completing links by clicking?
- LinkManager.currentLink = linkDoc;
+ LinkManager.currentLink = linkDoc;
- runInAction(() => {
- if (linkDoc) {
- TaskCompletionBox.textDisplayed = "Link Created";
- TaskCompletionBox.popupX = e.screenX;
- TaskCompletionBox.popupY = e.screenY - 133;
- TaskCompletionBox.taskCompleted = true;
+ runInAction(() => {
+ if (linkDoc) {
+ TaskCompletionBox.textDisplayed = 'Link Created';
+ TaskCompletionBox.popupX = e.screenX;
+ TaskCompletionBox.popupY = e.screenY - 133;
+ TaskCompletionBox.taskCompleted = true;
- LinkDescriptionPopup.popupX = e.screenX;
- LinkDescriptionPopup.popupY = e.screenY - 100;
- LinkDescriptionPopup.descriptionPopup = true;
+ LinkDescriptionPopup.popupX = e.screenX;
+ LinkDescriptionPopup.popupY = e.screenY - 100;
+ LinkDescriptionPopup.descriptionPopup = true;
- const rect = document.body.getBoundingClientRect();
- if (LinkDescriptionPopup.popupX + 200 > rect.width) {
- LinkDescriptionPopup.popupX -= 190;
- TaskCompletionBox.popupX -= 40;
- }
- if (LinkDescriptionPopup.popupY + 100 > rect.height) {
- LinkDescriptionPopup.popupY -= 40;
- TaskCompletionBox.popupY -= 40;
- }
+ const rect = document.body.getBoundingClientRect();
+ if (LinkDescriptionPopup.popupX + 200 > rect.width) {
+ LinkDescriptionPopup.popupX -= 190;
+ TaskCompletionBox.popupX -= 40;
+ }
+ if (LinkDescriptionPopup.popupY + 100 > rect.height) {
+ LinkDescriptionPopup.popupY -= 40;
+ TaskCompletionBox.popupY -= 40;
+ }
- setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
+ setTimeout(
+ action(() => (TaskCompletionBox.taskCompleted = false)),
+ 2500
+ );
+ }
+ });
}
- });
- }
- }
- })));
- }
+ }
+ })
+ )
+ );
+ };
- public static finishLinkClick = undoBatch(action((screenX: number, screenY: number, startLink: Doc, endLink: Doc, startIsAnnotation: boolean, endLinkView?: DocumentView,) => {
- if (startLink === endLink) {
- DocumentLinksButton.StartLink = undefined;
- DocumentLinksButton.StartLinkView = undefined;
- DocumentLinksButton.AnnotationId = undefined;
- DocumentLinksButton.AnnotationUri = undefined;
- //!this.props.StartLink
- } else if (startLink !== endLink) {
- endLink = endLinkView?.docView?._componentView?.getAnchor?.() || endLink;
- startLink = DocumentLinksButton.StartLinkView?.docView?._componentView?.getAnchor?.() || startLink;
- const linkDoc = DocUtils.MakeLink({ doc: startLink }, { doc: endLink },
- DocumentLinksButton.AnnotationId ? "hypothes.is annotation" : undefined, undefined, undefined, true);
+ public static finishLinkClick = undoBatch(
+ action((screenX: number, screenY: number, startLink: Doc, endLink: Doc, startIsAnnotation: boolean, endLinkView?: DocumentView) => {
+ if (startLink === endLink) {
+ DocumentLinksButton.StartLink = undefined;
+ DocumentLinksButton.StartLinkView = undefined;
+ DocumentLinksButton.AnnotationId = undefined;
+ DocumentLinksButton.AnnotationUri = undefined;
+ //!this.props.StartLink
+ } else if (startLink !== endLink) {
+ endLink = endLinkView?.docView?._componentView?.getAnchor?.() || endLink;
+ startLink = DocumentLinksButton.StartLinkView?.docView?._componentView?.getAnchor?.() || startLink;
+ const linkDoc = DocUtils.MakeLink({ doc: startLink }, { doc: endLink }, DocumentLinksButton.AnnotationId ? 'hypothes.is annotation' : undefined, undefined, undefined, true);
- LinkManager.currentLink = linkDoc;
+ LinkManager.currentLink = linkDoc;
- if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) { // if linking from a Hypothes.is annotation
- Doc.GetProto(linkDoc as Doc).linksToAnnotation = true;
- Doc.GetProto(linkDoc as Doc).annotationId = DocumentLinksButton.AnnotationId;
- Doc.GetProto(linkDoc as Doc).annotationUri = DocumentLinksButton.AnnotationUri;
- const dashHyperlink = Doc.globalServerPath(startIsAnnotation ? endLink : startLink);
- Hypothesis.makeLink(StrCast(startIsAnnotation ? endLink.title : startLink.title), dashHyperlink, DocumentLinksButton.AnnotationId,
- (startIsAnnotation ? startLink : endLink)); // edit annotation to add a Dash hyperlink to the linked doc
- }
+ if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) {
+ // if linking from a Hypothes.is annotation
+ Doc.GetProto(linkDoc as Doc).linksToAnnotation = true;
+ Doc.GetProto(linkDoc as Doc).annotationId = DocumentLinksButton.AnnotationId;
+ Doc.GetProto(linkDoc as Doc).annotationUri = DocumentLinksButton.AnnotationUri;
+ const dashHyperlink = Doc.globalServerPath(startIsAnnotation ? endLink : startLink);
+ Hypothesis.makeLink(StrCast(startIsAnnotation ? endLink.title : startLink.title), dashHyperlink, DocumentLinksButton.AnnotationId, startIsAnnotation ? startLink : endLink); // edit annotation to add a Dash hyperlink to the linked doc
+ }
- if (linkDoc) {
- TaskCompletionBox.textDisplayed = "Link Created";
- TaskCompletionBox.popupX = screenX;
- TaskCompletionBox.popupY = screenY - 133;
- TaskCompletionBox.taskCompleted = true;
+ if (linkDoc) {
+ TaskCompletionBox.textDisplayed = 'Link Created';
+ TaskCompletionBox.popupX = screenX;
+ TaskCompletionBox.popupY = screenY - 133;
+ TaskCompletionBox.taskCompleted = true;
- if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
- LinkDescriptionPopup.popupX = screenX;
- LinkDescriptionPopup.popupY = screenY - 100;
- LinkDescriptionPopup.descriptionPopup = true;
- }
+ if (LinkDescriptionPopup.showDescriptions === 'ON' || !LinkDescriptionPopup.showDescriptions) {
+ LinkDescriptionPopup.popupX = screenX;
+ LinkDescriptionPopup.popupY = screenY - 100;
+ LinkDescriptionPopup.descriptionPopup = true;
+ }
- const rect = document.body.getBoundingClientRect();
- if (LinkDescriptionPopup.popupX + 200 > rect.width) {
- LinkDescriptionPopup.popupX -= 190;
- TaskCompletionBox.popupX -= 40;
- }
- if (LinkDescriptionPopup.popupY + 100 > rect.height) {
- LinkDescriptionPopup.popupY -= 40;
- TaskCompletionBox.popupY -= 40;
- }
+ const rect = document.body.getBoundingClientRect();
+ if (LinkDescriptionPopup.popupX + 200 > rect.width) {
+ LinkDescriptionPopup.popupX -= 190;
+ TaskCompletionBox.popupX -= 40;
+ }
+ if (LinkDescriptionPopup.popupY + 100 > rect.height) {
+ LinkDescriptionPopup.popupY -= 40;
+ TaskCompletionBox.popupY -= 40;
+ }
- setTimeout(action(() => { TaskCompletionBox.taskCompleted = false; }), 2500);
+ setTimeout(
+ action(() => {
+ TaskCompletionBox.taskCompleted = false;
+ }),
+ 2500
+ );
+ }
}
- }
- }));
+ })
+ );
@action clearLinks() {
DocumentLinksButton.StartLink = undefined;
@@ -208,9 +243,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
const results = [] as Doc[];
const filters = this.props.View.props.docFilters();
Array.from(new Set<Doc>(this.props.View.allLinks)).forEach(link => {
- if (DocUtils.FilterDocs([link], filters, []).length ||
- DocUtils.FilterDocs([link.anchor2 as Doc], filters, []).length ||
- DocUtils.FilterDocs([link.anchor1 as Doc], filters, []).length) {
+ if (DocUtils.FilterDocs([link], filters, []).length || DocUtils.FilterDocs([link.anchor2 as Doc], filters, []).length || DocUtils.FilterDocs([link.anchor1 as Doc], filters, []).length) {
results.push(link);
}
});
@@ -219,48 +252,45 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
/**
* gets the JSX of the link button (btn used to start/complete links) OR the link-view button (btn on bottom left of each linked node)
- *
+ *
* todo:glr / anh seperate functionality such as onClick onPointerDown of link menu button
*/
@computed get linkButtonInner() {
- const btnDim = "30px";
- const link = <img style={{ width: "22px", height: "16px" }} src={`/assets/${"link.png"}`} />;
- const isActive = (DocumentLinksButton.StartLink === this.props.View.props.Document) && this.props.StartLink;
- return (!this.props.InMenu ?
- <div className="documentLinksButton-cont"
- style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}
- >
- <div className={"documentLinksButton"}
- onPointerDown={this.onLinkMenuOpen} onClick={this.onLinkClick}
+ const btnDim = '30px';
+ const link = <img style={{ width: '22px', height: '16px' }} src={`/assets/${'link.png'}`} />;
+ const isActive = DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink;
+ return !this.props.InMenu ? (
+ <div className="documentLinksButton-cont" style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}>
+ <div
+ className={'documentLinksButton'}
+ onPointerDown={this.onLinkMenuOpen}
+ onClick={this.onLinkClick}
style={{
backgroundColor: Colors.LIGHT_BLUE,
color: Colors.BLACK,
- fontSize: "20px",
+ fontSize: '20px',
width: btnDim,
height: btnDim,
}}>
{Array.from(this.filteredLinks).length}
</div>
</div>
- :
- <div className="documentLinksButton-menu" >
- {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? //if the origin node is not this node
- <div className={"documentLinksButton-endLink"} ref={this._linkButton}
+ ) : (
+ <div className="documentLinksButton-menu">
+ {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node
+ <div
+ className={'documentLinksButton-endLink'}
+ ref={this._linkButton}
onPointerDown={DocumentLinksButton.StartLink && this.completeLink}
onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)}>
<FontAwesomeIcon className="documentdecorations-icon" icon="link" />
</div>
- : (null)
- }
- {
- this.props.InMenu && this.props.StartLink ? //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
- <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton}
- onPointerDown={isActive ? undefined : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}>
- <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
- </div>
- :
- (null)
- }
+ ) : null}
+ {this.props.InMenu && this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
+ <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? undefined : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}>
+ <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
+ </div>
+ ) : null}
</div>
);
}
@@ -268,25 +298,23 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
render() {
TraceMobx();
- const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link";
- const buttonTitle = "Tap to view links; double tap to open link collection";
+ const menuTitle = this.props.StartLink ? 'Drag or tap to start link' : 'Tap to complete link';
+ const buttonTitle = 'Tap to view links; double tap to open link collection';
const title = this.props.InMenu ? menuTitle : buttonTitle;
//render circular tooltip if it isn't set to invisible and show the number of doc links the node has, and render inner-menu link button for starting/stopping links if currently in menu
- return (!Array.from(this.filteredLinks).length && !this.props.AlwaysOn) ? (null) :
- <div className="documentLinksButton-wrapper"
+ return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? null : (
+ <div
+ className="documentLinksButton-wrapper"
style={{
- transform: this.props.InMenu ? undefined :
- `scale(${(this.props.ContentScaling?.() || 1) * this.props.View.screenToLocalTransform().Scale})`
- }} >
- {
- (this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) ||
- (!DocumentLinksButton.LinkEditorDocView && !this.props.InMenu) ?
- <Tooltip title={<div className="dash-tooltip">{title}</div>}>
- {this.linkButtonInner}
- </Tooltip>
- : this.linkButtonInner
- }
- </div>;
+ transform: this.props.InMenu ? undefined : `scale(${this.props.scaling})`,
+ }}>
+ {(this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) || (!DocumentLinksButton.LinkEditorDocView && !this.props.InMenu) ? (
+ <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>
+ ) : (
+ this.linkButtonInner
+ )}
+ </div>
+ );
}
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3a8552325..6bf0c365a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -175,7 +175,6 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
LayoutTemplateString?: string;
dontCenter?: 'x' | 'y' | 'xy';
dontScaleFilter?: (doc: Doc) => boolean; // decides whether a document can be scaled to fit its container vs native size with scrolling
- ContentScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal
NativeWidth?: () => number;
NativeHeight?: () => number;
LayoutTemplate?: () => Opt<Doc>;
@@ -192,6 +191,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
export interface DocumentViewInternalProps extends DocumentViewProps {
NativeWidth: () => number;
NativeHeight: () => number;
+ NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps
isSelected: (outsideReaction?: boolean) => boolean;
select: (ctrlPressed: boolean) => void;
DocumentView: () => DocumentView;
@@ -235,8 +235,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
@computed get ShowTitle() {
return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as Opt<string>;
}
- @computed get ContentScale() {
- return this.props.ContentScaling?.() || 1;
+ @computed get NativeDimScaling() {
+ return this.props.NativeDimScaling?.() || 1;
}
@computed get thumb() {
return ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb))?.url.href.replace('.png', '_m.png');
@@ -428,7 +428,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
let nheight = Doc.NativeHeight(layoutDoc);
const width = layoutDoc._width || 0;
const height = layoutDoc._height || (nheight / nwidth) * width;
- const scale = this.props.ScreenToLocalTransform().Scale * this.ContentScale;
+ const scale = this.props.ScreenToLocalTransform().Scale * this.NativeDimScaling;
const actualdW = Math.max(width + dW * scale, 20);
const actualdH = Math.max(height + dH * scale, 20);
doc.x = (doc.x || 0) + dX * (actualdW - width);
@@ -491,10 +491,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
if (this._mainCont.current) {
const dragData = new DragManager.DocumentDragData([this.props.Document]);
- const [left, top] = this.props.ScreenToLocalTransform().scale(this.ContentScale).inverse().transformPoint(0, 0);
+ const [left, top] = this.props.ScreenToLocalTransform().scale(this.NativeDimScaling).inverse().transformPoint(0, 0);
dragData.offset = this.props
.ScreenToLocalTransform()
- .scale(this.ContentScale)
+ .scale(this.NativeDimScaling)
.transformDirection(x - left, y - top);
dragData.offset[0] = Math.min(this.rootDoc[WidthSym](), dragData.offset[0]);
dragData.offset[1] = Math.min(this.rootDoc[HeightSym](), dragData.offset[1]);
@@ -961,7 +961,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
panelHeight = () => this.props.PanelHeight() - this.headerMargin;
screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
- contentScaling = () => this.ContentScale;
onClickFunc = () => this.onClickHandler;
setHeight = (height: number) => (this.layoutDoc._height = height);
setContentView = action((view: { getAnchor?: () => Doc; forward?: () => boolean; back?: () => boolean }) => (this._componentView = view));
@@ -989,6 +988,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
? true
: false;
};
+ linkButtonInverseScaling = () => (this.props.NativeDimScaling?.() || 1) * this.props.DocumentView().screenToLocalTransform().Scale;
@computed get contents() {
TraceMobx();
const audioView = !this.layoutDoc._showAudio ? null : (
@@ -1041,7 +1041,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
thumbShown={this.thumbShown}
isHovering={this.isHovering}
setContentView={this.setContentView}
- scaling={this.contentScaling}
+ NativeDimScaling={this.props.NativeDimScaling}
PanelHeight={this.panelHeight}
setHeight={!this.props.suppressSetHeight ? this.setHeight : undefined}
isContentActive={this.isContentActive}
@@ -1055,7 +1055,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
{(!this.props.isSelected() && !this._isHovering) || this.hideLinkButton || this.props.renderDepth === -1 || SnappingManager.GetIsDragging() ? null : (
<DocumentLinksButton
View={this.props.DocumentView()}
- ContentScaling={this.props.ContentScaling}
+ scaling={this.linkButtonInverseScaling}
Offset={[this.topMost ? 0 : !this.props.isSelected() ? -15 : -30, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? -15 : -30]}
/>
)}
@@ -1503,7 +1503,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return this.props.dontCenter?.includes('y') ? 0 : this.Yshift;
}
- toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight());
+ toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this.props.PanelWidth(), this.props.PanelHeight());
focus = (doc: Doc, options?: DocFocusOptions) => this.docView?.focus(doc, options);
getBounds = () => {
if (!this.docView || !this.docView.ContentDiv || this.props.Document.presBox || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
@@ -1564,7 +1564,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
NativeHeight = () => this.effectiveNativeHeight;
PanelWidth = () => this.panelWidth;
PanelHeight = () => this.panelHeight;
- ContentScale = () => this.nativeScaling;
+ NativeDimScaling = () => this.nativeScaling;
selfView = () => this;
screenToLocalTransform = () =>
this.props
@@ -1620,9 +1620,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
PanelHeight={this.PanelHeight}
NativeWidth={this.NativeWidth}
NativeHeight={this.NativeHeight}
+ NativeDimScaling={this.NativeDimScaling}
isSelected={this.isSelected}
select={this.select}
- ContentScaling={this.ContentScale}
ScreenToLocalTransform={this.screenToLocalTransform}
focus={this.props.focus || emptyFunction}
ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))}
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index c170f9867..a714518cc 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -12,11 +12,12 @@ import { LightboxView } from '../LightboxView';
import './EquationBox.scss';
import { FieldView, FieldViewProps } from './FieldView';
-
@observer
export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(EquationBox, fieldKey); }
- public static SelectOnLoad: string = "";
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(EquationBox, fieldKey);
+ }
+ public static SelectOnLoad: string = '';
_ref: React.RefObject<EquationEditor> = React.createRef();
componentDidMount() {
if (EquationBox.SelectOnLoad === this.rootDoc[Id] && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath()))) {
@@ -25,75 +26,82 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._ref.current!.mathField.focus();
this._ref.current!.mathField.select();
}
- reaction(() => StrCast(this.dataDoc.text),
+ reaction(
+ () => StrCast(this.dataDoc.text),
text => {
if (text && text !== this._ref.current!.mathField.latex()) {
this._ref.current!.mathField.latex(text);
}
- });
- reaction(() => this.props.isSelected(),
+ }
+ );
+ reaction(
+ () => this.props.isSelected(),
selected => {
if (this._ref.current) {
- if (selected) this._ref.current.element.current.children[0].addEventListener("keydown", this.keyPressed, true);
- else this._ref.current.element.current.children[0].removeEventListener("keydown", this.keyPressed);
+ if (selected) this._ref.current.element.current.children[0].addEventListener('keydown', this.keyPressed, true);
+ else this._ref.current.element.current.children[0].removeEventListener('keydown', this.keyPressed);
}
- }, { fireImmediately: true });
+ },
+ { fireImmediately: true }
+ );
}
plot: any;
@action
keyPressed = (e: KeyboardEvent) => {
- const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace("px", ""));
- const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace("px", ""));
- if (e.key === "Enter") {
+ const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace('px', ''));
+ const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace('px', ''));
+ if (e.key === 'Enter') {
const nextEq = Docs.Create.EquationDocument({
- title: "# math", text: StrCast(this.dataDoc.text), _width, _height: 25,
- x: NumCast(this.layoutDoc.x), y: NumCast(this.layoutDoc.y) + _height + 10
+ title: '# math',
+ text: StrCast(this.dataDoc.text),
+ _width,
+ _height: 25,
+ x: NumCast(this.layoutDoc.x),
+ y: NumCast(this.layoutDoc.y) + _height + 10,
});
EquationBox.SelectOnLoad = nextEq[Id];
this.props.addDocument?.(nextEq);
e.stopPropagation();
-
}
- if (e.key === "Tab") {
+ if (e.key === 'Tab') {
const graph = Docs.Create.FunctionPlotDocument([this.rootDoc], {
x: NumCast(this.layoutDoc.x) + this.layoutDoc[WidthSym](),
y: NumCast(this.layoutDoc.y),
- _width: 400, _height: 300, backgroundColor: "white"
+ _width: 400,
+ _height: 300,
+ backgroundColor: 'white',
});
this.props.addDocument?.(graph);
e.stopPropagation();
}
- if (e.key === "Backspace" && !this.dataDoc.text) this.props.removeDocument?.(this.rootDoc);
- }
+ if (e.key === 'Backspace' && !this.dataDoc.text) this.props.removeDocument?.(this.rootDoc);
+ };
onChange = (str: string) => {
this.dataDoc.text = str;
const style = this._ref.current && getComputedStyle(this._ref.current.element.current);
if (style) {
- const _height = Number(style.height.replace("px", ""));
- const _width = Number(style.width.replace("px", ""));
+ const _height = Number(style.height.replace('px', ''));
+ const _width = Number(style.width.replace('px', ''));
this.layoutDoc._width = Math.max(35, _width);
this.layoutDoc._height = Math.max(25, _height);
}
- }
+ };
render() {
TraceMobx();
- const scale = (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
- return (<div className="equationBox-cont"
- onPointerDown={e => !e.ctrlKey && e.stopPropagation()}
- style={{
- transform: `scale(${scale})`,
- width: `${100 / scale}%`,
- height: `${100 / scale}%`,
- pointerEvents: !this.props.isSelected() ? "none" : undefined,
- }}
- onKeyDown={e => e.stopPropagation()}
- >
- <EquationEditor ref={this._ref}
- value={this.dataDoc.text || "x"}
- spaceBehavesLikeTab={true}
- onChange={this.onChange}
- autoCommands="pi theta sqrt sum prod alpha beta gamma rho"
- autoOperatorNames="sin cos tan" />
- </div>);
+ const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
+ return (
+ <div
+ className="equationBox-cont"
+ onPointerDown={e => !e.ctrlKey && e.stopPropagation()}
+ style={{
+ transform: `scale(${scale})`,
+ width: `${100 / scale}%`,
+ height: `${100 / scale}%`,
+ pointerEvents: !this.props.isSelected() ? 'none' : undefined,
+ }}
+ onKeyDown={e => e.stopPropagation()}>
+ <EquationEditor ref={this._ref} value={this.dataDoc.text || 'x'} spaceBehavesLikeTab={true} onChange={this.onChange} autoCommands="pi theta sqrt sum prod alpha beta gamma rho" autoOperatorNames="sin cos tan" />
+ </div>
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 67cf18d8b..5a6c49809 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -1,18 +1,18 @@
-import React = require("react");
-import { computed } from "mobx";
-import { observer } from "mobx-react";
-import { DateField } from "../../../fields/DateField";
-import { Doc, Field, FieldResult, Opt } from "../../../fields/Doc";
-import { List } from "../../../fields/List";
-import { WebField } from "../../../fields/URLField";
-import { DocumentView, DocumentViewSharedProps } from "./DocumentView";
-import { ScriptField } from "../../../fields/ScriptField";
-import { RecordingBox } from "./RecordingBox";
+import React = require('react');
+import { computed } from 'mobx';
+import { observer } from 'mobx-react';
+import { DateField } from '../../../fields/DateField';
+import { Doc, Field, FieldResult, Opt } from '../../../fields/Doc';
+import { List } from '../../../fields/List';
+import { WebField } from '../../../fields/URLField';
+import { DocumentView, DocumentViewSharedProps } from './DocumentView';
+import { ScriptField } from '../../../fields/ScriptField';
+import { RecordingBox } from './RecordingBox';
//
// these properties get assigned through the render() method of the DocumentView when it creates this node.
// However, that only happens because the properties are "defined" in the markup for the field view.
-// See the LayoutString method on each field view : ImageBox, FormattedTextBox, etc.
+// See the LayoutString method on each field view : ImageBox, FormattedTextBox, etc.
//
export interface FieldViewProps extends DocumentViewSharedProps {
// FieldView specific props that are not part of DocumentView props
@@ -23,10 +23,10 @@ export interface FieldViewProps extends DocumentViewSharedProps {
isContentActive: (outsideReaction?: boolean) => boolean | undefined;
isDocumentActive?: () => boolean;
isSelected: (outsideReaction?: boolean) => boolean;
- scaling?: () => number;
setHeight?: (height: number) => void;
- onBrowseClick?: () => (ScriptField | undefined);
- onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => (boolean | undefined);
+ NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to DocumentViewInternalsProps
+ onBrowseClick?: () => ScriptField | undefined;
+ onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => boolean | undefined;
// properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React)
pointerEvents?: () => Opt<string>;
@@ -42,7 +42,7 @@ export interface FieldViewProps extends DocumentViewSharedProps {
@observer
export class FieldView extends React.Component<FieldViewProps> {
public static LayoutString(fieldType: { name: string }, fieldStr: string) {
- return `<${fieldType.name} {...props} fieldKey={'${fieldStr}'}/>`; //e.g., "<ImageBox {...props} fieldKey={"data} />"
+ return `<${fieldType.name} {...props} fieldKey={'${fieldStr}'}/>`; //e.g., "<ImageBox {...props} fieldKey={"data} />"
}
@computed
@@ -75,23 +75,22 @@ export class FieldView extends React.Component<FieldViewProps> {
//}
else if (field instanceof DateField) {
return <p>{field.date.toLocaleString()}</p>;
- }
- else if (field instanceof Doc) {
- return <p><b>{field.title?.toString()}</b></p>;
- }
- else if (field instanceof List) {
- return <div> {field.length ? field.map(f => Field.toString(f)).join(", ") : ""} </div>;
+ } else if (field instanceof Doc) {
+ return (
+ <p>
+ <b>{field.title?.toString()}</b>
+ </p>
+ );
+ } else if (field instanceof List) {
+ return <div> {field.length ? field.map(f => Field.toString(f)).join(', ') : ''} </div>;
}
// bcz: this belongs here, but it doesn't render well so taking it out for now
else if (field instanceof WebField) {
return <p>{Field.toString(field.url.href)}</p>;
- }
- else if (!(field instanceof Promise)) {
+ } else if (!(field instanceof Promise)) {
return <p>{Field.toString(field)}</p>;
- }
- else {
- return <p> {"Waiting for server..."} </p>;
+ } else {
+ return <p> {'Waiting for server...'} </p>;
}
}
-
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index ffa839fcb..9590bcb15 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -148,8 +148,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
cropping.title = 'crop: ' + this.rootDoc.title;
cropping.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc._width);
cropping.y = NumCast(this.rootDoc.y);
- cropping._width = anchw * (this.props.scaling?.() || 1);
- cropping._height = anchh * (this.props.scaling?.() || 1);
+ cropping._width = anchw * (this.props.NativeDimScaling?.() || 1);
+ cropping._height = anchh * (this.props.NativeDimScaling?.() || 1);
cropping.isLinkButton = undefined;
const croppingProto = Doc.GetProto(cropping);
croppingProto.annotationOn = undefined;
@@ -384,7 +384,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
render() {
TraceMobx();
const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding);
- const borderRadius = borderRad?.includes('px') ? `${Number(borderRad.split('px')[0]) / (this.props.scaling?.() || 1)}px` : borderRad;
+ const borderRadius = borderRad?.includes('px') ? `${Number(borderRad.split('px')[0]) / (this.props.NativeDimScaling?.() || 1)}px` : borderRad;
return (
<div
className="imageBox"
@@ -407,7 +407,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
PanelHeight={this.props.PanelHeight}
ScreenToLocalTransform={this.screenToLocalTransform}
select={emptyFunction}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
removeDocument={this.removeDocument}
moveDocument={this.moveDocument}
@@ -420,7 +420,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
rootDoc={this.rootDoc}
scrollTop={0}
down={this._marqueeing}
- scaling={this.props.scaling}
+ scaling={this.props.NativeDimScaling}
docView={this.props.docViewPath().slice(-1)[0]}
addDocument={this.addDocument}
finishMarquee={this.finishMarquee}
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index c4b42301e..e9ed594d3 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -373,7 +373,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
runInAction(() => {
const localDelta = this.props
.ScreenToLocalTransform()
- .scale(this.props.scaling?.() || 1)
+ .scale(this.props.NativeDimScaling?.() || 1)
.transformDirection(delta[0], delta[1]);
const fullWidth = this.layoutDoc[WidthSym]();
const mapWidth = fullWidth - this.sidebarWidth();
@@ -559,8 +559,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// }
};
- panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (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);
+ panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
+ panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop));
transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()];
opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()];
@@ -589,13 +589,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// docFilters={docFilters || this.props.docFilters}
// dontRenderDocuments={docFilters ? false : true}
// select={emptyFunction}
- // ContentScaling={returnOne}
// bringToFront={emptyFunction}
// whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
// removeDocument={this.removeDocument}
// moveDocument={this.moveDocument}
// addDocument={this.sidebarAddDocument}
- // childPointerEvents={true}
+ // childPointerEvents={"all"}
// pointerEvents={Doc.ActiveTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
return (
<div className="mapBox" ref={this._ref}>
diff --git a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
index 72569135b..630ae18f5 100644
--- a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
+++ b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
@@ -62,7 +62,7 @@ export class MapBoxInfoWindow extends React.Component<MapBoxInfoWindowProps & Vi
setHeight={emptyFunction}
isAnnotationOverlay={false}
select={emptyFunction}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
isContentActive={returnTrue}
chromeHidden={true}
rootSelected={returnFalse}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index fe18abba9..fad22d6e9 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -104,8 +104,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const anchx = NumCast(cropping.x);
const anchy = NumCast(cropping.y);
- const anchw = cropping[WidthSym]() * (this.props.scaling?.() || 1);
- const anchh = cropping[HeightSym]() * (this.props.scaling?.() || 1);
+ const anchw = cropping[WidthSym]() * (this.props.NativeDimScaling?.() || 1);
+ const anchh = cropping[HeightSym]() * (this.props.NativeDimScaling?.() || 1);
const viewScale = 1;
cropping.title = 'crop: ' + this.rootDoc.title;
cropping.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc._width);
@@ -290,11 +290,11 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
(e, down, delta) => {
const localDelta = this.props
.ScreenToLocalTransform()
- .scale(this.props.scaling?.() || 1)
+ .scale(this.props.NativeDimScaling?.() || 1)
.transformDirection(delta[0], delta[1]);
const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']);
const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
- const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this.props.scaling?.() || 1)) / nativeWidth;
+ const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this.props.NativeDimScaling?.() || 1)) / nativeWidth;
if (ratio >= 1) {
this.layoutDoc.nativeWidth = nativeWidth * ratio;
onButton && (this.layoutDoc._width = this.layoutDoc[WidthSym]() + localDelta[0]);
@@ -433,12 +433,11 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return this._showSidebar || this.layoutDoc._showSidebar ? true : false;
}
- contentScaling = () => 1;
isPdfContentActive = () => this.isAnyChildContentActive() || this.props.isSelected();
@computed get renderPdfView() {
TraceMobx();
const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
- const scale = previewScale * (this.props.scaling?.() || 1);
+ const scale = previewScale * (this.props.NativeDimScaling?.() || 1);
return (
<div
className={'pdfBox'}
@@ -473,7 +472,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
removeDocument={this.removeDocument}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
crop={this.crop}
- ContentScaling={returnOne}
/>
</div>
<SidebarAnnos
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 942072524..76a24d831 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -295,7 +295,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
isAnnotationOverlay={true}
select={emptyFunction}
isContentActive={returnFalse}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
whenChildContentsActiveChanged={emptyFunction}
removeDocument={returnFalse}
moveDocument={returnFalse}
@@ -317,7 +317,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
isAnnotationOverlay={true}
select={emptyFunction}
isContentActive={emptyFunction}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
xPadding={25}
yPadding={10}
whenChildContentsActiveChanged={emptyFunction}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index b1f7d8023..681f7c5b2 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -898,7 +898,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
contentFunc = () => [this.youtubeVideoId ? this.youtubeContent : this.content];
- scaling = () => this.props.scaling?.() || 1;
+ scaling = () => this.props.NativeDimScaling?.() || 1;
panelWidth = () => (this.props.PanelWidth() * this.heightPercent) / 100;
panelHeight = () => (this.layoutDoc._fitWidth ? this.panelWidth() / (Doc.NativeAspect(this.rootDoc) || 1) : (this.props.PanelHeight() * this.heightPercent) / 100);
@@ -911,7 +911,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
.scale(100 / this.heightPercent);
};
- marqueeFitScaling = () => ((this.props.scaling?.() || 1) * this.heightPercent) / 100;
+ marqueeFitScaling = () => ((this.props.NativeDimScaling?.() || 1) * this.heightPercent) / 100;
marqueeOffset = () => [((this.panelWidth() / 2) * (1 - this.heightPercent / 100)) / (this.heightPercent / 100), 0];
timelineDocFilter = () => [`_timelineLabel:true,${Utils.noRecursionHack}:x`];
@@ -1124,7 +1124,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
ScreenToLocalTransform={this.screenToLocalTransform}
docFilters={this.timelineDocFilter}
select={emptyFunction}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
removeDocument={this.removeDocument}
moveDocument={this.moveDocument}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 05da8bd7b..71d6959a3 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -200,7 +200,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
autoHeight => {
if (autoHeight) {
this.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']);
- this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']) * (this.props.scaling?.() || 1));
+ this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']) * (this.props.NativeDimScaling?.() || 1));
}
}
);
@@ -276,7 +276,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
if (this._sidebarRef?.current?.makeDocUnfiltered(doc)) return 1;
if (doc !== this.rootDoc && this._outerRef.current) {
- const windowHeight = this.props.PanelHeight() / (this.props.scaling?.() || 1);
+ const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
const scrollTo = Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.layoutDoc._scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(doc.y) + doc[HeightSym](), this.getScrollHeight()));
if (scrollTo !== undefined && this._initialScroll === undefined) {
const focusSpeed = smooth ? 500 : 0;
@@ -310,7 +310,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.props.docViewPath().lastElement()?.docView?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here.
if (this._iframe?.contentWindow && this._iframe.contentDocument && !this._iframe.contentWindow.getSelection()?.isCollapsed) {
const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
- const scale = (this.props.scaling?.() || 1) * mainContBounds.scale;
+ const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale;
const sel = this._iframe.contentWindow.getSelection();
if (sel) {
this._textAnnotationCreator = () => this.createTextAnnotation(sel, !sel.isCollapsed ? sel.getRangeAt(0) : undefined);
@@ -322,7 +322,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
iframeDown = (e: PointerEvent) => {
const sel = this._iframe?.contentWindow?.getSelection?.();
const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
- const scale = (this.props.scaling?.() || 1) * mainContBounds.scale;
+ const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale;
const word = getWordAtPoint(e.target, e.clientX, e.clientY);
this._setPreviewCursor?.(e.clientX, e.clientY, false, true);
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
@@ -604,7 +604,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
funcs.push({
description: (!this.layoutDoc.forceReflow ? 'Force' : 'Prevent') + ' Reflow',
event: () => {
- const nw = !this.layoutDoc.forceReflow ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.scaling?.() || 1);
+ const nw = !this.layoutDoc.forceReflow ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.NativeDimScaling?.() || 1);
this.layoutDoc.forceReflow = !nw;
if (nw) {
Doc.SetInPlace(this.layoutDoc, this.fieldKey + '-nativeWidth', nw, true);
@@ -717,12 +717,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._draggingSidebar = true;
const localDelta = this.props
.ScreenToLocalTransform()
- .scale(this.props.scaling?.() || 1)
+ .scale(this.props.NativeDimScaling?.() || 1)
.transformDirection(delta[0], delta[1]);
const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']);
const nativeHeight = NumCast(this.layoutDoc[this.fieldKey + '-nativeHeight']);
const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
- const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this.props.scaling?.() || 1)) / nativeWidth;
+ const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this.props.NativeDimScaling?.() || 1)) / nativeWidth;
if (ratio >= 1) {
this.layoutDoc.nativeWidth = nativeWidth * ratio;
this.layoutDoc.nativeHeight = nativeHeight * (1 + ratio);
@@ -834,8 +834,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => (this._searchString = e.currentTarget.value);
showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno));
setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func);
- panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth; // (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);
+ panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth; // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
+ panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop));
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter('textInlineAnnotations')];
@@ -852,7 +852,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
render() {
const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any);
const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
- const scale = previewScale * (this.props.scaling?.() || 1);
+ const scale = previewScale * (this.props.NativeDimScaling?.() || 1);
const renderAnnotations = (docFilters?: () => string[]) => (
<CollectionFreeFormView
{...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
@@ -864,12 +864,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
PanelWidth={this.panelWidth}
PanelHeight={this.panelHeight}
ScreenToLocalTransform={this.scrollXf}
- scaling={returnOne}
+ NativeDimScaling={returnOne}
dropAction={'alias'}
docFilters={docFilters || this.basicFilter}
dontRenderDocuments={docFilters ? false : true}
select={emptyFunction}
- ContentScaling={returnOne}
bringToFront={emptyFunction}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
removeDocument={this.removeDocument}
@@ -950,7 +949,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
layoutDoc={this.layoutDoc}
dataDoc={this.dataDoc}
setHeight={emptyFunction}
- nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth) - WebBox.sidebarResizerWidth / (this.props.scaling?.() || 1)}
+ nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth) - WebBox.sidebarResizerWidth / (this.props.NativeDimScaling?.() || 1)}
showSidebar={this.SidebarShown}
sidebarAddDocument={this.sidebarAddDocument}
moveDocument={this.moveDocument}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 383c22ba8..e9b048c5e 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -968,7 +968,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
@computed get contentScaling() {
- return Doc.NativeAspect(this.rootDoc, this.dataDoc, false) ? this.props.scaling?.() || 1 : 1;
+ return Doc.NativeAspect(this.rootDoc, this.dataDoc, false) ? this.props.NativeDimScaling?.() || 1 : 1;
}
componentDidMount() {
!this.props.dontSelectOnLoad && this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
@@ -1691,7 +1691,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
};
fitContentsToBox = () => this.props.Document._fitContentsToBox;
- sidebarContentScaling = () => (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
+ sidebarContentScaling = () => (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
if (!this.layoutDoc._showSidebar) this.toggleSidebar();
// console.log("printting allSideBarDocs");
@@ -1705,7 +1705,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
sidebarScreenToLocal = () =>
this.props
.ScreenToLocalTransform()
- .translate(-(this.props.PanelWidth() - this.sidebarWidth()) / (this.props.scaling?.() || 1), 0)
+ .translate(-(this.props.PanelWidth() - this.sidebarWidth()) / (this.props.NativeDimScaling?.() || 1), 0)
.scale(1 / NumCast(this.layoutDoc._viewScale, 1));
@computed get audioHandle() {
@@ -1768,7 +1768,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
scaleField={this.SidebarKey + '-scale'}
isAnnotationOverlay={false}
select={emptyFunction}
- scaling={this.sidebarContentScaling}
+ NativeDimScaling={this.sidebarContentScaling}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
removeDocument={this.sidebarRemDocument}
moveDocument={this.sidebarMoveDocument}
@@ -1793,7 +1793,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
TraceMobx();
const active = this.props.isContentActive() || this.props.isSelected();
const selected = active;
- const scale = (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
+ const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === '100%' ? '-rounded' : '';
const interactive = (Doc.ActiveTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || !this.layoutDoc._lockedPosition);
if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide);
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index bd5e8caab..0cf15d297 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -199,11 +199,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
};
- headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
- e.stopPropagation();
- e.preventDefault();
- };
-
/**
* Function to drag and drop the pres element to a diferent location
*/
@@ -477,8 +472,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
})}
onPointerOver={this.onPointerOver}
onPointerLeave={this.onPointerLeave}
- onPointerDown={this.headerDown}
- onPointerUp={this.headerUp}>
+ onPointerDown={this.headerDown}>
{/* {miniView ?
// when width is LESS than 110 px
<div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}>
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 837734edf..2c83082b7 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -41,7 +41,6 @@ interface IViewerProps extends FieldViewProps {
url: string;
loaded?: (nw: number, nh: number, np: number) => void;
setPdfViewer: (view: PDFViewer) => void;
- ContentScaling?: () => number;
anchorMenuClick?: () => undefined | ((anchor: Doc) => void);
crop: (region: Doc | undefined, addCrop?: boolean) => Doc | undefined;
}
@@ -97,7 +96,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
autoHeight => {
if (autoHeight) {
this.props.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']);
- this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']) * (this.props.scaling?.() || 1));
+ this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']) * (this.props.NativeDimScaling?.() || 1));
}
}
);
@@ -162,7 +161,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
const mainCont = this._mainCont.current;
let focusSpeed: Opt<number>;
if (doc !== this.props.rootDoc && mainCont) {
- const windowHeight = this.props.PanelHeight() / (this.props.scaling?.() || 1);
+ const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
const scrollTo = doc.unrendered ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, 0.1 * windowHeight, NumCast(this.props.Document.scrollHeight));
if (scrollTo !== undefined && scrollTo !== this.props.layoutDoc._scrollTop) {
focusSpeed = 500;
@@ -486,8 +485,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno));
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);
+ panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
+ panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter('textInlineAnnotations')];
transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()];
opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()];
@@ -509,7 +508,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
PanelWidth={this.panelWidth}
dropAction={'alias'}
select={emptyFunction}
- ContentScaling={this.contentZoom}
bringToFront={emptyFunction}
docFilters={docFilters || this.basicFilter}
styleProvider={this.childStyleProvider}
@@ -556,10 +554,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
@computed get pdfViewerDiv() {
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 = () => NumCast(this.props.layoutDoc._viewScale, 1);
savedAnnotations = () => this._savedAnnotations;
render() {
TraceMobx();
@@ -574,8 +568,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
onClick={this.onClick}
style={{
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})`,
+ height: !this.props.Document._fitWidth && window.screen.width > 600 ? Doc.NativeHeight(this.props.Document) : `100%`,
}}>
{this.pdfViewerDiv}
{this.annotationLayer}