aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-09-13 10:11:49 -0400
committerbobzel <zzzman@gmail.com>2022-09-13 10:11:49 -0400
commit36b17b5b0878eeb2eb23fd4c5078e06fcc002aaf (patch)
tree33c1a3fb50381d09bf89bd43d869544a3c52c7b6 /src/client/views/collections/collectionFreeForm
parent7696d85b7b737a29cab189f4c65f395c5de132c7 (diff)
parentbb9f0d4dec849bdaf2d358d060707b2ed1ed677d (diff)
Merge branch 'sharing-jenny' of https://github.com/brown-dash/Dash-Web into sharing-jenny
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx8
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss28
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx321
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.scss20
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx29
7 files changed, 198 insertions, 218 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index a0ebe4cdc..89cc22d07 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -34,6 +34,7 @@ export interface PoolData {
zIndex?: number;
width?: number;
height?: number;
+ backgroundColor?: string;
color?: string;
opacity?: number;
transition?: string;
@@ -45,6 +46,7 @@ export interface PoolData {
export interface ViewDefResult {
ele: JSX.Element;
bounds?: ViewDefBounds;
+ inkMask?: number; //sort elements into either the mask layer (which has a mixedBlendMode appropriate for transparent masks), or the regular documents layer; -1 = no mask, 0 = mask layer but stroke is transprent (hidden), >0 = mask layer and not hidden
}
function toLabel(target: FieldResult<Field>) {
if (typeof target === 'number' || Number(target)) {
@@ -393,8 +395,10 @@ function normalizeResults(
0
);
aggBounds.r = aggBounds.x + Math.max(minWidth, aggBounds.r - aggBounds.x);
- const wscale = panelDim[0] / (aggBounds.r - aggBounds.x);
- let scale = wscale * (aggBounds.b - aggBounds.y) > panelDim[1] ? panelDim[1] / (aggBounds.b - aggBounds.y) : wscale;
+ const width = aggBounds.r - aggBounds.x === 0 ? 1 : aggBounds.r - aggBounds.x;
+ const height = aggBounds.b - aggBounds.y === 0 ? 1 : aggBounds.b - aggBounds.y;
+ const wscale = panelDim[0] / width;
+ let scale = wscale * height > panelDim[1] ? panelDim[1] / height : wscale;
if (Number.isNaN(scale)) scale = 1;
Array.from(docMap.entries())
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index d979ef961..bf9de6760 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -195,7 +195,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
const bDocBounds = (B.props as any).DocumentView?.().getBounds() || { left: 0, right: 0, top: 0, bottom: 0 };
const aleft = this.visibleX(adiv);
const bleft = this.visibleX(bdiv);
- const clipped = aleft !== a.left || atop !== a.top || bleft !== b.left || btop !== b.top;
+ const aclipped = aleft !== a.left || atop !== a.top;
+ const bclipped = bleft !== b.left || btop !== b.top;
+ if (aclipped && bclipped) return undefined;
+ const clipped = aclipped || bclipped;
const pt1 = [aleft + a.width / 2, atop + a.height / 2];
const pt2 = [bleft + b.width / 2, btop + b.width / 2];
const pt1vec = [(bDocBounds.left + bDocBounds.right) / 2 - pt1[0], (bDocBounds.top + bDocBounds.bottom) / 2 - pt1[1]];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 8720c9097..b8344dc0c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -5,11 +5,14 @@ import { DocumentManager } from '../../../util/DocumentManager';
import './CollectionFreeFormLinksView.scss';
import { CollectionFreeFormLinkView } from './CollectionFreeFormLinkView';
import React = require('react');
+import { LightboxView } from '../../LightboxView';
@observer
export class CollectionFreeFormLinksView extends React.Component<React.PropsWithChildren<{}>> {
@computed get uniqueConnections() {
- return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews)).map(c => <CollectionFreeFormLinkView key={c.l[Id]} A={c.a} B={c.b} LinkDocs={[c.l]} />);
+ return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews))
+ .filter(c => !LightboxView.LightboxDoc || (LightboxView.IsLightboxDocView(c.a.docViewPath) && LightboxView.IsLightboxDocView(c.b.docViewPath)))
+ .map(c => <CollectionFreeFormLinkView key={c.l[Id]} A={c.a} B={c.b} LinkDocs={[c.l]} />);
}
render() {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 79e063f7f..d80fcdfc3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,4 +1,4 @@
-@import "../../global/globalCssVariables";
+@import '../../global/globalCssVariables';
.collectionfreeformview-none {
position: inherit;
@@ -20,8 +20,24 @@
pointer-events: none;
}
+.collectionfreeformview-mask-empty,
+.collectionfreeformview-mask {
+ z-index: 5000;
+ width: $INK_MASK_SIZE;
+ height: $INK_MASK_SIZE;
+ transform: translate($INK_MASK_SIZE_HALF, $INK_MASK_SIZE_HALF);
+ pointer-events: none;
+ position: absolute;
+ background-color: transparent;
+ transition: background-color 1s ease 0s;
+}
+.collectionfreeformview-mask {
+ mix-blend-mode: multiply;
+ background-color: rgba(0, 0, 0, 0.7);
+}
+
.collectionfreeformview-viewdef {
- >.collectionFreeFormDocumentView-container {
+ > .collectionFreeFormDocumentView-container {
pointer-events: none;
.contentFittingDocumentDocumentView-previewDoc {
@@ -210,13 +226,13 @@
}
}
- .collectionfreeformview>.jsx-parser {
+ .collectionfreeformview > .jsx-parser {
position: inherit;
height: 100%;
width: 100%;
}
- >.jsx-parser {
+ > .jsx-parser {
z-index: 0;
}
@@ -268,6 +284,6 @@
.pullpane-indicator {
z-index: 99999;
- background-color: rgba($color: #000000, $alpha: .4);
+ background-color: rgba($color: #000000, $alpha: 0.4);
position: absolute;
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 4174661d8..039407e77 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -23,7 +23,6 @@ import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { HistoryUtil } from '../../../util/History';
import { InteractionUtils } from '../../../util/InteractionUtils';
-import { RecordingApi } from '../../../util/RecordingApi';
import { ReplayMovements } from '../../../util/ReplayMovements';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { SelectionManager } from '../../../util/SelectionManager';
@@ -35,7 +34,7 @@ import { COLLECTION_BORDER_WIDTH } from '../../../views/global/globalCssVariable
import { Timeline } from '../../animationtimeline/Timeline';
import { ContextMenu } from '../../ContextMenu';
import { GestureOverlay } from '../../GestureOverlay';
-import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
+import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
import { LightboxView } from '../../LightboxView';
import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView';
import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment, ViewSpecPrefix } from '../../nodes/DocumentView';
@@ -45,7 +44,6 @@ import { PresBox } from '../../nodes/trails/PresBox';
import { VideoBox } from '../../nodes/VideoBox';
import { CreateImage } from '../../nodes/WebBoxRenderer';
import { StyleProp } from '../../StyleProvider';
-import { CollectionDockingView } from '../CollectionDockingView';
import { CollectionSubView } from '../CollectionSubView';
import { TreeViewType } from '../CollectionTreeView';
import { TabDocView } from '../TabDocView';
@@ -54,12 +52,11 @@ import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCurso
import './CollectionFreeFormView.scss';
import { MarqueeView } from './MarqueeView';
import React = require('react');
-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;
@@ -110,19 +107,19 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observable _hLines: number[] | undefined;
@observable _vLines: number[] | undefined;
@observable _firstRender = true; // this turns off rendering of the collection's content so that there's instant feedback when a tab is switched of what content will be shown.
- @observable _pullCoords: number[] = [0, 0];
- @observable _pullDirection: string = '';
@observable _showAnimTimeline = false;
@observable _clusterSets: Doc[][] = [];
@observable _deleteList: DocumentView[] = [];
@observable _timelineRef = React.createRef<Timeline>();
@observable _marqueeRef = React.createRef<HTMLDivElement>();
@observable _marqueeViewRef = React.createRef<MarqueeView>();
- @observable _keyframeEditing = false;
@observable ChildDrag: DocumentView | undefined; // child document view being dragged. needed to update drop areas of groups when a group item is dragged.
@computed get views() {
- return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele);
+ const viewsMask = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask !== -1).map(ele => ele.ele);
+ const renderableEles = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask === -1).map(ele => ele.ele);
+ if (viewsMask.length) renderableEles.push(<div className={`collectionfreeformview-mask${this._layoutElements.some(ele => (ele.inkMask ?? 0) > 0) ? '' : '-empty'}`}>{viewsMask}</div>);
+ return renderableEles;
}
@computed get fitToContentVals() {
return {
@@ -131,7 +128,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
}
@computed get fitContentsToBox() {
- return (this.props.fitContentsToBox?.() || this.Document._fitContentsToBox) && !this.isAnnotationOverlay;
+ return (this.props.fitContentsToBox?.() || this.Document._fitContentsToBox || this.Document.isGroup) && !this.isAnnotationOverlay;
}
@computed get contentBounds() {
const cb = Cast(this.rootDoc.contentBounds, listSpec('number'));
@@ -151,11 +148,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 {
@@ -185,8 +182,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.Document.lastFrame = Math.max(NumCast(this.Document._currentFrame), NumCast(this.Document.lastFrame));
}
};
- @action setKeyFrameEditing = (set: boolean) => (this._keyframeEditing = set);
- getKeyFrameEditing = () => this._keyframeEditing;
onBrowseClickHandler = () => this.props.onBrowseClick?.() || ScriptCast(this.layoutDoc.onBrowseClick);
onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick);
onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
@@ -236,11 +231,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const newBoxes = newBox instanceof Doc ? [newBox] : newBox;
for (const newBox of newBoxes) {
if (newBox.activeFrame !== undefined) {
- const vals = CollectionFreeFormDocumentView.animFields.map(field => newBox[field]);
- CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[`${field}-indexed`]);
- CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[field]);
+ const vals = CollectionFreeFormDocumentView.animFields.map(field => newBox[field.key]);
+ CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[`${field.key}-indexed`]);
+ CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[field.key]);
delete newBox.activeFrame;
- CollectionFreeFormDocumentView.animFields.forEach((field, i) => field !== 'opacity' && (newBox[field] = vals[i]));
+ CollectionFreeFormDocumentView.animFields.forEach((field, i) => field.key !== 'opacity' && (newBox[field.key] = vals[i]));
}
}
if (this.Document._currentFrame !== undefined && !this.props.isAnnotationOverlay) {
@@ -272,16 +267,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
.sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
zsorted.forEach((doc, index) => (doc.zIndex = doc.isInkMask ? 5000 : index + 1));
const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000));
- const dropPos = this.Document._currentFrame !== undefined ? [dvals.x || 0, dvals.y || 0] : [NumCast(refDoc.x), NumCast(refDoc.y)];
+ const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)];
for (let i = 0; i < docDragData.droppedDocuments.length; i++) {
const d = docDragData.droppedDocuments[i];
const layoutDoc = Doc.Layout(d);
if (this.Document._currentFrame !== undefined) {
CollectionFreeFormDocumentView.setupKeyframes([d], NumCast(this.Document._currentFrame), false);
- const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000));
- vals.x = x + (vals.x || 0) - dropPos[0];
- vals.y = y + (vals.y || 0) - dropPos[1];
- vals._scrollTop = this.Document.editScrollProgressivize ? vals._scrollTop : undefined;
+ const pvals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); // get filled in values (uses defaults when not value is specified) for position
+ const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000), false); // get non-default values for everything else
+ vals.x = x + NumCast(pvals.x) - dropPos[0];
+ vals.y = y + NumCast(pvals.y) - dropPos[1];
CollectionFreeFormDocumentView.setValues(NumCast(this.Document._currentFrame), d, vals);
} else {
d.x = x + NumCast(d.x) - dropPos[0];
@@ -463,20 +458,23 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
getClusterColor = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => {
let styleProp = this.props.styleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1
- if (property !== StyleProp.BackgroundColor) return styleProp;
- const cluster = NumCast(doc?.cluster);
- if (this.Document._useClusters) {
- if (this._clusterSets.length <= cluster) {
- setTimeout(() => doc && this.updateCluster(doc));
- } else {
- // choose a cluster color from a palette
- const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)'];
- styleProp = colors[cluster % colors.length];
- const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
- // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document
- set?.map(s => (styleProp = StrCast(s.backgroundColor)));
- }
- } //else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray";
+ switch (property) {
+ case StyleProp.BackgroundColor:
+ const cluster = NumCast(doc?.cluster);
+ if (this.Document._useClusters) {
+ if (this._clusterSets.length <= cluster) {
+ setTimeout(() => doc && this.updateCluster(doc));
+ } else {
+ // choose a cluster color from a palette
+ const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)'];
+ styleProp = colors[cluster % colors.length];
+ const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
+ // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document
+ set?.map(s => (styleProp = StrCast(s.backgroundColor)));
+ }
+ }
+ break;
+ }
return styleProp;
};
@@ -497,7 +495,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const currentCol = DocListCast(this.rootDoc.currentInkDoc);
const rootDocList = DocListCast(this.rootDoc.data);
currentCol.push(rootDocList[rootDocList.length - 1]);
- console.log(currentCol);
this._batch?.end();
}
@@ -522,17 +519,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case InkTool.Pen:
break; // the GestureOverlay handles ink stroke input -- either as gestures, or drying as ink strokes that are added to document views
case InkTool.Eraser:
- document.addEventListener('pointermove', this.onEraserMove);
- document.addEventListener('pointerup', this.onEraserUp);
this._batch = UndoManager.StartBatch('collectionErase');
- e.stopPropagation();
- e.preventDefault();
+ setupMoveUpEvents(this, e, this.onEraserMove, this.onEraserUp, emptyFunction);
break;
case InkTool.None:
if (!(this.props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
this._hitCluster = this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY));
- document.addEventListener('pointermove', this.onPointerMove);
- document.addEventListener('pointerup', this.onPointerUp);
+ setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, false);
}
break;
}
@@ -571,13 +564,25 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case GestureUtils.Gestures.Stroke:
const points = ge.points;
const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
- const inkDoc = Docs.Create.InkDocument(ActiveInkColor(), Doc.ActiveTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), points, {
- title: 'ink stroke',
- x: B.x - ActiveInkWidth() / 2,
- y: B.y - ActiveInkWidth() / 2,
- _width: B.width + ActiveInkWidth(),
- _height: B.height + ActiveInkWidth(),
- });
+ const inkDoc = Docs.Create.InkDocument(
+ ActiveInkColor(),
+ Doc.ActiveTool,
+ ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
+ ActiveInkBezierApprox(),
+ ActiveFillColor(),
+ ActiveArrowStart(),
+ ActiveArrowEnd(),
+ ActiveDash(),
+ points,
+ ActiveIsInkMask(),
+ {
+ title: 'ink stroke',
+ x: B.x - ActiveInkWidth() / 2,
+ y: B.y - ActiveInkWidth() / 2,
+ _width: B.width + ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
+ _height: B.height + ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
+ }
+ );
if (Doc.ActiveTool === InkTool.Write) {
this.unprocessedDocs.push(inkDoc);
CollectionFreeFormView.collectionsWithUnprocessedInk.add(this);
@@ -685,23 +690,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
onEraserUp = (e: PointerEvent): void => {
- if (!InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) {
- document.removeEventListener('pointermove', this.onEraserMove);
- document.removeEventListener('pointerup', this.onEraserUp);
- this._deleteList.forEach(ink => ink.props.removeDocument?.(ink.rootDoc));
- this._deleteList = [];
- this._batch?.end();
- }
- };
-
- @action
- onPointerUp = (e: PointerEvent): void => {
- if (!InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) {
- document.removeEventListener('pointermove', this.onPointerMove);
- document.removeEventListener('pointerup', this.onPointerUp);
- this.removeMoveListeners();
- this.removeEndListeners();
- }
+ this._deleteList.forEach(ink => ink.props.removeDocument?.(ink.rootDoc));
+ this._deleteList = [];
+ this._batch?.end();
};
onClick = (e: React.MouseEvent) => {
@@ -739,46 +730,42 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
* However, if Shift is held, then no segmentation is done -- instead any intersected stroke is deleted in its entirety.
*/
@action
- onEraserMove = (e: PointerEvent) => {
+ onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => {
const currPoint = { X: e.clientX, Y: e.clientY };
- this.getEraserIntersections({ X: this._lastX, Y: this._lastY }, currPoint).forEach(intersect => {
+ this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => {
if (!this._deleteList.includes(intersect.inkView)) {
this._deleteList.push(intersect.inkView);
SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.strokeWidth?.toString()) || '1');
SetActiveInkColor(StrCast(intersect.inkView.rootDoc.color?.toString()) || 'black');
// create a new curve by appending all curves of the current segment together in order to render a single new stroke.
- !e.shiftKey &&
+ if (!e.shiftKey) {
this.segmentInkStroke(intersect.inkView, intersect.t).forEach(segment =>
GestureOverlay.Instance.dispatchGesture(
GestureUtils.Gestures.Stroke,
segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[])
)
);
+ }
// Lower ink opacity to give the user a visual indicator of deletion.
intersect.inkView.layoutDoc.opacity = 0.5;
+ intersect.inkView.layoutDoc.dontIntersect = true;
}
});
- this._lastX = currPoint.X;
- this._lastY = currPoint.Y;
-
- e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers
- e.preventDefault();
+ return false;
};
@action
- onPointerMove = (e: PointerEvent): void => {
- if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) return;
+ onPointerMove = (e: PointerEvent): boolean => {
+ if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) return false;
if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) {
Doc.ActiveTool = InkTool.None;
if (this.props.isContentActive(true)) e.stopPropagation();
} else if (!e.cancelBubble) {
if (this.tryDragCluster(e, this._hitCluster)) {
- document.removeEventListener('pointermove', this.onPointerMove);
- document.removeEventListener('pointerup', this.onPointerUp);
+ return true;
} else this.pan(e);
- e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers
- e.preventDefault();
}
+ return false;
};
/**
@@ -788,6 +775,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
getEraserIntersections = (lastPoint: { X: number; Y: number }, currPoint: { X: number; Y: number }) => {
const eraserMin = { X: Math.min(lastPoint.X, currPoint.X), Y: Math.min(lastPoint.Y, currPoint.Y) };
const eraserMax = { X: Math.max(lastPoint.X, currPoint.X), Y: Math.max(lastPoint.Y, currPoint.Y) };
+
return this.childDocs
.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView))
.filter(inkView => inkView?.ComponentView instanceof InkingStroke)
@@ -875,7 +863,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const tVals: number[] = [];
// Iterating through all ink strokes in the current freeform collection.
this.childDocs
- .filter(doc => doc.type === DocumentType.INK)
+ .filter(doc => doc.type === DocumentType.INK && !doc.dontIntersect)
.forEach(doc => {
const otherInk = DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)?.ComponentView as InkingStroke;
const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
@@ -906,7 +894,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers
e.preventDefault();
document.removeEventListener('pointermove', this.onPointerMove);
- document.removeEventListener('pointerup', this.onPointerUp);
return;
}
// TODO: nda - this allows us to pan collections with finger -> only want to do this when collection is selected'
@@ -954,13 +941,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2;
// const transformed = this.getTransform().inverse().transformPoint(centerX, centerY);
- if (!this._pullDirection) {
- // if we are not bezel movement
- this.pan({ clientX: centerX, clientY: centerY });
- } else {
- this._pullCoords = [centerX, centerY];
- }
-
this._lastX = centerX;
this._lastY = centerY;
}
@@ -985,24 +965,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2;
this._lastX = centerX;
this._lastY = centerY;
- const screenBox = this._mainCont?.getBoundingClientRect();
-
- // determine if we are using a bezel movement
- if (screenBox) {
- if (screenBox.right - centerX < 100) {
- this._pullCoords = [centerX, centerY];
- this._pullDirection = 'right';
- } else if (centerX - screenBox.left < 100) {
- this._pullCoords = [centerX, centerY];
- this._pullDirection = 'left';
- } else if (screenBox.bottom - centerY < 100) {
- this._pullCoords = [centerX, centerY];
- this._pullDirection = 'bottom';
- } else if (centerY - screenBox.top < 100) {
- this._pullCoords = [centerX, centerY];
- this._pullDirection = 'top';
- }
- }
this.removeMoveListeners();
this.addMoveListeners();
@@ -1014,19 +976,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
cleanUpInteractions = () => {
- switch (this._pullDirection) {
- case 'left':
- case 'right':
- case 'top':
- case 'bottom':
- CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], { title: 'New Collection' }), this._pullDirection);
- }
-
- this._pullDirection = '';
- this._pullCoords = [0, 0];
-
- document.removeEventListener('pointermove', this.onPointerMove);
- document.removeEventListener('pointerup', this.onPointerUp);
this.removeMoveListeners();
this.removeEndListeners();
};
@@ -1055,7 +1004,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();
@@ -1068,17 +1017,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
setPan(panX: number, panY: number, panTime: number = 0, clamp: boolean = false) {
- // set the current respective FFview to the tab being panned.
- Doc.UserDoc()?.presentationMode === 'recording' && RecordingApi.Instance.setRecordingFFView(this);
- // TODO: make this based off the specific recording FFView
- Doc.UserDoc()?.presentationMode === 'none' && RecordingApi.Instance.setPlayFFView(this);
-
- // TODO: zzz + michael to figure out this merge in case of strange behaviour
- // if (Doc.UserDoc()?.presentationMode === 'watching') {
- // RecordingApi.Instance.pauseVideoAndMovements();
- // Doc.UserDoc().presentationMode = 'none';
- // // RecordingApi.Instance.pauseMovements()
- // }
// this is the easiest way to do this -> will talk with Bob about using mobx to do this to remove this line of code.
if (Doc.UserDoc()?.presentationMode === 'watching') ReplayMovements.Instance.pauseFromInteraction();
@@ -1202,12 +1140,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const { panX, panY, scale } = cantTransform ? savedState : this.calculatePanIntoView(doc, xfToCollection, options?.willZoom ? options?.scale || 0.75 : undefined);
if (!cantTransform) {
// only pan and zoom to focus on a document if the document is not an annotation in an annotation overlay collection
- newState.initializers![this.Document[Id]] = { panX: panX, panY: panY };
+ newState.initializers![this.Document[Id]] = { panX, panY };
HistoryUtil.pushState(newState);
}
// focus on the document in the collection
const didMove = !cantTransform && !doc.z && (panX !== savedState.panX || panY !== savedState.panY || scale !== savedState.scale);
- const focusSpeed = options?.instant ? 0 : didMove ? (doc.focusSpeed !== undefined ? Number(doc.focusSpeed) : 500) : 0;
+ const focusSpeed = options?.instant ? 0 : didMove ? NumCast(doc.focusSpeed, 500) : 0;
// glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
if (didMove) {
scale && (this.Document[this.scaleFieldKey] = scale);
@@ -1226,8 +1164,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.Document._panY = restoreState.panY;
this.Document[this.scaleFieldKey] = restoreState.scale;
}
- runInAction(() => (this._viewTransition = 0));
}
+ runInAction(() => (this._viewTransition = 0));
return resetView;
};
const xf = !cantTransform
@@ -1252,17 +1190,20 @@ 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,
scale: newScale,
};
}
- const pw = this.props.PanelWidth() / NumCast(this.layoutDoc._viewScale, 1);
- const ph = this.props.PanelHeight() / NumCast(this.layoutDoc._viewScale, 1);
- const cx = NumCast(this.layoutDoc._panX);
- const cy = NumCast(this.layoutDoc._panY);
+
+ const panelWidth = this.props.isAnnotationOverlay ? this.nativeWidth : this.props.PanelWidth();
+ const panelHeight = this.props.isAnnotationOverlay ? this.nativeHeight : this.props.PanelHeight();
+ const pw = panelWidth / NumCast(this.layoutDoc._viewScale, 1);
+ const ph = panelHeight / NumCast(this.layoutDoc._viewScale, 1);
+ const cx = NumCast(this.layoutDoc._panX) + (this.props.isAnnotationOverlay ? pw / 2 : 0);
+ const cy = NumCast(this.layoutDoc._panY) + (this.props.isAnnotationOverlay ? ph / 2 : 0);
const screen = { left: cx - pw / 2, right: cx + pw / 2, top: cy - ph / 2, bot: cy + ph / 2 };
if (screen.right - screen.left < bounds.right - bounds.left || screen.bot - screen.top < bounds.bot - bounds.top) {
return {
@@ -1272,8 +1213,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
}
return {
- panX: cx + Math.min(0, bounds.left - pw / 10 - screen.left) + Math.max(0, bounds.right + pw / 10 - screen.right),
- panY: cy + Math.min(0, bounds.top - ph / 10 - screen.top) + Math.max(0, bounds.bot + ph / 10 - screen.bot),
+ panX: (this.props.isAnnotationOverlay ? NumCast(this.layoutDoc._panX) : cx) + Math.min(0, bounds.left - pw / 10 - screen.left) + Math.max(0, bounds.right + pw / 10 - screen.right),
+ panY: (this.props.isAnnotationOverlay ? NumCast(this.layoutDoc._panY) : cy) + Math.min(0, bounds.top - ph / 10 - screen.top) + Math.max(0, bounds.bot + ph / 10 - screen.bot),
};
};
@@ -1302,7 +1243,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) {
@@ -1374,22 +1315,23 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
});
getCalculatedPositions(params: { pair: { layout: Doc; data?: Doc }; index: number; collection: Doc }): PoolData {
- const layoutDoc = Doc.Layout(params.pair.layout);
- const { z, color, zIndex } = params.pair.layout;
- const { x, y, opacity } =
- this.Document._currentFrame === undefined
- ? { x: params.pair.layout.x, y: params.pair.layout.y, opacity: this.props.styleProvider?.(params.pair.layout, this.props, StyleProp.Opacity) }
- : CollectionFreeFormDocumentView.getValues(params.pair.layout, NumCast(this.Document._currentFrame));
+ const curFrame = Cast(this.Document._currentFrame, 'number');
+ const childDoc = params.pair.layout;
+ const childDocLayout = Doc.Layout(childDoc);
+ const { z, zIndex } = childDoc;
+ const { backgroundColor, color } = curFrame === undefined ? { backgroundColor: undefined, color: undefined } : CollectionFreeFormDocumentView.getStringValues(childDoc, curFrame);
+ const { x, y, opacity } = curFrame === undefined ? { x: childDoc.x, y: childDoc.y, opacity: this.props.childOpacity?.() } : CollectionFreeFormDocumentView.getValues(childDoc, curFrame);
return {
x: NumCast(x),
y: NumCast(y),
z: Cast(z, 'number'),
- color: StrCast(color),
+ color: Cast(color, 'string') ? StrCast(color) : this.props.styleProvider?.(childDoc, this.props, StyleProp.Color),
+ backgroundColor: Cast(backgroundColor, 'string') ? StrCast(backgroundColor) : this.props.styleProvider?.(childDoc, this.props, StyleProp.BackgroundColor),
+ opacity: Cast(opacity, 'number') ?? this.props.styleProvider?.(childDoc, this.props, StyleProp.Opacity),
zIndex: Cast(zIndex, 'number'),
- transition: StrCast(layoutDoc.dataTransition),
- opacity: this._keyframeEditing ? 1 : Cast(opacity, 'number', null),
- width: Cast(layoutDoc._width, 'number'),
- height: Cast(layoutDoc._height, 'number'),
+ width: Cast(childDocLayout._width, 'number'),
+ height: Cast(childDocLayout._height, 'number'),
+ transition: StrCast(childDocLayout.dataTransition),
pair: params.pair,
replica: '',
};
@@ -1504,7 +1446,17 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
for (const entry of array) {
const lastPos = this._cachedPool.get(entry[0]); // last computed pos
const newPos = entry[1];
- if (!lastPos || newPos.opacity !== lastPos.opacity || newPos.x !== lastPos.x || newPos.y !== lastPos.y || newPos.z !== lastPos.z || newPos.zIndex !== lastPos.zIndex) {
+ if (
+ !lastPos ||
+ newPos.color !== lastPos.color ||
+ newPos.backgroundColor !== lastPos.backgroundColor ||
+ newPos.opacity !== lastPos.opacity ||
+ newPos.x !== lastPos.x ||
+ newPos.y !== lastPos.y ||
+ newPos.z !== lastPos.z ||
+ newPos.zIndex !== lastPos.zIndex ||
+ newPos.transition !== lastPos.transition
+ ) {
this._layoutPoolData.set(entry[0], newPos);
}
if (!lastPos || newPos.height !== lastPos.height || newPos.width !== lastPos.width) {
@@ -1521,6 +1473,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
elements.push({
ele: this.getChildDocView(entry[1]),
bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica),
+ inkMask: BoolCast(entry[1].pair.layout.isInkMask) ? NumCast(entry[1].pair.layout.opacity) : -1,
})
);
@@ -1573,11 +1526,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
setTimeout(
action(() => {
this._firstRender = false;
- this._disposers.layoutComputation = reaction(
- () => this.doLayoutComputation,
- elements => (this._layoutElements = elements || []),
- { fireImmediately: true, name: 'doLayout' }
- );
this._marqueeRef.current?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
@@ -1594,10 +1542,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const c = [NumCast(this.layoutDoc.x) + this.layoutDoc[WidthSym]() / 2, NumCast(this.layoutDoc.y) + this.layoutDoc[HeightSym]() / 2];
const p = [NumCast(this.layoutDoc._panX), NumCast(this.layoutDoc._panY)];
const pbounds = {
- x: (cbounds.x - p[0]) * this.zoomScaling() + c[0],
- y: (cbounds.y - p[1]) * this.zoomScaling() + c[1],
- r: (cbounds.r - p[0]) * this.zoomScaling() + c[0],
- b: (cbounds.b - p[1]) * this.zoomScaling() + c[1],
+ x: cbounds.x - p[0] + c[0],
+ y: cbounds.y - p[1] + c[1],
+ r: cbounds.r - p[0] + c[0],
+ b: cbounds.b - p[1] + c[1],
};
this.layoutDoc._width = pbounds.r - pbounds.x;
this.layoutDoc._height = pbounds.b - pbounds.y;
@@ -1609,6 +1557,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
},
{ fireImmediately: true }
);
+
+ this._disposers.layoutComputation = reaction(
+ () => this.doLayoutComputation,
+ elements => (this._layoutElements = elements || []),
+ { fireImmediately: true, name: 'doLayout' }
+ );
})
);
}
@@ -1632,9 +1586,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);
+ }
}
}
}
@@ -1888,7 +1844,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@computed get placeholder() {
return (
<div className="collectionfreeformview-placeholder" style={{ background: StrCast(this.Document.backgroundColor) }}>
- <span className="collectionfreeformview-placeholderSpan">{this.props.Document.title?.toString()}</span>
+ <span className="collectionfreeformview-placeholderSpan">{this.props.Document.annotationOn ? '' : this.props.Document.title?.toString()}</span>
</div>
);
}
@@ -1902,6 +1858,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
ungroup={this.props.Document._isGroup ? this.promoteCollection : undefined}
nudge={this.isAnnotationOverlay || this.props.renderDepth > 0 ? undefined : this.nudge}
addDocTab={this.addDocTab}
+ slowLoadDocuments={this.slowLoadDocuments}
trySelectCluster={this.trySelectCluster}
activeDocuments={this.getActiveDocuments}
selectDocuments={this.selectDocuments}
@@ -1910,7 +1867,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
getContainerTransform={this.getContainerTransform}
getTransform={this.getTransform}
isAnnotationOverlay={this.isAnnotationOverlay}>
- <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0 : undefined }}>
+ <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0.7 : undefined }}>
{this.layoutDoc._backgroundGridShow ? (
<div>
<CollectionFreeFormBackgroundGrid // bcz : UGHH don't know why, but if we don't wrap in a div, then PDF's don't render whenn taking snapshot of a dashboard and the background grid is on!!?
@@ -1944,13 +1901,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;
@@ -1984,22 +1941,13 @@ 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} />}
- <div
- className={'pullpane-indicator'}
- style={{
- display: this._pullDirection ? 'block' : 'none',
- top: clientRect ? (this._pullDirection === 'bottom' ? this._pullCoords[1] - clientRect.y : 0) : 'auto',
- left: clientRect ? (this._pullDirection === 'right' ? this._pullCoords[0] - clientRect.x : 0) : 'auto',
- width: clientRect ? (this._pullDirection === 'left' ? this._pullCoords[0] - clientRect.left : this._pullDirection === 'right' ? clientRect.right - this._pullCoords[0] : clientRect.width) : 0,
- height: clientRect ? (this._pullDirection === 'top' ? this._pullCoords[1] - clientRect.top : this._pullDirection === 'bottom' ? clientRect.bottom - this._pullCoords[1] : clientRect.height) : 0,
- }}></div>
{
// uncomment to show snap lines
<div className="snapLines" style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', pointerEvents: 'none' }}>
@@ -2269,3 +2217,6 @@ ScriptingGlobals.add(function nextKeyFrame(readOnly: boolean) {
ScriptingGlobals.add(function prevKeyFrame(readOnly: boolean) {
!readOnly && (SelectionManager.Views()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true);
});
+ScriptingGlobals.add(function pinWithView(readOnly: boolean) {
+ !readOnly && SelectionManager.Views().forEach(view => TabDocView.PinDoc(view.rootDoc, { pinDocView: true, panelWidth: view.props.PanelWidth(), panelHeight: view.props.PanelHeight() }));
+});
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
index 41e4d6b6a..e0f5cbe5b 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
@@ -1,16 +1,14 @@
-
.marqueeView {
position: inherit;
- top:0;
- left:0;
- width:100%;
- height:100%;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
overflow: hidden;
border-radius: inherit;
user-select: none;
}
-
.marqueeView:focus-within {
overflow: hidden;
}
@@ -22,13 +20,13 @@
border-color: black;
pointer-events: none;
.marquee-legend {
- bottom:-18px;
- left:0;
+ bottom: -18px;
+ left: 0;
position: absolute;
font-size: 9;
- white-space:nowrap;
+ white-space: nowrap;
}
.marquee-legend::after {
- content: "Press <space> for lasso"
+ content: 'Press <space> for lasso';
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 4513ffb39..58a00bbac 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -40,6 +40,16 @@ interface MarqueeViewProps {
nudge?: (x: number, y: number, nudgeTime?: number) => boolean;
ungroup?: () => void;
setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void;
+ slowLoadDocuments: (
+ files: File[] | string,
+ options: DocumentOptions,
+ generatedDocuments: Doc[],
+ text: string,
+ completed: ((doc: Doc[]) => void) | undefined,
+ clientX: number,
+ clientY: number,
+ addDocument: (doc: Doc | Doc[]) => boolean
+ ) => Promise<void>;
}
export interface MarqueeViewBounds {
@@ -277,8 +287,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
const hideMarquee = () => {
this.hideMarquee();
MarqueeOptionsMenu.Instance.fadeOut(true);
- document.removeEventListener('pointerdown', hideMarquee);
- document.removeEventListener('wheel', hideMarquee);
+ document.removeEventListener('pointerdown', hideMarquee, true);
+ document.removeEventListener('wheel', hideMarquee, true);
};
if (PresBox.startMarquee) {
this.pinWithView();
@@ -292,8 +302,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
MarqueeOptionsMenu.Instance.hideMarquee = this.hideMarquee;
MarqueeOptionsMenu.Instance.jumpTo(e.clientX, e.clientY);
MarqueeOptionsMenu.Instance.pinWithView = this.pinWithView;
- document.addEventListener('pointerdown', hideMarquee);
- document.addEventListener('wheel', hideMarquee);
+ document.addEventListener('pointerdown', hideMarquee, true);
+ document.addEventListener('wheel', hideMarquee, true);
} else {
this.hideMarquee();
}
@@ -330,7 +340,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this._downY = y;
const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
if ([AclAdmin, AclEdit, AclAugment].includes(effectiveAcl)) {
- PreviewCursor.Show(x, y, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument, this.props.nudge);
+ PreviewCursor.Show(x, y, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument, this.props.nudge, this.props.slowLoadDocuments);
}
this.clearSelection();
}
@@ -356,14 +366,9 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
};
@action
- showMarquee = () => {
- this._visible = true;
- };
-
+ showMarquee = () => (this._visible = true);
@action
- hideMarquee = () => {
- this._visible = false;
- };
+ hideMarquee = () => (this._visible = false);
@undoBatch
@action